]> git.zerfleddert.de Git - fnordlicht-mini/blob - firmware/fnordlicht-firmware/static_programs.c
911e379a48945820490f4f0a084835666bdac50d
[fnordlicht-mini] / firmware / fnordlicht-firmware / static_programs.c
1 /* vim:ts=4 sts=4 et tw=80
2 *
3 * fnordlicht firmware
4 *
5 * for additional information please
6 * see http://lochraster.org/fnordlichtmini
7 *
8 * (c) by Alexander Neumann <alexander@bumpern.de>
9 *
10 * This program is free software: you can redistribute it and/or modify it
11 * under the terms of the GNU General Public License version 3 as published by
12 * the Free Software Foundation.
13 *
14 * This program is distributed in the hope that it will be useful, but WITHOUT
15 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
16 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
17 * more details.
18 *
19 * You should have received a copy of the GNU General Public License along with
20 * this program. If not, see <http://www.gnu.org/licenses/>.
21 */
22
23 #include <stdlib.h>
24 #include <avr/pgmspace.h>
25 #include "static_programs.h"
26 #include "color.h"
27 #include "pwm.h"
28 #include "timer.h"
29 #include "remote.h"
30 #include "../common/common.h"
31 #include "storage.h"
32
33 #if CONFIG_SCRIPT
34
35 /* global list of programs */
36 PROGMEM program_handler static_programs[] = {
37 program_colorwheel,
38 program_random,
39 program_replay,
40 program_showcfg,
41 };
42
43 #define DEBUG_COLORLEVEL 32u
44
45 PT_THREAD(program_showcfg(struct process_t *process))
46 {
47 static uint16_t sleep;
48 static struct rgb_color_t c, d;
49 static uint8_t i;
50
51 PT_BEGIN(&process->pt);
52
53 c.red = (remote_address() & 0x01u) ? DEBUG_COLORLEVEL : 0;
54 c.green = (remote_address() & 0x02u) ? DEBUG_COLORLEVEL : 0;
55 c.blue = (remote_address() & 0x04u) ? DEBUG_COLORLEVEL : 0;
56
57 d.red = d.green = d.blue = DEBUG_COLORLEVEL;
58
59 global_pwm.target.rgb = c;
60
61 for (i = 0; i < 3u; i++)
62 {
63 /* sleep 1s (remember: we are called every 100ms) */
64 sleep = 10;
65 while (sleep--)
66 PT_YIELD(&process->pt);
67
68 global_pwm.target.rgb = d;
69
70 sleep = 5;
71 while (sleep--)
72 PT_YIELD(&process->pt);
73
74 global_pwm.target.rgb = c;
75 }
76
77 /* now start default script */
78 if (storage_valid_config() && (startup_config.params.mode == STARTUP_PROGRAM)) {
79 script_start(0, startup_config.params.program, (union program_params_t *)startup_config.params.program_parameters);
80 } else {
81 script_start_default();
82 }
83
84 PT_END(&process->pt);
85 }
86
87 PT_THREAD(program_colorwheel(struct process_t *process))
88 {
89 static uint16_t sleep;
90 static struct hsv_color_t c;
91
92 PT_BEGIN(&process->pt);
93
94 c.hue = process->params.colorwheel.hue_start;
95 c.value = process->params.colorwheel.value;
96 c.saturation = process->params.colorwheel.saturation;
97
98 int8_t add = process->params.colorwheel.add_addr;
99 c.hue += remote_address() * add * process->params.colorwheel.hue_step;
100
101 while (1) {
102 /* set new color */
103 pwm_fade_hsv(&c, process->params.colorwheel.fade_step, process->params.colorwheel.fade_delay);
104
105 c.hue += process->params.colorwheel.hue_step;
106
107 /* wait until target reached */
108 PT_WAIT_UNTIL(&process->pt, pwm_target_reached());
109
110 /* sleep (in seconds, remember: we are called every 100ms) */
111 sleep = 10 * process->params.colorwheel.fade_sleep;
112 while (sleep--)
113 PT_YIELD(&process->pt);
114 }
115
116 PT_END(&process->pt);
117 }
118
119 PT_THREAD(program_random(struct process_t *process))
120 {
121 static uint16_t sleep;
122 static struct hsv_color_t c;
123
124 PT_BEGIN(&process->pt);
125
126 /* initialize random generator */
127 uint16_t seed = process->params.random.seed;
128 if (process->params.random.use_address)
129 seed ^= remote_address();
130 srandom(seed);
131
132 c.value = process->params.random.value;
133 c.saturation = process->params.random.saturation;
134
135 while (1) {
136 /* generate new color */
137 union uint32_t_access rnd;
138 rnd.raw = random();
139
140 /* use lower word for hue */
141 rnd.words[0] %= 360;
142
143 /* check for minimal color distance, regenerate random if not */
144 int16_t min_distance = process->params.random.min_distance;
145 if (min_distance) {
146 int16_t distance = c.hue - rnd.words[0];
147 if (distance < 0)
148 distance = -distance;
149
150 if (distance > 180)
151 distance = 360-distance;
152
153 if (distance < min_distance)
154 continue;
155 }
156
157 /* copy color to structure */
158 c.hue = rnd.words[0];
159
160 /* fade to new color */
161 pwm_fade_hsv(&c, process->params.random.fade_step, process->params.random.fade_delay);
162
163 /* wait until target reached */
164 if (process->params.random.wait_for_fade)
165 PT_WAIT_UNTIL(&process->pt, pwm_target_reached());
166
167 /* sleep (remember: we are called every 100ms) */
168 if (process->params.random.fade_sleep > 0) {
169 sleep = process->params.random.fade_sleep;
170
171 while (sleep--)
172 PT_YIELD(&process->pt);
173 }
174 }
175
176 PT_END(&process->pt);
177 }
178
179 PT_THREAD(program_replay(struct process_t *process))
180 {
181 static uint8_t pos;
182 static enum {
183 UP = 0,
184 DOWN = 1,
185 } direction;
186 static struct storage_color_t c;
187
188 PT_BEGIN(&process->pt);
189
190 /* reset variables */
191 pos = process->params.replay.start;
192 direction = UP;
193
194 while (1) {
195 /* load next color value */
196 storage_load_color(pos, &c);
197
198 if (c.color.rgb_marker == 0xff) {
199 struct rgb_color_t color;
200 color.red = c.color.red;
201 color.green = c.color.green;
202 color.blue = c.color.blue;
203
204 pwm_fade_rgb(&color, c.step, c.delay);
205 } else {
206 struct hsv_color_t color;
207 color.hue = c.color.hue;
208 color.saturation = c.color.saturation;
209 color.value = c.color.value;
210
211 pwm_fade_hsv(&color, c.step, c.delay);
212 }
213
214 /* update pos */
215 if (direction == UP) {
216 /* check for upper end */
217 if (pos == process->params.replay.end) {
218 switch (process->params.replay.repeat) {
219 case REPEAT_NONE: PT_EXIT(&process->pt);
220 break;
221 case REPEAT_START: pos = process->params.replay.start;
222 break;
223 case REPEAT_REVERSE: direction = DOWN;
224 pos--;
225 break;
226 }
227 } else
228 pos++;
229 } else {
230 if (pos == process->params.replay.start) {
231 direction = UP;
232 pos++;
233 } else
234 pos--;
235 }
236
237 /* wait */
238 while (c.pause--)
239 PT_YIELD(&process->pt);
240 }
241
242 PT_END(&process->pt);
243 }
244
245 #endif
Impressum, Datenschutz