]> www.fi.muni.cz Git - bike-lights.git/blob - firmware/pattern.c
3354c6f5e5d59b8a46e4c5991d736ab70e6e4a55
[bike-lights.git] / firmware / pattern.c
1 #include <avr/io.h>
2 #include <stdlib.h> // for NULL
3
4 #include "lights.h"
5
6 static unsigned char led_counters[N_LEDS];
7 static pattern_t *led_patterns[N_LEDS];
8
9 static unsigned char fibonacci[8] = {
10         0, 1, 2, 3, 5, 8, 13, 21,
11 };
12
13 static pattern_t boot_pattern[] = {
14         { 1, D_5 },
15         { 0, D_5 },
16         { 1, D_3 },
17         { 0, D_3 },
18         { 1, D_2 },
19         { 0, D_2 },
20         { 1, D_1 },
21         { 0, D_1 },
22         { 1, D_1 },
23         { 0, D_1 },
24         { 1, D_1 },
25         { 0, D_1 },
26         { 1, D_1 },
27         { 0, D_1 },
28         { 1, D_8 },
29         { 0, D_8 },
30         PATTERN_END
31 };
32
33 static pattern_t pattern_num[] = {
34         { 0, D_5 },
35         { 1, D_1 }, /* 10 */
36         { 0, D_5 },
37         { 1, D_1 }, /*  9 */
38         { 0, D_5 },
39         { 1, D_1 }, /*  8 */
40         { 0, D_5 },
41         { 1, D_1 }, /*  7 */
42         { 0, D_5 },
43         { 1, D_1 }, /*  6 */
44         { 0, D_5 },
45         { 1, D_1 }, /*  5 */
46         { 0, D_5 },
47         { 1, D_1 }, /*  4 */
48         { 0, D_5 },
49         { 1, D_1 }, /*  3 */
50         { 0, D_5 },
51         { 1, D_1 }, /*  2 */
52         { 0, D_5 },
53         { 1, D_1 }, /*  1 */
54         { 0, D_13 },
55         PATTERN_END
56 };
57
58 static pattern_t pattern_invnum[] = {
59         { 1, D_5 },
60         { 0, D_1 }, /* 10 */
61         { 1, D_5 },
62         { 0, D_1 }, /*  9 */
63         { 1, D_5 },
64         { 0, D_1 }, /*  8 */
65         { 1, D_5 },
66         { 0, D_1 }, /*  7 */
67         { 1, D_5 },
68         { 0, D_1 }, /*  6 */
69         { 1, D_5 },
70         { 0, D_1 }, /*  5 */
71         { 1, D_5 },
72         { 0, D_1 }, /*  4 */
73         { 1, D_5 },
74         { 0, D_1 }, /*  3 */
75         { 1, D_5 },
76         { 0, D_1 }, /*  2 */
77         { 1, D_5 },
78         { 0, D_1 }, /*  1 */
79         { 1, D_13 },
80         PATTERN_END
81 };
82
83 pattern_t off_pattern[] = {
84         { 0, D_1 },
85         PATTERN_END
86 };
87
88 static void led_set_mode(unsigned char n, unsigned char mode)
89 {
90         if (n < N_PWMLEDS) {
91                 pwmled_set_mode(n, mode);
92         } else if (n < N_LEDS) {
93                 gpio_set(n - N_PWMLEDS, mode);
94         }
95 }
96
97 void led_set_pattern(unsigned char n, pattern_t *pattern)
98 {
99         if (!pattern)
100                 pattern = off_pattern;
101
102         led_patterns[n] = pattern;
103
104         led_counters[n] = fibonacci[pattern->duration_fib];
105
106         led_set_mode(n, pattern->mode);
107 }
108
109 void init_pattern()
110 {
111         unsigned char i;
112
113         for (i = 0; i < N_LEDS; i++)
114                 led_set_pattern(i, NULL);
115
116         led_set_pattern(N_PWMLEDS+1, boot_pattern);
117 }
118
119 pattern_t *number_pattern(unsigned char num, unsigned char inv)
120 {
121         if (num >= 10)
122                 num = 10;
123
124         if (inv) {
125                 return pattern_invnum
126                         + sizeof(pattern_invnum)/sizeof(pattern_t)
127                         - 2 - 2*num;
128         } else {
129                 return pattern_num
130                         + sizeof(pattern_num)/sizeof(pattern_t)
131                         - 2 - 2*num;
132         }
133 }
134
135 static pattern_t *pattern_select(unsigned char n)
136 {
137         switch(n) {
138         case 0: return pwmled0_pattern_select();
139         case 1: return pwmled1_pattern_select();
140         case 2: return pwmled2_pattern_select();
141         case 3: return status_led_pattern_select();
142         case 4: return illumination_led_pattern_select();
143         case 6: return laser_pattern_select();
144         default: return NULL;
145         }
146 }
147
148 void pattern_reload()
149 {
150         unsigned char i;
151
152         for (i = 0; i < N_LEDS; i++)
153                 led_set_pattern(i, pattern_select(i));
154 }
155
156 static void inline pattern_finished(unsigned char n)
157 {
158         unsigned char i;
159
160         led_patterns[n] = NULL;
161
162         if (n < N_PWMLEDS) {
163                 for (i = 0; i < N_PWMLEDS; i++)
164                         if (led_patterns[i])
165                                 return;
166
167                 /* all pwmleds finished; restart them */
168                 for (i = 0; i < N_PWMLEDS; i++)
169                         led_set_pattern(i, pattern_select(i));
170         } else if (n == 3) {
171                 if (!led_patterns[4])
172                         led_set_pattern(4, pattern_select(4));
173         } else if (n == 4) {
174                 if (!led_patterns[3])
175                         led_set_pattern(3, pattern_select(3));
176         } else {
177                 led_set_pattern(n, pattern_select(n));
178         }
179 }
180
181 void patterns_next_tick()
182 {
183         unsigned char i;
184
185         for (i = 0; i < N_LEDS; i++) {
186                 if (!led_patterns[i]) {
187                         pattern_finished(i);
188                         continue;
189                 }
190
191                 if (--led_counters[i] == 0) {
192                         pattern_t *p = led_patterns[i];
193                         p++;
194                         if (p->duration_fib == 0) { // END
195                                 /* Keep the last state, wait for others */
196                                 pattern_finished(i);
197                                 continue;
198                         }
199                         led_set_pattern(i, p);
200                 }
201
202         }
203 }
204