1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
|
/* 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;
}
}
|