1use std::time::Duration;
54use crate::fb::{RTrig, FTrig, Ton};
55
56#[derive(Debug, Clone, Copy, PartialEq, Eq)]
62#[repr(u8)]
63pub enum Animation {
64 Off = 0,
65 Steady = 1,
66 Flash = 2,
67 TwoColorFlash = 3,
68 TwoColorShift = 4,
69 EndsSteady = 5,
70 EndsFlash = 6,
71 Scroll = 7,
72 CenterScroll = 8,
73 Bounce = 9,
74 CenterBounce = 10,
75 IntensitySweep = 11,
77 TwoColorSweep = 12,
78 Spectrum = 13,
80 SingleEndSteady = 14,
81 SingleEndFlash = 15,
82}
83
84#[derive(Debug, Clone, Copy, PartialEq, Eq)]
86#[repr(u8)]
87pub enum Color {
88 Green = 0,
89 Red = 1,
90 Orange = 2,
91 Amber = 3,
92 Yellow = 4,
93 LimeGreen = 5,
94 SpringGreen = 6,
95 Cyan = 7,
96 SkyBlue = 8,
97 Blue = 9,
98 Violet = 10,
99 Magenta = 11,
100 Rose = 12,
101 DaylightWhite = 13,
102 Custom1 = 14,
103 Custom2 = 15,
104 IncandescentWhite = 16,
105 WarmWhite = 17,
106 FluorescentWhite = 18,
107 NeutralWhite = 19,
108 CoolWhite = 20,
109}
110
111#[derive(Debug, Clone, Copy, PartialEq, Eq)]
113#[repr(u8)]
114pub enum ColorIntensity {
115 High = 0,
116 Low = 1,
117 Medium = 2,
118 Off = 3,
119 Custom = 4,
120}
121
122#[derive(Debug, Clone, Copy, PartialEq, Eq)]
124#[repr(u8)]
125pub enum Direction {
126 Up = 0,
127 Down = 1,
128}
129
130#[derive(Debug, Clone, Copy, PartialEq, Eq)]
132#[repr(u8)]
133pub enum PulsePattern {
134 Normal = 0,
135 Strobe = 1,
136 ThreePulse = 2,
137 Sos = 3,
138 Random = 4,
139}
140
141#[derive(Debug, Clone, Copy, PartialEq, Eq)]
143#[repr(u8)]
144pub enum ScrollStyle {
145 Solid = 0,
146 Tail = 1,
147 Ripple = 2,
148}
149
150#[derive(Debug, Clone, Copy, PartialEq, Eq)]
152#[repr(u8)]
153pub enum Speed {
154 Medium = 0,
155 Fast = 1,
156 Slow = 2,
157 CustomFlashRate = 3,
158}
159
160#[derive(Debug, Clone)]
171pub struct Wls15RunMode {
172 pub animation: u8,
174 pub color1: u8,
176 pub color1_intensity: u8,
178 pub color2: u8,
180 pub color2_intensity: u8,
182 pub speed: u8,
184 pub pulse_pattern: u8,
186 pub scroll_bounce_style: u8,
188 pub percent_width_color1: u8,
190 pub direction: u8,
192}
193
194impl Wls15RunMode {
195 pub fn new() -> Self {
197 Self {
198 animation: 0,
199 color1: 0,
200 color1_intensity: 0,
201 color2: 0,
202 color2_intensity: 0,
203 speed: 0,
204 pulse_pattern: 0,
205 scroll_bounce_style: 0,
206 percent_width_color1: 0,
207 direction: 0,
208 }
209 }
210
211 pub fn off(&mut self) {
213 self.animation = Animation::Off as u8;
214 }
215
216 pub fn alert(&mut self, color: Color, intensity: ColorIntensity, speed: Speed) {
221 self.color1 = color as u8;
222 self.speed = speed as u8;
223 self.color1_intensity = intensity as u8;
224 self.color2_intensity = ColorIntensity::Off as u8;
225 self.percent_width_color1 = 0;
226 self.animation = Animation::CenterScroll as u8;
227 }
228
229 pub fn knight_rider(&mut self, color: Color) {
234 self.color2 = Color::WarmWhite as u8;
235 self.scroll_bounce_style = ScrollStyle::Tail as u8;
236 self.color2_intensity = ColorIntensity::Off as u8;
237 self.percent_width_color1 = 40;
238 self.color1 = color as u8;
239 self.color1_intensity = ColorIntensity::High as u8;
240 self.speed = Speed::Medium as u8;
241 self.animation = Animation::Bounce as u8;
242 }
243
244 pub fn pulse(&mut self, color: Color, intensity: ColorIntensity, speed: Speed) {
248 self.color1 = color as u8;
249 self.speed = speed as u8;
250 self.color1_intensity = intensity as u8;
251 self.color2_intensity = ColorIntensity::Off as u8;
252 self.percent_width_color1 = 0;
253 self.animation = Animation::TwoColorSweep as u8;
254 }
255
256 pub fn spectrum(&mut self, speed: Speed) {
260 self.animation = Animation::Spectrum as u8;
261 self.speed = speed as u8;
262 self.percent_width_color1 = 0;
263 }
264
265 pub fn steady(&mut self, color: Color, intensity: ColorIntensity) {
267 self.color1 = color as u8;
268 self.color1_intensity = intensity as u8;
269 self.animation = Animation::Steady as u8;
270 }
271
272 pub fn flash(&mut self, color: Color, intensity: ColorIntensity, speed: Speed) {
274 self.color1 = color as u8;
275 self.color1_intensity = intensity as u8;
276 self.speed = speed as u8;
277 self.animation = Animation::Flash as u8;
278 }
279}
280
281impl Default for Wls15RunMode {
282 fn default() -> Self {
283 Self::new()
284 }
285}
286
287#[derive(Debug, Clone)]
305pub struct Wls15Digital {
306 pub q1: bool,
308 pub q2: bool,
310
311 req_q1: bool,
312 req_q2: bool,
313 enable_blink: bool,
314 blink_time: Duration,
315 blink_timer: Ton,
316 blink_bit: bool,
317 rt_blink: RTrig,
318 ft_blink: FTrig,
319}
320
321impl Wls15Digital {
322 pub fn new() -> Self {
324 Self {
325 q1: false,
326 q2: false,
327 req_q1: false,
328 req_q2: false,
329 enable_blink: false,
330 blink_time: Duration::from_secs(1),
331 blink_timer: Ton::new(),
332 blink_bit: false,
333 rt_blink: RTrig::new(),
334 ft_blink: FTrig::new(),
335 }
336 }
337
338 pub fn off(&mut self) {
340 self.req_q1 = false;
341 self.req_q2 = false;
342 }
343
344 pub fn red(&mut self) {
346 self.req_q1 = true;
347 self.req_q2 = false;
348 }
349
350 pub fn green(&mut self) {
352 self.req_q1 = false;
353 self.req_q2 = true;
354 }
355
356 pub fn blue(&mut self) {
358 self.req_q1 = true;
359 self.req_q2 = true;
360 }
361
362 pub fn blink_on(&mut self, interval: Duration) {
364 self.enable_blink = true;
365 self.blink_time = interval;
366 }
367
368 pub fn blink_off(&mut self) {
370 self.enable_blink = false;
371 }
372
373 pub fn call(&mut self) {
379 if self.blink_timer.call(true, self.blink_time) {
381 self.blink_bit = !self.blink_bit;
382 self.blink_timer.reset();
383 }
384
385 let rising = self.rt_blink.call(self.blink_bit);
386 let falling = self.ft_blink.call(self.blink_bit);
387
388 if self.enable_blink {
389 if rising {
390 self.q1 = self.req_q1;
391 self.q2 = self.req_q2;
392 }
393 if falling {
394 self.q1 = false;
395 self.q2 = false;
396 }
397 } else {
398 self.q1 = self.req_q1;
399 self.q2 = self.req_q2;
400 }
401 }
402}
403
404impl Default for Wls15Digital {
405 fn default() -> Self {
406 Self::new()
407 }
408}
409
410#[cfg(test)]
411mod tests {
412 use super::*;
413
414 #[test]
415 fn test_run_mode_off() {
416 let mut light = Wls15RunMode::new();
417 light.steady(Color::Red, ColorIntensity::High);
418 assert_eq!(light.animation, Animation::Steady as u8);
419 light.off();
420 assert_eq!(light.animation, Animation::Off as u8);
421 }
422
423 #[test]
424 fn test_run_mode_alert() {
425 let mut light = Wls15RunMode::new();
426 light.alert(Color::Red, ColorIntensity::High, Speed::Medium);
427 assert_eq!(light.animation, Animation::CenterScroll as u8);
428 assert_eq!(light.color1, Color::Red as u8);
429 assert_eq!(light.color1_intensity, ColorIntensity::High as u8);
430 assert_eq!(light.color2_intensity, ColorIntensity::Off as u8);
431 }
432
433 #[test]
434 fn test_run_mode_knight_rider() {
435 let mut light = Wls15RunMode::new();
436 light.knight_rider(Color::Red);
437 assert_eq!(light.animation, Animation::Bounce as u8);
438 assert_eq!(light.scroll_bounce_style, ScrollStyle::Tail as u8);
439 assert_eq!(light.color1, Color::Red as u8);
440 assert_eq!(light.percent_width_color1, 40);
441 }
442
443 #[test]
444 fn test_run_mode_pulse() {
445 let mut light = Wls15RunMode::new();
446 light.pulse(Color::Green, ColorIntensity::High, Speed::Slow);
447 assert_eq!(light.animation, Animation::TwoColorSweep as u8);
448 assert_eq!(light.color1, Color::Green as u8);
449 assert_eq!(light.speed, Speed::Slow as u8);
450 }
451
452 #[test]
453 fn test_run_mode_spectrum() {
454 let mut light = Wls15RunMode::new();
455 light.spectrum(Speed::Fast);
456 assert_eq!(light.animation, Animation::Spectrum as u8);
457 assert_eq!(light.speed, Speed::Fast as u8);
458 }
459
460 #[test]
461 fn test_digital_colors() {
462 let mut light = Wls15Digital::new();
463
464 light.red();
465 light.call();
466 assert_eq!((light.q1, light.q2), (true, false));
467
468 light.green();
469 light.call();
470 assert_eq!((light.q1, light.q2), (false, true));
471
472 light.blue();
473 light.call();
474 assert_eq!((light.q1, light.q2), (true, true));
475
476 light.off();
477 light.call();
478 assert_eq!((light.q1, light.q2), (false, false));
479 }
480
481 #[test]
482 fn test_digital_blink_off_tracks_color() {
483 let mut light = Wls15Digital::new();
484 light.red();
485 light.blink_off();
486 light.call();
487 assert_eq!((light.q1, light.q2), (true, false));
488 }
489
490 #[test]
491 fn test_enum_values() {
492 assert_eq!(Animation::Off as u8, 0);
493 assert_eq!(Animation::Spectrum as u8, 13);
494 assert_eq!(Color::Green as u8, 0);
495 assert_eq!(Color::Red as u8, 1);
496 assert_eq!(Color::CoolWhite as u8, 20);
497 assert_eq!(ColorIntensity::High as u8, 0);
498 assert_eq!(ColorIntensity::Off as u8, 3);
499 assert_eq!(Direction::Up as u8, 0);
500 assert_eq!(Direction::Down as u8, 1);
501 assert_eq!(PulsePattern::Sos as u8, 3);
502 assert_eq!(ScrollStyle::Tail as u8, 1);
503 assert_eq!(Speed::Fast as u8, 1);
504 }
505}