]> git.zerfleddert.de Git - fnordlicht-mini/blame - firmware/fnordlicht-controller/ui.c
reference firmware
[fnordlicht-mini] / firmware / fnordlicht-controller / ui.c
CommitLineData
ec1bef8e 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
35static struct pt btn_thread;
36/* buttons are idle at start (internal pullups active) */
37static uint8_t btn_state = _BV(BTN1_PIN) | _BV(BTN2_PIN);
38static uint8_t btn_last_sample = _BV(BTN1_PIN) | _BV(BTN2_PIN);
39static uint8_t btn_press = 0;
40
41static struct pt blink_thread;
42static uint8_t blink_seq_led1 = 0;
43static uint8_t blink_seq_led2 = 0;
44
45static struct pt input_thread;
46
47/* initialize the button and led pins */
48void 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 */
69void 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 */
76bool 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 */
82static 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 */
117static 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
156static 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
202void 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
230static 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
237static 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 */
254static 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 */
289void 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