From 15758319e9901ada7e67a7c0c3288e53d803f059 Mon Sep 17 00:00:00 2001 From: "Jan \"Yenya\" Kasprzak" Date: Wed, 26 Jun 2013 22:35:37 +0200 Subject: [PATCH] braking is handled behind the patterns inside pattern.c See the comment above pwmled_update_mode(): This is tricky: we use a single pattern for all three pwmleds, but on some occasions, we want to be able to modify only a single pwmled status without affecting other outputs. For example, during braking, we want to modify only the rear pwmled status. We don't use a separate "braking" pattern for every other pattern used, but instead we change the pwmled0 status regardless of the original value when braking. The rule is the following: - if during braking the pwmled2 (front) is at mode 2, we switch it to mode 3 (which has the same target current) to avoid flicker. - if pwmled0 (rear) is off, we set it to mode 2 (if it is with mode 1, we keep it at mode 1) TODO: something similar should be done for the "entering the dark area" condition, where we want to switch pwmled2 (front) on, to mode 2. --- firmware/control.c | 19 ++++--------------- firmware/lights.h | 2 ++ firmware/pattern.c | 40 +++++++++++++++++++++++++++++++++++----- 3 files changed, 41 insertions(+), 20 deletions(-) diff --git a/firmware/control.c b/firmware/control.c index a789acc..8477722 100644 --- a/firmware/control.c +++ b/firmware/control.c @@ -28,12 +28,6 @@ static pattern_t panic_pattern[] = { PATTERN_END }; -static pattern_t brake_pattern [] = { - { 4, D_2 }, - { 3, D_8 }, - PATTERN_END -}; - static pattern_t slow_pattern[] = { { PWM_PAT(1, 0, 0), D_1 }, { PWM_PAT(0, 0, 1), D_1 }, @@ -70,7 +64,8 @@ pattern_t on_pattern[] = { PATTERN_END }; -static unsigned char dim_mode, towbar_mode, braking; +volatile unsigned char braking; +static unsigned char dim_mode, towbar_mode; void init_control() { @@ -84,7 +79,7 @@ void brake_on() braking = 1; gpio_set(0, 1); led_set_pattern(N_STATUS_LED, status_led_pattern_select()); - led_set_pattern(0, pwmled_pattern_select()); + pwmleds_update_mode(); } void brake_off() @@ -92,7 +87,7 @@ void brake_off() braking = 0; gpio_set(0, 0); led_set_pattern(N_STATUS_LED, status_led_pattern_select()); - led_set_pattern(0, pwmled_pattern_select()); + pwmleds_update_mode(); } void toggle_dim_mode() @@ -112,12 +107,6 @@ pattern_t *pwmled_pattern_select() if (battery_critical) return slow_pattern; - if (towbar_mode) - return NULL; - - if (braking) - return brake_pattern; - switch (ambient_zone) { case 0: return night_pattern; case 1: diff --git a/firmware/lights.h b/firmware/lights.h index 26f7372..2c06b57 100644 --- a/firmware/lights.h +++ b/firmware/lights.h @@ -108,6 +108,7 @@ void patterns_next_tick(); void led_set_pattern(unsigned char led, pattern_t *pattern); pattern_t *number_pattern(unsigned char num, unsigned char inv); void pattern_reload(); +void pwmleds_update_mode(); /* buttons.c */ #define MAX_USER_PARAMS 3 @@ -129,6 +130,7 @@ unsigned char battery_gauge(); /* control.c */ extern pattern_t on_pattern[]; +extern volatile unsigned char braking; void init_control(); void brake_on(); diff --git a/firmware/pattern.c b/firmware/pattern.c index ab63e34..c9f4ded 100644 --- a/firmware/pattern.c +++ b/firmware/pattern.c @@ -85,11 +85,41 @@ pattern_t off_pattern[] = { PATTERN_END }; -static void inline pwmleds_set_mode(unsigned char mode) +/* + * This is tricky: we use a single pattern for all three pwmleds, + * but on some occasions, we want to be able to modify only a single + * pwmled status without affecting other outputs. For example, during + * braking, we want to modify only the rear pwmled status. We don't + * use a separate "braking" pattern for every other pattern used, but instead + * we change the pwmled0 status regardless of the original value when + * braking. The rule is the following: + * - if during braking the pwmled2 (front) is at mode 2, we switch it to + * mode 3 (which has the same target current) to avoid flicker. + * - if pwmled0 (rear) is off, we set it to mode 2 + * (if it is with mode 1, we keep it at mode 1) + * TODO: something similar should be done for the "entering the dark area" + * condition, where we want to switch pwmled2 (front) on, to mode 2. + */ +void pwmleds_update_mode() { - pwmled_set_mode(0, mode & 3); - pwmled_set_mode(1, (mode >> 2) & 1); - pwmled_set_mode(2, (mode >> 3) & 3); + unsigned char mode, mode0, mode1, mode2; + + mode = led_patterns[0]->mode; + + mode0 = mode & 3; + mode1 = (mode >> 2) & 1; + mode2 = (mode >> 3) & 3; + + if (braking) { + if (!mode0) + mode0 = 2; + if (mode2 == 2) + mode2 = 3; + } + + pwmled_set_mode(0, mode0); + pwmled_set_mode(1, mode1); + pwmled_set_mode(2, mode2); } void led_set_pattern(unsigned char n, pattern_t *pattern) @@ -102,7 +132,7 @@ void led_set_pattern(unsigned char n, pattern_t *pattern) led_counters[n] = fibonacci[pattern->duration_fib]; if (n == 0) { - pwmleds_set_mode(pattern->mode); + pwmleds_update_mode(); } else if (n < N_LEDS) { gpio_set(n - 1, pattern->mode); } -- 2.39.3