]>
Commit | Line | Data |
---|---|---|
ec1bef8e | 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, | |
0c9ba54a | 40 | program_showcfg, |
ec1bef8e | 41 | }; |
42 | ||
3ae23878 | 43 | #define DEBUG_COLORLEVEL 32u |
44 | ||
0c9ba54a | 45 | PT_THREAD(program_showcfg(struct process_t *process)) |
46 | { | |
47 | static uint16_t sleep; | |
3ae23878 | 48 | static struct rgb_color_t c, d; |
49 | static uint8_t i; | |
0c9ba54a | 50 | |
51 | PT_BEGIN(&process->pt); | |
52 | ||
3ae23878 | 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; | |
0c9ba54a | 56 | |
3ae23878 | 57 | d.red = d.green = d.blue = DEBUG_COLORLEVEL; |
0c9ba54a | 58 | |
3ae23878 | 59 | global_pwm.target.rgb = c; |
0c9ba54a | 60 | |
3ae23878 | 61 | for (i = 0; i < 3u; i++) |
62 | { | |
63 | /* sleep 1s (remember: we are called every 100ms) */ | |
64 | sleep = 10; | |
65 | while (sleep--) | |
0c9ba54a | 66 | PT_YIELD(&process->pt); |
67 | ||
3ae23878 | 68 | global_pwm.target.rgb = d; |
0c9ba54a | 69 | |
3ae23878 | 70 | sleep = 5; |
71 | while (sleep--) | |
72 | PT_YIELD(&process->pt); | |
0c9ba54a | 73 | |
3ae23878 | 74 | global_pwm.target.rgb = c; |
75 | } | |
0c9ba54a | 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 | ||
ec1bef8e | 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 |