use std::time::Duration;
use crate::fb::{RTrig, FTrig, Ton};
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
#[repr(u8)]
pub enum Animation {
Off = 0,
Steady = 1,
Flash = 2,
TwoColorFlash = 3,
TwoColorShift = 4,
EndsSteady = 5,
EndsFlash = 6,
Scroll = 7,
CenterScroll = 8,
Bounce = 9,
CenterBounce = 10,
IntensitySweep = 11,
TwoColorSweep = 12,
Spectrum = 13,
SingleEndSteady = 14,
SingleEndFlash = 15,
}
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
#[repr(u8)]
pub enum Color {
Green = 0,
Red = 1,
Orange = 2,
Amber = 3,
Yellow = 4,
LimeGreen = 5,
SpringGreen = 6,
Cyan = 7,
SkyBlue = 8,
Blue = 9,
Violet = 10,
Magenta = 11,
Rose = 12,
DaylightWhite = 13,
Custom1 = 14,
Custom2 = 15,
IncandescentWhite = 16,
WarmWhite = 17,
FluorescentWhite = 18,
NeutralWhite = 19,
CoolWhite = 20,
}
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
#[repr(u8)]
pub enum ColorIntensity {
High = 0,
Low = 1,
Medium = 2,
Off = 3,
Custom = 4,
}
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
#[repr(u8)]
pub enum Direction {
Up = 0,
Down = 1,
}
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
#[repr(u8)]
pub enum PulsePattern {
Normal = 0,
Strobe = 1,
ThreePulse = 2,
Sos = 3,
Random = 4,
}
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
#[repr(u8)]
pub enum ScrollStyle {
Solid = 0,
Tail = 1,
Ripple = 2,
}
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
#[repr(u8)]
pub enum Speed {
Medium = 0,
Fast = 1,
Slow = 2,
CustomFlashRate = 3,
}
#[derive(Debug, Clone)]
pub struct Wls15RunMode {
pub animation: u8,
pub color1: u8,
pub color1_intensity: u8,
pub color2: u8,
pub color2_intensity: u8,
pub speed: u8,
pub pulse_pattern: u8,
pub scroll_bounce_style: u8,
pub percent_width_color1: u8,
pub direction: u8,
}
impl Wls15RunMode {
pub fn new() -> Self {
Self {
animation: 0,
color1: 0,
color1_intensity: 0,
color2: 0,
color2_intensity: 0,
speed: 0,
pulse_pattern: 0,
scroll_bounce_style: 0,
percent_width_color1: 0,
direction: 0,
}
}
pub fn off(&mut self) {
self.animation = Animation::Off as u8;
}
pub fn alert(&mut self, color: Color, intensity: ColorIntensity, speed: Speed) {
self.color1 = color as u8;
self.speed = speed as u8;
self.color1_intensity = intensity as u8;
self.color2_intensity = ColorIntensity::Off as u8;
self.percent_width_color1 = 0;
self.animation = Animation::CenterScroll as u8;
}
pub fn knight_rider(&mut self, color: Color) {
self.color2 = Color::WarmWhite as u8;
self.scroll_bounce_style = ScrollStyle::Tail as u8;
self.color2_intensity = ColorIntensity::Off as u8;
self.percent_width_color1 = 40;
self.color1 = color as u8;
self.color1_intensity = ColorIntensity::High as u8;
self.speed = Speed::Medium as u8;
self.animation = Animation::Bounce as u8;
}
pub fn pulse(&mut self, color: Color, intensity: ColorIntensity, speed: Speed) {
self.color1 = color as u8;
self.speed = speed as u8;
self.color1_intensity = intensity as u8;
self.color2_intensity = ColorIntensity::Off as u8;
self.percent_width_color1 = 0;
self.animation = Animation::TwoColorSweep as u8;
}
pub fn spectrum(&mut self, speed: Speed) {
self.animation = Animation::Spectrum as u8;
self.speed = speed as u8;
self.percent_width_color1 = 0;
}
pub fn steady(&mut self, color: Color, intensity: ColorIntensity) {
self.color1 = color as u8;
self.color1_intensity = intensity as u8;
self.animation = Animation::Steady as u8;
}
pub fn flash(&mut self, color: Color, intensity: ColorIntensity, speed: Speed) {
self.color1 = color as u8;
self.color1_intensity = intensity as u8;
self.speed = speed as u8;
self.animation = Animation::Flash as u8;
}
}
impl Default for Wls15RunMode {
fn default() -> Self {
Self::new()
}
}
#[derive(Debug, Clone)]
pub struct Wls15Digital {
pub q1: bool,
pub q2: bool,
req_q1: bool,
req_q2: bool,
enable_blink: bool,
blink_time: Duration,
blink_timer: Ton,
blink_bit: bool,
rt_blink: RTrig,
ft_blink: FTrig,
}
impl Wls15Digital {
pub fn new() -> Self {
Self {
q1: false,
q2: false,
req_q1: false,
req_q2: false,
enable_blink: false,
blink_time: Duration::from_secs(1),
blink_timer: Ton::new(),
blink_bit: false,
rt_blink: RTrig::new(),
ft_blink: FTrig::new(),
}
}
pub fn off(&mut self) {
self.req_q1 = false;
self.req_q2 = false;
}
pub fn red(&mut self) {
self.req_q1 = true;
self.req_q2 = false;
}
pub fn green(&mut self) {
self.req_q1 = false;
self.req_q2 = true;
}
pub fn blue(&mut self) {
self.req_q1 = true;
self.req_q2 = true;
}
pub fn blink_on(&mut self, interval: Duration) {
self.enable_blink = true;
self.blink_time = interval;
}
pub fn blink_off(&mut self) {
self.enable_blink = false;
}
pub fn call(&mut self) {
if self.blink_timer.call(true, self.blink_time) {
self.blink_bit = !self.blink_bit;
self.blink_timer.reset();
}
let rising = self.rt_blink.call(self.blink_bit);
let falling = self.ft_blink.call(self.blink_bit);
if self.enable_blink {
if rising {
self.q1 = self.req_q1;
self.q2 = self.req_q2;
}
if falling {
self.q1 = false;
self.q2 = false;
}
} else {
self.q1 = self.req_q1;
self.q2 = self.req_q2;
}
}
}
impl Default for Wls15Digital {
fn default() -> Self {
Self::new()
}
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn test_run_mode_off() {
let mut light = Wls15RunMode::new();
light.steady(Color::Red, ColorIntensity::High);
assert_eq!(light.animation, Animation::Steady as u8);
light.off();
assert_eq!(light.animation, Animation::Off as u8);
}
#[test]
fn test_run_mode_alert() {
let mut light = Wls15RunMode::new();
light.alert(Color::Red, ColorIntensity::High, Speed::Medium);
assert_eq!(light.animation, Animation::CenterScroll as u8);
assert_eq!(light.color1, Color::Red as u8);
assert_eq!(light.color1_intensity, ColorIntensity::High as u8);
assert_eq!(light.color2_intensity, ColorIntensity::Off as u8);
}
#[test]
fn test_run_mode_knight_rider() {
let mut light = Wls15RunMode::new();
light.knight_rider(Color::Red);
assert_eq!(light.animation, Animation::Bounce as u8);
assert_eq!(light.scroll_bounce_style, ScrollStyle::Tail as u8);
assert_eq!(light.color1, Color::Red as u8);
assert_eq!(light.percent_width_color1, 40);
}
#[test]
fn test_run_mode_pulse() {
let mut light = Wls15RunMode::new();
light.pulse(Color::Green, ColorIntensity::High, Speed::Slow);
assert_eq!(light.animation, Animation::TwoColorSweep as u8);
assert_eq!(light.color1, Color::Green as u8);
assert_eq!(light.speed, Speed::Slow as u8);
}
#[test]
fn test_run_mode_spectrum() {
let mut light = Wls15RunMode::new();
light.spectrum(Speed::Fast);
assert_eq!(light.animation, Animation::Spectrum as u8);
assert_eq!(light.speed, Speed::Fast as u8);
}
#[test]
fn test_digital_colors() {
let mut light = Wls15Digital::new();
light.red();
light.call();
assert_eq!((light.q1, light.q2), (true, false));
light.green();
light.call();
assert_eq!((light.q1, light.q2), (false, true));
light.blue();
light.call();
assert_eq!((light.q1, light.q2), (true, true));
light.off();
light.call();
assert_eq!((light.q1, light.q2), (false, false));
}
#[test]
fn test_digital_blink_off_tracks_color() {
let mut light = Wls15Digital::new();
light.red();
light.blink_off();
light.call();
assert_eq!((light.q1, light.q2), (true, false));
}
#[test]
fn test_enum_values() {
assert_eq!(Animation::Off as u8, 0);
assert_eq!(Animation::Spectrum as u8, 13);
assert_eq!(Color::Green as u8, 0);
assert_eq!(Color::Red as u8, 1);
assert_eq!(Color::CoolWhite as u8, 20);
assert_eq!(ColorIntensity::High as u8, 0);
assert_eq!(ColorIntensity::Off as u8, 3);
assert_eq!(Direction::Up as u8, 0);
assert_eq!(Direction::Down as u8, 1);
assert_eq!(PulsePattern::Sos as u8, 3);
assert_eq!(ScrollStyle::Tail as u8, 1);
assert_eq!(Speed::Fast as u8, 1);
}
}