From: Jan "Yenya" Kasprzak Date: Fri, 30 Nov 2012 16:37:53 +0000 (+0100) Subject: firmware: control logic moved to a separate module X-Git-Url: https://www.fi.muni.cz/~kas/git//home/kas/public_html/git/?a=commitdiff_plain;h=647f353f4d8c87c5cf18cae905e9d600cd0e6bcb;p=bike-lights.git firmware: control logic moved to a separate module - buttons.c now controls status LEDs only when setting parameters - pattern.c: can use NULL instead of off_pattern has number_pattern() than can also set up inverted patterns contains only number and boot patterns as static variables can reload all patterns if some state changes - ambient.c resets all patterns when ambient zone changes - control.c: - now contains almost all pattern strings, only those needed by other modules are exported - status LED and illumination LED can be controlled by buttons.c - separate _pattern_select() function for each LED --- diff --git a/firmware/Makefile b/firmware/Makefile index 70c2c32..7be101d 100644 --- a/firmware/Makefile +++ b/firmware/Makefile @@ -1,7 +1,7 @@ PROGRAM=lights SRC=main.c logging.c adc.c pwm.c tmr.c pwmled.c gpio.c ambient.c pattern.c \ - buttons.c battery.c + buttons.c battery.c control.c OBJ=$(SRC:.c=.o) diff --git a/firmware/ambient.c b/firmware/ambient.c index f6f5220..025b0c4 100644 --- a/firmware/ambient.c +++ b/firmware/ambient.c @@ -24,6 +24,8 @@ void ambient_zone_changed() log_byte(ambient_zone); log_word(ambient_val); log_flush(); + + pattern_reload(); } void ambient_adc(uint16_t adcval) diff --git a/firmware/buttons.c b/firmware/buttons.c index 0742f92..c1a785d 100644 --- a/firmware/buttons.c +++ b/firmware/buttons.c @@ -2,6 +2,7 @@ #include #include #include +#include // for NULL #include "lights.h" @@ -26,33 +27,33 @@ static void inline set_status_led(unsigned char n, pattern_t *pattern) led_set_pattern(n + N_PWMLEDS, pattern); } -pattern_t *status_pattern_select(unsigned char n) +unsigned char buttons_setup_in_progress() { - if (user_params_state) // Setup in progress - return number_pattern(n == 0 - ? user_params_state - : 1 + user_params[user_params_state-1] - ); - else if (!(prev_pin & _BV(PA3)) || !(prev_pin & _BV(PA4))) - // at least one button is pressed - return off_pattern; - // otherwise, an ordinary state - if (n == 0) { - // error led - return number_pattern(1 + ambient_zone); - } else { - return jiffies > 500 ? number_pattern(2) : zero_pattern; // for now - } + if (user_params_state // setup in progress ... + // or at least one button is pressed: + || !(prev_pin & _BV(PA3)) + || !(prev_pin & _BV(PA4))) + return 1; + return 0; } -static void toggle_bright_mode() +pattern_t *buttons_setup_status0_pattern_select() { - // TODO + if (user_params_state) // Setup in progress + return number_pattern(user_params_state, 1); + else + return NULL; } -static void set_panic_mode() +pattern_t *buttons_setup_status1_pattern_select() { - // TODO + if (user_params_state) // Setup in progress + return number_pattern( + 1 + user_params[user_params_state-1], + 1 + ); + else + return NULL; } unsigned char get_user_param(unsigned char param) @@ -68,7 +69,7 @@ static inline void short_press(unsigned char button) if (user_params_state == 0) { if (button == 0) - toggle_bright_mode(); + toggle_dim_mode(); else set_panic_mode(); return; @@ -89,7 +90,7 @@ static inline void short_press(unsigned char button) } // FIXME: notify somebody about user_params change? - set_status_led(1, status_pattern_select(1)); + set_status_led(1, buttons_setup_status1_pattern_select()); user_params_starttime = jiffies; } @@ -107,8 +108,8 @@ static inline void long_press(unsigned char button) if (user_params_state > MAX_USER_PARAMS) user_params_state = 1; - set_status_led(0, status_pattern_select(0)); - set_status_led(1, status_pattern_select(1)); + set_status_led(0, buttons_setup_status0_pattern_select()); + set_status_led(1, buttons_setup_status1_pattern_select()); user_params_starttime = jiffies; } @@ -146,13 +147,13 @@ static void handle_button(unsigned char button, unsigned char cur, // BEWARE: pins are at _zero_ when pressed! if (!cur && prev) { // --- just pressed --- button_start[button] = jiffies; - set_status_led(button, off_pattern); + set_status_led(button, NULL); } else if (!cur && !prev) { // --- is still pressed --- uint16_t duration = jiffies - button_start[button]; if (duration > 80) { - set_status_led(button, on_pattern); + set_status_led(button, on1_pattern); // acknowledge long press } } else if (cur && !prev) { // --- just released --- @@ -161,7 +162,7 @@ static void handle_button(unsigned char button, unsigned char cur, if (duration > 6 && duration < 30) { short_press(button); } else if (duration > 80) { - set_status_led(button, off_pattern); + set_status_led(button, NULL); long_press(button); } // ignore other button-press durations @@ -179,8 +180,8 @@ void timer_check_buttons() if (user_params_state && jiffies - user_params_starttime > 1000) { user_params_state = 0; - set_status_led(0, status_pattern_select(0)); - set_status_led(1, status_pattern_select(1)); + set_status_led(0, buttons_setup_status0_pattern_select()); + set_status_led(1, buttons_setup_status1_pattern_select()); } } diff --git a/firmware/control.c b/firmware/control.c new file mode 100644 index 0000000..0b842a7 --- /dev/null +++ b/firmware/control.c @@ -0,0 +1,205 @@ +#include +#include // for NULL + +#include "lights.h" + +static pattern_t panic_pattern[] = { + { 3, 1 }, // FIXME: will be 4, but let's be safe while testing + { 0, 1 }, + { 3, 1 }, + { 0, 1 }, + { 3, 1 }, + { 0, 1 }, + { 3, 1 }, + { 0, 1 }, + { 3, 1 }, + { 0, 1 }, + { 3, 1 }, + { 0, 1 }, + { 3, 1 }, + { 0, 1 }, + { 3, 1 }, + { 0, 1 }, + { 3, 1 }, + { 0, 1 }, + { 3, 1 }, + { 0, 1 }, + { 3, 1 }, + { 0, 1 }, + PATTERN_END +}; + +pattern_t on1_pattern [] = { + { 1, PATTERN_FOREVER } +}; + +static pattern_t on2_pattern [] = { + { 2, PATTERN_FOREVER } +}; + +static pattern_t on3_pattern [] = { + { 3, PATTERN_FOREVER } +}; + +static pattern_t normal2_pattern[] = { + { 2, 0x1 }, + { 0, 0x1 }, + { 2, 0x1 }, + { 0, 0x8 }, + { 1, 0x1 }, + { 0, 0x1 }, + { 1, 0x1 }, + { 0, 0x8 }, + PATTERN_END +}; + +static pattern_t normal3_pattern[] = { + { 2, 0x1 }, + { 0, 0x1 }, + { 2, 0x1 }, + { 0, 0x8 }, + { 1, 0x1 }, + { 0, 0x1 }, + { 1, 0x1 }, + { 0, 0x8 }, + PATTERN_END +}; + +static pattern_t normal4_pattern[] = { + { 2, 0x1 }, + { 0, 0x1 }, + { 2, 0x1 }, + { 0, 0x8 }, + { 1, 0x1 }, + { 0, 0x1 }, + { 1, 0x1 }, + { 0, 0x8 }, + PATTERN_END +}; + +static pattern_t slow1_pattern[] = { + { 1, 0x01 }, + { 0, 0x10 }, + PATTERN_END +}; + +static pattern_t slow2_pattern[] = { + { 2, 0x01 }, + { 0, 0x10 }, + PATTERN_END +}; + +static pattern_t slow3_pattern[] = { + { 3, 0x01 }, + { 0, 0x10 }, + PATTERN_END +}; + +static unsigned char dim_mode, towbar_mode; + +void init_control() +{ + dim_mode = 0; + towbar_mode = 0; +} + +void toggle_dim_mode() +{ + dim_mode = !dim_mode; + pattern_reload(); +} + +void set_panic_mode() +{ + if (!dim_mode) + led_set_pattern(0, panic_pattern); + + led_set_pattern(1, panic_pattern); + led_set_pattern(2, panic_pattern); + led_set_pattern(4, panic_pattern); +} + +pattern_t *pwmled0_pattern_select() +{ + // TODO: battery critical + + if (towbar_mode) + return NULL; + + switch (ambient_zone) { + case 0: return dim_mode ? NULL : on1_pattern; + case 1: return dim_mode ? NULL : slow2_pattern; + case 2: return dim_mode ? slow3_pattern : slow2_pattern; + case 3: + default: return dim_mode ? slow3_pattern : normal4_pattern; + } +} + +pattern_t *pwmled1_pattern_select() +{ + // TODO: battery critical + + if (towbar_mode) { + switch (ambient_zone) { + case 0: + case 1: + return dim_mode ? on2_pattern : on1_pattern; + case 2: return dim_mode ? NULL : on2_pattern; + case 3: + default: return dim_mode ? NULL : on3_pattern; + } + } else { + switch (ambient_zone) { + case 0: return dim_mode ? slow1_pattern : normal2_pattern; + case 1: return dim_mode ? slow2_pattern : normal3_pattern; + case 2: return dim_mode ? NULL : normal4_pattern; + case 3: + default: return NULL; + } + } +} + +pattern_t *pwmled2_pattern_select() +{ + // TODO: battery critical + + switch (ambient_zone) { + case 0: return dim_mode ? on2_pattern : on3_pattern; + case 1: return dim_mode ? slow1_pattern : normal2_pattern; + case 2: + case 3: + default: + return dim_mode ? slow2_pattern : normal3_pattern; + } +} + +pattern_t *status_led_pattern_select() +{ + if (buttons_setup_in_progress()) + return buttons_setup_status0_pattern_select(); + + // FIXME: do something sane + return number_pattern(1 + ambient_zone, 1); +} + +pattern_t *illumination_led_pattern_select() +{ + // todo: battery critical + + switch (ambient_zone) { + case 0: return dim_mode + ? number_pattern(1, 1) + : on1_pattern; + case 1: return dim_mode + ? number_pattern(2, 1) + : number_pattern(3, 1); + case 2: return dim_mode + ? number_pattern(3, 0) + : number_pattern(4, 0); + case 3: + default: return dim_mode + ? number_pattern(5, 0) + : number_pattern(6, 0); + } +} + diff --git a/firmware/lights.h b/firmware/lights.h index 8187142..4a23436 100644 --- a/firmware/lights.h +++ b/firmware/lights.h @@ -66,15 +66,11 @@ typedef struct { #define PATTERN_FOREVER 0x1F #define PATTERN_END { 0, 0 } -extern pattern_t off_pattern[]; -extern pattern_t zero_pattern[]; -extern pattern_t on_pattern[]; -extern pattern_t mode1_pattern[]; - void init_pattern(); void patterns_next_tick(); void led_set_pattern(unsigned char led, pattern_t *pattern); -pattern_t *number_pattern(unsigned char num); +pattern_t *number_pattern(unsigned char num, unsigned char inv); +void pattern_reload(); /* buttons.c */ #define MAX_USER_PARAMS 3 @@ -82,14 +78,28 @@ void init_buttons(); void susp_buttons(); void timer_check_buttons(); unsigned char get_user_param(unsigned char param); -pattern_t *status_pattern_select(unsigned char n); unsigned char buttons_wait_for_release(); +unsigned char buttons_setup_in_progress(); +pattern_t *buttons_setup_status0_pattern_select(); +pattern_t *buttons_setup_status1_pattern_select(); /* battery.c */ extern volatile unsigned char battery_100mv; void battery_adc(); void init_battery(); +/* control.c */ +extern pattern_t on1_pattern[]; + +void init_control(); +void toggle_dim_mode(); +void set_panic_mode(); +pattern_t *pwmled0_pattern_select(); +pattern_t *pwmled1_pattern_select(); +pattern_t *pwmled2_pattern_select(); +pattern_t *status_led_pattern_select(); +pattern_t *illumination_led_pattern_select(); + /* main.c */ void power_down(); diff --git a/firmware/main.c b/firmware/main.c index 26b8f1c..90bea63 100644 --- a/firmware/main.c +++ b/firmware/main.c @@ -21,6 +21,7 @@ static void hw_setup() init_gpio(); init_ambient(); init_pattern(); + init_control(); set_sleep_mode(SLEEP_MODE_IDLE); } diff --git a/firmware/pattern.c b/firmware/pattern.c index 3aec77b..59692bf 100644 --- a/firmware/pattern.c +++ b/firmware/pattern.c @@ -1,42 +1,12 @@ #include +#include // for NULL #include "lights.h" static unsigned char led_counters[N_LEDS]; static pattern_t *led_patterns[N_LEDS]; -pattern_t off_pattern[] = { - { 0, PATTERN_FOREVER }, -}; - -pattern_t zero_pattern[] = { - { 0, 0x10 }, - PATTERN_END -}; - -pattern_t on_pattern[] = { - { 1, PATTERN_FOREVER }, -}; - -pattern_t blink_pattern[] = { - { 1, 0x4 }, - { 0, 0x8 }, - PATTERN_END -}; - -pattern_t mode1_pattern[] = { - { 2, 0x1 }, - { 0, 0x1 }, - { 2, 0x1 }, - { 0, 0x8 }, - { 1, 0x1 }, - { 0, 0x1 }, - { 1, 0x1 }, - { 0, 0x8 }, - PATTERN_END -}; - -pattern_t boot_pattern[] = { +static pattern_t boot_pattern[] = { { 1, 0x6 }, { 0, 0x6 }, { 1, 0x3 }, @@ -56,7 +26,7 @@ pattern_t boot_pattern[] = { PATTERN_END }; -pattern_t pattern_num[] = { +static pattern_t pattern_num[] = { { 0, 0x5 }, { 1, 0x1 }, /* 10 */ { 0, 0x5 }, @@ -81,7 +51,30 @@ pattern_t pattern_num[] = { PATTERN_END }; -static unsigned char test_running; +static pattern_t pattern_invnum[] = { + { 1, 0x5 }, + { 0, 0x1 }, /* 10 */ + { 1, 0x5 }, + { 0, 0x1 }, /* 9 */ + { 1, 0x5 }, + { 0, 0x1 }, /* 8 */ + { 1, 0x5 }, + { 0, 0x1 }, /* 7 */ + { 1, 0x5 }, + { 0, 0x1 }, /* 6 */ + { 1, 0x5 }, + { 0, 0x1 }, /* 5 */ + { 1, 0x5 }, + { 0, 0x1 }, /* 4 */ + { 1, 0x5 }, + { 0, 0x1 }, /* 3 */ + { 1, 0x5 }, + { 0, 0x1 }, /* 2 */ + { 1, 0x5 }, + { 0, 0x1 }, /* 1 */ + { 1, 0x1E }, + PATTERN_END +}; static void led_set_mode(unsigned char n, unsigned char mode) { @@ -94,10 +87,13 @@ static void led_set_mode(unsigned char n, unsigned char mode) void led_set_pattern(unsigned char n, pattern_t *pattern) { - if (!pattern) - pattern = off_pattern; - led_patterns[n] = pattern; + + if (!pattern) { + led_set_mode(n, 0); + return; + } + led_counters[n] = pattern->duration; led_set_mode(n, pattern->mode); } @@ -107,30 +103,45 @@ void init_pattern() unsigned char i; for (i = 0; i < N_LEDS; i++) - led_set_pattern(i, zero_pattern); + led_set_pattern(i, NULL); led_set_pattern(N_PWMLEDS+1, boot_pattern); - test_running = 0; } -pattern_t *number_pattern(unsigned char num) +pattern_t *number_pattern(unsigned char num, unsigned char inv) { if (num >= 9) num = 9; - return pattern_num + sizeof(pattern_num)/sizeof(pattern_t) - - 2 - 2*num; + if (inv) { + return pattern_invnum + + sizeof(pattern_invnum)/sizeof(pattern_t) + - 2 - 2*num; + } else { + return pattern_num + + sizeof(pattern_num)/sizeof(pattern_t) + - 2 - 2*num; + } +} + +static pattern_t *pattern_select(unsigned char n) +{ + switch(n) { + case 0: return pwmled0_pattern_select(); + case 1: return pwmled1_pattern_select(); + case 2: return pwmled2_pattern_select(); + case 3: return status_led_pattern_select(); + case 4: return illumination_led_pattern_select(); + default: return NULL; + } } -static inline pattern_t *pattern_select(unsigned char n) +void pattern_reload() { - if (n < N_PWMLEDS) - return mode1_pattern; - else if (n == 3) - return status_pattern_select(0); - else if (n == 4) - return status_pattern_select(1); - return off_pattern; + unsigned char i; + + for (i = 0; i < N_LEDS; i++) + led_set_pattern(i, pattern_select(i)); } void patterns_next_tick() @@ -138,6 +149,9 @@ void patterns_next_tick() unsigned char i; for (i = 0; i < N_LEDS; i++) { + if (!led_patterns[i]) + continue; + if (led_counters[i] == 0) { pattern_t *p = led_patterns[i]; p++;