An applicaiton and simulator for a bike lighting system #245
|
@ -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<D: SpiDevice, P: ValidSpiPinout<D>> {
|
||||
struct BikeUI<
|
||||
D: SpiDevice,
|
||||
P: ValidSpiPinout<D>,
|
||||
LeftId: PinId,
|
||||
RightId: PinId,
|
||||
PreviousId: PinId,
|
||||
NextId: PinId,
|
||||
> {
|
||||
spi: RefCell<Spi<Enabled, D, P, 8>>,
|
||||
left_blinker_button: Pin<LeftId, FunctionSio<SioInput>, PullDown>,
|
||||
right_blinker_button: Pin<RightId, FunctionSio<SioInput>, PullDown>,
|
||||
previous_animation_button: Pin<PreviousId, FunctionSio<SioInput>, PullDown>,
|
||||
next_animation_button: Pin<NextId, FunctionSio<SioInput>, PullDown>,
|
||||
}
|
||||
|
||||
impl<D: SpiDevice, P: ValidSpiPinout<D>> BikeUI<D, P> {
|
||||
fn new(spi: Spi<Enabled, D, P, 8>) -> Self {
|
||||
impl<
|
||||
D: SpiDevice,
|
||||
P: ValidSpiPinout<D>,
|
||||
LeftId: PinId,
|
||||
RightId: PinId,
|
||||
PreviousId: PinId,
|
||||
NextId: PinId,
|
||||
> BikeUI<D, P, LeftId, RightId, PreviousId, NextId>
|
||||
{
|
||||
fn new(
|
||||
spi: Spi<Enabled, D, P, 8>,
|
||||
left_blinker_button: Pin<LeftId, FunctionSio<SioInput>, PullDown>,
|
||||
right_blinker_button: Pin<RightId, FunctionSio<SioInput>, PullDown>,
|
||||
previous_animation_button: Pin<PreviousId, FunctionSio<SioInput>, PullDown>,
|
||||
next_animation_button: Pin<NextId, FunctionSio<SioInput>, PullDown>,
|
||||
) -> Self {
|
||||
Self {
|
||||
spi: RefCell::new(spi),
|
||||
left_blinker_button,
|
||||
right_blinker_button,
|
||||
previous_animation_button,
|
||||
next_animation_button,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl<D: SpiDevice, P: ValidSpiPinout<D>> UI for BikeUI<D, P> {
|
||||
impl<
|
||||
D: SpiDevice,
|
||||
P: ValidSpiPinout<D>,
|
||||
LeftId: PinId,
|
||||
RightId: PinId,
|
||||
PreviousId: PinId,
|
||||
NextId: PinId,
|
||||
> UI for BikeUI<D, P, LeftId, RightId, PreviousId, NextId>
|
||||
{
|
||||
fn check_event(&self) -> Option<Event> {
|
||||
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());
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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;
|
||||
|
||||
|
|
Loading…
Reference in New Issue