]> git.zerfleddert.de Git - fnordlicht-mini/blob - firmware/fnordlicht-firmware/static_programs.c
5dc7c2d9136403faa5fb1270ac3f5844da5aa2f4
[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 #include "script.h"
33
34 #if CONFIG_SCRIPT
35
36 /* global list of programs */
37 PROGMEM program_handler static_programs[] = {
38 program_colorwheel,
39 program_random,
40 program_replay,
41 program_showcfg,
42 };
43
44 #define DEBUG_COLORLEVEL 32u
45
46 PT_THREAD(program_showcfg(struct process_t *process))
47 {
48 static uint16_t sleep;
49 static struct rgb_color_t c, d;
50 static uint8_t i;
51
52 PT_BEGIN(&process->pt);
53
54 c.red = (remote_address() & 0x01u) ? DEBUG_COLORLEVEL : 0;
55 c.green = (remote_address() & 0x02u) ? DEBUG_COLORLEVEL : 0;
56 c.blue = (remote_address() & 0x04u) ? DEBUG_COLORLEVEL : 0;
57
58 d.red = d.green = d.blue = 0;
59
60 global_pwm.target.rgb = c;
61
62 for (i = 0; i < 3u; i++)
63 {
64 /* sleep 1s (remember: we are called every 100ms) */
65 sleep = 10;
66 while (sleep--)
67 PT_YIELD(&process->pt);
68
69 global_pwm.target.rgb = c;
70
71 sleep = 5;
72 while (sleep--)
73 PT_YIELD(&process->pt);
74
75 global_pwm.target.rgb = d;
76 }
77
78 script_stop();
79
80 /* now start default script */
81 if (storage_valid_config() && (startup_config.params.mode == STARTUP_PROGRAM)) {
82 script_start(0, startup_config.params.program, (union program_params_t *)startup_config.params.program_parameters);
83 } else {
84 script_start_default();
85 }
86
87 /* hack: script_start() stuff above will reinitialize PT structures, so we
88 can't call any PT stuff any more and quit directly */
89 return 0;
90
91 PT_END(&process->pt);
92 }
93
94 PT_THREAD(program_colorwheel(struct process_t *process))
95 {
96 static uint16_t sleep;
97 static struct hsv_color_t c;
98
99 PT_BEGIN(&process->pt);
100
101 c.hue = process->params.colorwheel.hue_start;
102 c.value = process->params.colorwheel.value;
103 c.saturation = process->params.colorwheel.saturation;
104
105 int8_t add = process->params.colorwheel.add_addr;
106 c.hue += remote_address() * add * process->params.colorwheel.hue_step;
107
108 while (1) {
109 /* set new color */
110 pwm_fade_hsv(&c, process->params.colorwheel.fade_step, process->params.colorwheel.fade_delay);
111
112 c.hue += process->params.colorwheel.hue_step;
113
114 /* wait until target reached */
115 PT_WAIT_UNTIL(&process->pt, pwm_target_reached());
116
117 /* sleep (in seconds, remember: we are called every 100ms) */
118 sleep = 10 * process->params.colorwheel.fade_sleep;
119 while (sleep--)
120 PT_YIELD(&process->pt);
121 }
122
123 PT_END(&process->pt);
124 }
125
126 PT_THREAD(program_random(struct process_t *process))
127 {
128 static uint16_t sleep;
129 static struct hsv_color_t c;
130
131 PT_BEGIN(&process->pt);
132
133 /* initialize random generator */
134 uint16_t seed = process->params.random.seed;
135 if (process->params.random.use_address)
136 seed ^= remote_address();
137 srandom(seed);
138
139 c.value = process->params.random.value;
140 c.saturation = process->params.random.saturation;
141
142 while (1) {
143 /* generate new color */
144 union uint32_t_access rnd;
145 rnd.raw = random();
146
147 /* use lower word for hue */
148 rnd.words[0] %= 360;
149
150 /* check for minimal color distance, regenerate random if not */
151 int16_t min_distance = process->params.random.min_distance;
152 if (min_distance) {
153 int16_t distance = c.hue - rnd.words[0];
154 if (distance < 0)
155 distance = -distance;
156
157 if (distance > 180)
158 distance = 360-distance;
159
160 if (distance < min_distance)
161 continue;
162 }
163
164 /* copy color to structure */
165 c.hue = rnd.words[0];
166
167 /* fade to new color */
168 pwm_fade_hsv(&c, process->params.random.fade_step, process->params.random.fade_delay);
169
170 /* wait until target reached */
171 if (process->params.random.wait_for_fade)
172 PT_WAIT_UNTIL(&process->pt, pwm_target_reached());
173
174 /* sleep (remember: we are called every 100ms) */
175 if (process->params.random.fade_sleep > 0) {
176 sleep = process->params.random.fade_sleep;
177
178 while (sleep--)
179 PT_YIELD(&process->pt);
180 }
181 }
182
183 PT_END(&process->pt);
184 }
185
186 PT_THREAD(program_replay(struct process_t *process))
187 {
188 static uint8_t pos;
189 static enum {
190 UP = 0,
191 DOWN = 1,
192 } direction;
193 static struct storage_color_t c;
194
195 PT_BEGIN(&process->pt);
196
197 /* reset variables */
198 pos = process->params.replay.start;
199 direction = UP;
200
201 while (1) {
202 /* load next color value */
203 storage_load_color(pos, &c);
204
205 if (c.color.rgb_marker == 0xff) {
206 struct rgb_color_t color;
207 color.red = c.color.red;
208 color.green = c.color.green;
209 color.blue = c.color.blue;
210
211 pwm_fade_rgb(&color, c.step, c.delay);
212 } else {
213 struct hsv_color_t color;
214 color.hue = c.color.hue;
215 color.saturation = c.color.saturation;
216 color.value = c.color.value;
217
218 pwm_fade_hsv(&color, c.step, c.delay);
219 }
220
221 /* update pos */
222 if (direction == UP) {
223 /* check for upper end */
224 if (pos == process->params.replay.end) {
225 switch (process->params.replay.repeat) {
226 case REPEAT_NONE: PT_EXIT(&process->pt);
227 break;
228 case REPEAT_START: pos = process->params.replay.start;
229 break;
230 case REPEAT_REVERSE: direction = DOWN;
231 pos--;
232 break;
233 }
234 } else
235 pos++;
236 } else {
237 if (pos == process->params.replay.start) {
238 direction = UP;
239 pos++;
240 } else
241 pos--;
242 }
243
244 /* wait */
245 while (c.pause--)
246 PT_YIELD(&process->pt);
247 }
248
249 PT_END(&process->pt);
250 }
251
252 #endif
Impressum, Datenschutz