4 * (c) by Alexander Neumann <alexander@lochraster.org>
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.
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.
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.
19 * For more information on the GPL, please go to:
20 * http://www.gnu.org/copyleft/gpl.html
24 #include <util/delay.h>
25 #include <avr/pgmspace.h>
30 #include "../common/pt/pt.h"
31 #include "remote-proto.h"
33 /* module local variables */
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;
41 static struct pt blink_thread
;
42 static uint8_t blink_seq_led1
= 0;
43 static uint8_t blink_seq_led2
= 0;
45 static struct pt input_thread
;
47 /* initialize the button and led pins */
50 /* initialize buttons */
51 BTN_DDR
&= ~(_BV(BTN1_PIN
) | _BV(BTN2_PIN
));
52 BTN_PORT
|= _BV(BTN1_PIN
) | _BV(BTN2_PIN
);
55 LED_DDR
|= _BV(LED1_PIN
) | _BV(LED2_PIN
);
56 LED_PORT
&= ~(_BV(LED1_PIN
) | _BV(LED2_PIN
));
58 /* initialize button sample thread and variables */
61 /* initialize blink thread and variables */
62 PT_INIT(&blink_thread
);
64 /* initialize input thread */
65 PT_INIT(&input_thread
);
68 /* blink out a sequence (LSB first), every bit is 150ms long */
69 void ui_blink(uint8_t sequence1
, uint8_t sequence2
)
71 blink_seq_led1
= sequence1
;
72 blink_seq_led2
= sequence2
;
75 /* check if the current blink sequency is done */
76 bool ui_blinking(void)
78 return !(blink_seq_led1
|| blink_seq_led2
);
81 /* sample buttons, set bit in btn_press if a button has been pressed */
82 static PT_THREAD(ui_sample_buttons(struct pt
*thread
))
84 /* make sure no variable is created on the stack */
85 static timer_t btn_timer
;
90 /* only execute this thread every 10ms */
91 timer_set(&btn_timer
, 1);
92 PT_WAIT_UNTIL(thread
, timer_expired(&btn_timer
));
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
));
98 /* mark bits which stayed the same since last sample */
99 btn_last_sample
^= ~btn_sample
;
101 /* mark bits which have not changed, but whose state is different */
102 btn_last_sample
= btn_state
^ (btn_sample
& btn_last_sample
);
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
;
108 /* remember new state and last sample */
109 btn_state
^= btn_last_sample
;
110 btn_last_sample
= btn_sample
;
116 /* execute led blinking */
117 static PT_THREAD(ui_do_blinking(struct pt
*thread
))
125 /* wait until there is something to do */
126 PT_WAIT_UNTIL(thread
, blink_seq_led1
|| blink_seq_led2
);
128 /* turn leds on/off, according to blink sequence */
129 if (blink_seq_led1
& 1)
134 if (blink_seq_led2
& 1)
139 blink_seq_led1
>>= 1;
140 blink_seq_led2
>>= 1;
144 PT_WAIT_UNTIL(thread
, timer_expired(&t
));
155 #define MASTER_PROGRAMS 4
156 static PROGMEM
uint8_t master_parameters
[] = {
157 /* colorwheel forward rainbow */
158 0, /* program index */
162 0, 0, /* hue start (little endian) */
163 20, 0, /* hue step (little endian) */
165 255, /* saturation */
168 /* colorwheel all same color */
169 0, /* program index */
173 0, 0, /* hue start (little endian) */
174 20, 0, /* hue step (little endian) */
176 255, /* saturation */
179 /* colorwheel all same color, low saturation */
180 0, /* program index */
184 0, 0, /* hue start (little endian) */
185 20, 0, /* hue step (little endian) */
187 150, /* saturation */
190 /* colorwheel all same color, low saturation */
191 0, /* program index */
195 0, 0, /* hue start (little endian) */
196 120, 0, /* hue step (little endian) */
198 255, /* saturation */
202 void start_program(uint8_t index
)
204 /* load parameters */
206 uint8_t raw
[REMOTE_MSG_LEN
];
207 struct remote_msg_start_program_t msg
;
210 /* reset data structure */
211 memset(&data
, '\0', REMOTE_MSG_LEN
);
213 data
.msg
.address
= 255;
214 data
.msg
.cmd
= REMOTE_CMD_START_PROGRAM
;
216 uint8_t *ptr
= &master_parameters
[index
*REMOTE_STARTUP_MAX_PARAMSIZE
];
217 data
.msg
.script
= pgm_read_byte(ptr
++);
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
;
224 for (uint8_t i
= 0; i
< REMOTE_MSG_LEN
; i
++)
225 uart_putc(data
.raw
[i
]);
230 static void send_resync(uint8_t addr
)
232 for (uint8_t i
= 0; i
< REMOTE_SYNC_LEN
; i
++)
233 uart_putc(REMOTE_CMD_RESYNC
);
237 static void send_stop(uint8_t addr
)
239 /* load parameters */
241 uint8_t raw
[REMOTE_MSG_LEN
];
242 struct remote_msg_t msg
;
245 data
.msg
.cmd
= REMOTE_CMD_STOP
;
246 data
.msg
.address
= addr
;
247 data
.msg
.data
[0] = 1;
249 for (uint8_t i
= 0; i
< REMOTE_MSG_LEN
; i
++)
250 uart_putc(data
.raw
[i
]);
254 static PT_THREAD(ui_input(struct pt
*thread
))
257 static uint8_t option_set
;
258 static uint8_t current_program
;
266 if (btn_press
& _BV(BTN1_PIN
)) {
267 PT_WAIT_UNTIL(thread
, fifo_empty(&global_uart
.tx
));
269 PT_WAIT_UNTIL(thread
, fifo_empty(&global_uart
.tx
));
271 PT_WAIT_UNTIL(thread
, fifo_empty(&global_uart
.tx
));
272 start_program(current_program
);
273 current_program
= (current_program
+1) % MASTER_PROGRAMS
;
276 if (btn_press
& _BV(BTN2_PIN
)) {
288 /* poll for user actions */
292 PT_SCHEDULE(ui_sample_buttons(&btn_thread
));
295 PT_SCHEDULE(ui_do_blinking(&blink_thread
));
298 PT_SCHEDULE(ui_input(&input_thread
));