diff --git a/bike-lights/bike/src/main.rs b/bike-lights/bike/src/main.rs index 4e45da7..b309376 100644 --- a/bike-lights/bike/src/main.rs +++ b/bike-lights/bike/src/main.rs @@ -3,21 +3,21 @@ extern crate alloc; +use alloc::boxed::Box; use az::*; use core::cell::RefCell; use cortex_m::delay::Delay; use embedded_alloc::Heap; -use embedded_hal::{blocking::spi::Write, digital::v2::OutputPin}; +use embedded_hal::{blocking::spi::Write, digital::v2::InputPin}; use fixed::types::I16F16; use fugit::RateExtU32; -use lights_core::{ - BodyPattern, DashboardPattern, Event, TRANS_PRIDE_BODY, TRANS_PRIDE_DASHBOARD, UI, -}; +use lights_core::{App, BodyPattern, DashboardPattern, Event, Instant, State, FPS, UI}; use panic_halt as _; use rp_pico::{ entry, hal::{ clocks::init_clocks_and_plls, + gpio::{FunctionSio, Pin, PinId, PullDown, SioInput}, pac::{CorePeripherals, Peripherals}, spi::{Enabled, Spi, SpiDevice, ValidSpiPinout}, watchdog::Watchdog, @@ -32,25 +32,74 @@ static HEAP: Heap = Heap::empty(); const LIGHT_SCALE: I16F16 = I16F16::lit("256.0"); const GLOBAL_BRIGHTESS: u8 = 1; -struct BikeUI> { +struct BikeUI< + D: SpiDevice, + P: ValidSpiPinout, + LeftId: PinId, + RightId: PinId, + PreviousId: PinId, + NextId: PinId, +> { spi: RefCell>, + left_blinker_button: Pin, PullDown>, + right_blinker_button: Pin, PullDown>, + previous_animation_button: Pin, PullDown>, + next_animation_button: Pin, PullDown>, } -impl> BikeUI { - fn new(spi: Spi) -> Self { +impl< + D: SpiDevice, + P: ValidSpiPinout, + LeftId: PinId, + RightId: PinId, + PreviousId: PinId, + NextId: PinId, + > BikeUI +{ + fn new( + spi: Spi, + left_blinker_button: Pin, PullDown>, + right_blinker_button: Pin, PullDown>, + previous_animation_button: Pin, PullDown>, + next_animation_button: Pin, PullDown>, + ) -> Self { Self { spi: RefCell::new(spi), + left_blinker_button, + right_blinker_button, + previous_animation_button, + next_animation_button, } } } -impl> UI for BikeUI { +impl< + D: SpiDevice, + P: ValidSpiPinout, + LeftId: PinId, + RightId: PinId, + PreviousId: PinId, + NextId: PinId, + > UI for BikeUI +{ fn check_event(&self) -> Option { - None + if self.left_blinker_button.is_high().unwrap_or(false) { + Some(Event::LeftBlinker) + } else if self.right_blinker_button.is_high().unwrap_or(false) { + Some(Event::RightBlinker) + } else if self.previous_animation_button.is_high().unwrap_or(false) { + Some(Event::PreviousPattern) + } else if self.next_animation_button.is_high().unwrap_or(false) { + Some(Event::NextPattern) + } else { + None + } } fn update_lights(&self, dashboard_lights: DashboardPattern, body_lights: BodyPattern) { let mut lights: [u8; 20] = [0; 20]; + // Check https://www.pololu.com/product/3089 for the end frame calculations. It is not what + // I thought. lights[16] = 0xff; lights[17] = 0xff; lights[18] = 0xff; @@ -110,25 +159,29 @@ fn main() -> ! { embedded_hal::spi::MODE_1, ); - let ui = BikeUI::new(spi); + let left_blinker_button = pins.gpio18.into_pull_down_input(); + let right_blinker_button = pins.gpio19.into_function(); + let previous_animation_button = pins.gpio20.into_function(); + let next_animation_button = pins.gpio21.into_pull_down_input(); - // let app = App::new(Box::new(ui)); - // app.tick(TRANS_PRIDE_DASHBOARD, TRANS_PRIDE_BODY); - ui.update_lights(TRANS_PRIDE_DASHBOARD, TRANS_PRIDE_BODY); + let ui = BikeUI::new( + spi, + left_blinker_button, + right_blinker_button, + previous_animation_button, + next_animation_button, + ); - /* - spi.write(&[ - 0, 0, 0, 0, 0xe1, 0x80, 0x00, 0x00, 0xe1, 0x00, 0x80, 0x00, 0xe1, 0x00, 0x00, 0x80, 0xff, - 0xff, 0xff, 0xff, - ]); - */ + let mut app = App::new(Box::new(ui)); let mut led_pin = pins.led.into_push_pull_output(); + let mut time = Instant::default(); + let delay_ms = 1000 / (FPS as u32); loop { - led_pin.set_high().unwrap(); - delay.delay_ms(500); - led_pin.set_low().unwrap(); - delay.delay_ms(500); + app.tick(time); + + delay.delay_ms(delay_ms); + time = time + Instant(delay_ms.into()); } } diff --git a/bike-lights/core/src/lib.rs b/bike-lights/core/src/lib.rs index 361d39b..28e803c 100644 --- a/bike-lights/core/src/lib.rs +++ b/bike-lights/core/src/lib.rs @@ -3,7 +3,13 @@ extern crate alloc; use alloc::boxed::Box; use az::*; -use core::{clone::Clone, cmp::PartialEq, ops::Sub, option::Option}; +use core::{ + clone::Clone, + cmp::PartialEq, + default::Default, + ops::{Add, Sub}, + option::Option, +}; use fixed::types::{I48F16, I8F8, U128F0, U16F0}; mod patterns; @@ -30,6 +36,20 @@ fn linear_ease(value: I8F8, frames: U16F0, slope: I8F8) -> I8F8 { #[derive(Clone, Copy)] pub struct Instant(pub U128F0); +impl Default for Instant { + fn default() -> Self { + Self(U128F0::from(0 as u8)) + } +} + +impl Add for Instant { + type Output = Self; + + fn add(self, r: Self) -> Self::Output { + Self(self.0 + r.0) + } +} + impl Sub for Instant { type Output = Self;