diff --git a/bike-lights/bike/src/main.rs b/bike-lights/bike/src/main.rs index a683804..962e0dc 100644 --- a/bike-lights/bike/src/main.rs +++ b/bike-lights/bike/src/main.rs @@ -33,6 +33,31 @@ const LIGHT_SCALE: I16F16 = I16F16::lit("256.0"); const DASHBOARD_BRIGHTESS: u8 = 1; const BODY_BRIGHTNESS: u8 = 8; +struct DebouncedButton { + debounce: Instant, + pin: Pin, PullUp>, +} + +impl DebouncedButton

{ + fn new(pin: Pin, PullUp>) -> Self { + Self { + debounce: Instant((0 as u32).into()), + pin, + } + } + + fn is_low(&self, time: Instant) -> bool { + if time <= self.debounce { + return false; + } + self.pin.is_low().unwrap_or(false) + } + + fn set_debounce(&mut self, time: Instant) { + self.debounce = time + Instant((100 as u32).into()); + } +} + struct BikeUI< D: SpiDevice, P: ValidSpiPinout, @@ -42,10 +67,10 @@ struct BikeUI< NextId: PinId, > { spi: RefCell>, - left_blinker_button: Pin, PullUp>, - right_blinker_button: Pin, PullUp>, - previous_animation_button: Pin, PullUp>, - next_animation_button: Pin, PullUp>, + left_blinker_button: DebouncedButton, + right_blinker_button: DebouncedButton, + previous_animation_button: DebouncedButton, + next_animation_button: DebouncedButton, } impl< @@ -66,10 +91,10 @@ impl< ) -> Self { Self { spi: RefCell::new(spi), - left_blinker_button, - right_blinker_button, - previous_animation_button, - next_animation_button, + left_blinker_button: DebouncedButton::new(left_blinker_button), + right_blinker_button: DebouncedButton::new(right_blinker_button), + previous_animation_button: DebouncedButton::new(previous_animation_button), + next_animation_button: DebouncedButton::new(next_animation_button), } } } @@ -83,14 +108,18 @@ impl< NextId: PinId, > UI for BikeUI { - fn check_event(&self) -> Option { - if self.left_blinker_button.is_low().unwrap_or(false) { + fn check_event(&mut self, current_time: Instant) -> Option { + if self.left_blinker_button.is_low(current_time) { + self.left_blinker_button.set_debounce(current_time); Some(Event::LeftBlinker) - } else if self.right_blinker_button.is_low().unwrap_or(false) { + } else if self.right_blinker_button.is_low(current_time) { + self.right_blinker_button.set_debounce(current_time); Some(Event::RightBlinker) - } else if self.previous_animation_button.is_low().unwrap_or(false) { + } else if self.previous_animation_button.is_low(current_time) { + self.previous_animation_button.set_debounce(current_time); Some(Event::PreviousPattern) - } else if self.next_animation_button.is_low().unwrap_or(false) { + } else if self.next_animation_button.is_low(current_time) { + self.next_animation_button.set_debounce(current_time); Some(Event::NextPattern) } else { None @@ -111,9 +140,9 @@ impl< } for (idx, rgb) in body_lights.iter().enumerate() { lights[(idx + 4) * 4 + 0] = 0xe0 + BODY_BRIGHTNESS; - lights[(idx + 4) * 4 + 1] = (I16F16::from(rgb.r) * LIGHT_SCALE).saturating_as(); - lights[(idx + 4) * 4 + 2] = (I16F16::from(rgb.b) * LIGHT_SCALE).saturating_as(); - lights[(idx + 4) * 4 + 3] = (I16F16::from(rgb.g) * LIGHT_SCALE).saturating_as(); + lights[(idx + 4) * 4 + 1] = (I16F16::from(rgb.b) * LIGHT_SCALE).saturating_as(); + lights[(idx + 4) * 4 + 2] = (I16F16::from(rgb.g) * LIGHT_SCALE).saturating_as(); + lights[(idx + 4) * 4 + 3] = (I16F16::from(rgb.r) * LIGHT_SCALE).saturating_as(); } let mut spi = self.spi.borrow_mut(); spi.write(lights.as_slice()); diff --git a/bike-lights/core/src/lib.rs b/bike-lights/core/src/lib.rs index 6bdf9b1..b686d83 100644 --- a/bike-lights/core/src/lib.rs +++ b/bike-lights/core/src/lib.rs @@ -33,7 +33,7 @@ fn linear_ease(value: I8F8, frames: U16F0, slope: I8F8) -> I8F8 { value_i16f16.saturating_as() } -#[derive(Clone, Copy)] +#[derive(Clone, Copy, PartialOrd, Ord, PartialEq, Eq)] pub struct Instant(pub U128F0); impl Default for Instant { @@ -61,7 +61,7 @@ impl Sub for Instant { pub const FPS: u8 = 30; pub trait UI { - fn check_event(&self) -> Option; + fn check_event(&mut self, current_time: Instant) -> Option; fn update_lights(&self, dashboard_lights: DashboardPattern, body_lights: BodyPattern); } @@ -193,12 +193,10 @@ impl Blinker { fn new( starting_dashboard: DashboardPattern, starting_body: BodyPattern, - home_dashboard: DashboardPattern, - home_body: BodyPattern, direction: BlinkerDirection, time: Instant, ) -> Self { - let mut ending_dashboard = home_dashboard.clone(); + let mut ending_dashboard = OFF_DASHBOARD.clone(); match direction { BlinkerDirection::Left => { @@ -213,7 +211,7 @@ impl Blinker { } } - let mut ending_body = home_body.clone(); + let mut ending_body = OFF_BODY.clone(); match direction { BlinkerDirection::Left => { for i in 0..30 { @@ -241,8 +239,8 @@ impl Blinker { time, ), fade_in: Fade::new( - home_dashboard.clone(), - home_body.clone(), + OFF_DASHBOARD.clone(), + OFF_BODY.clone(), ending_dashboard.clone(), ending_body.clone(), BLINKER_FRAMES, @@ -251,8 +249,8 @@ impl Blinker { fade_out: Fade::new( ending_dashboard.clone(), ending_body.clone(), - home_dashboard.clone(), - home_body.clone(), + OFF_DASHBOARD.clone(), + OFF_BODY.clone(), BLINKER_FRAMES, time, ), @@ -395,8 +393,6 @@ impl App { self.current_animation = Box::new(Blinker::new( self.dashboard_lights.clone(), self.lights.clone(), - self.home_pattern.dashboard(), - self.home_pattern.body(), BlinkerDirection::Left, time, )); @@ -405,8 +401,6 @@ impl App { self.current_animation = Box::new(Blinker::new( self.dashboard_lights.clone(), self.lights.clone(), - self.home_pattern.dashboard(), - self.home_pattern.body(), BlinkerDirection::Right, time, )); @@ -456,7 +450,7 @@ impl App { } pub fn tick(&mut self, time: Instant) { - match self.ui.check_event() { + match self.ui.check_event(time) { Some(event) => { self.update_state(event); self.update_animation(time); diff --git a/bike-lights/core/src/patterns.rs b/bike-lights/core/src/patterns.rs index fbaab4e..41b9f99 100644 --- a/bike-lights/core/src/patterns.rs +++ b/bike-lights/core/src/patterns.rs @@ -26,26 +26,26 @@ pub const BLINKER_AMBER: RGB = RGB { }; pub const PRIDE_RED: RGB = RGB { - r: I8F8::lit("0.89"), - g: I8F8::lit("0.01"), - b: I8F8::lit("0.01"), + r: I8F8::lit("0.95"), + g: I8F8::lit("0.00"), + b: I8F8::lit("0.00"), }; pub const PRIDE_ORANGE: RGB = RGB { r: I8F8::lit("1.0"), - g: I8F8::lit("0.54"), + g: I8F8::lit("0.25"), b: I8F8::lit("0"), }; pub const PRIDE_YELLOW: RGB = RGB { r: I8F8::lit("1.0"), - g: I8F8::lit("0.92"), + g: I8F8::lit("0.85"), b: I8F8::lit("0"), }; pub const PRIDE_GREEN: RGB = RGB { r: I8F8::lit("0"), - g: I8F8::lit("0.5"), + g: I8F8::lit("0.95"), b: I8F8::lit("0.05"), }; @@ -56,9 +56,9 @@ pub const PRIDE_INDIGO: RGB = RGB { }; pub const PRIDE_VIOLET: RGB = RGB { - r: I8F8::lit("0.45"), - g: I8F8::lit("0.16"), - b: I8F8::lit("0.50"), + r: I8F8::lit("0.75"), + g: I8F8::lit("0.0"), + b: I8F8::lit("0.80"), }; pub const TRANS_BLUE: RGB = RGB { @@ -178,7 +178,7 @@ pub const BRAKES_DASHBOARD: DashboardPattern = [BRAKES_RED; 3]; pub const BRAKES_BODY: BodyPattern = [BRAKES_RED; 60]; -pub const BLINKER_FRAMES: U16F0 = U16F0::lit("15"); +pub const BLINKER_FRAMES: U16F0 = U16F0::lit("10"); pub const LEFT_BLINKER_DASHBOARD: DashboardPattern = [BLINKER_AMBER, RGB_OFF, RGB_OFF]; diff --git a/bike-lights/simulator/src/main.rs b/bike-lights/simulator/src/main.rs index 407a11d..e96d0ee 100644 --- a/bike-lights/simulator/src/main.rs +++ b/bike-lights/simulator/src/main.rs @@ -152,7 +152,7 @@ struct GTKUI { } impl UI for GTKUI { - fn check_event(&self) -> Option { + fn check_event(&mut self, _: Instant) -> Option { match self.rx.try_recv() { Ok(event) => Some(event), Err(TryRecvError::Empty) => None,