From: Jan "Yenya" Kasprzak Date: Fri, 31 Jan 2014 16:32:05 +0000 (+0100) Subject: Status LED visual feedback for buttons and battery X-Git-Url: https://www.fi.muni.cz/~kas/git//home/kas/public_html/git/?p=heater.git;a=commitdiff_plain;h=d3b9a34d6b153bd04e7d233c2e2bbcecc70a6fa5 Status LED visual feedback for buttons and battery --- diff --git a/firmware/main.c b/firmware/main.c index d35fb21..76bed47 100644 --- a/firmware/main.c +++ b/firmware/main.c @@ -33,10 +33,10 @@ * Status LED: * When powering up by a button press, the LED goes on to provide a visual * feedback, and is switched off after the button is released. - * TODO: After a button press, the # of blinks of the LED reflects the + * After a button press, the # of blinks of the LED reflects the * chosen output power level for some time. Afterwards, it displays * the battery level. - * TODO: When the battery is completely exhausted, the output power is switched + * When the battery is completely exhausted, the output power is switched * off, the LED keeps blinking for some time, and then the whole system is * switched off to avoid deep discharge of the battery. * @@ -106,6 +106,10 @@ static unsigned char power_levels[] = { #define N_POWER_LEVELS (sizeof(power_levels) / sizeof(power_levels[0])) static unsigned char power_level = 0; // selected power level +static unsigned char power_level_changed; // for visual feedback + +#define LED_PWRCHANGE_COUNT 3 +#define LED_BATTEMPTY_COUNT 60 /* timing by WDT */ static volatile unsigned char jiffies, next_clock_tick; @@ -114,6 +118,7 @@ static volatile unsigned char jiffies, next_clock_tick; #define BUTTON_SHORT_MIN 1 #define BUTTON_LONG_MIN 10 + /* ========= Analog to Digital Converter (battery voltage) ========== */ static void adc_init() { @@ -341,13 +346,78 @@ static void power_down() hw_setup(); } +/* ============ Status LED blinking =================================== */ +static unsigned char blink_on_time, blink_off_time, n_blinks; +static unsigned char blink_counter; + +static unsigned char battery_level() +{ + unsigned char i, adc8; + + // NOTE: we use 8-bit value only, so we don't need lock to protect + // us against concurrently running ADC IRQ handler: + adc8 = batt_off >> 8; + + for (i = 0; i < BATT_N_LEVELS; i++) + if (batt_levels[i] > adc8) + break; + + return i; +} + +static void status_led_next_pattern() +{ + static unsigned char battery_exhausted; + + if (power_level_changed) { + power_level_changed--; + n_blinks = power_level + 1; + } else { + unsigned char b_level = battery_level(); + if (b_level) { + battery_exhausted = 0; + } else if (battery_exhausted) { + if (!--battery_exhausted) + power_down(); + } else { + battery_exhausted = LED_BATTEMPTY_COUNT; + } + + n_blinks = b_level + 1; + } + + blink_on_time = 2; + blink_off_time = 1; + blink_counter = 10; +} + +static void timer_blink() +{ + if (blink_counter) { + blink_counter--; + } else if (!status_led_is_on()) { + status_led_on(); + blink_counter = blink_on_time; + } else if (n_blinks) { + --n_blinks; + status_led_off(); + blink_counter = blink_off_time; + } else { + status_led_next_pattern(); + } +} + /* ======== Button press detection and handling ===================== */ static void button_pressed(unsigned char button, unsigned char long_press) { // ignore simlultaneous button 1 and 2 press + // Note: we set power_level_changed after each button press, + // even when the power is at maximum, to provide visual feedback + // with status LED. if (long_press) { if (button == 1) { power_down(); + return; } else if (button == 2) { power_level = N_POWER_LEVELS-1; } @@ -357,6 +427,7 @@ static void button_pressed(unsigned char button, unsigned char long_press) --power_level; } else { power_down(); + return; } } else if (button == 2) { if (power_level < N_POWER_LEVELS-1) { @@ -364,6 +435,8 @@ static void button_pressed(unsigned char button, unsigned char long_press) } } } + power_level_changed = LED_PWRCHANGE_COUNT; + status_led_next_pattern(); } static unsigned char button_state, button_state_time; @@ -397,52 +470,7 @@ static void timer_check_buttons() button_state_time = 0; } -/* ============ Status LED blinking =================================== */ -static unsigned char blink_on_time, blink_off_time, n_blinks; -static unsigned char blink_counter; - -static unsigned char battery_level() -{ - unsigned char i, adc8; - - // NOTE: we use 8-bit value only, so we don't need lock to protect - // us against concurrently running ADC IRQ handler: - adc8 = batt_off >> 8; - - for (i = 0; i < BATT_N_LEVELS; i++) - if (batt_levels[i] > adc8) - break; - - return i; -} - -static void status_led_next_pattern() -{ - - // for now, display the selected intensity - // n_blinks = power_level + 1; - n_blinks = battery_level() + 1; - blink_on_time = 0; - blink_off_time = 2; - blink_counter = 10; -} - -static void timer_blink() -{ - if (blink_counter) { - blink_counter--; - } else if (status_led_is_on()) { - status_led_off(); - blink_counter = blink_off_time; - } else if (n_blinks) { - --n_blinks; - status_led_on(); - blink_counter = blink_on_time; - } else { - status_led_next_pattern(); - } -} - +/* ===================== Output power control ======================== */ static void calculate_power_level() { uint32_t pwm;