]> git.zerfleddert.de Git - fnordlicht-mini/blob - firmware/fnordlicht-controller/ui.c
a9c559aa5aef343cf33a863d1a313fce16e0ca71
[fnordlicht-mini] / firmware / fnordlicht-controller / ui.c
1 /*
2 * unzap firmware
3 *
4 * (c) by Alexander Neumann <alexander@lochraster.org>
5 *
6 * This program is free software; you can redistribute it and/or modify
7 * it under the terms of the GNU General Public License version 2 as
8 * published by the Free Software Foundation.
9 *
10 * This program is distributed in the hope that it will be useful,
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 * GNU General Public License for more details.
14 *
15 * You should have received a copy of the GNU General Public License
16 * along with this program; if not, write to the Free Software
17 * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
18 *
19 * For more information on the GPL, please go to:
20 * http://www.gnu.org/copyleft/gpl.html
21 */
22
23 #include <avr/io.h>
24 #include <util/delay.h>
25 #include <avr/pgmspace.h>
26 #include "globals.h"
27 #include "ui.h"
28 #include "timer.h"
29 #include "uart.h"
30 #include "../common/pt/pt.h"
31 #include "remote-proto.h"
32
33 /* module local variables */
34
35 static struct pt btn_thread;
36 /* buttons are idle at start (internal pullups active) */
37 static uint8_t btn_state = _BV(BTN1_PIN) | _BV(BTN2_PIN);
38 static uint8_t btn_last_sample = _BV(BTN1_PIN) | _BV(BTN2_PIN);
39 static uint8_t btn_press = 0;
40
41 static struct pt blink_thread;
42 static uint8_t blink_seq_led1 = 0;
43 static uint8_t blink_seq_led2 = 0;
44
45 static struct pt input_thread;
46
47 /* initialize the button and led pins */
48 void ui_init(void)
49 {
50 /* initialize buttons */
51 BTN_DDR &= ~(_BV(BTN1_PIN) | _BV(BTN2_PIN));
52 BTN_PORT |= _BV(BTN1_PIN) | _BV(BTN2_PIN);
53
54 /* initialize leds */
55 LED_DDR |= _BV(LED1_PIN) | _BV(LED2_PIN);
56 LED_PORT &= ~(_BV(LED1_PIN) | _BV(LED2_PIN));
57
58 /* initialize button sample thread and variables */
59 PT_INIT(&btn_thread);
60
61 /* initialize blink thread and variables */
62 PT_INIT(&blink_thread);
63
64 /* initialize input thread */
65 PT_INIT(&input_thread);
66 }
67
68 /* blink out a sequence (LSB first), every bit is 150ms long */
69 void ui_blink(uint8_t sequence1, uint8_t sequence2)
70 {
71 blink_seq_led1 = sequence1;
72 blink_seq_led2 = sequence2;
73 }
74
75 /* check if the current blink sequency is done */
76 bool ui_blinking(void)
77 {
78 return !(blink_seq_led1 || blink_seq_led2);
79 }
80
81 /* sample buttons, set bit in btn_press if a button has been pressed */
82 static PT_THREAD(ui_sample_buttons(struct pt *thread))
83 {
84 /* make sure no variable is created on the stack */
85 static timer_t btn_timer;
86
87 PT_BEGIN(thread);
88
89 while(1) {
90 /* only execute this thread every 10ms */
91 timer_set(&btn_timer, 1);
92 PT_WAIT_UNTIL(thread, timer_expired(&btn_timer));
93
94 /* sample buttons */
95 /* ATTENTION: make SURE, btn_sample is NOT created on the stack! */
96 register uint8_t btn_sample = BTN_PIN & (_BV(BTN1_PIN) | _BV(BTN2_PIN));
97
98 /* mark bits which stayed the same since last sample */
99 btn_last_sample ^= ~btn_sample;
100
101 /* mark bits which have not changed, but whose state is different */
102 btn_last_sample = btn_state ^ (btn_sample & btn_last_sample);
103
104 /* if old state is one (button not pressed), new state is zero (button pressed),
105 * so set these bits in btn_press */
106 btn_press |= btn_last_sample & btn_state;
107
108 /* remember new state and last sample */
109 btn_state ^= btn_last_sample;
110 btn_last_sample = btn_sample;
111 }
112
113 PT_END(thread);
114 }
115
116 /* execute led blinking */
117 static PT_THREAD(ui_do_blinking(struct pt *thread))
118 {
119 static timer_t t;
120
121 PT_BEGIN(thread);
122
123 while (1) {
124
125 /* wait until there is something to do */
126 PT_WAIT_UNTIL(thread, blink_seq_led1 || blink_seq_led2);
127
128 /* turn leds on/off, according to blink sequence */
129 if (blink_seq_led1 & 1)
130 LED1_ON();
131 else
132 LED1_OFF();
133
134 if (blink_seq_led2 & 1)
135 LED2_ON();
136 else
137 LED2_OFF();
138
139 blink_seq_led1 >>= 1;
140 blink_seq_led2 >>= 1;
141
142 /* wait 150ms */
143 timer_set(&t, 15);
144 PT_WAIT_UNTIL(thread, timer_expired(&t));
145
146 /* turn off leds */
147 LED1_OFF();
148 LED2_OFF();
149
150 }
151
152 PT_END(thread);
153 }
154
155 #define MASTER_PROGRAMS 4
156 static PROGMEM uint8_t master_parameters[] = {
157 /* colorwheel forward rainbow */
158 0, /* program index */
159 5, /* fade step */
160 1, /* fade delay */
161 0, /* fade sleep */
162 0, 0, /* hue start (little endian) */
163 20, 0, /* hue step (little endian) */
164 -1, /* addr add */
165 255, /* saturation */
166 255, /* value */
167
168 /* colorwheel all same color */
169 0, /* program index */
170 5, /* fade step */
171 1, /* fade delay */
172 0, /* fade sleep */
173 0, 0, /* hue start (little endian) */
174 20, 0, /* hue step (little endian) */
175 0, /* addr add */
176 255, /* saturation */
177 255, /* value */
178
179 /* colorwheel all same color, low saturation */
180 0, /* program index */
181 5, /* fade step */
182 1, /* fade delay */
183 0, /* fade sleep */
184 0, 0, /* hue start (little endian) */
185 20, 0, /* hue step (little endian) */
186 0, /* addr add */
187 150, /* saturation */
188 255, /* value */
189
190 /* colorwheel all same color, low saturation */
191 0, /* program index */
192 5, /* fade step */
193 1, /* fade delay */
194 0, /* fade sleep */
195 0, 0, /* hue start (little endian) */
196 120, 0, /* hue step (little endian) */
197 0, /* addr add */
198 255, /* saturation */
199 120, /* value */
200 };
201
202 void start_program(uint8_t index)
203 {
204 /* load parameters */
205 union {
206 uint8_t raw[REMOTE_MSG_LEN];
207 struct remote_msg_start_program_t msg;
208 } data;
209
210 /* reset data structure */
211 memset(&data, '\0', REMOTE_MSG_LEN);
212
213 data.msg.address = 255;
214 data.msg.cmd = REMOTE_CMD_START_PROGRAM;
215
216 uint8_t *ptr = &master_parameters[index*REMOTE_STARTUP_MAX_PARAMSIZE];
217 data.msg.script = pgm_read_byte(ptr++);
218
219 for (uint8_t i = 0; i < REMOTE_STARTUP_MAX_PARAMSIZE; i++) {
220 uint8_t d = pgm_read_byte(ptr++);
221 data.msg.params[i] = d;
222 }
223
224 for (uint8_t i = 0; i < REMOTE_MSG_LEN; i++)
225 uart_putc(data.raw[i]);
226
227 ui_blink(0x01, 0);
228 }
229
230 static void send_resync(uint8_t addr)
231 {
232 for (uint8_t i = 0; i < REMOTE_SYNC_LEN; i++)
233 uart_putc(REMOTE_CMD_RESYNC);
234 uart_putc(addr);
235 }
236
237 static void send_stop(uint8_t addr)
238 {
239 /* load parameters */
240 union {
241 uint8_t raw[REMOTE_MSG_LEN];
242 struct remote_msg_t msg;
243 } data;
244
245 data.msg.cmd = REMOTE_CMD_STOP;
246 data.msg.address = addr;
247 data.msg.data[0] = 1;
248
249 for (uint8_t i = 0; i < REMOTE_MSG_LEN; i++)
250 uart_putc(data.raw[i]);
251 }
252
253 /* parse input */
254 static PT_THREAD(ui_input(struct pt*thread))
255 {
256 static timer_t t;
257 static uint8_t option_set;
258 static uint8_t current_program;
259
260 PT_BEGIN(thread);
261
262 current_program = 0;
263
264 while(1) {
265
266 if (btn_press & _BV(BTN1_PIN)) {
267 PT_WAIT_UNTIL(thread, fifo_empty(&global_uart.tx));
268 send_resync(0);
269 PT_WAIT_UNTIL(thread, fifo_empty(&global_uart.tx));
270 send_stop(255);
271 PT_WAIT_UNTIL(thread, fifo_empty(&global_uart.tx));
272 start_program(current_program);
273 current_program = (current_program+1) % MASTER_PROGRAMS;
274 }
275
276 if (btn_press & _BV(BTN2_PIN)) {
277 //uart_putc('2');
278 }
279
280 btn_press = 0;
281
282 PT_YIELD(thread);
283 }
284
285 PT_END(thread);
286 }
287
288 /* poll for user actions */
289 void ui_poll(void)
290 {
291 /* sample buttons */
292 PT_SCHEDULE(ui_sample_buttons(&btn_thread));
293
294 /* do blinking */
295 PT_SCHEDULE(ui_do_blinking(&blink_thread));
296
297 /* process input */
298 PT_SCHEDULE(ui_input(&input_thread));
299 }
Impressum, Datenschutz