/* SAM7DFU blink code support * (C) 2006 by Harald Welte <laforge@gnumonks.org> * */ #include <os/pit.h> #include <os/dbgu.h> #include <os/led.h> #include <os/blinkcode.h> #define NUM_LEDS 2 enum blinkcode_state { BLINKCODE_STATE_NONE, BLINKCODE_STATE_SILENT, /* period of silence at start */ BLINKCODE_STATE_INIT, /* initial long light */ BLINKCODE_STATE_BLINK_OFF, /* blinking out, currently off */ BLINKCODE_STATE_BLINK_ON, /* blinking out, currently on */ BLINKCODE_STATE_DONE, }; #define TIME_SILENT (1*HZ) #define TIME_INIT (1*HZ) #define TIME_BLINK (HZ/4) struct blinker { struct timer_list timer; enum blinkcode_state state; int num; int cur; u_int8_t led; }; static struct blinker blink_state[NUM_LEDS]; static void blinkcode_cb(void *data) { /* we got called back by the timer */ struct blinker *bl = data; DEBUGPCRF("(jiffies=%lu, data=%p, state=%u)", jiffies, data, bl->state); switch (bl->state) { case BLINKCODE_STATE_NONE: led_switch(bl->led, 0); bl->state = BLINKCODE_STATE_SILENT; bl->timer.expires = jiffies + TIME_SILENT; bl->cur = bl->num; break; case BLINKCODE_STATE_SILENT: /* we've finished the period of silence, turn led on */ led_switch(bl->led, 1); bl->state = BLINKCODE_STATE_INIT; bl->timer.expires = jiffies + TIME_INIT; break; case BLINKCODE_STATE_INIT: /* we've finished the period of init */ led_switch(bl->led, 0); bl->state = BLINKCODE_STATE_BLINK_OFF; bl->timer.expires = jiffies + TIME_INIT; break; case BLINKCODE_STATE_BLINK_OFF: /* we've been off, turn on */ led_switch(bl->led, 1); bl->state = BLINKCODE_STATE_BLINK_ON; bl->cur--; bl->timer.expires = jiffies + TIME_BLINK; if (bl->cur <= 0) bl->state = BLINKCODE_STATE_DONE; break; case BLINKCODE_STATE_BLINK_ON: /* we've been on, turn off */ led_switch(bl->led, 0); bl->state = BLINKCODE_STATE_BLINK_OFF; bl->timer.expires = jiffies + TIME_BLINK; break; case BLINKCODE_STATE_DONE: /* we've been on, turn off */ led_switch(bl->led, 0); return; break; } /* default case: re-add the timer */ timer_add(&bl->timer); } void blinkcode_set(int led, enum blinkcode_num num) { DEBUGPCRF("(jiffies=%lu, led=%u, num=%u)", jiffies, led, num); if (--led > NUM_LEDS) return; timer_del(&blink_state[led].timer); blink_state[led].num = num; blink_state[led].state = BLINKCODE_STATE_NONE; blink_state[led].timer.expires = jiffies; if (num != BLINKCODE_NONE) timer_add(&blink_state[led].timer); } void blinkcode_init(void) { int i; for (i = 0; i < NUM_LEDS; i++) { blink_state[i].num = 0; blink_state[i].state = BLINKCODE_STATE_NONE; blink_state[i].led = i+1; blink_state[i].timer.data = &blink_state[i]; blink_state[i].timer.function = &blinkcode_cb; } }