#include "led.h" #include "io.h" /* hardware io */ static io_pin_t POWER_LED = IO_PC(7); static io_pin_t CHARGE = IO_PD(1); enum led_color { LED_C_RED, LED_C_GREEN, LED_C_OFF }; static enum led_color led_color; static inline void led_set(enum led_color color) { switch (color) { case LED_C_RED: io_clear_pin(POWER_LED); io_set_pin(CHARGE); break; case LED_C_GREEN: io_clear_pin(CHARGE); io_set_pin(POWER_LED); break; case LED_C_OFF: default: io_clear_pin(CHARGE); io_clear_pin(POWER_LED); break; } led_color = color; } /* blinken lights */ static uint8_t blink_cnt; static uint8_t orange_cnt; /* state for sequence */ static enum led_state state; static enum led_state state_next; static uint8_t seq_max; static uint8_t seq_cnt; static const uint8_t T_SEQ = 196; static const uint8_t T_ON = 98; static bool counting; void led_set_blink_seq(uint8_t n_blinks, enum led_state color) { if (color == state) return; blink_cnt = 0; seq_cnt = 0; seq_max = 2 * n_blinks + 1; state = color; } void led_set_solid(enum led_state color) { if (state != LED_BLINK_RED_FAST) state = color; state_next = color; } void led_set_blink(enum led_state color) { if (state != LED_BLINK_RED_FAST) state = color; state_next = color; } irqreturn_t led_wdt_handler(void) { counting = false; switch (state) { case LED_BLINK_GREEN_SLOW: if (blink_cnt < T_ON) led_set(LED_C_GREEN); else led_set(LED_C_OFF); blink_cnt += 1; break; case LED_BLINK_GREEN_FAST: if (blink_cnt < T_ON) led_set(LED_C_GREEN); else led_set(LED_C_OFF); blink_cnt += 4; break; case LED_BLINK_RED_FAST: counting = true; if (!seq_cnt) { led_set(LED_C_OFF); } else if (blink_cnt < T_ON) led_set(seq_cnt % 2 ? LED_C_OFF : LED_C_RED); else led_set(LED_C_OFF); blink_cnt += 16; break; case LED_BLINK_ORANGE: if (blink_cnt < T_ON) led_set(orange_cnt % 2 ? LED_C_GREEN : LED_C_RED); else led_set(LED_C_OFF); orange_cnt++; blink_cnt += 4; break; case LED_ORANGE: led_set(orange_cnt % 2 ? LED_C_GREEN : LED_C_RED); orange_cnt++; blink_cnt+=4; break; case LED_GREEN: led_set(LED_C_GREEN); break; case LED_RED: led_set(LED_C_RED); break; case LED_OFF: default: led_set(LED_C_OFF); break; } if (blink_cnt >= T_SEQ - 1) { blink_cnt = 0; if (counting) { if (seq_cnt < seq_max) { seq_cnt++; } else { state = state_next; seq_cnt = 0; counting = false; } } else { state = state_next; } } return IRQ_HANDLED; }