From fc2e88add283e6b54358b77b6bc08421949fbf2e Mon Sep 17 00:00:00 2001 From: Savanni D'Gerinel Date: Sun, 26 Nov 2023 13:03:19 -0500 Subject: [PATCH 01/16] Set up a GTK simulator for the bike lights engine --- Cargo.lock | 35 ++++ Cargo.toml | 2 + bike-lights/core/Cargo.toml | 8 + bike-lights/core/src/lib.rs | 14 ++ bike-lights/simulator/Cargo.toml | 15 ++ bike-lights/simulator/src/main.rs | 295 ++++++++++++++++++++++++++++++ 6 files changed, 369 insertions(+) create mode 100644 bike-lights/core/Cargo.toml create mode 100644 bike-lights/core/src/lib.rs create mode 100644 bike-lights/simulator/Cargo.toml create mode 100644 bike-lights/simulator/src/main.rs diff --git a/Cargo.lock b/Cargo.lock index 4118f22..66bcce8 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -330,6 +330,12 @@ version = "1.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "d468802bab17cbc0cc575e9b053f41e72aa36bfa6b7f55e3529ffa43161b97fa" +[[package]] +name = "az" +version = "1.2.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7b7e4c2464d97fe331d41de9d5db0def0a96f4d823b8b32a2efd503578988973" + [[package]] name = "backtrace" version = "0.3.69" @@ -1117,6 +1123,18 @@ dependencies = [ "tokio", ] +[[package]] +name = "fixed" +version = "1.24.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "02c69ce7e7c0f17aa18fdd9d0de39727adb9c6281f2ad12f57cbe54ae6e76e7d" +dependencies = [ + "az", + "bytemuck", + "half", + "typenum", +] + [[package]] name = "flate2" version = "1.0.28" @@ -2303,6 +2321,10 @@ dependencies = [ "vcpkg", ] +[[package]] +name = "lights-core" +version = "0.1.0" + [[package]] name = "linux-raw-sys" version = "0.3.8" @@ -3751,6 +3773,19 @@ version = "0.3.7" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "d66dc143e6b11c1eddc06d5c423cfc97062865baf299914ab64caa38182078fe" +[[package]] +name = "simulator" +version = "0.1.0" +dependencies = [ + "cairo-rs", + "fixed", + "gio", + "glib", + "gtk4", + "libadwaita", + "pango", +] + [[package]] name = "siphasher" version = "0.2.3" diff --git a/Cargo.toml b/Cargo.toml index 538b62b..47cc89e 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -2,6 +2,8 @@ resolver = "2" members = [ "authdb", + "bike-lights/core", + "bike-lights/simulator", "changeset", "config", "config-derive", diff --git a/bike-lights/core/Cargo.toml b/bike-lights/core/Cargo.toml new file mode 100644 index 0000000..4c709a8 --- /dev/null +++ b/bike-lights/core/Cargo.toml @@ -0,0 +1,8 @@ +[package] +name = "lights-core" +version = "0.1.0" +edition = "2021" + +# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html + +[dependencies] diff --git a/bike-lights/core/src/lib.rs b/bike-lights/core/src/lib.rs new file mode 100644 index 0000000..7d12d9a --- /dev/null +++ b/bike-lights/core/src/lib.rs @@ -0,0 +1,14 @@ +pub fn add(left: usize, right: usize) -> usize { + left + right +} + +#[cfg(test)] +mod tests { + use super::*; + + #[test] + fn it_works() { + let result = add(2, 2); + assert_eq!(result, 4); + } +} diff --git a/bike-lights/simulator/Cargo.toml b/bike-lights/simulator/Cargo.toml new file mode 100644 index 0000000..0a93f0f --- /dev/null +++ b/bike-lights/simulator/Cargo.toml @@ -0,0 +1,15 @@ +[package] +name = "simulator" +version = "0.1.0" +edition = "2021" + +# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html + +[dependencies] +adw = { version = "0.5", package = "libadwaita", features = [ "v1_2" ] } +cairo-rs = { version = "0.18" } +fixed = { version = "1" } +gio = { version = "0.18" } +glib = { version = "0.18" } +gtk = { version = "0.7", package = "gtk4", features = [ "v4_8" ] } +pango = { version = "*" } diff --git a/bike-lights/simulator/src/main.rs b/bike-lights/simulator/src/main.rs new file mode 100644 index 0000000..97fcdee --- /dev/null +++ b/bike-lights/simulator/src/main.rs @@ -0,0 +1,295 @@ +use adw::prelude::*; +use glib::Object; +use gtk::subclass::prelude::*; +use std::{cell::RefCell, env, rc::Rc}; + +const WIDTH: i32 = 640; +const HEIGHT: i32 = 480; + +pub struct RGB { + pub r: u8, + pub g: u8, + pub b: u8, +} + +pub struct DashboardLightsPrivate { + lights: Rc>, +} + +#[glib::object_subclass] +impl ObjectSubclass for DashboardLightsPrivate { + const NAME: &'static str = "DashboardLights"; + type Type = DashboardLights; + type ParentType = gtk::DrawingArea; + + fn new() -> Self { + Self { + lights: Rc::new(RefCell::new([ + RGB { r: 0, g: 0, b: 0 }, + RGB { r: 0, g: 0, b: 0 }, + RGB { r: 0, g: 0, b: 0 }, + ])), + } + } +} + +impl ObjectImpl for DashboardLightsPrivate {} +impl WidgetImpl for DashboardLightsPrivate {} +impl DrawingAreaImpl for DashboardLightsPrivate {} + +glib::wrapper! { + pub struct DashboardLights(ObjectSubclass) @extends gtk::DrawingArea, gtk::Widget; +} + +impl DashboardLights { + pub fn new() -> Self { + let s: Self = Object::builder().build(); + + s.set_width_request(WIDTH); + s.set_height_request(100); + + s.set_draw_func({ + let s = s.clone(); + move |_, context, width, _| { + let start = width as f64 / 2. - 150.; + let lights = s.imp().lights.borrow(); + for i in 0..3 { + context.set_source_rgb( + lights[i].r as f64, + lights[i].g as f64, + lights[i].b as f64, + ); + context.rectangle(start + 100. * i as f64, 10., 80., 80.); + let _ = context.fill(); + } + } + }); + + s + } + + pub fn set_lights(&self, lights: [RGB; 3]) { + *self.imp().lights.borrow_mut() = lights; + self.queue_draw(); + } +} + +pub struct BikeLightsPrivate { + lights: Rc>, +} + +#[glib::object_subclass] +impl ObjectSubclass for BikeLightsPrivate { + const NAME: &'static str = "BikeLights"; + type Type = BikeLights; + type ParentType = gtk::DrawingArea; + + fn new() -> Self { + Self { + lights: Rc::new(RefCell::new([ + RGB { r: 0, g: 0, b: 0 }, + RGB { r: 0, g: 0, b: 0 }, + RGB { r: 0, g: 0, b: 0 }, + RGB { r: 0, g: 0, b: 0 }, + RGB { r: 0, g: 0, b: 0 }, + RGB { r: 0, g: 0, b: 0 }, + RGB { r: 0, g: 0, b: 0 }, + RGB { r: 0, g: 0, b: 0 }, + RGB { r: 0, g: 0, b: 0 }, + RGB { r: 0, g: 0, b: 0 }, + RGB { r: 0, g: 0, b: 0 }, + RGB { r: 0, g: 0, b: 0 }, + RGB { r: 0, g: 0, b: 0 }, + RGB { r: 0, g: 0, b: 0 }, + RGB { r: 0, g: 0, b: 0 }, + RGB { r: 0, g: 0, b: 0 }, + RGB { r: 0, g: 0, b: 0 }, + RGB { r: 0, g: 0, b: 0 }, + RGB { r: 0, g: 0, b: 0 }, + RGB { r: 0, g: 0, b: 0 }, + RGB { r: 0, g: 0, b: 0 }, + RGB { r: 0, g: 0, b: 0 }, + RGB { r: 0, g: 0, b: 0 }, + RGB { r: 0, g: 0, b: 0 }, + RGB { r: 0, g: 0, b: 0 }, + RGB { r: 0, g: 0, b: 0 }, + RGB { r: 0, g: 0, b: 0 }, + RGB { r: 0, g: 0, b: 0 }, + RGB { r: 0, g: 0, b: 0 }, + RGB { r: 0, g: 0, b: 0 }, + RGB { r: 0, g: 0, b: 0 }, + RGB { r: 0, g: 0, b: 0 }, + RGB { r: 0, g: 0, b: 0 }, + RGB { r: 0, g: 0, b: 0 }, + RGB { r: 0, g: 0, b: 0 }, + RGB { r: 0, g: 0, b: 0 }, + RGB { r: 0, g: 0, b: 0 }, + RGB { r: 0, g: 0, b: 0 }, + RGB { r: 0, g: 0, b: 0 }, + RGB { r: 0, g: 0, b: 0 }, + RGB { r: 0, g: 0, b: 0 }, + RGB { r: 0, g: 0, b: 0 }, + RGB { r: 0, g: 0, b: 0 }, + RGB { r: 0, g: 0, b: 0 }, + RGB { r: 0, g: 0, b: 0 }, + RGB { r: 0, g: 0, b: 0 }, + RGB { r: 0, g: 0, b: 0 }, + RGB { r: 0, g: 0, b: 0 }, + RGB { r: 0, g: 0, b: 0 }, + RGB { r: 0, g: 0, b: 0 }, + RGB { r: 0, g: 0, b: 0 }, + RGB { r: 0, g: 0, b: 0 }, + RGB { r: 0, g: 0, b: 0 }, + RGB { r: 0, g: 0, b: 0 }, + RGB { r: 0, g: 0, b: 0 }, + RGB { r: 0, g: 0, b: 0 }, + RGB { r: 0, g: 0, b: 0 }, + RGB { r: 0, g: 0, b: 0 }, + RGB { r: 0, g: 0, b: 0 }, + RGB { r: 0, g: 0, b: 0 }, + ])), + } + } +} + +impl ObjectImpl for BikeLightsPrivate {} +impl WidgetImpl for BikeLightsPrivate {} +impl DrawingAreaImpl for BikeLightsPrivate {} + +glib::wrapper! { + pub struct BikeLights(ObjectSubclass) @extends gtk::DrawingArea, gtk::Widget; +} + +impl BikeLights { + pub fn new() -> Self { + let s: Self = Object::builder().build(); + + s.set_width_request(WIDTH); + s.set_height_request(200); + + s.set_draw_func({ + let s = s.clone(); + move |_, context, _, _| { + let lights = s.imp().lights.borrow(); + for i in 0..30 { + context.set_source_rgb( + lights[i].r as f64, + lights[i].g as f64, + lights[i].b as f64, + ); + context.rectangle(5. + 20. * i as f64, 5., 15., 15.); + let _ = context.fill(); + } + for i in 0..30 { + context.set_source_rgb( + lights[i + 30].r as f64, + lights[i + 30].g as f64, + lights[i + 30].b as f64, + ); + context.rectangle(5. + 20. * i as f64, 30., 15., 15.); + let _ = context.fill(); + } + } + }); + + s + } + + pub fn set_lights(&self, lights: [RGB; 60]) { + *self.imp().lights.borrow_mut() = lights; + self.queue_draw(); + } +} + +fn main() { + let app = adw::Application::builder() + .application_id("com.luminescent-dreams.bike-light-simulator") + .build(); + + app.connect_activate(move |app| { + let window = adw::ApplicationWindow::builder() + .application(app) + .default_width(WIDTH) + .default_height(HEIGHT) + .build(); + let layout = gtk::Box::builder() + .orientation(gtk::Orientation::Vertical) + .build(); + let controls = gtk::Box::builder() + .orientation(gtk::Orientation::Horizontal) + .build(); + + let dashboard_lights = DashboardLights::new(); + let bike_lights = BikeLights::new(); + + let left_button = gtk::Button::builder().label("L").build(); + let brake_button = gtk::Button::builder().label("Brakes").build(); + let right_button = gtk::Button::builder().label("R").build(); + + left_button.connect_clicked({ + let dashboard_lights = dashboard_lights.clone(); + move |_| { + dashboard_lights.set_lights([ + RGB { + r: 128, + g: 128, + b: 0, + }, + RGB { r: 0, g: 0, b: 0 }, + RGB { r: 0, g: 0, b: 0 }, + ]); + } + }); + + brake_button.connect_clicked({ + let dashboard_lights = dashboard_lights.clone(); + move |_| { + dashboard_lights.set_lights([ + RGB { r: 128, g: 0, b: 0 }, + RGB { r: 128, g: 0, b: 0 }, + RGB { r: 128, g: 0, b: 0 }, + ]); + } + }); + + right_button.connect_clicked({ + let dashboard_lights = dashboard_lights.clone(); + move |_| { + dashboard_lights.set_lights([ + RGB { r: 0, g: 0, b: 0 }, + RGB { r: 0, g: 0, b: 0 }, + RGB { + r: 128, + g: 128, + b: 0, + }, + ]); + } + }); + + controls.append(&left_button); + controls.append(&brake_button); + controls.append(&right_button); + layout.append(&controls); + + let pattern_controls = gtk::Box::builder() + .orientation(gtk::Orientation::Horizontal) + .build(); + + let previous_pattern = gtk::Button::builder().label("Previous").build(); + let next_pattern = gtk::Button::builder().label("Next").build(); + + pattern_controls.append(&previous_pattern); + pattern_controls.append(&next_pattern); + layout.append(&pattern_controls); + + layout.append(&dashboard_lights); + layout.append(&bike_lights); + + window.set_content(Some(&layout)); + window.present(); + }); + + let args: Vec = env::args().collect(); + ApplicationExtManual::run_with_args(&app, &args); +} -- 2.44.1 From 84b077e20c053c965afdf84d76ae2d7e14771995 Mon Sep 17 00:00:00 2001 From: Savanni D'Gerinel Date: Sun, 26 Nov 2023 20:57:28 -0500 Subject: [PATCH 02/16] Build the core of the application. --- Cargo.lock | 1 + bike-lights/core/src/lib.rs | 76 +++- bike-lights/core/src/patterns.rs | 671 ++++++++++++++++++++++++++++++ bike-lights/core/src/types.rs | 9 + bike-lights/simulator/Cargo.toml | 1 + bike-lights/simulator/src/main.rs | 119 +++--- 6 files changed, 807 insertions(+), 70 deletions(-) create mode 100644 bike-lights/core/src/patterns.rs create mode 100644 bike-lights/core/src/types.rs diff --git a/Cargo.lock b/Cargo.lock index 66bcce8..886e4a5 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -3783,6 +3783,7 @@ dependencies = [ "glib", "gtk4", "libadwaita", + "lights-core", "pango", ] diff --git a/bike-lights/core/src/lib.rs b/bike-lights/core/src/lib.rs index 7d12d9a..5c4ed49 100644 --- a/bike-lights/core/src/lib.rs +++ b/bike-lights/core/src/lib.rs @@ -1,14 +1,72 @@ -pub fn add(left: usize, right: usize) -> usize { - left + right +use std::time::Duration; + +mod patterns; +pub use patterns::*; + +mod types; +pub use types::{DashboardPattern, Pattern, RGB}; + +pub trait UI { + fn update_lights(&self, dashboard_lights: DashboardPattern, lights: Pattern); } -#[cfg(test)] -mod tests { - use super::*; +pub trait Animation { + fn tick(&self, frame: Duration) -> (DashboardPattern, Pattern); +} - #[test] - fn it_works() { - let result = add(2, 2); - assert_eq!(result, 4); +pub struct DefaultAnimation {} + +impl Animation for DefaultAnimation { + fn tick(&self, _: Duration) -> (DashboardPattern, Pattern) { + (PRIDE_DASHBOARD, PRIDE) + } +} + +#[derive(Clone)] +pub enum Event { + Brake, + BrakeRelease, + LeftBlinker, + LeftBlinkerRelease, + NextPattern, + PreviousPattern, + RightBlinker, + RightBlinkerRelease, +} + +#[derive(Clone)] +pub enum State { + Pattern(u8), + Brake, + LeftBlinker, + RightBlinker, + BrakeLeftBlinker, + BrakeRightBlinker, +} + +pub struct App { + ui: Box, + state: State, + current_animation: Box, + dashboard_lights: DashboardPattern, + lights: Pattern, +} + +impl App { + pub fn new(ui: Box) -> Self { + Self { + ui, + state: State::Pattern(0), + current_animation: Box::new(DefaultAnimation {}), + dashboard_lights: OFF_DASHBOARD, + lights: OFF, + } + } + + pub fn tick(&mut self, frame: Duration) { + let (dashboard, lights) = self.current_animation.tick(frame); + self.dashboard_lights = dashboard.clone(); + self.lights = lights.clone(); + self.ui.update_lights(dashboard, lights); } } diff --git a/bike-lights/core/src/patterns.rs b/bike-lights/core/src/patterns.rs new file mode 100644 index 0000000..063b4df --- /dev/null +++ b/bike-lights/core/src/patterns.rs @@ -0,0 +1,671 @@ +use crate::RGB; + +pub type DashboardPattern = [RGB; 3]; +pub type Pattern = [RGB; 60]; + +pub const OFF_DASHBOARD: DashboardPattern = [ + RGB { r: 0, g: 0, b: 0 }, + RGB { r: 0, g: 0, b: 0 }, + RGB { r: 0, g: 0, b: 0 }, +]; + +pub const OFF: Pattern = [ + RGB { r: 0, g: 0, b: 0 }, + RGB { r: 0, g: 0, b: 0 }, + RGB { r: 0, g: 0, b: 0 }, + RGB { r: 0, g: 0, b: 0 }, + RGB { r: 0, g: 0, b: 0 }, + RGB { r: 0, g: 0, b: 0 }, + RGB { r: 0, g: 0, b: 0 }, + RGB { r: 0, g: 0, b: 0 }, + RGB { r: 0, g: 0, b: 0 }, + RGB { r: 0, g: 0, b: 0 }, + RGB { r: 0, g: 0, b: 0 }, + RGB { r: 0, g: 0, b: 0 }, + RGB { r: 0, g: 0, b: 0 }, + RGB { r: 0, g: 0, b: 0 }, + RGB { r: 0, g: 0, b: 0 }, + RGB { r: 0, g: 0, b: 0 }, + RGB { r: 0, g: 0, b: 0 }, + RGB { r: 0, g: 0, b: 0 }, + RGB { r: 0, g: 0, b: 0 }, + RGB { r: 0, g: 0, b: 0 }, + RGB { r: 0, g: 0, b: 0 }, + RGB { r: 0, g: 0, b: 0 }, + RGB { r: 0, g: 0, b: 0 }, + RGB { r: 0, g: 0, b: 0 }, + RGB { r: 0, g: 0, b: 0 }, + RGB { r: 0, g: 0, b: 0 }, + RGB { r: 0, g: 0, b: 0 }, + RGB { r: 0, g: 0, b: 0 }, + RGB { r: 0, g: 0, b: 0 }, + RGB { r: 0, g: 0, b: 0 }, + RGB { r: 0, g: 0, b: 0 }, + RGB { r: 0, g: 0, b: 0 }, + RGB { r: 0, g: 0, b: 0 }, + RGB { r: 0, g: 0, b: 0 }, + RGB { r: 0, g: 0, b: 0 }, + RGB { r: 0, g: 0, b: 0 }, + RGB { r: 0, g: 0, b: 0 }, + RGB { r: 0, g: 0, b: 0 }, + RGB { r: 0, g: 0, b: 0 }, + RGB { r: 0, g: 0, b: 0 }, + RGB { r: 0, g: 0, b: 0 }, + RGB { r: 0, g: 0, b: 0 }, + RGB { r: 0, g: 0, b: 0 }, + RGB { r: 0, g: 0, b: 0 }, + RGB { r: 0, g: 0, b: 0 }, + RGB { r: 0, g: 0, b: 0 }, + RGB { r: 0, g: 0, b: 0 }, + RGB { r: 0, g: 0, b: 0 }, + RGB { r: 0, g: 0, b: 0 }, + RGB { r: 0, g: 0, b: 0 }, + RGB { r: 0, g: 0, b: 0 }, + RGB { r: 0, g: 0, b: 0 }, + RGB { r: 0, g: 0, b: 0 }, + RGB { r: 0, g: 0, b: 0 }, + RGB { r: 0, g: 0, b: 0 }, + RGB { r: 0, g: 0, b: 0 }, + RGB { r: 0, g: 0, b: 0 }, + RGB { r: 0, g: 0, b: 0 }, + RGB { r: 0, g: 0, b: 0 }, + RGB { r: 0, g: 0, b: 0 }, +]; + +pub const PRIDE_DASHBOARD: DashboardPattern = [ + RGB { r: 228, g: 3, b: 3 }, + RGB { + r: 255, + g: 237, + b: 0, + }, + RGB { + r: 115, + g: 41, + b: 130, + }, +]; + +pub const PRIDE: Pattern = [ + RGB { r: 228, g: 3, b: 3 }, + RGB { r: 228, g: 3, b: 3 }, + RGB { r: 228, g: 3, b: 3 }, + RGB { r: 228, g: 3, b: 3 }, + RGB { r: 228, g: 3, b: 3 }, + RGB { r: 228, g: 3, b: 3 }, + RGB { r: 228, g: 3, b: 3 }, + RGB { r: 228, g: 3, b: 3 }, + RGB { r: 228, g: 3, b: 3 }, + RGB { r: 228, g: 3, b: 3 }, + RGB { + r: 255, + g: 140, + b: 0, + }, + RGB { + r: 255, + g: 140, + b: 0, + }, + RGB { + r: 255, + g: 140, + b: 0, + }, + RGB { + r: 255, + g: 140, + b: 0, + }, + RGB { + r: 255, + g: 140, + b: 0, + }, + RGB { + r: 255, + g: 140, + b: 0, + }, + RGB { + r: 255, + g: 140, + b: 0, + }, + RGB { + r: 255, + g: 140, + b: 0, + }, + RGB { + r: 255, + g: 140, + b: 0, + }, + RGB { + r: 255, + g: 140, + b: 0, + }, + RGB { + r: 255, + g: 237, + b: 0, + }, + RGB { + r: 255, + g: 237, + b: 0, + }, + RGB { + r: 255, + g: 237, + b: 0, + }, + RGB { + r: 255, + g: 237, + b: 0, + }, + RGB { + r: 255, + g: 237, + b: 0, + }, + RGB { + r: 255, + g: 237, + b: 0, + }, + RGB { + r: 255, + g: 237, + b: 0, + }, + RGB { + r: 255, + g: 237, + b: 0, + }, + RGB { + r: 255, + g: 237, + b: 0, + }, + RGB { + r: 255, + g: 237, + b: 0, + }, + RGB { + r: 0, + g: 128, + b: 38, + }, + RGB { + r: 0, + g: 128, + b: 38, + }, + RGB { + r: 0, + g: 128, + b: 38, + }, + RGB { + r: 0, + g: 128, + b: 38, + }, + RGB { + r: 0, + g: 128, + b: 38, + }, + RGB { + r: 0, + g: 128, + b: 38, + }, + RGB { + r: 0, + g: 128, + b: 38, + }, + RGB { + r: 0, + g: 128, + b: 38, + }, + RGB { + r: 0, + g: 128, + b: 38, + }, + RGB { + r: 0, + g: 128, + b: 38, + }, + RGB { + r: 36, + g: 64, + b: 142, + }, + RGB { + r: 36, + g: 64, + b: 142, + }, + RGB { + r: 36, + g: 64, + b: 142, + }, + RGB { + r: 36, + g: 64, + b: 142, + }, + RGB { + r: 36, + g: 64, + b: 142, + }, + RGB { + r: 36, + g: 64, + b: 142, + }, + RGB { + r: 36, + g: 64, + b: 142, + }, + RGB { + r: 36, + g: 64, + b: 142, + }, + RGB { + r: 36, + g: 64, + b: 142, + }, + RGB { + r: 36, + g: 64, + b: 142, + }, + RGB { + r: 115, + g: 41, + b: 130, + }, + RGB { + r: 115, + g: 41, + b: 130, + }, + RGB { + r: 115, + g: 41, + b: 130, + }, + RGB { + r: 115, + g: 41, + b: 130, + }, + RGB { + r: 115, + g: 41, + b: 130, + }, + RGB { + r: 115, + g: 41, + b: 130, + }, + RGB { + r: 115, + g: 41, + b: 130, + }, + RGB { + r: 115, + g: 41, + b: 130, + }, + RGB { + r: 115, + g: 41, + b: 130, + }, + RGB { + r: 115, + g: 41, + b: 130, + }, +]; + +pub const TRANS_PRIDE_DASHBOARD: DashboardPattern = [ + RGB { + r: 91, + g: 206, + b: 250, + }, + RGB { + r: 255, + g: 255, + b: 255, + }, + RGB { + r: 245, + g: 169, + b: 184, + }, +]; + +pub const TRANS_PRIDE: Pattern = [ + RGB { + r: 91, + g: 206, + b: 250, + }, + RGB { + r: 91, + g: 206, + b: 250, + }, + RGB { + r: 91, + g: 206, + b: 250, + }, + RGB { + r: 91, + g: 206, + b: 250, + }, + RGB { + r: 91, + g: 206, + b: 250, + }, + RGB { + r: 91, + g: 206, + b: 250, + }, + RGB { + r: 91, + g: 206, + b: 250, + }, + RGB { + r: 91, + g: 206, + b: 250, + }, + RGB { + r: 91, + g: 206, + b: 250, + }, + RGB { + r: 91, + g: 206, + b: 250, + }, + RGB { + r: 91, + g: 206, + b: 250, + }, + RGB { + r: 91, + g: 206, + b: 250, + }, + RGB { + r: 245, + g: 169, + b: 184, + }, + RGB { + r: 245, + g: 169, + b: 184, + }, + RGB { + r: 245, + g: 169, + b: 184, + }, + RGB { + r: 245, + g: 169, + b: 184, + }, + RGB { + r: 245, + g: 169, + b: 184, + }, + RGB { + r: 245, + g: 169, + b: 184, + }, + RGB { + r: 245, + g: 169, + b: 184, + }, + RGB { + r: 245, + g: 169, + b: 184, + }, + RGB { + r: 245, + g: 169, + b: 184, + }, + RGB { + r: 245, + g: 169, + b: 184, + }, + RGB { + r: 245, + g: 169, + b: 184, + }, + RGB { + r: 245, + g: 169, + b: 184, + }, + RGB { + r: 255, + g: 255, + b: 255, + }, + RGB { + r: 255, + g: 255, + b: 255, + }, + RGB { + r: 255, + g: 255, + b: 255, + }, + RGB { + r: 255, + g: 255, + b: 255, + }, + RGB { + r: 255, + g: 255, + b: 255, + }, + RGB { + r: 255, + g: 255, + b: 255, + }, + RGB { + r: 255, + g: 255, + b: 255, + }, + RGB { + r: 255, + g: 255, + b: 255, + }, + RGB { + r: 255, + g: 255, + b: 255, + }, + RGB { + r: 255, + g: 255, + b: 255, + }, + RGB { + r: 255, + g: 255, + b: 255, + }, + RGB { + r: 255, + g: 255, + b: 255, + }, + RGB { + r: 245, + g: 169, + b: 184, + }, + RGB { + r: 245, + g: 169, + b: 184, + }, + RGB { + r: 245, + g: 169, + b: 184, + }, + RGB { + r: 245, + g: 169, + b: 184, + }, + RGB { + r: 245, + g: 169, + b: 184, + }, + RGB { + r: 245, + g: 169, + b: 184, + }, + RGB { + r: 245, + g: 169, + b: 184, + }, + RGB { + r: 245, + g: 169, + b: 184, + }, + RGB { + r: 245, + g: 169, + b: 184, + }, + RGB { + r: 245, + g: 169, + b: 184, + }, + RGB { + r: 245, + g: 169, + b: 184, + }, + RGB { + r: 245, + g: 169, + b: 184, + }, + RGB { + r: 91, + g: 206, + b: 250, + }, + RGB { + r: 91, + g: 206, + b: 250, + }, + RGB { + r: 91, + g: 206, + b: 250, + }, + RGB { + r: 91, + g: 206, + b: 250, + }, + RGB { + r: 91, + g: 206, + b: 250, + }, + RGB { + r: 91, + g: 206, + b: 250, + }, + RGB { + r: 91, + g: 206, + b: 250, + }, + RGB { + r: 91, + g: 206, + b: 250, + }, + RGB { + r: 91, + g: 206, + b: 250, + }, + RGB { + r: 91, + g: 206, + b: 250, + }, + RGB { + r: 91, + g: 206, + b: 250, + }, + RGB { + r: 91, + g: 206, + b: 250, + }, +]; diff --git a/bike-lights/core/src/types.rs b/bike-lights/core/src/types.rs new file mode 100644 index 0000000..07b1b8d --- /dev/null +++ b/bike-lights/core/src/types.rs @@ -0,0 +1,9 @@ +#[derive(Clone)] +pub struct RGB { + pub r: u8, + pub g: u8, + pub b: u8, +} + +pub type DashboardPattern = [RGB; 3]; +pub type Pattern = [RGB; 60]; diff --git a/bike-lights/simulator/Cargo.toml b/bike-lights/simulator/Cargo.toml index 0a93f0f..42787ae 100644 --- a/bike-lights/simulator/Cargo.toml +++ b/bike-lights/simulator/Cargo.toml @@ -12,4 +12,5 @@ fixed = { version = "1" } gio = { version = "0.18" } glib = { version = "0.18" } gtk = { version = "0.7", package = "gtk4", features = [ "v4_8" ] } +lights-core = { path = "../core" } pango = { version = "*" } diff --git a/bike-lights/simulator/src/main.rs b/bike-lights/simulator/src/main.rs index 97fcdee..e959e68 100644 --- a/bike-lights/simulator/src/main.rs +++ b/bike-lights/simulator/src/main.rs @@ -1,19 +1,19 @@ use adw::prelude::*; -use glib::Object; +use glib::{Object, Sender}; use gtk::subclass::prelude::*; +use lights_core::{App, DashboardPattern, Pattern, RGB, UI}; use std::{cell::RefCell, env, rc::Rc}; const WIDTH: i32 = 640; const HEIGHT: i32 = 480; -pub struct RGB { - pub r: u8, - pub g: u8, - pub b: u8, +pub struct Update { + dashboard: DashboardPattern, + lights: Pattern, } pub struct DashboardLightsPrivate { - lights: Rc>, + lights: Rc>, } #[glib::object_subclass] @@ -55,9 +55,9 @@ impl DashboardLights { let lights = s.imp().lights.borrow(); for i in 0..3 { context.set_source_rgb( - lights[i].r as f64, - lights[i].g as f64, - lights[i].b as f64, + lights[i].r as f64 / 256., + lights[i].g as f64 / 256., + lights[i].b as f64 / 256., ); context.rectangle(start + 100. * i as f64, 10., 80., 80.); let _ = context.fill(); @@ -75,7 +75,7 @@ impl DashboardLights { } pub struct BikeLightsPrivate { - lights: Rc>, + lights: Rc>, } #[glib::object_subclass] @@ -173,18 +173,18 @@ impl BikeLights { let lights = s.imp().lights.borrow(); for i in 0..30 { context.set_source_rgb( - lights[i].r as f64, - lights[i].g as f64, - lights[i].b as f64, + lights[i].r as f64 / 256., + lights[i].g as f64 / 256., + lights[i].b as f64 / 256., ); context.rectangle(5. + 20. * i as f64, 5., 15., 15.); let _ = context.fill(); } for i in 0..30 { context.set_source_rgb( - lights[i + 30].r as f64, - lights[i + 30].g as f64, - lights[i + 30].b as f64, + lights[i + 30].r as f64 / 256., + lights[i + 30].g as f64 / 256., + lights[i + 30].b as f64 / 256., ); context.rectangle(5. + 20. * i as f64, 30., 15., 15.); let _ = context.fill(); @@ -201,14 +201,42 @@ impl BikeLights { } } +struct GTKUI { + tx: Rc>>>, +} + +impl UI for GTKUI { + fn update_lights(&self, dashboard_lights: DashboardPattern, lights: Pattern) { + if let Some(tx) = self.tx.borrow().as_ref() { + tx.send(Update { + dashboard: dashboard_lights, + lights, + }) + .unwrap(); + } + } +} + fn main() { - let app = adw::Application::builder() + let adw_app = adw::Application::builder() .application_id("com.luminescent-dreams.bike-light-simulator") .build(); - app.connect_activate(move |app| { + adw_app.connect_activate(move |adw_app| { + let (tx, rx) = gtk::glib::MainContext::channel::(gtk::glib::Priority::DEFAULT); + + std::thread::spawn(move || { + let mut bike_app = App::new(Box::new(GTKUI { + tx: Rc::new(RefCell::new(Some(tx))), + })); + loop { + bike_app.tick(std::time::Duration::from_millis(0)); + std::thread::sleep(std::time::Duration::from_millis(100)); + } + }); + let window = adw::ApplicationWindow::builder() - .application(app) + .application(adw_app) .default_width(WIDTH) .default_height(HEIGHT) .build(); @@ -226,47 +254,6 @@ fn main() { let brake_button = gtk::Button::builder().label("Brakes").build(); let right_button = gtk::Button::builder().label("R").build(); - left_button.connect_clicked({ - let dashboard_lights = dashboard_lights.clone(); - move |_| { - dashboard_lights.set_lights([ - RGB { - r: 128, - g: 128, - b: 0, - }, - RGB { r: 0, g: 0, b: 0 }, - RGB { r: 0, g: 0, b: 0 }, - ]); - } - }); - - brake_button.connect_clicked({ - let dashboard_lights = dashboard_lights.clone(); - move |_| { - dashboard_lights.set_lights([ - RGB { r: 128, g: 0, b: 0 }, - RGB { r: 128, g: 0, b: 0 }, - RGB { r: 128, g: 0, b: 0 }, - ]); - } - }); - - right_button.connect_clicked({ - let dashboard_lights = dashboard_lights.clone(); - move |_| { - dashboard_lights.set_lights([ - RGB { r: 0, g: 0, b: 0 }, - RGB { r: 0, g: 0, b: 0 }, - RGB { - r: 128, - g: 128, - b: 0, - }, - ]); - } - }); - controls.append(&left_button); controls.append(&brake_button); controls.append(&right_button); @@ -286,10 +273,20 @@ fn main() { layout.append(&dashboard_lights); layout.append(&bike_lights); + rx.attach(None, { + let dashboard_lights = dashboard_lights.clone(); + let bike_lights = bike_lights.clone(); + move |Update { dashboard, lights }| { + dashboard_lights.set_lights(dashboard); + bike_lights.set_lights(lights); + glib::ControlFlow::Continue + } + }); + window.set_content(Some(&layout)); window.present(); }); let args: Vec = env::args().collect(); - ApplicationExtManual::run_with_args(&app, &args); + ApplicationExtManual::run_with_args(&adw_app, &args); } -- 2.44.1 From 06aedc34bb99c0af0f1e896ae15c0779533e3c68 Mon Sep 17 00:00:00 2001 From: Savanni D'Gerinel Date: Sun, 26 Nov 2023 21:19:09 -0500 Subject: [PATCH 03/16] Now I'm able to send messages from the UI to the core --- bike-lights/core/src/lib.rs | 17 +++++---- bike-lights/simulator/src/main.rs | 57 +++++++++++++++++++++++++------ 2 files changed, 57 insertions(+), 17 deletions(-) diff --git a/bike-lights/core/src/lib.rs b/bike-lights/core/src/lib.rs index 5c4ed49..d9b3c06 100644 --- a/bike-lights/core/src/lib.rs +++ b/bike-lights/core/src/lib.rs @@ -7,31 +7,30 @@ mod types; pub use types::{DashboardPattern, Pattern, RGB}; pub trait UI { + fn check_event(&self) -> Option; fn update_lights(&self, dashboard_lights: DashboardPattern, lights: Pattern); } pub trait Animation { - fn tick(&self, frame: Duration) -> (DashboardPattern, Pattern); + fn tick(&self, time: std::time::Instant) -> (DashboardPattern, Pattern); } pub struct DefaultAnimation {} impl Animation for DefaultAnimation { - fn tick(&self, _: Duration) -> (DashboardPattern, Pattern) { + fn tick(&self, time: std::time::Instant) -> (DashboardPattern, Pattern) { (PRIDE_DASHBOARD, PRIDE) } } -#[derive(Clone)] +#[derive(Clone, Debug)] pub enum Event { Brake, BrakeRelease, LeftBlinker, - LeftBlinkerRelease, NextPattern, PreviousPattern, RightBlinker, - RightBlinkerRelease, } #[derive(Clone)] @@ -63,8 +62,12 @@ impl App { } } - pub fn tick(&mut self, frame: Duration) { - let (dashboard, lights) = self.current_animation.tick(frame); + pub fn tick(&mut self, time: std::time::Instant) { + match self.ui.check_event() { + Some(event) => println!("event received: {:?}", event), + None => (), + }; + let (dashboard, lights) = self.current_animation.tick(time); self.dashboard_lights = dashboard.clone(); self.lights = lights.clone(); self.ui.update_lights(dashboard, lights); diff --git a/bike-lights/simulator/src/main.rs b/bike-lights/simulator/src/main.rs index e959e68..be422e2 100644 --- a/bike-lights/simulator/src/main.rs +++ b/bike-lights/simulator/src/main.rs @@ -1,8 +1,13 @@ use adw::prelude::*; use glib::{Object, Sender}; use gtk::subclass::prelude::*; -use lights_core::{App, DashboardPattern, Pattern, RGB, UI}; -use std::{cell::RefCell, env, rc::Rc}; +use lights_core::{App, DashboardPattern, Event, Pattern, RGB, UI}; +use std::{ + cell::RefCell, + env, + rc::Rc, + sync::mpsc::{Receiver, TryRecvError}, +}; const WIDTH: i32 = 640; const HEIGHT: i32 = 480; @@ -202,18 +207,26 @@ impl BikeLights { } struct GTKUI { - tx: Rc>>>, + tx: Sender, + rx: Receiver, } impl UI for GTKUI { + fn check_event(&self) -> Option { + match self.rx.try_recv() { + Ok(event) => Some(event), + Err(TryRecvError::Empty) => None, + Err(TryRecvError::Disconnected) => None, + } + } + fn update_lights(&self, dashboard_lights: DashboardPattern, lights: Pattern) { - if let Some(tx) = self.tx.borrow().as_ref() { - tx.send(Update { + self.tx + .send(Update { dashboard: dashboard_lights, lights, }) .unwrap(); - } } } @@ -223,14 +236,17 @@ fn main() { .build(); adw_app.connect_activate(move |adw_app| { - let (tx, rx) = gtk::glib::MainContext::channel::(gtk::glib::Priority::DEFAULT); + let (update_tx, update_rx) = + gtk::glib::MainContext::channel::(gtk::glib::Priority::DEFAULT); + let (event_tx, event_rx) = std::sync::mpsc::channel(); std::thread::spawn(move || { let mut bike_app = App::new(Box::new(GTKUI { - tx: Rc::new(RefCell::new(Some(tx))), + tx: update_tx, + rx: event_rx, })); loop { - bike_app.tick(std::time::Duration::from_millis(0)); + bike_app.tick(std::time::Instant::now()); std::thread::sleep(std::time::Duration::from_millis(100)); } }); @@ -254,6 +270,27 @@ fn main() { let brake_button = gtk::Button::builder().label("Brakes").build(); let right_button = gtk::Button::builder().label("R").build(); + left_button.connect_clicked({ + let event_tx = event_tx.clone(); + move |_| { + let _ = event_tx.send(Event::LeftBlinker); + } + }); + + brake_button.connect_clicked({ + let event_tx = event_tx.clone(); + move |_| { + let _ = event_tx.send(Event::Brake); + } + }); + + right_button.connect_clicked({ + let event_tx = event_tx.clone(); + move |_| { + let _ = event_tx.send(Event::RightBlinker); + } + }); + controls.append(&left_button); controls.append(&brake_button); controls.append(&right_button); @@ -273,7 +310,7 @@ fn main() { layout.append(&dashboard_lights); layout.append(&bike_lights); - rx.attach(None, { + update_rx.attach(None, { let dashboard_lights = dashboard_lights.clone(); let bike_lights = bike_lights.clone(); move |Update { dashboard, lights }| { -- 2.44.1 From 0bb5e62f96f51192b31fa01793d8c066e8895d63 Mon Sep 17 00:00:00 2001 From: Savanni D'Gerinel Date: Sun, 26 Nov 2023 23:30:45 -0500 Subject: [PATCH 04/16] Set up a bunch of animations and some state transitions! --- bike-lights/core/src/lib.rs | 286 +++++++++++++++++++++++++++++- bike-lights/core/src/patterns.rs | 284 ++++++++++++++++++++++++++++- bike-lights/core/src/types.rs | 14 +- bike-lights/simulator/src/main.rs | 22 ++- 4 files changed, 580 insertions(+), 26 deletions(-) diff --git a/bike-lights/core/src/lib.rs b/bike-lights/core/src/lib.rs index d9b3c06..d7ef41b 100644 --- a/bike-lights/core/src/lib.rs +++ b/bike-lights/core/src/lib.rs @@ -1,28 +1,213 @@ -use std::time::Duration; - mod patterns; pub use patterns::*; mod types; pub use types::{DashboardPattern, Pattern, RGB}; +pub const FPS: u8 = 30; + pub trait UI { fn check_event(&self) -> Option; fn update_lights(&self, dashboard_lights: DashboardPattern, lights: Pattern); } pub trait Animation { - fn tick(&self, time: std::time::Instant) -> (DashboardPattern, Pattern); + fn tick(&mut self, time: std::time::Instant) -> (DashboardPattern, Pattern); } pub struct DefaultAnimation {} impl Animation for DefaultAnimation { - fn tick(&self, time: std::time::Instant) -> (DashboardPattern, Pattern) { + fn tick(&mut self, _: std::time::Instant) -> (DashboardPattern, Pattern) { (PRIDE_DASHBOARD, PRIDE) } } +pub struct Fade { + starting_dashboard: DashboardPattern, + starting_lights: Pattern, + + start_time: std::time::Instant, + dashboard_slope: Vec>, + body_slope: Vec>, + frames: u8, +} + +impl Fade { + fn new( + dashboard: DashboardPattern, + lights: Pattern, + ending_dashboard: DashboardPattern, + ending_lights: Pattern, + frames: u8, + time: std::time::Instant, + ) -> Self { + let mut dashboard_slope = Vec::new(); + let mut body_slope = Vec::new(); + for i in 0..3 { + let slope = RGB { + r: (ending_dashboard[i].r as f64 - dashboard[i].r as f64) / frames as f64, + g: (ending_dashboard[i].g as f64 - dashboard[i].g as f64) / frames as f64, + b: (ending_dashboard[i].b as f64 - dashboard[i].b as f64) / frames as f64, + }; + dashboard_slope.push(slope); + } + + for i in 0..60 { + let slope = RGB { + r: (ending_lights[i].r as f64 - lights[i].r as f64) / frames as f64, + g: (ending_lights[i].g as f64 - lights[i].g as f64) / frames as f64, + b: (ending_lights[i].b as f64 - lights[i].b as f64) / frames as f64, + }; + body_slope.push(slope); + } + + println!("dashboard slope: {:?}", dashboard_slope); + + Self { + starting_dashboard: dashboard, + starting_lights: lights, + start_time: time, + dashboard_slope, + body_slope, + frames, + } + } +} + +impl Animation for Fade { + fn tick(&mut self, time: std::time::Instant) -> (DashboardPattern, Pattern) { + let mut frames: u8 = ((time - self.start_time).as_millis() as f64 / FPS as f64) as u8; + if frames > self.frames { + frames = self.frames + } + let mut dashboard_pattern: DashboardPattern = OFF_DASHBOARD; + let mut body_pattern: Pattern = OFF; + + let apply = |value: f64, frames: f64, slope: f64| -> f64 { value + frames * slope }; + + for i in 0..3 { + dashboard_pattern[i].r = apply( + self.starting_dashboard[i].r as f64, + frames as f64, + self.dashboard_slope[i].r as f64, + ) as u8; + dashboard_pattern[i].g = apply( + self.starting_dashboard[i].g as f64, + frames as f64, + self.dashboard_slope[i].g as f64, + ) as u8; + dashboard_pattern[i].b = apply( + self.starting_dashboard[i].b as f64, + frames as f64, + self.dashboard_slope[i].b as f64, + ) as u8; + } + + for i in 0..60 { + body_pattern[i].r = apply( + self.starting_lights[i].r as f64, + frames as f64, + self.body_slope[i].r as f64, + ) as u8; + body_pattern[i].g = apply( + self.starting_lights[i].g as f64, + frames as f64, + self.body_slope[i].g as f64, + ) as u8; + body_pattern[i].b = apply( + self.starting_lights[i].b as f64, + frames as f64, + self.body_slope[i].b as f64, + ) as u8; + } + + (dashboard_pattern, body_pattern) + } +} + +#[derive(Debug)] +pub enum FadeDirection { + FadeIn, + FadeOut, +} + +pub struct LeftBlinker { + fade_in: Fade, + fade_out: Fade, + direction: FadeDirection, + + start_time: std::time::Instant, + frames: u8, +} + +impl LeftBlinker { + fn new( + starting_dashboard: DashboardPattern, + starting_body: Pattern, + time: std::time::Instant, + ) -> Self { + let mut ending_dashboard = starting_dashboard.clone(); + ending_dashboard[0].r = LEFT_DASHBOARD[0].r; + ending_dashboard[0].g = LEFT_DASHBOARD[0].g; + ending_dashboard[0].b = LEFT_DASHBOARD[0].b; + + let mut ending_body = starting_body.clone(); + for i in 0..30 { + ending_body[i].r = LEFT[i].r; + ending_body[i].g = LEFT[i].g; + ending_body[i].b = LEFT[i].b; + } + + LeftBlinker { + fade_in: Fade::new( + starting_dashboard.clone(), + starting_body.clone(), + ending_dashboard.clone(), + ending_body.clone(), + LEFT_FRAMES, + time, + ), + fade_out: Fade::new( + ending_dashboard.clone(), + ending_body.clone(), + starting_dashboard.clone(), + starting_body.clone(), + LEFT_FRAMES, + time, + ), + direction: FadeDirection::FadeIn, + start_time: time, + frames: LEFT_FRAMES, + } + } +} + +impl Animation for LeftBlinker { + fn tick(&mut self, time: std::time::Instant) -> (DashboardPattern, Pattern) { + let frames: u8 = ((time - self.start_time).as_millis() as f64 / FPS as f64) as u8; + if frames > self.frames { + match self.direction { + FadeDirection::FadeIn => { + self.direction = FadeDirection::FadeOut; + self.fade_out.start_time = time; + } + FadeDirection::FadeOut => { + self.direction = FadeDirection::FadeIn; + self.fade_in.start_time = time; + } + } + self.start_time = time; + } + println!("anim: {:?} {}", self.direction, frames); + + match self.direction { + FadeDirection::FadeIn => self.fade_in.tick(time), + FadeDirection::FadeOut => self.fade_out.tick(time), + } + } +} + #[derive(Clone, Debug)] pub enum Event { Brake, @@ -33,7 +218,7 @@ pub enum Event { RightBlinker, } -#[derive(Clone)] +#[derive(Clone, PartialEq)] pub enum State { Pattern(u8), Brake, @@ -46,6 +231,7 @@ pub enum State { pub struct App { ui: Box, state: State, + home_state: State, current_animation: Box, dashboard_lights: DashboardPattern, lights: Pattern, @@ -56,17 +242,103 @@ impl App { Self { ui, state: State::Pattern(0), + home_state: State::Pattern(0), current_animation: Box::new(DefaultAnimation {}), dashboard_lights: OFF_DASHBOARD, lights: OFF, } } + fn update_state(&mut self, time: std::time::Instant) { + match self.state { + State::Pattern(0) => { + self.current_animation = Box::new(Fade::new( + self.dashboard_lights.clone(), + self.lights.clone(), + PRIDE_DASHBOARD, + PRIDE, + DEFAULT_FRAMES, + time, + )) + } + State::Pattern(1) => { + self.current_animation = Box::new(Fade::new( + self.dashboard_lights.clone(), + self.lights.clone(), + TRANS_PRIDE_DASHBOARD, + TRANS_PRIDE, + DEFAULT_FRAMES, + time, + )) + } + State::Pattern(_) => {} + State::Brake => { + self.current_animation = Box::new(Fade::new( + self.dashboard_lights.clone(), + self.lights.clone(), + BRAKE_DASHBOARD, + BRAKES, + BRAKE_FRAMES, + time, + )); + } + State::LeftBlinker => { + self.current_animation = Box::new(LeftBlinker::new( + self.dashboard_lights.clone(), + self.lights.clone(), + time, + )); + } + State::RightBlinker => (), + State::BrakeLeftBlinker => (), + State::BrakeRightBlinker => (), + } + } + pub fn tick(&mut self, time: std::time::Instant) { match self.ui.check_event() { - Some(event) => println!("event received: {:?}", event), - None => (), + Some(event) => { + match event { + Event::Brake => { + if self.state == State::Brake { + self.state = self.home_state.clone(); + } else { + self.state = State::Brake; + } + } + Event::BrakeRelease => self.state = State::Pattern(0), + Event::LeftBlinker => match self.state { + State::Brake => self.state = State::BrakeLeftBlinker, + State::BrakeLeftBlinker => self.state = State::Brake, + State::LeftBlinker => self.state = self.home_state.clone(), + _ => self.state = State::LeftBlinker, + }, + Event::NextPattern => match self.state { + State::Pattern(i) => { + let next = i + 1; + self.state = State::Pattern(if next > 1 { 0 } else { next }); + self.home_state = self.state.clone(); + } + _ => (), + }, + Event::PreviousPattern => match self.state { + State::Pattern(i) => { + if i == 0 { + self.state = State::Pattern(1); + } else { + self.state = State::Pattern(i - 1); + } + self.home_state = self.state.clone(); + } + _ => (), + }, + Event::RightBlinker => {} + } + self.update_state(time); + } + None => {} }; + let (dashboard, lights) = self.current_animation.tick(time); self.dashboard_lights = dashboard.clone(); self.lights = lights.clone(); diff --git a/bike-lights/core/src/patterns.rs b/bike-lights/core/src/patterns.rs index 063b4df..697e087 100644 --- a/bike-lights/core/src/patterns.rs +++ b/bike-lights/core/src/patterns.rs @@ -1,7 +1,7 @@ use crate::RGB; -pub type DashboardPattern = [RGB; 3]; -pub type Pattern = [RGB; 60]; +pub type DashboardPattern = [RGB; 3]; +pub type Pattern = [RGB; 60]; pub const OFF_DASHBOARD: DashboardPattern = [ RGB { r: 0, g: 0, b: 0 }, @@ -72,17 +72,19 @@ pub const OFF: Pattern = [ RGB { r: 0, g: 0, b: 0 }, ]; +pub const DEFAULT_FRAMES: u8 = 30; + pub const PRIDE_DASHBOARD: DashboardPattern = [ RGB { r: 228, g: 3, b: 3 }, RGB { - r: 255, - g: 237, - b: 0, + r: 0, + g: 128, + b: 38, }, RGB { - r: 115, - g: 41, - b: 130, + r: 36, + g: 64, + b: 142, }, ]; @@ -669,3 +671,269 @@ pub const TRANS_PRIDE: Pattern = [ b: 250, }, ]; + +pub const BRAKE_FRAMES: u8 = 15; + +pub const BRAKE_DASHBOARD: DashboardPattern = [ + RGB { r: 128, g: 0, b: 0 }, + RGB { r: 128, g: 0, b: 0 }, + RGB { r: 128, g: 0, b: 0 }, +]; + +pub const BRAKES: Pattern = [ + RGB { r: 128, g: 0, b: 0 }, + RGB { r: 128, g: 0, b: 0 }, + RGB { r: 128, g: 0, b: 0 }, + RGB { r: 128, g: 0, b: 0 }, + RGB { r: 128, g: 0, b: 0 }, + RGB { r: 128, g: 0, b: 0 }, + RGB { r: 128, g: 0, b: 0 }, + RGB { r: 128, g: 0, b: 0 }, + RGB { r: 128, g: 0, b: 0 }, + RGB { r: 128, g: 0, b: 0 }, + RGB { r: 128, g: 0, b: 0 }, + RGB { r: 128, g: 0, b: 0 }, + RGB { r: 128, g: 0, b: 0 }, + RGB { r: 128, g: 0, b: 0 }, + RGB { r: 128, g: 0, b: 0 }, + RGB { r: 128, g: 0, b: 0 }, + RGB { r: 128, g: 0, b: 0 }, + RGB { r: 128, g: 0, b: 0 }, + RGB { r: 128, g: 0, b: 0 }, + RGB { r: 128, g: 0, b: 0 }, + RGB { r: 128, g: 0, b: 0 }, + RGB { r: 128, g: 0, b: 0 }, + RGB { r: 128, g: 0, b: 0 }, + RGB { r: 128, g: 0, b: 0 }, + RGB { r: 128, g: 0, b: 0 }, + RGB { r: 128, g: 0, b: 0 }, + RGB { r: 128, g: 0, b: 0 }, + RGB { r: 128, g: 0, b: 0 }, + RGB { r: 128, g: 0, b: 0 }, + RGB { r: 128, g: 0, b: 0 }, + RGB { r: 128, g: 0, b: 0 }, + RGB { r: 128, g: 0, b: 0 }, + RGB { r: 128, g: 0, b: 0 }, + RGB { r: 128, g: 0, b: 0 }, + RGB { r: 128, g: 0, b: 0 }, + RGB { r: 128, g: 0, b: 0 }, + RGB { r: 128, g: 0, b: 0 }, + RGB { r: 128, g: 0, b: 0 }, + RGB { r: 128, g: 0, b: 0 }, + RGB { r: 128, g: 0, b: 0 }, + RGB { r: 128, g: 0, b: 0 }, + RGB { r: 128, g: 0, b: 0 }, + RGB { r: 128, g: 0, b: 0 }, + RGB { r: 128, g: 0, b: 0 }, + RGB { r: 128, g: 0, b: 0 }, + RGB { r: 128, g: 0, b: 0 }, + RGB { r: 128, g: 0, b: 0 }, + RGB { r: 128, g: 0, b: 0 }, + RGB { r: 128, g: 0, b: 0 }, + RGB { r: 128, g: 0, b: 0 }, + RGB { r: 128, g: 0, b: 0 }, + RGB { r: 128, g: 0, b: 0 }, + RGB { r: 128, g: 0, b: 0 }, + RGB { r: 128, g: 0, b: 0 }, + RGB { r: 128, g: 0, b: 0 }, + RGB { r: 128, g: 0, b: 0 }, + RGB { r: 128, g: 0, b: 0 }, + RGB { r: 128, g: 0, b: 0 }, + RGB { r: 128, g: 0, b: 0 }, + RGB { r: 128, g: 0, b: 0 }, +]; + +pub const LEFT_FRAMES: u8 = 15; + +pub const LEFT_DASHBOARD: DashboardPattern = [ + RGB { + r: 255, + g: 191, + b: 0, + }, + RGB { r: 0, g: 0, b: 0 }, + RGB { r: 0, g: 0, b: 0 }, +]; + +pub const LEFT: Pattern = [ + RGB { + r: 255, + g: 191, + b: 0, + }, + RGB { + r: 255, + g: 191, + b: 0, + }, + RGB { + r: 255, + g: 191, + b: 0, + }, + RGB { + r: 255, + g: 191, + b: 0, + }, + RGB { + r: 255, + g: 191, + b: 0, + }, + RGB { + r: 255, + g: 191, + b: 0, + }, + RGB { + r: 255, + g: 191, + b: 0, + }, + RGB { + r: 255, + g: 191, + b: 0, + }, + RGB { + r: 255, + g: 191, + b: 0, + }, + RGB { + r: 255, + g: 191, + b: 0, + }, + RGB { + r: 255, + g: 191, + b: 0, + }, + RGB { + r: 255, + g: 191, + b: 0, + }, + RGB { + r: 255, + g: 191, + b: 0, + }, + RGB { + r: 255, + g: 191, + b: 0, + }, + RGB { + r: 255, + g: 191, + b: 0, + }, + RGB { + r: 255, + g: 191, + b: 0, + }, + RGB { + r: 255, + g: 191, + b: 0, + }, + RGB { + r: 255, + g: 191, + b: 0, + }, + RGB { + r: 255, + g: 191, + b: 0, + }, + RGB { + r: 255, + g: 191, + b: 0, + }, + RGB { + r: 255, + g: 191, + b: 0, + }, + RGB { + r: 255, + g: 191, + b: 0, + }, + RGB { + r: 255, + g: 191, + b: 0, + }, + RGB { + r: 255, + g: 191, + b: 0, + }, + RGB { + r: 255, + g: 191, + b: 0, + }, + RGB { + r: 255, + g: 191, + b: 0, + }, + RGB { + r: 255, + g: 191, + b: 0, + }, + RGB { + r: 255, + g: 191, + b: 0, + }, + RGB { + r: 255, + g: 191, + b: 0, + }, + RGB { + r: 255, + g: 191, + b: 0, + }, + RGB { r: 0, g: 0, b: 0 }, + RGB { r: 0, g: 0, b: 0 }, + RGB { r: 0, g: 0, b: 0 }, + RGB { r: 0, g: 0, b: 0 }, + RGB { r: 0, g: 0, b: 0 }, + RGB { r: 0, g: 0, b: 0 }, + RGB { r: 0, g: 0, b: 0 }, + RGB { r: 0, g: 0, b: 0 }, + RGB { r: 0, g: 0, b: 0 }, + RGB { r: 0, g: 0, b: 0 }, + RGB { r: 0, g: 0, b: 0 }, + RGB { r: 0, g: 0, b: 0 }, + RGB { r: 0, g: 0, b: 0 }, + RGB { r: 0, g: 0, b: 0 }, + RGB { r: 0, g: 0, b: 0 }, + RGB { r: 0, g: 0, b: 0 }, + RGB { r: 0, g: 0, b: 0 }, + RGB { r: 0, g: 0, b: 0 }, + RGB { r: 0, g: 0, b: 0 }, + RGB { r: 0, g: 0, b: 0 }, + RGB { r: 0, g: 0, b: 0 }, + RGB { r: 0, g: 0, b: 0 }, + RGB { r: 0, g: 0, b: 0 }, + RGB { r: 0, g: 0, b: 0 }, + RGB { r: 0, g: 0, b: 0 }, + RGB { r: 0, g: 0, b: 0 }, + RGB { r: 0, g: 0, b: 0 }, + RGB { r: 0, g: 0, b: 0 }, + RGB { r: 0, g: 0, b: 0 }, + RGB { r: 0, g: 0, b: 0 }, +]; diff --git a/bike-lights/core/src/types.rs b/bike-lights/core/src/types.rs index 07b1b8d..b3a8f4b 100644 --- a/bike-lights/core/src/types.rs +++ b/bike-lights/core/src/types.rs @@ -1,9 +1,9 @@ -#[derive(Clone)] -pub struct RGB { - pub r: u8, - pub g: u8, - pub b: u8, +#[derive(Clone, Default, Debug)] +pub struct RGB { + pub r: T, + pub g: T, + pub b: T, } -pub type DashboardPattern = [RGB; 3]; -pub type Pattern = [RGB; 60]; +pub type DashboardPattern = [RGB; 3]; +pub type Pattern = [RGB; 60]; diff --git a/bike-lights/simulator/src/main.rs b/bike-lights/simulator/src/main.rs index be422e2..edba09a 100644 --- a/bike-lights/simulator/src/main.rs +++ b/bike-lights/simulator/src/main.rs @@ -1,7 +1,7 @@ use adw::prelude::*; use glib::{Object, Sender}; use gtk::subclass::prelude::*; -use lights_core::{App, DashboardPattern, Event, Pattern, RGB, UI}; +use lights_core::{App, DashboardPattern, Event, Pattern, FPS, RGB, UI}; use std::{ cell::RefCell, env, @@ -73,7 +73,7 @@ impl DashboardLights { s } - pub fn set_lights(&self, lights: [RGB; 3]) { + pub fn set_lights(&self, lights: [RGB; 3]) { *self.imp().lights.borrow_mut() = lights; self.queue_draw(); } @@ -200,7 +200,7 @@ impl BikeLights { s } - pub fn set_lights(&self, lights: [RGB; 60]) { + pub fn set_lights(&self, lights: [RGB; 60]) { *self.imp().lights.borrow_mut() = lights; self.queue_draw(); } @@ -247,7 +247,7 @@ fn main() { })); loop { bike_app.tick(std::time::Instant::now()); - std::thread::sleep(std::time::Duration::from_millis(100)); + std::thread::sleep(std::time::Duration::from_millis(1000 / (FPS as u64))); } }); @@ -303,6 +303,20 @@ fn main() { let previous_pattern = gtk::Button::builder().label("Previous").build(); let next_pattern = gtk::Button::builder().label("Next").build(); + previous_pattern.connect_clicked({ + let event_tx = event_tx.clone(); + move |_| { + let _ = event_tx.send(Event::PreviousPattern); + } + }); + + next_pattern.connect_clicked({ + let event_tx = event_tx.clone(); + move |_| { + let _ = event_tx.send(Event::NextPattern); + } + }); + pattern_controls.append(&previous_pattern); pattern_controls.append(&next_pattern); layout.append(&pattern_controls); -- 2.44.1 From 22f0f9061c3a826ebe8a9e8e4b3c5cbb4bc7f840 Mon Sep 17 00:00:00 2001 From: Savanni D'Gerinel Date: Mon, 27 Nov 2023 09:37:36 -0500 Subject: [PATCH 05/16] Rotate the right side The actual bike is going to be a long loop which folds from the end of the left side to the back end of the right side. This requires that the colors get moved around for proper mirroring. --- bike-lights/core/src/lib.rs | 154 +++-- bike-lights/core/src/patterns.rs | 999 ++++++++++++++++++------------ bike-lights/simulator/src/main.rs | 8 +- 3 files changed, 714 insertions(+), 447 deletions(-) diff --git a/bike-lights/core/src/lib.rs b/bike-lights/core/src/lib.rs index d7ef41b..3573275 100644 --- a/bike-lights/core/src/lib.rs +++ b/bike-lights/core/src/lib.rs @@ -132,7 +132,12 @@ pub enum FadeDirection { FadeOut, } -pub struct LeftBlinker { +pub enum BlinkerDirection { + Left, + Right, +} + +pub struct Blinker { fade_in: Fade, fade_out: Fade, direction: FadeDirection, @@ -141,31 +146,53 @@ pub struct LeftBlinker { frames: u8, } -impl LeftBlinker { +impl Blinker { fn new( starting_dashboard: DashboardPattern, starting_body: Pattern, + direction: BlinkerDirection, time: std::time::Instant, ) -> Self { let mut ending_dashboard = starting_dashboard.clone(); - ending_dashboard[0].r = LEFT_DASHBOARD[0].r; - ending_dashboard[0].g = LEFT_DASHBOARD[0].g; - ending_dashboard[0].b = LEFT_DASHBOARD[0].b; - let mut ending_body = starting_body.clone(); - for i in 0..30 { - ending_body[i].r = LEFT[i].r; - ending_body[i].g = LEFT[i].g; - ending_body[i].b = LEFT[i].b; + match direction { + BlinkerDirection::Left => { + ending_dashboard[0].r = LEFT_DASHBOARD[0].r; + ending_dashboard[0].g = LEFT_DASHBOARD[0].g; + ending_dashboard[0].b = LEFT_DASHBOARD[0].b; + } + BlinkerDirection::Right => { + ending_dashboard[2].r = RIGHT_DASHBOARD[2].r; + ending_dashboard[2].g = RIGHT_DASHBOARD[2].g; + ending_dashboard[2].b = RIGHT_DASHBOARD[2].b; + } } - LeftBlinker { + let mut ending_body = starting_body.clone(); + match direction { + BlinkerDirection::Left => { + for i in 0..30 { + ending_body[i].r = LEFT[i].r; + ending_body[i].g = LEFT[i].g; + ending_body[i].b = LEFT[i].b; + } + } + BlinkerDirection::Right => { + for i in 30..60 { + ending_body[i].r = RIGHT[i].r; + ending_body[i].g = RIGHT[i].g; + ending_body[i].b = RIGHT[i].b; + } + } + } + + Blinker { fade_in: Fade::new( starting_dashboard.clone(), starting_body.clone(), ending_dashboard.clone(), ending_body.clone(), - LEFT_FRAMES, + BLINKER_FRAMES, time, ), fade_out: Fade::new( @@ -173,17 +200,17 @@ impl LeftBlinker { ending_body.clone(), starting_dashboard.clone(), starting_body.clone(), - LEFT_FRAMES, + BLINKER_FRAMES, time, ), direction: FadeDirection::FadeIn, start_time: time, - frames: LEFT_FRAMES, + frames: BLINKER_FRAMES, } } } -impl Animation for LeftBlinker { +impl Animation for Blinker { fn tick(&mut self, time: std::time::Instant) -> (DashboardPattern, Pattern) { let frames: u8 = ((time - self.start_time).as_millis() as f64 / FPS as f64) as u8; if frames > self.frames { @@ -249,7 +276,7 @@ impl App { } } - fn update_state(&mut self, time: std::time::Instant) { + fn update_animation(&mut self, time: std::time::Instant) { match self.state { State::Pattern(0) => { self.current_animation = Box::new(Fade::new( @@ -283,58 +310,75 @@ impl App { )); } State::LeftBlinker => { - self.current_animation = Box::new(LeftBlinker::new( + self.current_animation = Box::new(Blinker::new( self.dashboard_lights.clone(), self.lights.clone(), + BlinkerDirection::Left, + time, + )); + } + State::RightBlinker => { + self.current_animation = Box::new(Blinker::new( + self.dashboard_lights.clone(), + self.lights.clone(), + BlinkerDirection::Right, time, )); } - State::RightBlinker => (), State::BrakeLeftBlinker => (), State::BrakeRightBlinker => (), } } + fn update_state(&mut self, event: Event) { + match event { + Event::Brake => { + if self.state == State::Brake { + self.state = self.home_state.clone(); + } else { + self.state = State::Brake; + } + } + Event::BrakeRelease => self.state = self.home_state.clone(), + Event::LeftBlinker => match self.state { + State::Brake => self.state = State::BrakeLeftBlinker, + State::BrakeLeftBlinker => self.state = State::Brake, + State::LeftBlinker => self.state = self.home_state.clone(), + _ => self.state = State::LeftBlinker, + }, + Event::NextPattern => match self.state { + State::Pattern(i) => { + let next = i + 1; + self.state = State::Pattern(if next > 1 { 0 } else { next }); + self.home_state = self.state.clone(); + } + _ => (), + }, + Event::PreviousPattern => match self.state { + State::Pattern(i) => { + if i == 0 { + self.state = State::Pattern(1); + } else { + self.state = State::Pattern(i - 1); + } + self.home_state = self.state.clone(); + } + _ => (), + }, + Event::RightBlinker => match self.state { + State::Brake => self.state = State::BrakeRightBlinker, + State::BrakeRightBlinker => self.state = State::Brake, + State::RightBlinker => self.state = self.home_state.clone(), + _ => self.state = State::RightBlinker, + }, + } + } + pub fn tick(&mut self, time: std::time::Instant) { match self.ui.check_event() { Some(event) => { - match event { - Event::Brake => { - if self.state == State::Brake { - self.state = self.home_state.clone(); - } else { - self.state = State::Brake; - } - } - Event::BrakeRelease => self.state = State::Pattern(0), - Event::LeftBlinker => match self.state { - State::Brake => self.state = State::BrakeLeftBlinker, - State::BrakeLeftBlinker => self.state = State::Brake, - State::LeftBlinker => self.state = self.home_state.clone(), - _ => self.state = State::LeftBlinker, - }, - Event::NextPattern => match self.state { - State::Pattern(i) => { - let next = i + 1; - self.state = State::Pattern(if next > 1 { 0 } else { next }); - self.home_state = self.state.clone(); - } - _ => (), - }, - Event::PreviousPattern => match self.state { - State::Pattern(i) => { - if i == 0 { - self.state = State::Pattern(1); - } else { - self.state = State::Pattern(i - 1); - } - self.home_state = self.state.clone(); - } - _ => (), - }, - Event::RightBlinker => {} - } - self.update_state(time); + self.update_state(event); + self.update_animation(time); } None => {} }; diff --git a/bike-lights/core/src/patterns.rs b/bike-lights/core/src/patterns.rs index 697e087..767b835 100644 --- a/bike-lights/core/src/patterns.rs +++ b/bike-lights/core/src/patterns.rs @@ -89,16 +89,14 @@ pub const PRIDE_DASHBOARD: DashboardPattern = [ ]; pub const PRIDE: Pattern = [ + // Left Side + // Red RGB { r: 228, g: 3, b: 3 }, RGB { r: 228, g: 3, b: 3 }, RGB { r: 228, g: 3, b: 3 }, RGB { r: 228, g: 3, b: 3 }, RGB { r: 228, g: 3, b: 3 }, - RGB { r: 228, g: 3, b: 3 }, - RGB { r: 228, g: 3, b: 3 }, - RGB { r: 228, g: 3, b: 3 }, - RGB { r: 228, g: 3, b: 3 }, - RGB { r: 228, g: 3, b: 3 }, + // Orange RGB { r: 255, g: 140, @@ -124,6 +122,216 @@ pub const PRIDE: Pattern = [ g: 140, b: 0, }, + // Yellow + RGB { + r: 255, + g: 237, + b: 0, + }, + RGB { + r: 255, + g: 237, + b: 0, + }, + RGB { + r: 255, + g: 237, + b: 0, + }, + RGB { + r: 255, + g: 237, + b: 0, + }, + RGB { + r: 255, + g: 237, + b: 0, + }, + // Green + RGB { + r: 0, + g: 128, + b: 38, + }, + RGB { + r: 0, + g: 128, + b: 38, + }, + RGB { + r: 0, + g: 128, + b: 38, + }, + RGB { + r: 0, + g: 128, + b: 38, + }, + RGB { + r: 0, + g: 128, + b: 38, + }, + // Indigo + RGB { + r: 36, + g: 64, + b: 142, + }, + RGB { + r: 36, + g: 64, + b: 142, + }, + RGB { + r: 36, + g: 64, + b: 142, + }, + RGB { + r: 36, + g: 64, + b: 142, + }, + RGB { + r: 36, + g: 64, + b: 142, + }, + // Purple + RGB { + r: 115, + g: 41, + b: 130, + }, + RGB { + r: 115, + g: 41, + b: 130, + }, + RGB { + r: 115, + g: 41, + b: 130, + }, + RGB { + r: 115, + g: 41, + b: 130, + }, + RGB { + r: 115, + g: 41, + b: 130, + }, + // Right Side + // Purple + RGB { + r: 115, + g: 41, + b: 130, + }, + RGB { + r: 115, + g: 41, + b: 130, + }, + RGB { + r: 115, + g: 41, + b: 130, + }, + RGB { + r: 115, + g: 41, + b: 130, + }, + RGB { + r: 115, + g: 41, + b: 130, + }, + // Indigo + RGB { + r: 36, + g: 64, + b: 142, + }, + RGB { + r: 36, + g: 64, + b: 142, + }, + RGB { + r: 36, + g: 64, + b: 142, + }, + RGB { + r: 36, + g: 64, + b: 142, + }, + RGB { + r: 36, + g: 64, + b: 142, + }, + // Green + RGB { + r: 0, + g: 128, + b: 38, + }, + RGB { + r: 0, + g: 128, + b: 38, + }, + RGB { + r: 0, + g: 128, + b: 38, + }, + RGB { + r: 0, + g: 128, + b: 38, + }, + RGB { + r: 0, + g: 128, + b: 38, + }, + // Yellow + RGB { + r: 255, + g: 237, + b: 0, + }, + RGB { + r: 255, + g: 237, + b: 0, + }, + RGB { + r: 255, + g: 237, + b: 0, + }, + RGB { + r: 255, + g: 237, + b: 0, + }, + RGB { + r: 255, + g: 237, + b: 0, + }, + // Orange RGB { r: 255, g: 140, @@ -149,206 +357,12 @@ pub const PRIDE: Pattern = [ g: 140, b: 0, }, - RGB { - r: 255, - g: 237, - b: 0, - }, - RGB { - r: 255, - g: 237, - b: 0, - }, - RGB { - r: 255, - g: 237, - b: 0, - }, - RGB { - r: 255, - g: 237, - b: 0, - }, - RGB { - r: 255, - g: 237, - b: 0, - }, - RGB { - r: 255, - g: 237, - b: 0, - }, - RGB { - r: 255, - g: 237, - b: 0, - }, - RGB { - r: 255, - g: 237, - b: 0, - }, - RGB { - r: 255, - g: 237, - b: 0, - }, - RGB { - r: 255, - g: 237, - b: 0, - }, - RGB { - r: 0, - g: 128, - b: 38, - }, - RGB { - r: 0, - g: 128, - b: 38, - }, - RGB { - r: 0, - g: 128, - b: 38, - }, - RGB { - r: 0, - g: 128, - b: 38, - }, - RGB { - r: 0, - g: 128, - b: 38, - }, - RGB { - r: 0, - g: 128, - b: 38, - }, - RGB { - r: 0, - g: 128, - b: 38, - }, - RGB { - r: 0, - g: 128, - b: 38, - }, - RGB { - r: 0, - g: 128, - b: 38, - }, - RGB { - r: 0, - g: 128, - b: 38, - }, - RGB { - r: 36, - g: 64, - b: 142, - }, - RGB { - r: 36, - g: 64, - b: 142, - }, - RGB { - r: 36, - g: 64, - b: 142, - }, - RGB { - r: 36, - g: 64, - b: 142, - }, - RGB { - r: 36, - g: 64, - b: 142, - }, - RGB { - r: 36, - g: 64, - b: 142, - }, - RGB { - r: 36, - g: 64, - b: 142, - }, - RGB { - r: 36, - g: 64, - b: 142, - }, - RGB { - r: 36, - g: 64, - b: 142, - }, - RGB { - r: 36, - g: 64, - b: 142, - }, - RGB { - r: 115, - g: 41, - b: 130, - }, - RGB { - r: 115, - g: 41, - b: 130, - }, - RGB { - r: 115, - g: 41, - b: 130, - }, - RGB { - r: 115, - g: 41, - b: 130, - }, - RGB { - r: 115, - g: 41, - b: 130, - }, - RGB { - r: 115, - g: 41, - b: 130, - }, - RGB { - r: 115, - g: 41, - b: 130, - }, - RGB { - r: 115, - g: 41, - b: 130, - }, - RGB { - r: 115, - g: 41, - b: 130, - }, - RGB { - r: 115, - g: 41, - b: 130, - }, + // Red + RGB { r: 228, g: 3, b: 3 }, + RGB { r: 228, g: 3, b: 3 }, + RGB { r: 228, g: 3, b: 3 }, + RGB { r: 228, g: 3, b: 3 }, + RGB { r: 228, g: 3, b: 3 }, ]; pub const TRANS_PRIDE_DASHBOARD: DashboardPattern = [ @@ -370,6 +384,8 @@ pub const TRANS_PRIDE_DASHBOARD: DashboardPattern = [ ]; pub const TRANS_PRIDE: Pattern = [ + // Left Side + // Light Blue RGB { r: 91, g: 206, @@ -400,66 +416,7 @@ pub const TRANS_PRIDE: Pattern = [ g: 206, b: 250, }, - RGB { - r: 91, - g: 206, - b: 250, - }, - RGB { - r: 91, - g: 206, - b: 250, - }, - RGB { - r: 91, - g: 206, - b: 250, - }, - RGB { - r: 91, - g: 206, - b: 250, - }, - RGB { - r: 91, - g: 206, - b: 250, - }, - RGB { - r: 91, - g: 206, - b: 250, - }, - RGB { - r: 245, - g: 169, - b: 184, - }, - RGB { - r: 245, - g: 169, - b: 184, - }, - RGB { - r: 245, - g: 169, - b: 184, - }, - RGB { - r: 245, - g: 169, - b: 184, - }, - RGB { - r: 245, - g: 169, - b: 184, - }, - RGB { - r: 245, - g: 169, - b: 184, - }, + // Light Pink RGB { r: 245, g: 169, @@ -490,6 +447,7 @@ pub const TRANS_PRIDE: Pattern = [ g: 169, b: 184, }, + // White RGB { r: 255, g: 255, @@ -520,66 +478,7 @@ pub const TRANS_PRIDE: Pattern = [ g: 255, b: 255, }, - RGB { - r: 255, - g: 255, - b: 255, - }, - RGB { - r: 255, - g: 255, - b: 255, - }, - RGB { - r: 255, - g: 255, - b: 255, - }, - RGB { - r: 255, - g: 255, - b: 255, - }, - RGB { - r: 255, - g: 255, - b: 255, - }, - RGB { - r: 255, - g: 255, - b: 255, - }, - RGB { - r: 245, - g: 169, - b: 184, - }, - RGB { - r: 245, - g: 169, - b: 184, - }, - RGB { - r: 245, - g: 169, - b: 184, - }, - RGB { - r: 245, - g: 169, - b: 184, - }, - RGB { - r: 245, - g: 169, - b: 184, - }, - RGB { - r: 245, - g: 169, - b: 184, - }, + // Light Pink RGB { r: 245, g: 169, @@ -610,6 +509,7 @@ pub const TRANS_PRIDE: Pattern = [ g: 169, b: 184, }, + // Light Blue RGB { r: 91, g: 206, @@ -640,6 +540,132 @@ pub const TRANS_PRIDE: Pattern = [ g: 206, b: 250, }, + // Right side + // Light Blue + RGB { + r: 91, + g: 206, + b: 250, + }, + RGB { + r: 91, + g: 206, + b: 250, + }, + RGB { + r: 91, + g: 206, + b: 250, + }, + RGB { + r: 91, + g: 206, + b: 250, + }, + RGB { + r: 91, + g: 206, + b: 250, + }, + RGB { + r: 91, + g: 206, + b: 250, + }, + // Light Pink + RGB { + r: 245, + g: 169, + b: 184, + }, + RGB { + r: 245, + g: 169, + b: 184, + }, + RGB { + r: 245, + g: 169, + b: 184, + }, + RGB { + r: 245, + g: 169, + b: 184, + }, + RGB { + r: 245, + g: 169, + b: 184, + }, + RGB { + r: 245, + g: 169, + b: 184, + }, + // White + RGB { + r: 255, + g: 255, + b: 255, + }, + RGB { + r: 255, + g: 255, + b: 255, + }, + RGB { + r: 255, + g: 255, + b: 255, + }, + RGB { + r: 255, + g: 255, + b: 255, + }, + RGB { + r: 255, + g: 255, + b: 255, + }, + RGB { + r: 255, + g: 255, + b: 255, + }, + // Light Pink + RGB { + r: 245, + g: 169, + b: 184, + }, + RGB { + r: 245, + g: 169, + b: 184, + }, + RGB { + r: 245, + g: 169, + b: 184, + }, + RGB { + r: 245, + g: 169, + b: 184, + }, + RGB { + r: 245, + g: 169, + b: 184, + }, + RGB { + r: 245, + g: 169, + b: 184, + }, + // Light Blue RGB { r: 91, g: 206, @@ -675,75 +701,75 @@ pub const TRANS_PRIDE: Pattern = [ pub const BRAKE_FRAMES: u8 = 15; pub const BRAKE_DASHBOARD: DashboardPattern = [ - RGB { r: 128, g: 0, b: 0 }, - RGB { r: 128, g: 0, b: 0 }, - RGB { r: 128, g: 0, b: 0 }, + RGB { r: 255, g: 0, b: 0 }, + RGB { r: 255, g: 0, b: 0 }, + RGB { r: 255, g: 0, b: 0 }, ]; pub const BRAKES: Pattern = [ - RGB { r: 128, g: 0, b: 0 }, - RGB { r: 128, g: 0, b: 0 }, - RGB { r: 128, g: 0, b: 0 }, - RGB { r: 128, g: 0, b: 0 }, - RGB { r: 128, g: 0, b: 0 }, - RGB { r: 128, g: 0, b: 0 }, - RGB { r: 128, g: 0, b: 0 }, - RGB { r: 128, g: 0, b: 0 }, - RGB { r: 128, g: 0, b: 0 }, - RGB { r: 128, g: 0, b: 0 }, - RGB { r: 128, g: 0, b: 0 }, - RGB { r: 128, g: 0, b: 0 }, - RGB { r: 128, g: 0, b: 0 }, - RGB { r: 128, g: 0, b: 0 }, - RGB { r: 128, g: 0, b: 0 }, - RGB { r: 128, g: 0, b: 0 }, - RGB { r: 128, g: 0, b: 0 }, - RGB { r: 128, g: 0, b: 0 }, - RGB { r: 128, g: 0, b: 0 }, - RGB { r: 128, g: 0, b: 0 }, - RGB { r: 128, g: 0, b: 0 }, - RGB { r: 128, g: 0, b: 0 }, - RGB { r: 128, g: 0, b: 0 }, - RGB { r: 128, g: 0, b: 0 }, - RGB { r: 128, g: 0, b: 0 }, - RGB { r: 128, g: 0, b: 0 }, - RGB { r: 128, g: 0, b: 0 }, - RGB { r: 128, g: 0, b: 0 }, - RGB { r: 128, g: 0, b: 0 }, - RGB { r: 128, g: 0, b: 0 }, - RGB { r: 128, g: 0, b: 0 }, - RGB { r: 128, g: 0, b: 0 }, - RGB { r: 128, g: 0, b: 0 }, - RGB { r: 128, g: 0, b: 0 }, - RGB { r: 128, g: 0, b: 0 }, - RGB { r: 128, g: 0, b: 0 }, - RGB { r: 128, g: 0, b: 0 }, - RGB { r: 128, g: 0, b: 0 }, - RGB { r: 128, g: 0, b: 0 }, - RGB { r: 128, g: 0, b: 0 }, - RGB { r: 128, g: 0, b: 0 }, - RGB { r: 128, g: 0, b: 0 }, - RGB { r: 128, g: 0, b: 0 }, - RGB { r: 128, g: 0, b: 0 }, - RGB { r: 128, g: 0, b: 0 }, - RGB { r: 128, g: 0, b: 0 }, - RGB { r: 128, g: 0, b: 0 }, - RGB { r: 128, g: 0, b: 0 }, - RGB { r: 128, g: 0, b: 0 }, - RGB { r: 128, g: 0, b: 0 }, - RGB { r: 128, g: 0, b: 0 }, - RGB { r: 128, g: 0, b: 0 }, - RGB { r: 128, g: 0, b: 0 }, - RGB { r: 128, g: 0, b: 0 }, - RGB { r: 128, g: 0, b: 0 }, - RGB { r: 128, g: 0, b: 0 }, - RGB { r: 128, g: 0, b: 0 }, - RGB { r: 128, g: 0, b: 0 }, - RGB { r: 128, g: 0, b: 0 }, - RGB { r: 128, g: 0, b: 0 }, + RGB { r: 255, g: 0, b: 0 }, + RGB { r: 255, g: 0, b: 0 }, + RGB { r: 255, g: 0, b: 0 }, + RGB { r: 255, g: 0, b: 0 }, + RGB { r: 255, g: 0, b: 0 }, + RGB { r: 255, g: 0, b: 0 }, + RGB { r: 255, g: 0, b: 0 }, + RGB { r: 255, g: 0, b: 0 }, + RGB { r: 255, g: 0, b: 0 }, + RGB { r: 255, g: 0, b: 0 }, + RGB { r: 255, g: 0, b: 0 }, + RGB { r: 255, g: 0, b: 0 }, + RGB { r: 255, g: 0, b: 0 }, + RGB { r: 255, g: 0, b: 0 }, + RGB { r: 255, g: 0, b: 0 }, + RGB { r: 255, g: 0, b: 0 }, + RGB { r: 255, g: 0, b: 0 }, + RGB { r: 255, g: 0, b: 0 }, + RGB { r: 255, g: 0, b: 0 }, + RGB { r: 255, g: 0, b: 0 }, + RGB { r: 255, g: 0, b: 0 }, + RGB { r: 255, g: 0, b: 0 }, + RGB { r: 255, g: 0, b: 0 }, + RGB { r: 255, g: 0, b: 0 }, + RGB { r: 255, g: 0, b: 0 }, + RGB { r: 255, g: 0, b: 0 }, + RGB { r: 255, g: 0, b: 0 }, + RGB { r: 255, g: 0, b: 0 }, + RGB { r: 255, g: 0, b: 0 }, + RGB { r: 255, g: 0, b: 0 }, + RGB { r: 255, g: 0, b: 0 }, + RGB { r: 255, g: 0, b: 0 }, + RGB { r: 255, g: 0, b: 0 }, + RGB { r: 255, g: 0, b: 0 }, + RGB { r: 255, g: 0, b: 0 }, + RGB { r: 255, g: 0, b: 0 }, + RGB { r: 255, g: 0, b: 0 }, + RGB { r: 255, g: 0, b: 0 }, + RGB { r: 255, g: 0, b: 0 }, + RGB { r: 255, g: 0, b: 0 }, + RGB { r: 255, g: 0, b: 0 }, + RGB { r: 255, g: 0, b: 0 }, + RGB { r: 255, g: 0, b: 0 }, + RGB { r: 255, g: 0, b: 0 }, + RGB { r: 255, g: 0, b: 0 }, + RGB { r: 255, g: 0, b: 0 }, + RGB { r: 255, g: 0, b: 0 }, + RGB { r: 255, g: 0, b: 0 }, + RGB { r: 255, g: 0, b: 0 }, + RGB { r: 255, g: 0, b: 0 }, + RGB { r: 255, g: 0, b: 0 }, + RGB { r: 255, g: 0, b: 0 }, + RGB { r: 255, g: 0, b: 0 }, + RGB { r: 255, g: 0, b: 0 }, + RGB { r: 255, g: 0, b: 0 }, + RGB { r: 255, g: 0, b: 0 }, + RGB { r: 255, g: 0, b: 0 }, + RGB { r: 255, g: 0, b: 0 }, + RGB { r: 255, g: 0, b: 0 }, + RGB { r: 255, g: 0, b: 0 }, ]; -pub const LEFT_FRAMES: u8 = 15; +pub const BLINKER_FRAMES: u8 = 15; pub const LEFT_DASHBOARD: DashboardPattern = [ RGB { @@ -937,3 +963,198 @@ pub const LEFT: Pattern = [ RGB { r: 0, g: 0, b: 0 }, RGB { r: 0, g: 0, b: 0 }, ]; + +pub const RIGHT_FRAMES: u8 = 15; + +pub const RIGHT_DASHBOARD: DashboardPattern = [ + RGB { r: 0, g: 0, b: 0 }, + RGB { r: 0, g: 0, b: 0 }, + RGB { + r: 255, + g: 191, + b: 0, + }, +]; + +pub const RIGHT: Pattern = [ + RGB { r: 0, g: 0, b: 0 }, + RGB { r: 0, g: 0, b: 0 }, + RGB { r: 0, g: 0, b: 0 }, + RGB { r: 0, g: 0, b: 0 }, + RGB { r: 0, g: 0, b: 0 }, + RGB { r: 0, g: 0, b: 0 }, + RGB { r: 0, g: 0, b: 0 }, + RGB { r: 0, g: 0, b: 0 }, + RGB { r: 0, g: 0, b: 0 }, + RGB { r: 0, g: 0, b: 0 }, + RGB { r: 0, g: 0, b: 0 }, + RGB { r: 0, g: 0, b: 0 }, + RGB { r: 0, g: 0, b: 0 }, + RGB { r: 0, g: 0, b: 0 }, + RGB { r: 0, g: 0, b: 0 }, + RGB { r: 0, g: 0, b: 0 }, + RGB { r: 0, g: 0, b: 0 }, + RGB { r: 0, g: 0, b: 0 }, + RGB { r: 0, g: 0, b: 0 }, + RGB { r: 0, g: 0, b: 0 }, + RGB { r: 0, g: 0, b: 0 }, + RGB { r: 0, g: 0, b: 0 }, + RGB { r: 0, g: 0, b: 0 }, + RGB { r: 0, g: 0, b: 0 }, + RGB { r: 0, g: 0, b: 0 }, + RGB { r: 0, g: 0, b: 0 }, + RGB { r: 0, g: 0, b: 0 }, + RGB { r: 0, g: 0, b: 0 }, + RGB { r: 0, g: 0, b: 0 }, + RGB { r: 0, g: 0, b: 0 }, + RGB { + r: 255, + g: 191, + b: 0, + }, + RGB { + r: 255, + g: 191, + b: 0, + }, + RGB { + r: 255, + g: 191, + b: 0, + }, + RGB { + r: 255, + g: 191, + b: 0, + }, + RGB { + r: 255, + g: 191, + b: 0, + }, + RGB { + r: 255, + g: 191, + b: 0, + }, + RGB { + r: 255, + g: 191, + b: 0, + }, + RGB { + r: 255, + g: 191, + b: 0, + }, + RGB { + r: 255, + g: 191, + b: 0, + }, + RGB { + r: 255, + g: 191, + b: 0, + }, + RGB { + r: 255, + g: 191, + b: 0, + }, + RGB { + r: 255, + g: 191, + b: 0, + }, + RGB { + r: 255, + g: 191, + b: 0, + }, + RGB { + r: 255, + g: 191, + b: 0, + }, + RGB { + r: 255, + g: 191, + b: 0, + }, + RGB { + r: 255, + g: 191, + b: 0, + }, + RGB { + r: 255, + g: 191, + b: 0, + }, + RGB { + r: 255, + g: 191, + b: 0, + }, + RGB { + r: 255, + g: 191, + b: 0, + }, + RGB { + r: 255, + g: 191, + b: 0, + }, + RGB { + r: 255, + g: 191, + b: 0, + }, + RGB { + r: 255, + g: 191, + b: 0, + }, + RGB { + r: 255, + g: 191, + b: 0, + }, + RGB { + r: 255, + g: 191, + b: 0, + }, + RGB { + r: 255, + g: 191, + b: 0, + }, + RGB { + r: 255, + g: 191, + b: 0, + }, + RGB { + r: 255, + g: 191, + b: 0, + }, + RGB { + r: 255, + g: 191, + b: 0, + }, + RGB { + r: 255, + g: 191, + b: 0, + }, + RGB { + r: 255, + g: 191, + b: 0, + }, +]; diff --git a/bike-lights/simulator/src/main.rs b/bike-lights/simulator/src/main.rs index edba09a..11a547c 100644 --- a/bike-lights/simulator/src/main.rs +++ b/bike-lights/simulator/src/main.rs @@ -170,7 +170,9 @@ impl BikeLights { let s: Self = Object::builder().build(); s.set_width_request(WIDTH); - s.set_height_request(200); + s.set_height_request(640); + + let center = WIDTH as f64 / 2.; s.set_draw_func({ let s = s.clone(); @@ -182,7 +184,7 @@ impl BikeLights { lights[i].g as f64 / 256., lights[i].b as f64 / 256., ); - context.rectangle(5. + 20. * i as f64, 5., 15., 15.); + context.rectangle(center - 45., 5. + 20. * i as f64, 15., 15.); let _ = context.fill(); } for i in 0..30 { @@ -191,7 +193,7 @@ impl BikeLights { lights[i + 30].g as f64 / 256., lights[i + 30].b as f64 / 256., ); - context.rectangle(5. + 20. * i as f64, 30., 15., 15.); + context.rectangle(center + 15., 5. + 20. * (30. - (i + 1) as f64), 15., 15.); let _ = context.fill(); } } -- 2.44.1 From 6164cb3b39a38b8ae6b237a20e4aebd16355e126 Mon Sep 17 00:00:00 2001 From: Savanni D'Gerinel Date: Mon, 27 Nov 2023 18:51:36 -0500 Subject: [PATCH 06/16] Refactor the bike library until it compiles with no_std Theoretically, this is the first step to getting to running on the pico --- Cargo.lock | 13 +++++++ Cargo.toml | 1 + bike-lights/bike/.cargo/config | 12 +++++++ bike-lights/bike/Cargo.toml | 15 +++++++++ bike-lights/bike/src/main.rs | 10 ++++++ bike-lights/core/src/lib.rs | 56 +++++++++++++++++++------------ bike-lights/core/src/types.rs | 34 ++++++++++++++++++- bike-lights/simulator/src/main.rs | 9 +++-- 8 files changed, 126 insertions(+), 24 deletions(-) create mode 100644 bike-lights/bike/.cargo/config create mode 100644 bike-lights/bike/Cargo.toml create mode 100644 bike-lights/bike/src/main.rs diff --git a/Cargo.lock b/Cargo.lock index 886e4a5..c3142d1 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -373,6 +373,19 @@ version = "1.6.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "8c3c1a368f70d6cf7302d78f8f7093da241fb8e8807c05cc9e51a125895a6d5b" +[[package]] +name = "bike" +version = "0.1.0" +dependencies = [ + "cortex-m", + "cortex-m-rt", + "embedded-hal", + "fugit", + "lights-core", + "panic-halt", + "rp-pico", +] + [[package]] name = "bit-set" version = "0.5.3" diff --git a/Cargo.toml b/Cargo.toml index 47cc89e..fe7eceb 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -2,6 +2,7 @@ resolver = "2" members = [ "authdb", + "bike-lights/bike", "bike-lights/core", "bike-lights/simulator", "changeset", diff --git a/bike-lights/bike/.cargo/config b/bike-lights/bike/.cargo/config new file mode 100644 index 0000000..ef4d7f1 --- /dev/null +++ b/bike-lights/bike/.cargo/config @@ -0,0 +1,12 @@ +[build] +target = "thumbv6m-none-eabi" + +[target.thumbv6m-none-eabi] +rustflags = [ + "-C", "link-arg=--nmagic", + "-C", "link-arg=-Tlink.x", + "-C", "inline-threshold=5", + "-C", "no-vectorize-loops", +] + +runner = "elf2uf2-rs -d" diff --git a/bike-lights/bike/Cargo.toml b/bike-lights/bike/Cargo.toml new file mode 100644 index 0000000..80fc201 --- /dev/null +++ b/bike-lights/bike/Cargo.toml @@ -0,0 +1,15 @@ +[package] +name = "bike" +version = "0.1.0" +edition = "2021" + +# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html + +[dependencies] +cortex-m = "0.7.7" +cortex-m-rt = "0.7.3" +embedded-hal = "0.2.7" +fugit = "0.3.7" +panic-halt = "0.2.0" +rp-pico = "0.8.0" +lights-core = { path = "../core" } diff --git a/bike-lights/bike/src/main.rs b/bike-lights/bike/src/main.rs new file mode 100644 index 0000000..824e3b4 --- /dev/null +++ b/bike-lights/bike/src/main.rs @@ -0,0 +1,10 @@ +#![no_main] +#![no_std] + +use panic_halt as _; +use rp_pico::entry; + +#[entry] +fn main() -> ! { + loop {} +} diff --git a/bike-lights/core/src/lib.rs b/bike-lights/core/src/lib.rs index 3573275..ab87421 100644 --- a/bike-lights/core/src/lib.rs +++ b/bike-lights/core/src/lib.rs @@ -1,9 +1,26 @@ +#![no_std] + +extern crate alloc; +use alloc::boxed::Box; +use core::{clone::Clone, cmp::PartialEq, ops::Sub, option::Option}; + mod patterns; pub use patterns::*; mod types; pub use types::{DashboardPattern, Pattern, RGB}; +#[derive(Clone, Copy)] +pub struct Instant(pub u128); + +impl Sub for Instant { + type Output = Self; + + fn sub(self, r: Self) -> Self::Output { + Self(self.0 - r.0) + } +} + pub const FPS: u8 = 30; pub trait UI { @@ -12,13 +29,13 @@ pub trait UI { } pub trait Animation { - fn tick(&mut self, time: std::time::Instant) -> (DashboardPattern, Pattern); + fn tick(&mut self, time: Instant) -> (DashboardPattern, Pattern); } pub struct DefaultAnimation {} impl Animation for DefaultAnimation { - fn tick(&mut self, _: std::time::Instant) -> (DashboardPattern, Pattern) { + fn tick(&mut self, _: Instant) -> (DashboardPattern, Pattern) { (PRIDE_DASHBOARD, PRIDE) } } @@ -27,9 +44,9 @@ pub struct Fade { starting_dashboard: DashboardPattern, starting_lights: Pattern, - start_time: std::time::Instant, - dashboard_slope: Vec>, - body_slope: Vec>, + start_time: Instant, + dashboard_slope: [RGB; 3], + body_slope: [RGB; 60], frames: u8, } @@ -40,17 +57,17 @@ impl Fade { ending_dashboard: DashboardPattern, ending_lights: Pattern, frames: u8, - time: std::time::Instant, + time: Instant, ) -> Self { - let mut dashboard_slope = Vec::new(); - let mut body_slope = Vec::new(); + let mut dashboard_slope = [Default::default(); 3]; + let mut body_slope = [Default::default(); 60]; for i in 0..3 { let slope = RGB { r: (ending_dashboard[i].r as f64 - dashboard[i].r as f64) / frames as f64, g: (ending_dashboard[i].g as f64 - dashboard[i].g as f64) / frames as f64, b: (ending_dashboard[i].b as f64 - dashboard[i].b as f64) / frames as f64, }; - dashboard_slope.push(slope); + dashboard_slope[i] = slope; } for i in 0..60 { @@ -59,11 +76,9 @@ impl Fade { g: (ending_lights[i].g as f64 - lights[i].g as f64) / frames as f64, b: (ending_lights[i].b as f64 - lights[i].b as f64) / frames as f64, }; - body_slope.push(slope); + body_slope[i] = slope; } - println!("dashboard slope: {:?}", dashboard_slope); - Self { starting_dashboard: dashboard, starting_lights: lights, @@ -76,8 +91,8 @@ impl Fade { } impl Animation for Fade { - fn tick(&mut self, time: std::time::Instant) -> (DashboardPattern, Pattern) { - let mut frames: u8 = ((time - self.start_time).as_millis() as f64 / FPS as f64) as u8; + fn tick(&mut self, time: Instant) -> (DashboardPattern, Pattern) { + let mut frames: u8 = ((time - self.start_time).0 as f64 / FPS as f64) as u8; if frames > self.frames { frames = self.frames } @@ -142,7 +157,7 @@ pub struct Blinker { fade_out: Fade, direction: FadeDirection, - start_time: std::time::Instant, + start_time: Instant, frames: u8, } @@ -151,7 +166,7 @@ impl Blinker { starting_dashboard: DashboardPattern, starting_body: Pattern, direction: BlinkerDirection, - time: std::time::Instant, + time: Instant, ) -> Self { let mut ending_dashboard = starting_dashboard.clone(); @@ -211,8 +226,8 @@ impl Blinker { } impl Animation for Blinker { - fn tick(&mut self, time: std::time::Instant) -> (DashboardPattern, Pattern) { - let frames: u8 = ((time - self.start_time).as_millis() as f64 / FPS as f64) as u8; + fn tick(&mut self, time: Instant) -> (DashboardPattern, Pattern) { + let frames: u8 = ((time - self.start_time).0 as f64 / FPS as f64) as u8; if frames > self.frames { match self.direction { FadeDirection::FadeIn => { @@ -226,7 +241,6 @@ impl Animation for Blinker { } self.start_time = time; } - println!("anim: {:?} {}", self.direction, frames); match self.direction { FadeDirection::FadeIn => self.fade_in.tick(time), @@ -276,7 +290,7 @@ impl App { } } - fn update_animation(&mut self, time: std::time::Instant) { + fn update_animation(&mut self, time: Instant) { match self.state { State::Pattern(0) => { self.current_animation = Box::new(Fade::new( @@ -374,7 +388,7 @@ impl App { } } - pub fn tick(&mut self, time: std::time::Instant) { + pub fn tick(&mut self, time: Instant) { match self.ui.check_event() { Some(event) => { self.update_state(event); diff --git a/bike-lights/core/src/types.rs b/bike-lights/core/src/types.rs index b3a8f4b..145b515 100644 --- a/bike-lights/core/src/types.rs +++ b/bike-lights/core/src/types.rs @@ -1,4 +1,6 @@ -#[derive(Clone, Default, Debug)] +use core::default::Default; + +#[derive(Clone, Copy, Default, Debug)] pub struct RGB { pub r: T, pub g: T, @@ -6,4 +8,34 @@ pub struct RGB { } pub type DashboardPattern = [RGB; 3]; +/* +#[derive(Clone)] +pub struct DashboardPattern(pub [RGB; 3]); +*/ + +/* +impl Clone for DashboardPattern { + fn clone(&self) -> Self { + let mut v: [RGB; 3] = Default::default(); + for i in 0..3 { + v[i] = self.0[i] + } + Self(v) + } +} +*/ + pub type Pattern = [RGB; 60]; +/* +pub struct Pattern(pub [RGB; 60]); + +impl Pattern { + pub fn clone(&self) -> Self { + let mut v: [RGB; 60] = [Default::default(); 60]; + for i in 0..60 { + v[i] = self.0[i] + } + Self(v) + } +} +*/ diff --git a/bike-lights/simulator/src/main.rs b/bike-lights/simulator/src/main.rs index 11a547c..64d5222 100644 --- a/bike-lights/simulator/src/main.rs +++ b/bike-lights/simulator/src/main.rs @@ -1,7 +1,7 @@ use adw::prelude::*; use glib::{Object, Sender}; use gtk::subclass::prelude::*; -use lights_core::{App, DashboardPattern, Event, Pattern, FPS, RGB, UI}; +use lights_core::{App, DashboardPattern, Event, Instant, Pattern, FPS, RGB, UI}; use std::{ cell::RefCell, env, @@ -248,7 +248,12 @@ fn main() { rx: event_rx, })); loop { - bike_app.tick(std::time::Instant::now()); + bike_app.tick(Instant( + (std::time::SystemTime::now() + .duration_since(std::time::UNIX_EPOCH) + .unwrap()) + .as_millis(), + )); std::thread::sleep(std::time::Duration::from_millis(1000 / (FPS as u64))); } }); -- 2.44.1 From 0b949111d20f68331dbecb47d1e69580b9495105 Mon Sep 17 00:00:00 2001 From: Savanni D'Gerinel Date: Mon, 27 Nov 2023 20:35:45 -0500 Subject: [PATCH 07/16] Switch to a fixed point arithmatic library --- Cargo.lock | 4 + bike-lights/core/Cargo.toml | 2 + bike-lights/core/src/lib.rs | 160 ++-- bike-lights/core/src/patterns.rs | 1413 ++++++----------------------- bike-lights/core/src/types.rs | 34 +- bike-lights/simulator/src/main.rs | 112 +-- 6 files changed, 401 insertions(+), 1324 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index c3142d1..2d6a554 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -2337,6 +2337,10 @@ dependencies = [ [[package]] name = "lights-core" version = "0.1.0" +dependencies = [ + "az", + "fixed", +] [[package]] name = "linux-raw-sys" diff --git a/bike-lights/core/Cargo.toml b/bike-lights/core/Cargo.toml index 4c709a8..be3f09e 100644 --- a/bike-lights/core/Cargo.toml +++ b/bike-lights/core/Cargo.toml @@ -6,3 +6,5 @@ edition = "2021" # See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html [dependencies] +az = { version = "1" } +fixed = { version = "1" } diff --git a/bike-lights/core/src/lib.rs b/bike-lights/core/src/lib.rs index ab87421..c8523eb 100644 --- a/bike-lights/core/src/lib.rs +++ b/bike-lights/core/src/lib.rs @@ -2,16 +2,33 @@ extern crate alloc; use alloc::boxed::Box; +use az::*; use core::{clone::Clone, cmp::PartialEq, ops::Sub, option::Option}; +use fixed::types::{I16F0, I16F16, I48F16, I8F8, U128F0, U16F0}; mod patterns; pub use patterns::*; mod types; -pub use types::{DashboardPattern, Pattern, RGB}; +pub use types::{BodyPattern, DashboardPattern, RGB}; + +fn calculate_frames(starting_time: U128F0, now: U128F0) -> U16F0 { + let frames_128 = (now - starting_time) / U128F0::from(FPS); + (frames_128 % U128F0::from(U16F0::MAX)).cast() +} + +fn calculate_slope(start: I8F8, end: I8F8, frames: U16F0) -> I8F8 { + let slope_i16f16 = (I48F16::from(end) - I48F16::from(start)) / I48F16::from(frames); + slope_i16f16.saturating_as() +} + +fn linear_ease(value: I8F8, frames: U16F0, slope: I8F8) -> I8F8 { + let value_i16f16 = I48F16::from(value) + I48F16::from(frames) * I48F16::from(slope); + value_i16f16.saturating_as() +} #[derive(Clone, Copy)] -pub struct Instant(pub u128); +pub struct Instant(pub U128F0); impl Sub for Instant { type Output = Self; @@ -25,56 +42,56 @@ pub const FPS: u8 = 30; pub trait UI { fn check_event(&self) -> Option; - fn update_lights(&self, dashboard_lights: DashboardPattern, lights: Pattern); + fn update_lights(&self, dashboard_lights: DashboardPattern, body_lights: BodyPattern); } pub trait Animation { - fn tick(&mut self, time: Instant) -> (DashboardPattern, Pattern); + fn tick(&mut self, time: Instant) -> (DashboardPattern, BodyPattern); } pub struct DefaultAnimation {} impl Animation for DefaultAnimation { - fn tick(&mut self, _: Instant) -> (DashboardPattern, Pattern) { - (PRIDE_DASHBOARD, PRIDE) + fn tick(&mut self, _: Instant) -> (DashboardPattern, BodyPattern) { + (PRIDE_DASHBOARD, PRIDE_BODY) } } pub struct Fade { starting_dashboard: DashboardPattern, - starting_lights: Pattern, + starting_lights: BodyPattern, start_time: Instant, - dashboard_slope: [RGB; 3], - body_slope: [RGB; 60], - frames: u8, + dashboard_slope: [RGB; 3], + body_slope: [RGB; 60], + frames: U16F0, } impl Fade { fn new( dashboard: DashboardPattern, - lights: Pattern, + lights: BodyPattern, ending_dashboard: DashboardPattern, - ending_lights: Pattern, - frames: u8, + ending_lights: BodyPattern, + frames: U16F0, time: Instant, ) -> Self { let mut dashboard_slope = [Default::default(); 3]; let mut body_slope = [Default::default(); 60]; for i in 0..3 { let slope = RGB { - r: (ending_dashboard[i].r as f64 - dashboard[i].r as f64) / frames as f64, - g: (ending_dashboard[i].g as f64 - dashboard[i].g as f64) / frames as f64, - b: (ending_dashboard[i].b as f64 - dashboard[i].b as f64) / frames as f64, + r: calculate_slope(dashboard[i].r, ending_dashboard[i].r, frames), + g: calculate_slope(dashboard[i].g, ending_dashboard[i].g, frames), + b: calculate_slope(dashboard[i].b, ending_dashboard[i].b, frames), }; dashboard_slope[i] = slope; } for i in 0..60 { let slope = RGB { - r: (ending_lights[i].r as f64 - lights[i].r as f64) / frames as f64, - g: (ending_lights[i].g as f64 - lights[i].g as f64) / frames as f64, - b: (ending_lights[i].b as f64 - lights[i].b as f64) / frames as f64, + r: calculate_slope(lights[i].r, ending_lights[i].r, frames), + g: calculate_slope(lights[i].g, ending_lights[i].g, frames), + b: calculate_slope(lights[i].b, ending_lights[i].b, frames), }; body_slope[i] = slope; } @@ -91,50 +108,39 @@ impl Fade { } impl Animation for Fade { - fn tick(&mut self, time: Instant) -> (DashboardPattern, Pattern) { - let mut frames: u8 = ((time - self.start_time).0 as f64 / FPS as f64) as u8; + fn tick(&mut self, time: Instant) -> (DashboardPattern, BodyPattern) { + let mut frames = calculate_frames(self.start_time.0, time.0); if frames > self.frames { frames = self.frames } let mut dashboard_pattern: DashboardPattern = OFF_DASHBOARD; - let mut body_pattern: Pattern = OFF; - - let apply = |value: f64, frames: f64, slope: f64| -> f64 { value + frames * slope }; + let mut body_pattern: BodyPattern = OFF_BODY; for i in 0..3 { - dashboard_pattern[i].r = apply( - self.starting_dashboard[i].r as f64, - frames as f64, - self.dashboard_slope[i].r as f64, - ) as u8; - dashboard_pattern[i].g = apply( - self.starting_dashboard[i].g as f64, - frames as f64, - self.dashboard_slope[i].g as f64, - ) as u8; - dashboard_pattern[i].b = apply( - self.starting_dashboard[i].b as f64, - frames as f64, - self.dashboard_slope[i].b as f64, - ) as u8; + dashboard_pattern[i].r = linear_ease( + self.starting_dashboard[i].r, + frames, + self.dashboard_slope[i].r, + ); + dashboard_pattern[i].g = linear_ease( + self.starting_dashboard[i].g, + frames, + self.dashboard_slope[i].g, + ); + dashboard_pattern[i].b = linear_ease( + self.starting_dashboard[i].b, + frames, + self.dashboard_slope[i].b, + ); } for i in 0..60 { - body_pattern[i].r = apply( - self.starting_lights[i].r as f64, - frames as f64, - self.body_slope[i].r as f64, - ) as u8; - body_pattern[i].g = apply( - self.starting_lights[i].g as f64, - frames as f64, - self.body_slope[i].g as f64, - ) as u8; - body_pattern[i].b = apply( - self.starting_lights[i].b as f64, - frames as f64, - self.body_slope[i].b as f64, - ) as u8; + body_pattern[i].r = + linear_ease(self.starting_lights[i].r, frames, self.body_slope[i].r); + body_pattern[i].g = + linear_ease(self.starting_lights[i].g, frames, self.body_slope[i].g); + body_pattern[i].b = + linear_ease(self.starting_lights[i].b, frames, self.body_slope[i].b); } (dashboard_pattern, body_pattern) @@ -158,13 +164,13 @@ pub struct Blinker { direction: FadeDirection, start_time: Instant, - frames: u8, + frames: U16F0, } impl Blinker { fn new( starting_dashboard: DashboardPattern, - starting_body: Pattern, + starting_body: BodyPattern, direction: BlinkerDirection, time: Instant, ) -> Self { @@ -172,14 +178,14 @@ impl Blinker { match direction { BlinkerDirection::Left => { - ending_dashboard[0].r = LEFT_DASHBOARD[0].r; - ending_dashboard[0].g = LEFT_DASHBOARD[0].g; - ending_dashboard[0].b = LEFT_DASHBOARD[0].b; + ending_dashboard[0].r = LEFT_BLINKER_DASHBOARD[0].r; + ending_dashboard[0].g = LEFT_BLINKER_DASHBOARD[0].g; + ending_dashboard[0].b = LEFT_BLINKER_DASHBOARD[0].b; } BlinkerDirection::Right => { - ending_dashboard[2].r = RIGHT_DASHBOARD[2].r; - ending_dashboard[2].g = RIGHT_DASHBOARD[2].g; - ending_dashboard[2].b = RIGHT_DASHBOARD[2].b; + ending_dashboard[2].r = RIGHT_BLINKER_DASHBOARD[2].r; + ending_dashboard[2].g = RIGHT_BLINKER_DASHBOARD[2].g; + ending_dashboard[2].b = RIGHT_BLINKER_DASHBOARD[2].b; } } @@ -187,16 +193,16 @@ impl Blinker { match direction { BlinkerDirection::Left => { for i in 0..30 { - ending_body[i].r = LEFT[i].r; - ending_body[i].g = LEFT[i].g; - ending_body[i].b = LEFT[i].b; + ending_body[i].r = LEFT_BLINKER_BODY[i].r; + ending_body[i].g = LEFT_BLINKER_BODY[i].g; + ending_body[i].b = LEFT_BLINKER_BODY[i].b; } } BlinkerDirection::Right => { for i in 30..60 { - ending_body[i].r = RIGHT[i].r; - ending_body[i].g = RIGHT[i].g; - ending_body[i].b = RIGHT[i].b; + ending_body[i].r = RIGHT_BLINKER_BODY[i].r; + ending_body[i].g = RIGHT_BLINKER_BODY[i].g; + ending_body[i].b = RIGHT_BLINKER_BODY[i].b; } } } @@ -226,8 +232,8 @@ impl Blinker { } impl Animation for Blinker { - fn tick(&mut self, time: Instant) -> (DashboardPattern, Pattern) { - let frames: u8 = ((time - self.start_time).0 as f64 / FPS as f64) as u8; + fn tick(&mut self, time: Instant) -> (DashboardPattern, BodyPattern) { + let frames = calculate_frames(self.start_time.0, time.0); if frames > self.frames { match self.direction { FadeDirection::FadeIn => { @@ -275,7 +281,7 @@ pub struct App { home_state: State, current_animation: Box, dashboard_lights: DashboardPattern, - lights: Pattern, + lights: BodyPattern, } impl App { @@ -286,7 +292,7 @@ impl App { home_state: State::Pattern(0), current_animation: Box::new(DefaultAnimation {}), dashboard_lights: OFF_DASHBOARD, - lights: OFF, + lights: OFF_BODY, } } @@ -297,7 +303,7 @@ impl App { self.dashboard_lights.clone(), self.lights.clone(), PRIDE_DASHBOARD, - PRIDE, + PRIDE_BODY, DEFAULT_FRAMES, time, )) @@ -307,7 +313,7 @@ impl App { self.dashboard_lights.clone(), self.lights.clone(), TRANS_PRIDE_DASHBOARD, - TRANS_PRIDE, + TRANS_PRIDE_BODY, DEFAULT_FRAMES, time, )) @@ -317,9 +323,9 @@ impl App { self.current_animation = Box::new(Fade::new( self.dashboard_lights.clone(), self.lights.clone(), - BRAKE_DASHBOARD, - BRAKES, - BRAKE_FRAMES, + BRAKES_DASHBOARD, + BRAKES_BODY, + BRAKES_FRAMES, time, )); } diff --git a/bike-lights/core/src/patterns.rs b/bike-lights/core/src/patterns.rs index 767b835..e566a5d 100644 --- a/bike-lights/core/src/patterns.rs +++ b/bike-lights/core/src/patterns.rs @@ -1,1160 +1,311 @@ -use crate::RGB; +use crate::{BodyPattern, DashboardPattern, RGB}; +use fixed::types::{I8F8, U16F0}; -pub type DashboardPattern = [RGB; 3]; -pub type Pattern = [RGB; 60]; +pub const RGB_OFF: RGB = RGB { + r: I8F8::lit("0"), + g: I8F8::lit("0"), + b: I8F8::lit("0"), +}; -pub const OFF_DASHBOARD: DashboardPattern = [ - RGB { r: 0, g: 0, b: 0 }, - RGB { r: 0, g: 0, b: 0 }, - RGB { r: 0, g: 0, b: 0 }, -]; +pub const RGB_WHITE: RGB = RGB { + r: I8F8::lit("1"), + g: I8F8::lit("1"), + b: I8F8::lit("1"), +}; -pub const OFF: Pattern = [ - RGB { r: 0, g: 0, b: 0 }, - RGB { r: 0, g: 0, b: 0 }, - RGB { r: 0, g: 0, b: 0 }, - RGB { r: 0, g: 0, b: 0 }, - RGB { r: 0, g: 0, b: 0 }, - RGB { r: 0, g: 0, b: 0 }, - RGB { r: 0, g: 0, b: 0 }, - RGB { r: 0, g: 0, b: 0 }, - RGB { r: 0, g: 0, b: 0 }, - RGB { r: 0, g: 0, b: 0 }, - RGB { r: 0, g: 0, b: 0 }, - RGB { r: 0, g: 0, b: 0 }, - RGB { r: 0, g: 0, b: 0 }, - RGB { r: 0, g: 0, b: 0 }, - RGB { r: 0, g: 0, b: 0 }, - RGB { r: 0, g: 0, b: 0 }, - RGB { r: 0, g: 0, b: 0 }, - RGB { r: 0, g: 0, b: 0 }, - RGB { r: 0, g: 0, b: 0 }, - RGB { r: 0, g: 0, b: 0 }, - RGB { r: 0, g: 0, b: 0 }, - RGB { r: 0, g: 0, b: 0 }, - RGB { r: 0, g: 0, b: 0 }, - RGB { r: 0, g: 0, b: 0 }, - RGB { r: 0, g: 0, b: 0 }, - RGB { r: 0, g: 0, b: 0 }, - RGB { r: 0, g: 0, b: 0 }, - RGB { r: 0, g: 0, b: 0 }, - RGB { r: 0, g: 0, b: 0 }, - RGB { r: 0, g: 0, b: 0 }, - RGB { r: 0, g: 0, b: 0 }, - RGB { r: 0, g: 0, b: 0 }, - RGB { r: 0, g: 0, b: 0 }, - RGB { r: 0, g: 0, b: 0 }, - RGB { r: 0, g: 0, b: 0 }, - RGB { r: 0, g: 0, b: 0 }, - RGB { r: 0, g: 0, b: 0 }, - RGB { r: 0, g: 0, b: 0 }, - RGB { r: 0, g: 0, b: 0 }, - RGB { r: 0, g: 0, b: 0 }, - RGB { r: 0, g: 0, b: 0 }, - RGB { r: 0, g: 0, b: 0 }, - RGB { r: 0, g: 0, b: 0 }, - RGB { r: 0, g: 0, b: 0 }, - RGB { r: 0, g: 0, b: 0 }, - RGB { r: 0, g: 0, b: 0 }, - RGB { r: 0, g: 0, b: 0 }, - RGB { r: 0, g: 0, b: 0 }, - RGB { r: 0, g: 0, b: 0 }, - RGB { r: 0, g: 0, b: 0 }, - RGB { r: 0, g: 0, b: 0 }, - RGB { r: 0, g: 0, b: 0 }, - RGB { r: 0, g: 0, b: 0 }, - RGB { r: 0, g: 0, b: 0 }, - RGB { r: 0, g: 0, b: 0 }, - RGB { r: 0, g: 0, b: 0 }, - RGB { r: 0, g: 0, b: 0 }, - RGB { r: 0, g: 0, b: 0 }, - RGB { r: 0, g: 0, b: 0 }, - RGB { r: 0, g: 0, b: 0 }, -]; +pub const BRAKES_RED: RGB = RGB { + r: I8F8::lit("1"), + g: I8F8::lit("0"), + b: I8F8::lit("0"), +}; -pub const DEFAULT_FRAMES: u8 = 30; +pub const BLINKER_AMBER: RGB = RGB { + r: I8F8::lit("1"), + g: I8F8::lit("0.74"), + b: I8F8::lit("0"), +}; -pub const PRIDE_DASHBOARD: DashboardPattern = [ - RGB { r: 228, g: 3, b: 3 }, - RGB { - r: 0, - g: 128, - b: 38, - }, - RGB { - r: 36, - g: 64, - b: 142, - }, -]; +pub const PRIDE_RED: RGB = RGB { + r: I8F8::lit("0.89"), + g: I8F8::lit("0.01"), + b: I8F8::lit("0.01"), +}; -pub const PRIDE: Pattern = [ +pub const PRIDE_ORANGE: RGB = RGB { + r: I8F8::lit("1.0"), + g: I8F8::lit("0.54"), + b: I8F8::lit("0"), +}; + +pub const PRIDE_YELLOW: RGB = RGB { + r: I8F8::lit("1.0"), + g: I8F8::lit("0.92"), + b: I8F8::lit("0"), +}; + +pub const PRIDE_GREEN: RGB = RGB { + r: I8F8::lit("0"), + g: I8F8::lit("0.5"), + b: I8F8::lit("0.14"), +}; + +pub const PRIDE_INDIGO: RGB = RGB { + r: I8F8::lit("0.14"), + g: I8F8::lit("0.25"), + b: I8F8::lit("0.55"), +}; + +pub const PRIDE_VIOLET: RGB = RGB { + r: I8F8::lit("0.45"), + g: I8F8::lit("0.16"), + b: I8F8::lit("0.50"), +}; + +pub const TRANS_BLUE: RGB = RGB { + r: I8F8::lit("0.36"), + g: I8F8::lit("0.81"), + b: I8F8::lit("0.98"), +}; + +pub const TRANS_PINK: RGB = RGB { + r: I8F8::lit("0.96"), + g: I8F8::lit("0.66"), + b: I8F8::lit("0.72"), +}; + +pub const OFF_DASHBOARD: DashboardPattern = [RGB_OFF; 3]; +pub const OFF_BODY: BodyPattern = [RGB_OFF; 60]; + +pub const DEFAULT_FRAMES: U16F0 = U16F0::lit("30"); + +pub const PRIDE_DASHBOARD: DashboardPattern = [PRIDE_RED, PRIDE_GREEN, PRIDE_INDIGO]; + +pub const PRIDE_BODY: BodyPattern = [ // Left Side // Red - RGB { r: 228, g: 3, b: 3 }, - RGB { r: 228, g: 3, b: 3 }, - RGB { r: 228, g: 3, b: 3 }, - RGB { r: 228, g: 3, b: 3 }, - RGB { r: 228, g: 3, b: 3 }, + PRIDE_RED, + PRIDE_RED, + PRIDE_RED, + PRIDE_RED, + PRIDE_RED, // Orange - RGB { - r: 255, - g: 140, - b: 0, - }, - RGB { - r: 255, - g: 140, - b: 0, - }, - RGB { - r: 255, - g: 140, - b: 0, - }, - RGB { - r: 255, - g: 140, - b: 0, - }, - RGB { - r: 255, - g: 140, - b: 0, - }, + PRIDE_ORANGE, + PRIDE_ORANGE, + PRIDE_ORANGE, + PRIDE_ORANGE, + PRIDE_ORANGE, // Yellow - RGB { - r: 255, - g: 237, - b: 0, - }, - RGB { - r: 255, - g: 237, - b: 0, - }, - RGB { - r: 255, - g: 237, - b: 0, - }, - RGB { - r: 255, - g: 237, - b: 0, - }, - RGB { - r: 255, - g: 237, - b: 0, - }, + PRIDE_YELLOW, + PRIDE_YELLOW, + PRIDE_YELLOW, + PRIDE_YELLOW, + PRIDE_YELLOW, // Green - RGB { - r: 0, - g: 128, - b: 38, - }, - RGB { - r: 0, - g: 128, - b: 38, - }, - RGB { - r: 0, - g: 128, - b: 38, - }, - RGB { - r: 0, - g: 128, - b: 38, - }, - RGB { - r: 0, - g: 128, - b: 38, - }, + PRIDE_GREEN, + PRIDE_GREEN, + PRIDE_GREEN, + PRIDE_GREEN, + PRIDE_GREEN, // Indigo - RGB { - r: 36, - g: 64, - b: 142, - }, - RGB { - r: 36, - g: 64, - b: 142, - }, - RGB { - r: 36, - g: 64, - b: 142, - }, - RGB { - r: 36, - g: 64, - b: 142, - }, - RGB { - r: 36, - g: 64, - b: 142, - }, - // Purple - RGB { - r: 115, - g: 41, - b: 130, - }, - RGB { - r: 115, - g: 41, - b: 130, - }, - RGB { - r: 115, - g: 41, - b: 130, - }, - RGB { - r: 115, - g: 41, - b: 130, - }, - RGB { - r: 115, - g: 41, - b: 130, - }, + PRIDE_INDIGO, + PRIDE_INDIGO, + PRIDE_INDIGO, + PRIDE_INDIGO, + PRIDE_INDIGO, + // Violet + PRIDE_VIOLET, + PRIDE_VIOLET, + PRIDE_VIOLET, + PRIDE_VIOLET, + PRIDE_VIOLET, // Right Side - // Purple - RGB { - r: 115, - g: 41, - b: 130, - }, - RGB { - r: 115, - g: 41, - b: 130, - }, - RGB { - r: 115, - g: 41, - b: 130, - }, - RGB { - r: 115, - g: 41, - b: 130, - }, - RGB { - r: 115, - g: 41, - b: 130, - }, + // Violet + PRIDE_VIOLET, + PRIDE_VIOLET, + PRIDE_VIOLET, + PRIDE_VIOLET, + PRIDE_VIOLET, // Indigo - RGB { - r: 36, - g: 64, - b: 142, - }, - RGB { - r: 36, - g: 64, - b: 142, - }, - RGB { - r: 36, - g: 64, - b: 142, - }, - RGB { - r: 36, - g: 64, - b: 142, - }, - RGB { - r: 36, - g: 64, - b: 142, - }, + PRIDE_INDIGO, + PRIDE_INDIGO, + PRIDE_INDIGO, + PRIDE_INDIGO, + PRIDE_INDIGO, // Green - RGB { - r: 0, - g: 128, - b: 38, - }, - RGB { - r: 0, - g: 128, - b: 38, - }, - RGB { - r: 0, - g: 128, - b: 38, - }, - RGB { - r: 0, - g: 128, - b: 38, - }, - RGB { - r: 0, - g: 128, - b: 38, - }, + PRIDE_GREEN, + PRIDE_GREEN, + PRIDE_GREEN, + PRIDE_GREEN, + PRIDE_GREEN, // Yellow - RGB { - r: 255, - g: 237, - b: 0, - }, - RGB { - r: 255, - g: 237, - b: 0, - }, - RGB { - r: 255, - g: 237, - b: 0, - }, - RGB { - r: 255, - g: 237, - b: 0, - }, - RGB { - r: 255, - g: 237, - b: 0, - }, + PRIDE_YELLOW, + PRIDE_YELLOW, + PRIDE_YELLOW, + PRIDE_YELLOW, + PRIDE_YELLOW, // Orange - RGB { - r: 255, - g: 140, - b: 0, - }, - RGB { - r: 255, - g: 140, - b: 0, - }, - RGB { - r: 255, - g: 140, - b: 0, - }, - RGB { - r: 255, - g: 140, - b: 0, - }, - RGB { - r: 255, - g: 140, - b: 0, - }, + PRIDE_ORANGE, + PRIDE_ORANGE, + PRIDE_ORANGE, + PRIDE_ORANGE, + PRIDE_ORANGE, // Red - RGB { r: 228, g: 3, b: 3 }, - RGB { r: 228, g: 3, b: 3 }, - RGB { r: 228, g: 3, b: 3 }, - RGB { r: 228, g: 3, b: 3 }, - RGB { r: 228, g: 3, b: 3 }, + PRIDE_RED, + PRIDE_RED, + PRIDE_RED, + PRIDE_RED, + PRIDE_RED, ]; -pub const TRANS_PRIDE_DASHBOARD: DashboardPattern = [ - RGB { - r: 91, - g: 206, - b: 250, - }, - RGB { - r: 255, - g: 255, - b: 255, - }, - RGB { - r: 245, - g: 169, - b: 184, - }, -]; +pub const TRANS_PRIDE_DASHBOARD: DashboardPattern = [TRANS_BLUE, RGB_WHITE, TRANS_PINK]; -pub const TRANS_PRIDE: Pattern = [ +pub const TRANS_PRIDE_BODY: BodyPattern = [ // Left Side - // Light Blue - RGB { - r: 91, - g: 206, - b: 250, - }, - RGB { - r: 91, - g: 206, - b: 250, - }, - RGB { - r: 91, - g: 206, - b: 250, - }, - RGB { - r: 91, - g: 206, - b: 250, - }, - RGB { - r: 91, - g: 206, - b: 250, - }, - RGB { - r: 91, - g: 206, - b: 250, - }, - // Light Pink - RGB { - r: 245, - g: 169, - b: 184, - }, - RGB { - r: 245, - g: 169, - b: 184, - }, - RGB { - r: 245, - g: 169, - b: 184, - }, - RGB { - r: 245, - g: 169, - b: 184, - }, - RGB { - r: 245, - g: 169, - b: 184, - }, - RGB { - r: 245, - g: 169, - b: 184, - }, - // White - RGB { - r: 255, - g: 255, - b: 255, - }, - RGB { - r: 255, - g: 255, - b: 255, - }, - RGB { - r: 255, - g: 255, - b: 255, - }, - RGB { - r: 255, - g: 255, - b: 255, - }, - RGB { - r: 255, - g: 255, - b: 255, - }, - RGB { - r: 255, - g: 255, - b: 255, - }, - // Light Pink - RGB { - r: 245, - g: 169, - b: 184, - }, - RGB { - r: 245, - g: 169, - b: 184, - }, - RGB { - r: 245, - g: 169, - b: 184, - }, - RGB { - r: 245, - g: 169, - b: 184, - }, - RGB { - r: 245, - g: 169, - b: 184, - }, - RGB { - r: 245, - g: 169, - b: 184, - }, - // Light Blue - RGB { - r: 91, - g: 206, - b: 250, - }, - RGB { - r: 91, - g: 206, - b: 250, - }, - RGB { - r: 91, - g: 206, - b: 250, - }, - RGB { - r: 91, - g: 206, - b: 250, - }, - RGB { - r: 91, - g: 206, - b: 250, - }, - RGB { - r: 91, - g: 206, - b: 250, - }, + TRANS_BLUE, TRANS_BLUE, TRANS_BLUE, TRANS_BLUE, TRANS_BLUE, TRANS_BLUE, TRANS_PINK, TRANS_PINK, + TRANS_PINK, TRANS_PINK, TRANS_PINK, TRANS_PINK, RGB_WHITE, RGB_WHITE, RGB_WHITE, RGB_WHITE, + RGB_WHITE, RGB_WHITE, TRANS_PINK, TRANS_PINK, TRANS_PINK, TRANS_PINK, TRANS_PINK, TRANS_PINK, + TRANS_BLUE, TRANS_BLUE, TRANS_BLUE, TRANS_BLUE, TRANS_BLUE, TRANS_BLUE, // Right side - // Light Blue - RGB { - r: 91, - g: 206, - b: 250, - }, - RGB { - r: 91, - g: 206, - b: 250, - }, - RGB { - r: 91, - g: 206, - b: 250, - }, - RGB { - r: 91, - g: 206, - b: 250, - }, - RGB { - r: 91, - g: 206, - b: 250, - }, - RGB { - r: 91, - g: 206, - b: 250, - }, - // Light Pink - RGB { - r: 245, - g: 169, - b: 184, - }, - RGB { - r: 245, - g: 169, - b: 184, - }, - RGB { - r: 245, - g: 169, - b: 184, - }, - RGB { - r: 245, - g: 169, - b: 184, - }, - RGB { - r: 245, - g: 169, - b: 184, - }, - RGB { - r: 245, - g: 169, - b: 184, - }, - // White - RGB { - r: 255, - g: 255, - b: 255, - }, - RGB { - r: 255, - g: 255, - b: 255, - }, - RGB { - r: 255, - g: 255, - b: 255, - }, - RGB { - r: 255, - g: 255, - b: 255, - }, - RGB { - r: 255, - g: 255, - b: 255, - }, - RGB { - r: 255, - g: 255, - b: 255, - }, - // Light Pink - RGB { - r: 245, - g: 169, - b: 184, - }, - RGB { - r: 245, - g: 169, - b: 184, - }, - RGB { - r: 245, - g: 169, - b: 184, - }, - RGB { - r: 245, - g: 169, - b: 184, - }, - RGB { - r: 245, - g: 169, - b: 184, - }, - RGB { - r: 245, - g: 169, - b: 184, - }, - // Light Blue - RGB { - r: 91, - g: 206, - b: 250, - }, - RGB { - r: 91, - g: 206, - b: 250, - }, - RGB { - r: 91, - g: 206, - b: 250, - }, - RGB { - r: 91, - g: 206, - b: 250, - }, - RGB { - r: 91, - g: 206, - b: 250, - }, - RGB { - r: 91, - g: 206, - b: 250, - }, + TRANS_BLUE, TRANS_BLUE, TRANS_BLUE, TRANS_BLUE, TRANS_BLUE, TRANS_BLUE, TRANS_PINK, TRANS_PINK, + TRANS_PINK, TRANS_PINK, TRANS_PINK, TRANS_PINK, RGB_WHITE, RGB_WHITE, RGB_WHITE, RGB_WHITE, + RGB_WHITE, RGB_WHITE, TRANS_PINK, TRANS_PINK, TRANS_PINK, TRANS_PINK, TRANS_PINK, TRANS_PINK, + TRANS_BLUE, TRANS_BLUE, TRANS_BLUE, TRANS_BLUE, TRANS_BLUE, TRANS_BLUE, ]; -pub const BRAKE_FRAMES: u8 = 15; +pub const BRAKES_FRAMES: U16F0 = U16F0::lit("15"); -pub const BRAKE_DASHBOARD: DashboardPattern = [ - RGB { r: 255, g: 0, b: 0 }, - RGB { r: 255, g: 0, b: 0 }, - RGB { r: 255, g: 0, b: 0 }, +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 LEFT_BLINKER_DASHBOARD: DashboardPattern = [BLINKER_AMBER, RGB_OFF, RGB_OFF]; + +pub const LEFT_BLINKER_BODY: BodyPattern = [ + BLINKER_AMBER, + BLINKER_AMBER, + BLINKER_AMBER, + BLINKER_AMBER, + BLINKER_AMBER, + BLINKER_AMBER, + BLINKER_AMBER, + BLINKER_AMBER, + BLINKER_AMBER, + BLINKER_AMBER, + BLINKER_AMBER, + BLINKER_AMBER, + BLINKER_AMBER, + BLINKER_AMBER, + BLINKER_AMBER, + BLINKER_AMBER, + BLINKER_AMBER, + BLINKER_AMBER, + BLINKER_AMBER, + BLINKER_AMBER, + BLINKER_AMBER, + BLINKER_AMBER, + BLINKER_AMBER, + BLINKER_AMBER, + BLINKER_AMBER, + BLINKER_AMBER, + BLINKER_AMBER, + BLINKER_AMBER, + BLINKER_AMBER, + BLINKER_AMBER, + RGB_OFF, + RGB_OFF, + RGB_OFF, + RGB_OFF, + RGB_OFF, + RGB_OFF, + RGB_OFF, + RGB_OFF, + RGB_OFF, + RGB_OFF, + RGB_OFF, + RGB_OFF, + RGB_OFF, + RGB_OFF, + RGB_OFF, + RGB_OFF, + RGB_OFF, + RGB_OFF, + RGB_OFF, + RGB_OFF, + RGB_OFF, + RGB_OFF, + RGB_OFF, + RGB_OFF, + RGB_OFF, + RGB_OFF, + RGB_OFF, + RGB_OFF, + RGB_OFF, + RGB_OFF, ]; -pub const BRAKES: Pattern = [ - RGB { r: 255, g: 0, b: 0 }, - RGB { r: 255, g: 0, b: 0 }, - RGB { r: 255, g: 0, b: 0 }, - RGB { r: 255, g: 0, b: 0 }, - RGB { r: 255, g: 0, b: 0 }, - RGB { r: 255, g: 0, b: 0 }, - RGB { r: 255, g: 0, b: 0 }, - RGB { r: 255, g: 0, b: 0 }, - RGB { r: 255, g: 0, b: 0 }, - RGB { r: 255, g: 0, b: 0 }, - RGB { r: 255, g: 0, b: 0 }, - RGB { r: 255, g: 0, b: 0 }, - RGB { r: 255, g: 0, b: 0 }, - RGB { r: 255, g: 0, b: 0 }, - RGB { r: 255, g: 0, b: 0 }, - RGB { r: 255, g: 0, b: 0 }, - RGB { r: 255, g: 0, b: 0 }, - RGB { r: 255, g: 0, b: 0 }, - RGB { r: 255, g: 0, b: 0 }, - RGB { r: 255, g: 0, b: 0 }, - RGB { r: 255, g: 0, b: 0 }, - RGB { r: 255, g: 0, b: 0 }, - RGB { r: 255, g: 0, b: 0 }, - RGB { r: 255, g: 0, b: 0 }, - RGB { r: 255, g: 0, b: 0 }, - RGB { r: 255, g: 0, b: 0 }, - RGB { r: 255, g: 0, b: 0 }, - RGB { r: 255, g: 0, b: 0 }, - RGB { r: 255, g: 0, b: 0 }, - RGB { r: 255, g: 0, b: 0 }, - RGB { r: 255, g: 0, b: 0 }, - RGB { r: 255, g: 0, b: 0 }, - RGB { r: 255, g: 0, b: 0 }, - RGB { r: 255, g: 0, b: 0 }, - RGB { r: 255, g: 0, b: 0 }, - RGB { r: 255, g: 0, b: 0 }, - RGB { r: 255, g: 0, b: 0 }, - RGB { r: 255, g: 0, b: 0 }, - RGB { r: 255, g: 0, b: 0 }, - RGB { r: 255, g: 0, b: 0 }, - RGB { r: 255, g: 0, b: 0 }, - RGB { r: 255, g: 0, b: 0 }, - RGB { r: 255, g: 0, b: 0 }, - RGB { r: 255, g: 0, b: 0 }, - RGB { r: 255, g: 0, b: 0 }, - RGB { r: 255, g: 0, b: 0 }, - RGB { r: 255, g: 0, b: 0 }, - RGB { r: 255, g: 0, b: 0 }, - RGB { r: 255, g: 0, b: 0 }, - RGB { r: 255, g: 0, b: 0 }, - RGB { r: 255, g: 0, b: 0 }, - RGB { r: 255, g: 0, b: 0 }, - RGB { r: 255, g: 0, b: 0 }, - RGB { r: 255, g: 0, b: 0 }, - RGB { r: 255, g: 0, b: 0 }, - RGB { r: 255, g: 0, b: 0 }, - RGB { r: 255, g: 0, b: 0 }, - RGB { r: 255, g: 0, b: 0 }, - RGB { r: 255, g: 0, b: 0 }, - RGB { r: 255, g: 0, b: 0 }, -]; - -pub const BLINKER_FRAMES: u8 = 15; - -pub const LEFT_DASHBOARD: DashboardPattern = [ - RGB { - r: 255, - g: 191, - b: 0, - }, - RGB { r: 0, g: 0, b: 0 }, - RGB { r: 0, g: 0, b: 0 }, -]; - -pub const LEFT: Pattern = [ - RGB { - r: 255, - g: 191, - b: 0, - }, - RGB { - r: 255, - g: 191, - b: 0, - }, - RGB { - r: 255, - g: 191, - b: 0, - }, - RGB { - r: 255, - g: 191, - b: 0, - }, - RGB { - r: 255, - g: 191, - b: 0, - }, - RGB { - r: 255, - g: 191, - b: 0, - }, - RGB { - r: 255, - g: 191, - b: 0, - }, - RGB { - r: 255, - g: 191, - b: 0, - }, - RGB { - r: 255, - g: 191, - b: 0, - }, - RGB { - r: 255, - g: 191, - b: 0, - }, - RGB { - r: 255, - g: 191, - b: 0, - }, - RGB { - r: 255, - g: 191, - b: 0, - }, - RGB { - r: 255, - g: 191, - b: 0, - }, - RGB { - r: 255, - g: 191, - b: 0, - }, - RGB { - r: 255, - g: 191, - b: 0, - }, - RGB { - r: 255, - g: 191, - b: 0, - }, - RGB { - r: 255, - g: 191, - b: 0, - }, - RGB { - r: 255, - g: 191, - b: 0, - }, - RGB { - r: 255, - g: 191, - b: 0, - }, - RGB { - r: 255, - g: 191, - b: 0, - }, - RGB { - r: 255, - g: 191, - b: 0, - }, - RGB { - r: 255, - g: 191, - b: 0, - }, - RGB { - r: 255, - g: 191, - b: 0, - }, - RGB { - r: 255, - g: 191, - b: 0, - }, - RGB { - r: 255, - g: 191, - b: 0, - }, - RGB { - r: 255, - g: 191, - b: 0, - }, - RGB { - r: 255, - g: 191, - b: 0, - }, - RGB { - r: 255, - g: 191, - b: 0, - }, - RGB { - r: 255, - g: 191, - b: 0, - }, - RGB { - r: 255, - g: 191, - b: 0, - }, - RGB { r: 0, g: 0, b: 0 }, - RGB { r: 0, g: 0, b: 0 }, - RGB { r: 0, g: 0, b: 0 }, - RGB { r: 0, g: 0, b: 0 }, - RGB { r: 0, g: 0, b: 0 }, - RGB { r: 0, g: 0, b: 0 }, - RGB { r: 0, g: 0, b: 0 }, - RGB { r: 0, g: 0, b: 0 }, - RGB { r: 0, g: 0, b: 0 }, - RGB { r: 0, g: 0, b: 0 }, - RGB { r: 0, g: 0, b: 0 }, - RGB { r: 0, g: 0, b: 0 }, - RGB { r: 0, g: 0, b: 0 }, - RGB { r: 0, g: 0, b: 0 }, - RGB { r: 0, g: 0, b: 0 }, - RGB { r: 0, g: 0, b: 0 }, - RGB { r: 0, g: 0, b: 0 }, - RGB { r: 0, g: 0, b: 0 }, - RGB { r: 0, g: 0, b: 0 }, - RGB { r: 0, g: 0, b: 0 }, - RGB { r: 0, g: 0, b: 0 }, - RGB { r: 0, g: 0, b: 0 }, - RGB { r: 0, g: 0, b: 0 }, - RGB { r: 0, g: 0, b: 0 }, - RGB { r: 0, g: 0, b: 0 }, - RGB { r: 0, g: 0, b: 0 }, - RGB { r: 0, g: 0, b: 0 }, - RGB { r: 0, g: 0, b: 0 }, - RGB { r: 0, g: 0, b: 0 }, - RGB { r: 0, g: 0, b: 0 }, -]; - -pub const RIGHT_FRAMES: u8 = 15; - -pub const RIGHT_DASHBOARD: DashboardPattern = [ - RGB { r: 0, g: 0, b: 0 }, - RGB { r: 0, g: 0, b: 0 }, - RGB { - r: 255, - g: 191, - b: 0, - }, -]; - -pub const RIGHT: Pattern = [ - RGB { r: 0, g: 0, b: 0 }, - RGB { r: 0, g: 0, b: 0 }, - RGB { r: 0, g: 0, b: 0 }, - RGB { r: 0, g: 0, b: 0 }, - RGB { r: 0, g: 0, b: 0 }, - RGB { r: 0, g: 0, b: 0 }, - RGB { r: 0, g: 0, b: 0 }, - RGB { r: 0, g: 0, b: 0 }, - RGB { r: 0, g: 0, b: 0 }, - RGB { r: 0, g: 0, b: 0 }, - RGB { r: 0, g: 0, b: 0 }, - RGB { r: 0, g: 0, b: 0 }, - RGB { r: 0, g: 0, b: 0 }, - RGB { r: 0, g: 0, b: 0 }, - RGB { r: 0, g: 0, b: 0 }, - RGB { r: 0, g: 0, b: 0 }, - RGB { r: 0, g: 0, b: 0 }, - RGB { r: 0, g: 0, b: 0 }, - RGB { r: 0, g: 0, b: 0 }, - RGB { r: 0, g: 0, b: 0 }, - RGB { r: 0, g: 0, b: 0 }, - RGB { r: 0, g: 0, b: 0 }, - RGB { r: 0, g: 0, b: 0 }, - RGB { r: 0, g: 0, b: 0 }, - RGB { r: 0, g: 0, b: 0 }, - RGB { r: 0, g: 0, b: 0 }, - RGB { r: 0, g: 0, b: 0 }, - RGB { r: 0, g: 0, b: 0 }, - RGB { r: 0, g: 0, b: 0 }, - RGB { r: 0, g: 0, b: 0 }, - RGB { - r: 255, - g: 191, - b: 0, - }, - RGB { - r: 255, - g: 191, - b: 0, - }, - RGB { - r: 255, - g: 191, - b: 0, - }, - RGB { - r: 255, - g: 191, - b: 0, - }, - RGB { - r: 255, - g: 191, - b: 0, - }, - RGB { - r: 255, - g: 191, - b: 0, - }, - RGB { - r: 255, - g: 191, - b: 0, - }, - RGB { - r: 255, - g: 191, - b: 0, - }, - RGB { - r: 255, - g: 191, - b: 0, - }, - RGB { - r: 255, - g: 191, - b: 0, - }, - RGB { - r: 255, - g: 191, - b: 0, - }, - RGB { - r: 255, - g: 191, - b: 0, - }, - RGB { - r: 255, - g: 191, - b: 0, - }, - RGB { - r: 255, - g: 191, - b: 0, - }, - RGB { - r: 255, - g: 191, - b: 0, - }, - RGB { - r: 255, - g: 191, - b: 0, - }, - RGB { - r: 255, - g: 191, - b: 0, - }, - RGB { - r: 255, - g: 191, - b: 0, - }, - RGB { - r: 255, - g: 191, - b: 0, - }, - RGB { - r: 255, - g: 191, - b: 0, - }, - RGB { - r: 255, - g: 191, - b: 0, - }, - RGB { - r: 255, - g: 191, - b: 0, - }, - RGB { - r: 255, - g: 191, - b: 0, - }, - RGB { - r: 255, - g: 191, - b: 0, - }, - RGB { - r: 255, - g: 191, - b: 0, - }, - RGB { - r: 255, - g: 191, - b: 0, - }, - RGB { - r: 255, - g: 191, - b: 0, - }, - RGB { - r: 255, - g: 191, - b: 0, - }, - RGB { - r: 255, - g: 191, - b: 0, - }, - RGB { - r: 255, - g: 191, - b: 0, - }, +pub const RIGHT_BLINKER_DASHBOARD: DashboardPattern = [RGB_OFF, RGB_OFF, BLINKER_AMBER]; + +pub const RIGHT_BLINKER_BODY: BodyPattern = [ + RGB_OFF, + RGB_OFF, + RGB_OFF, + RGB_OFF, + RGB_OFF, + RGB_OFF, + RGB_OFF, + RGB_OFF, + RGB_OFF, + RGB_OFF, + RGB_OFF, + RGB_OFF, + RGB_OFF, + RGB_OFF, + RGB_OFF, + RGB_OFF, + RGB_OFF, + RGB_OFF, + RGB_OFF, + RGB_OFF, + RGB_OFF, + RGB_OFF, + RGB_OFF, + RGB_OFF, + RGB_OFF, + RGB_OFF, + RGB_OFF, + RGB_OFF, + RGB_OFF, + RGB_OFF, + BLINKER_AMBER, + BLINKER_AMBER, + BLINKER_AMBER, + BLINKER_AMBER, + BLINKER_AMBER, + BLINKER_AMBER, + BLINKER_AMBER, + BLINKER_AMBER, + BLINKER_AMBER, + BLINKER_AMBER, + BLINKER_AMBER, + BLINKER_AMBER, + BLINKER_AMBER, + BLINKER_AMBER, + BLINKER_AMBER, + BLINKER_AMBER, + BLINKER_AMBER, + BLINKER_AMBER, + BLINKER_AMBER, + BLINKER_AMBER, + BLINKER_AMBER, + BLINKER_AMBER, + BLINKER_AMBER, + BLINKER_AMBER, + BLINKER_AMBER, + BLINKER_AMBER, + BLINKER_AMBER, + BLINKER_AMBER, + BLINKER_AMBER, + BLINKER_AMBER, ]; diff --git a/bike-lights/core/src/types.rs b/bike-lights/core/src/types.rs index 145b515..c7acf2a 100644 --- a/bike-lights/core/src/types.rs +++ b/bike-lights/core/src/types.rs @@ -1,4 +1,5 @@ use core::default::Default; +use fixed::types::I8F8; #[derive(Clone, Copy, Default, Debug)] pub struct RGB { @@ -7,35 +8,10 @@ pub struct RGB { pub b: T, } -pub type DashboardPattern = [RGB; 3]; -/* -#[derive(Clone)] -pub struct DashboardPattern(pub [RGB; 3]); -*/ +const DASHBOARD_LIGHT_COUNT: usize = 3; -/* -impl Clone for DashboardPattern { - fn clone(&self) -> Self { - let mut v: [RGB; 3] = Default::default(); - for i in 0..3 { - v[i] = self.0[i] - } - Self(v) - } -} -*/ +pub type DashboardPattern = [RGB; DASHBOARD_LIGHT_COUNT]; -pub type Pattern = [RGB; 60]; -/* -pub struct Pattern(pub [RGB; 60]); +const BODY_LIGHT_COUNT: usize = 60; -impl Pattern { - pub fn clone(&self) -> Self { - let mut v: [RGB; 60] = [Default::default(); 60]; - for i in 0..60 { - v[i] = self.0[i] - } - Self(v) - } -} -*/ +pub type BodyPattern = [RGB; BODY_LIGHT_COUNT]; diff --git a/bike-lights/simulator/src/main.rs b/bike-lights/simulator/src/main.rs index 64d5222..407a11d 100644 --- a/bike-lights/simulator/src/main.rs +++ b/bike-lights/simulator/src/main.rs @@ -1,7 +1,10 @@ use adw::prelude::*; +use fixed::types::{I8F8, U128F0}; use glib::{Object, Sender}; use gtk::subclass::prelude::*; -use lights_core::{App, DashboardPattern, Event, Instant, Pattern, FPS, RGB, UI}; +use lights_core::{ + App, BodyPattern, DashboardPattern, Event, Instant, FPS, OFF_BODY, OFF_DASHBOARD, RGB, UI, +}; use std::{ cell::RefCell, env, @@ -14,7 +17,7 @@ const HEIGHT: i32 = 480; pub struct Update { dashboard: DashboardPattern, - lights: Pattern, + lights: BodyPattern, } pub struct DashboardLightsPrivate { @@ -29,11 +32,7 @@ impl ObjectSubclass for DashboardLightsPrivate { fn new() -> Self { Self { - lights: Rc::new(RefCell::new([ - RGB { r: 0, g: 0, b: 0 }, - RGB { r: 0, g: 0, b: 0 }, - RGB { r: 0, g: 0, b: 0 }, - ])), + lights: Rc::new(RefCell::new(OFF_DASHBOARD)), } } } @@ -60,9 +59,9 @@ impl DashboardLights { let lights = s.imp().lights.borrow(); for i in 0..3 { context.set_source_rgb( - lights[i].r as f64 / 256., - lights[i].g as f64 / 256., - lights[i].b as f64 / 256., + lights[i].r.into(), + lights[i].g.into(), + lights[i].b.into(), ); context.rectangle(start + 100. * i as f64, 10., 80., 80.); let _ = context.fill(); @@ -73,14 +72,14 @@ impl DashboardLights { s } - pub fn set_lights(&self, lights: [RGB; 3]) { + pub fn set_lights(&self, lights: DashboardPattern) { *self.imp().lights.borrow_mut() = lights; self.queue_draw(); } } pub struct BikeLightsPrivate { - lights: Rc>, + lights: Rc>, } #[glib::object_subclass] @@ -91,68 +90,7 @@ impl ObjectSubclass for BikeLightsPrivate { fn new() -> Self { Self { - lights: Rc::new(RefCell::new([ - RGB { r: 0, g: 0, b: 0 }, - RGB { r: 0, g: 0, b: 0 }, - RGB { r: 0, g: 0, b: 0 }, - RGB { r: 0, g: 0, b: 0 }, - RGB { r: 0, g: 0, b: 0 }, - RGB { r: 0, g: 0, b: 0 }, - RGB { r: 0, g: 0, b: 0 }, - RGB { r: 0, g: 0, b: 0 }, - RGB { r: 0, g: 0, b: 0 }, - RGB { r: 0, g: 0, b: 0 }, - RGB { r: 0, g: 0, b: 0 }, - RGB { r: 0, g: 0, b: 0 }, - RGB { r: 0, g: 0, b: 0 }, - RGB { r: 0, g: 0, b: 0 }, - RGB { r: 0, g: 0, b: 0 }, - RGB { r: 0, g: 0, b: 0 }, - RGB { r: 0, g: 0, b: 0 }, - RGB { r: 0, g: 0, b: 0 }, - RGB { r: 0, g: 0, b: 0 }, - RGB { r: 0, g: 0, b: 0 }, - RGB { r: 0, g: 0, b: 0 }, - RGB { r: 0, g: 0, b: 0 }, - RGB { r: 0, g: 0, b: 0 }, - RGB { r: 0, g: 0, b: 0 }, - RGB { r: 0, g: 0, b: 0 }, - RGB { r: 0, g: 0, b: 0 }, - RGB { r: 0, g: 0, b: 0 }, - RGB { r: 0, g: 0, b: 0 }, - RGB { r: 0, g: 0, b: 0 }, - RGB { r: 0, g: 0, b: 0 }, - RGB { r: 0, g: 0, b: 0 }, - RGB { r: 0, g: 0, b: 0 }, - RGB { r: 0, g: 0, b: 0 }, - RGB { r: 0, g: 0, b: 0 }, - RGB { r: 0, g: 0, b: 0 }, - RGB { r: 0, g: 0, b: 0 }, - RGB { r: 0, g: 0, b: 0 }, - RGB { r: 0, g: 0, b: 0 }, - RGB { r: 0, g: 0, b: 0 }, - RGB { r: 0, g: 0, b: 0 }, - RGB { r: 0, g: 0, b: 0 }, - RGB { r: 0, g: 0, b: 0 }, - RGB { r: 0, g: 0, b: 0 }, - RGB { r: 0, g: 0, b: 0 }, - RGB { r: 0, g: 0, b: 0 }, - RGB { r: 0, g: 0, b: 0 }, - RGB { r: 0, g: 0, b: 0 }, - RGB { r: 0, g: 0, b: 0 }, - RGB { r: 0, g: 0, b: 0 }, - RGB { r: 0, g: 0, b: 0 }, - RGB { r: 0, g: 0, b: 0 }, - RGB { r: 0, g: 0, b: 0 }, - RGB { r: 0, g: 0, b: 0 }, - RGB { r: 0, g: 0, b: 0 }, - RGB { r: 0, g: 0, b: 0 }, - RGB { r: 0, g: 0, b: 0 }, - RGB { r: 0, g: 0, b: 0 }, - RGB { r: 0, g: 0, b: 0 }, - RGB { r: 0, g: 0, b: 0 }, - RGB { r: 0, g: 0, b: 0 }, - ])), + lights: Rc::new(RefCell::new(OFF_BODY)), } } } @@ -180,18 +118,18 @@ impl BikeLights { let lights = s.imp().lights.borrow(); for i in 0..30 { context.set_source_rgb( - lights[i].r as f64 / 256., - lights[i].g as f64 / 256., - lights[i].b as f64 / 256., + lights[i].r.into(), + lights[i].g.into(), + lights[i].b.into(), ); context.rectangle(center - 45., 5. + 20. * i as f64, 15., 15.); let _ = context.fill(); } for i in 0..30 { context.set_source_rgb( - lights[i + 30].r as f64 / 256., - lights[i + 30].g as f64 / 256., - lights[i + 30].b as f64 / 256., + lights[i + 30].r.into(), + lights[i + 30].g.into(), + lights[i + 30].b.into(), ); context.rectangle(center + 15., 5. + 20. * (30. - (i + 1) as f64), 15., 15.); let _ = context.fill(); @@ -202,7 +140,7 @@ impl BikeLights { s } - pub fn set_lights(&self, lights: [RGB; 60]) { + pub fn set_lights(&self, lights: [RGB; 60]) { *self.imp().lights.borrow_mut() = lights; self.queue_draw(); } @@ -222,7 +160,7 @@ impl UI for GTKUI { } } - fn update_lights(&self, dashboard_lights: DashboardPattern, lights: Pattern) { + fn update_lights(&self, dashboard_lights: DashboardPattern, lights: BodyPattern) { self.tx .send(Update { dashboard: dashboard_lights, @@ -248,12 +186,12 @@ fn main() { rx: event_rx, })); loop { - bike_app.tick(Instant( - (std::time::SystemTime::now() + bike_app.tick(Instant(U128F0::from( + std::time::SystemTime::now() .duration_since(std::time::UNIX_EPOCH) - .unwrap()) - .as_millis(), - )); + .unwrap() + .as_millis(), + ))); std::thread::sleep(std::time::Duration::from_millis(1000 / (FPS as u64))); } }); -- 2.44.1 From 8d183d6d8cfba2f7e4799e30aac553d39b1e0acd Mon Sep 17 00:00:00 2001 From: Savanni D'Gerinel Date: Thu, 14 Dec 2023 12:41:13 -0500 Subject: [PATCH 08/16] Build some of the framework for the bike application This now sends a set of lights to the dashboard from a pico. I had to adjust some of the colors as they do not look nearly as good in lights as they do in the screen. There is no real application loop yet, no the ability to get feedback from external controls. --- Cargo.lock | 360 ++++++++++++++++++++++++++++++- bike-lights/bike/Cargo.toml | 17 +- bike-lights/bike/src/main.rs | 128 ++++++++++- bike-lights/core/src/lib.rs | 2 +- bike-lights/core/src/patterns.rs | 14 +- 5 files changed, 501 insertions(+), 20 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 2d6a554..edb3bff 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -120,6 +120,12 @@ version = "1.0.75" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "a4668cab20f66d8d020e1fbc0ebe47217433c1b6c8f2040faf858554e394ace6" +[[package]] +name = "arrayvec" +version = "0.7.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "96d30a06541fbafbc7f82ed10c06164cfbd2c401138f6addd8404629c4b16711" + [[package]] name = "async-channel" version = "1.9.0" @@ -351,6 +357,15 @@ dependencies = [ "rustc-demangle", ] +[[package]] +name = "bare-metal" +version = "0.2.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5deb64efa5bd81e31fcd1938615a6d98c82eafcbcd787162b6f63b91d6bac5b3" +dependencies = [ + "rustc_version 0.2.3", +] + [[package]] name = "base64" version = "0.9.3" @@ -377,9 +392,12 @@ checksum = "8c3c1a368f70d6cf7302d78f8f7093da241fb8e8807c05cc9e51a125895a6d5b" name = "bike" version = "0.1.0" dependencies = [ + "az", "cortex-m", "cortex-m-rt", + "embedded-alloc", "embedded-hal", + "fixed", "fugit", "lights-core", "panic-halt", @@ -407,6 +425,12 @@ version = "0.10.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "dc827186963e592360843fb5ba4b973e145841266c1357f7180c43526f2e5b61" +[[package]] +name = "bitfield" +version = "0.13.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "46afbd2983a5d5a7bd740ccb198caf5b82f45c40c09c0eed36052d91cb92e719" + [[package]] name = "bitflags" version = "1.3.2" @@ -711,6 +735,38 @@ version = "0.8.6" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "06ea2b9bc92be3c2baa9334a323ebca2d6f074ff852cd1d7b11064035cd3868f" +[[package]] +name = "cortex-m" +version = "0.7.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8ec610d8f49840a5b376c69663b6369e71f4b34484b9b2eb29fb918d92516cb9" +dependencies = [ + "bare-metal", + "bitfield", + "embedded-hal", + "volatile-register", +] + +[[package]] +name = "cortex-m-rt" +version = "0.7.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ee84e813d593101b1723e13ec38b6ab6abbdbaaa4546553f5395ed274079ddb1" +dependencies = [ + "cortex-m-rt-macros", +] + +[[package]] +name = "cortex-m-rt-macros" +version = "0.7.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f0f6f3e36f203cfedbc78b357fb28730aa2c6dc1ab060ee5c2405e843988d3c7" +dependencies = [ + "proc-macro2", + "quote", + "syn 1.0.109", +] + [[package]] name = "cpufeatures" version = "0.2.11" @@ -729,6 +785,15 @@ dependencies = [ "crc-catalog", ] +[[package]] +name = "crc-any" +version = "2.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a62ec9ff5f7965e4d7280bd5482acd20aadb50d632cf6c1d74493856b011fa73" +dependencies = [ + "debug-helper", +] + [[package]] name = "crc-catalog" version = "2.4.0" @@ -744,6 +809,12 @@ dependencies = [ "cfg-if", ] +[[package]] +name = "critical-section" +version = "1.1.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7059fff8937831a9ae6f0fe4d658ffabf58f2ca96aa9dec1c889f936f705f216" + [[package]] name = "crossbeam-deque" version = "0.8.4" @@ -845,6 +916,12 @@ version = "2.5.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "7e962a19be5cfc3f3bf6dd8f61eb50107f356ad6270fbb3ed41476571db78be5" +[[package]] +name = "debug-helper" +version = "0.3.13" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f578e8e2c440e7297e008bb5486a3a8a194775224bbc23729b0dbdfaeebf162e" + [[package]] name = "deflate" version = "0.8.6" @@ -937,6 +1014,35 @@ dependencies = [ "serde 1.0.193", ] +[[package]] +name = "embedded-alloc" +version = "0.5.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ddae17915accbac2cfbc64ea0ae6e3b330e6ea124ba108dada63646fd3c6f815" +dependencies = [ + "critical-section", + "linked_list_allocator", +] + +[[package]] +name = "embedded-dma" +version = "0.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "994f7e5b5cb23521c22304927195f236813053eb9c065dd2226a32ba64695446" +dependencies = [ + "stable_deref_trait", +] + +[[package]] +name = "embedded-hal" +version = "0.2.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "35949884794ad573cf46071e41c9b60efb0cb311e3ca01f7af807af1debc66ff" +dependencies = [ + "nb 0.1.3", + "void", +] + [[package]] name = "emseries" version = "0.6.0" @@ -1075,7 +1181,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "38e2275cc4e4fc009b0669731a1e5ab7ebf11f469eaede2bab9309a5b4d6057f" dependencies = [ "memoffset", - "rustc_version", + "rustc_version 0.4.0", ] [[package]] @@ -1253,6 +1359,45 @@ dependencies = [ "percent-encoding 2.3.1", ] +[[package]] +name = "frunk" +version = "0.4.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "11a351b59e12f97b4176ee78497dff72e4276fb1ceb13e19056aca7fa0206287" +dependencies = [ + "frunk_core", + "frunk_derives", +] + +[[package]] +name = "frunk_core" +version = "0.4.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "af2469fab0bd07e64ccf0ad57a1438f63160c69b2e57f04a439653d68eb558d6" + +[[package]] +name = "frunk_derives" +version = "0.4.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b0fa992f1656e1707946bbba340ad244f0814009ef8c0118eb7b658395f19a2e" +dependencies = [ + "frunk_proc_macro_helpers", + "quote", + "syn 2.0.48", +] + +[[package]] +name = "frunk_proc_macro_helpers" +version = "0.1.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "35b54add839292b743aeda6ebedbd8b11e93404f902c56223e51b9ec18a13d2c" +dependencies = [ + "frunk_core", + "proc-macro2", + "quote", + "syn 2.0.48", +] + [[package]] name = "ft-core" version = "0.1.0" @@ -1272,6 +1417,15 @@ version = "0.1.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "a06f77d526c1a601b7c4cdd98f54b5eaabffc14d5f2f0296febdc7f357c6d3ba" +[[package]] +name = "fugit" +version = "0.3.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "17186ad64927d5ac8f02c1e77ccefa08ccd9eaa314d5a4772278aa204a22f7e7" +dependencies = [ + "gcd", +] + [[package]] name = "futures" version = "0.3.29" @@ -1400,6 +1554,12 @@ dependencies = [ "slab", ] +[[package]] +name = "gcd" +version = "2.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1d758ba1b47b00caf47f24925c0074ecb20d6dfcffe7f6d53395c0465674841a" + [[package]] name = "gdk-pixbuf" version = "0.18.3" @@ -2207,6 +2367,15 @@ dependencies = [ "windows-sys 0.48.0", ] +[[package]] +name = "itertools" +version = "0.10.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b0fd2260e829bddf4cb6ea802289de2f86d6a7a690192fbe91b3f46e0f2c8473" +dependencies = [ + "either", +] + [[package]] name = "itertools" version = "0.12.0" @@ -2342,6 +2511,12 @@ dependencies = [ "fixed", ] +[[package]] +name = "linked_list_allocator" +version = "0.10.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9afa463f5405ee81cdb9cc2baf37e08ec7e4c8209442b5d72c04cfb2cd6e6286" + [[package]] name = "linux-raw-sys" version = "0.3.8" @@ -2570,6 +2745,21 @@ dependencies = [ "tempfile", ] +[[package]] +name = "nb" +version = "0.1.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "801d31da0513b6ec5214e9bf433a77966320625a37860f910be265be6e18d06f" +dependencies = [ + "nb 1.1.0", +] + +[[package]] +name = "nb" +version = "1.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8d5439c4ad607c3c23abf66de8c8bf57ba8adcd1f129e699851a6e43935d339d" + [[package]] name = "nix" version = "0.27.1" @@ -2685,6 +2875,26 @@ dependencies = [ "libc", ] +[[package]] +name = "num_enum" +version = "0.5.11" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1f646caf906c20226733ed5b1374287eb97e3c2a5c227ce668c1f2ce20ae57c9" +dependencies = [ + "num_enum_derive", +] + +[[package]] +name = "num_enum_derive" +version = "0.5.11" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "dcbff9bc912032c62bf65ef1d5aea88983b420f4f839db1e9b0c281a25c9c799" +dependencies = [ + "proc-macro2", + "quote", + "syn 1.0.109", +] + [[package]] name = "object" version = "0.32.1" @@ -2807,6 +3017,12 @@ dependencies = [ "system-deps", ] +[[package]] +name = "panic-halt" +version = "0.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "de96540e0ebde571dc55c73d60ef407c653844e6f9a1e2fdbd40c07b9252d812" + [[package]] name = "parking" version = "2.2.0" @@ -2981,6 +3197,17 @@ version = "0.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "8b870d8c151b6f2fb93e84a13146138f05d02ed11c7e7c54f8826aaaf7c9f184" +[[package]] +name = "pio" +version = "0.2.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "76e09694b50f89f302ed531c1f2a7569f0be5867aee4ab4f8f729bbeec0078e3" +dependencies = [ + "arrayvec", + "num_enum", + "paste", +] + [[package]] name = "piper" version = "0.2.1" @@ -3491,6 +3718,76 @@ dependencies = [ "thiserror", ] +[[package]] +name = "rp-pico" +version = "0.8.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6341771e6f8e5d130b2b3cbc23435b7847761adf198af09f4b2a60407d43bd56" +dependencies = [ + "cortex-m-rt", + "fugit", + "rp2040-boot2", + "rp2040-hal", + "usb-device", +] + +[[package]] +name = "rp2040-boot2" +version = "0.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7c92f344f63f950ee36cf4080050e4dce850839b9175da38f9d2ffb69b4dbb21" +dependencies = [ + "crc-any", +] + +[[package]] +name = "rp2040-hal" +version = "0.9.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1ff2b9ae7e6dd6720fd9f64250c9087260e50fe98b6b032ccca65be3581167ca" +dependencies = [ + "cortex-m", + "critical-section", + "embedded-dma", + "embedded-hal", + "frunk", + "fugit", + "itertools 0.10.5", + "nb 1.1.0", + "paste", + "pio", + "rand_core 0.6.4", + "rp2040-hal-macros", + "rp2040-pac", + "usb-device", + "vcell", + "void", +] + +[[package]] +name = "rp2040-hal-macros" +version = "0.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "86479063e497efe1ae81995ef9071f54fd1c7427e04d6c5b84cde545ff672a5e" +dependencies = [ + "cortex-m-rt", + "proc-macro2", + "quote", + "syn 1.0.109", +] + +[[package]] +name = "rp2040-pac" +version = "0.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "12d9d8375815f543f54835d01160d4e47f9e2cae75f17ff8f1ec19ce1da96e4c" +dependencies = [ + "cortex-m", + "cortex-m-rt", + "critical-section", + "vcell", +] + [[package]] name = "rsa" version = "0.9.6" @@ -3523,13 +3820,22 @@ version = "1.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "08d43f7aa6b08d49f382cde6a7982047c3426db949b1424bc4b7ec9ae12c6ce2" +[[package]] +name = "rustc_version" +version = "0.2.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "138e3e0acb6c9fb258b19b67cb8abd63c00679d2851805ea151465464fe9030a" +dependencies = [ + "semver 0.9.0", +] + [[package]] name = "rustc_version" version = "0.4.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "bfa0f585226d2e68097d4f95d113b15b83a82e819ab25717ec0590d9584ef366" dependencies = [ - "semver", + "semver 1.0.20", ] [[package]] @@ -3665,12 +3971,27 @@ version = "1.0.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "e388332cd64eb80cd595a00941baf513caffae8dce9cfd0467fc9c66397dade6" +[[package]] +name = "semver" +version = "0.9.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1d7eb9ef2c18661902cc47e535f9bc51b78acd254da71d375c2f6720d9a40403" +dependencies = [ + "semver-parser", +] + [[package]] name = "semver" version = "1.0.20" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "836fa6a3e1e547f9a2c4040802ec865b5d85f4014efe00555d7090a3dcaa1090" +[[package]] +name = "semver-parser" +version = "0.7.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "388a1df253eca08550bef6c72392cfe7c30914bf41df5269b68cbd6ff8f570a3" + [[package]] name = "serde" version = "0.9.15" @@ -3888,7 +4209,7 @@ version = "0.2.3" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "ce81b7bd7c4493975347ef60d8c7e8b742d4694f4c49f93e0a12ea263938176c" dependencies = [ - "itertools", + "itertools 0.12.0", "nom", "unicode_categories", ] @@ -4089,6 +4410,12 @@ dependencies = [ "urlencoding", ] +[[package]] +name = "stable_deref_trait" +version = "1.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a8f112729512f8e442d81f95a8a7ddf2b7c6b8a1a6f509a95864142b30cab2d3" + [[package]] name = "stringprep" version = "0.1.4" @@ -4679,6 +5006,12 @@ version = "2.1.3" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "daf8dba3b7eb870caf1ddeed7bc9d2a049f3cfdfae7cb521b087cc33ae4c49da" +[[package]] +name = "usb-device" +version = "0.2.9" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1f6cc3adc849b5292b4075fc0d5fdcf2f24866e88e336dd27a8943090a520508" + [[package]] name = "utf-8" version = "0.7.6" @@ -4726,6 +5059,12 @@ version = "1.7.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "126e423afe2dd9ac52142e7e9d5ce4135d7e13776c529d27fd6bc49f19e3280b" +[[package]] +name = "vcell" +version = "0.1.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "77439c1b53d2303b20d9459b1ade71a83c716e3f9c34f3228c00e6f185d6c002" + [[package]] name = "vcpkg" version = "0.2.15" @@ -4762,6 +5101,21 @@ dependencies = [ "warp", ] +[[package]] +name = "void" +version = "1.0.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6a02e4885ed3bc0f2de90ea6dd45ebcbb66dacffe03547fadbb0eeae2770887d" + +[[package]] +name = "volatile-register" +version = "0.2.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "de437e2a6208b014ab52972a27e59b33fa2920d3e00fe05026167a1c509d19cc" +dependencies = [ + "vcell", +] + [[package]] name = "wait-timeout" version = "0.2.0" diff --git a/bike-lights/bike/Cargo.toml b/bike-lights/bike/Cargo.toml index 80fc201..e62c730 100644 --- a/bike-lights/bike/Cargo.toml +++ b/bike-lights/bike/Cargo.toml @@ -6,10 +6,13 @@ edition = "2021" # See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html [dependencies] -cortex-m = "0.7.7" -cortex-m-rt = "0.7.3" -embedded-hal = "0.2.7" -fugit = "0.3.7" -panic-halt = "0.2.0" -rp-pico = "0.8.0" -lights-core = { path = "../core" } +az = { version = "1" } +cortex-m-rt = { version = "0.7.3" } +cortex-m = { version = "0.7.7" } +embedded-alloc = { version = "0.5.1" } +embedded-hal = { version = "0.2.7" } +fixed = { version = "1" } +fugit = { version = "0.3.7" } +lights-core = { path = "../core" } +panic-halt = { version = "0.2.0" } +rp-pico = { version = "0.8.0" } diff --git a/bike-lights/bike/src/main.rs b/bike-lights/bike/src/main.rs index 824e3b4..4e45da7 100644 --- a/bike-lights/bike/src/main.rs +++ b/bike-lights/bike/src/main.rs @@ -1,10 +1,134 @@ #![no_main] #![no_std] +extern crate alloc; + +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 fixed::types::I16F16; +use fugit::RateExtU32; +use lights_core::{ + BodyPattern, DashboardPattern, Event, TRANS_PRIDE_BODY, TRANS_PRIDE_DASHBOARD, UI, +}; use panic_halt as _; -use rp_pico::entry; +use rp_pico::{ + entry, + hal::{ + clocks::init_clocks_and_plls, + pac::{CorePeripherals, Peripherals}, + spi::{Enabled, Spi, SpiDevice, ValidSpiPinout}, + watchdog::Watchdog, + Clock, Sio, + }, + Pins, +}; + +#[global_allocator] +static HEAP: Heap = Heap::empty(); + +const LIGHT_SCALE: I16F16 = I16F16::lit("256.0"); +const GLOBAL_BRIGHTESS: u8 = 1; + +struct BikeUI> { + spi: RefCell>, +} + +impl> BikeUI { + fn new(spi: Spi) -> Self { + Self { + spi: RefCell::new(spi), + } + } +} + +impl> UI for BikeUI { + fn check_event(&self) -> Option { + None + } + + fn update_lights(&self, dashboard_lights: DashboardPattern, body_lights: BodyPattern) { + let mut lights: [u8; 20] = [0; 20]; + lights[16] = 0xff; + lights[17] = 0xff; + lights[18] = 0xff; + lights[19] = 0xff; + for (idx, rgb) in dashboard_lights.iter().enumerate() { + lights[(idx + 1) * 4 + 0] = 0xe0 + GLOBAL_BRIGHTESS; + lights[(idx + 1) * 4 + 1] = (I16F16::from(rgb.r) * LIGHT_SCALE).saturating_as(); + lights[(idx + 1) * 4 + 2] = (I16F16::from(rgb.b) * LIGHT_SCALE).saturating_as(); + lights[(idx + 1) * 4 + 3] = (I16F16::from(rgb.g) * LIGHT_SCALE).saturating_as(); + } + let mut spi = self.spi.borrow_mut(); + spi.write(lights.as_slice()); + } +} #[entry] fn main() -> ! { - loop {} + { + use core::mem::MaybeUninit; + const HEAP_SIZE: usize = 8096; + static mut HEAP_MEM: [MaybeUninit; HEAP_SIZE] = [MaybeUninit::uninit(); HEAP_SIZE]; + unsafe { HEAP.init(HEAP_MEM.as_ptr() as usize, HEAP_SIZE) } + } + + let mut pac = Peripherals::take().unwrap(); + let core = CorePeripherals::take().unwrap(); + let sio = Sio::new(pac.SIO); + let mut watchdog = Watchdog::new(pac.WATCHDOG); + + let pins = Pins::new( + pac.IO_BANK0, + pac.PADS_BANK0, + sio.gpio_bank0, + &mut pac.RESETS, + ); + + let clocks = init_clocks_and_plls( + 12_000_000u32, + pac.XOSC, + pac.CLOCKS, + pac.PLL_SYS, + pac.PLL_USB, + &mut pac.RESETS, + &mut watchdog, + ) + .ok() + .unwrap(); + + let mut delay = Delay::new(core.SYST, clocks.system_clock.freq().to_Hz()); + let mut spi_clk = pins.gpio10.into_function(); + let mut spi_sdo = pins.gpio11.into_function(); + let spi = Spi::<_, _, _, 8>::new(pac.SPI1, (spi_sdo, spi_clk)); + let mut spi = spi.init( + &mut pac.RESETS, + clocks.peripheral_clock.freq(), + 1_u32.MHz(), + embedded_hal::spi::MODE_1, + ); + + let ui = BikeUI::new(spi); + + // let app = App::new(Box::new(ui)); + // app.tick(TRANS_PRIDE_DASHBOARD, TRANS_PRIDE_BODY); + ui.update_lights(TRANS_PRIDE_DASHBOARD, TRANS_PRIDE_BODY); + + /* + spi.write(&[ + 0, 0, 0, 0, 0xe1, 0x80, 0x00, 0x00, 0xe1, 0x00, 0x80, 0x00, 0xe1, 0x00, 0x00, 0x80, 0xff, + 0xff, 0xff, 0xff, + ]); + */ + + let mut led_pin = pins.led.into_push_pull_output(); + + loop { + led_pin.set_high().unwrap(); + delay.delay_ms(500); + led_pin.set_low().unwrap(); + delay.delay_ms(500); + } } diff --git a/bike-lights/core/src/lib.rs b/bike-lights/core/src/lib.rs index c8523eb..361d39b 100644 --- a/bike-lights/core/src/lib.rs +++ b/bike-lights/core/src/lib.rs @@ -4,7 +4,7 @@ extern crate alloc; use alloc::boxed::Box; use az::*; use core::{clone::Clone, cmp::PartialEq, ops::Sub, option::Option}; -use fixed::types::{I16F0, I16F16, I48F16, I8F8, U128F0, U16F0}; +use fixed::types::{I48F16, I8F8, U128F0, U16F0}; mod patterns; pub use patterns::*; diff --git a/bike-lights/core/src/patterns.rs b/bike-lights/core/src/patterns.rs index e566a5d..0c8f609 100644 --- a/bike-lights/core/src/patterns.rs +++ b/bike-lights/core/src/patterns.rs @@ -46,12 +46,12 @@ pub const PRIDE_YELLOW: RGB = RGB { pub const PRIDE_GREEN: RGB = RGB { r: I8F8::lit("0"), g: I8F8::lit("0.5"), - b: I8F8::lit("0.14"), + b: I8F8::lit("0.05"), }; pub const PRIDE_INDIGO: RGB = RGB { - r: I8F8::lit("0.14"), - g: I8F8::lit("0.25"), + r: I8F8::lit("0.04"), + g: I8F8::lit("0.15"), b: I8F8::lit("0.55"), }; @@ -62,15 +62,15 @@ pub const PRIDE_VIOLET: RGB = RGB { }; pub const TRANS_BLUE: RGB = RGB { - r: I8F8::lit("0.36"), - g: I8F8::lit("0.81"), + r: I8F8::lit("0.06"), + g: I8F8::lit("0.41"), b: I8F8::lit("0.98"), }; pub const TRANS_PINK: RGB = RGB { r: I8F8::lit("0.96"), - g: I8F8::lit("0.66"), - b: I8F8::lit("0.72"), + g: I8F8::lit("0.16"), + b: I8F8::lit("0.32"), }; pub const OFF_DASHBOARD: DashboardPattern = [RGB_OFF; 3]; -- 2.44.1 From ef5415303b0d323c8a2e800a28893e0395c23cd5 Mon Sep 17 00:00:00 2001 From: Savanni D'Gerinel Date: Thu, 14 Dec 2023 18:00:45 -0500 Subject: [PATCH 09/16] Start monitoring events --- bike-lights/bike/src/main.rs | 99 +++++++++++++++++++++++++++--------- bike-lights/core/src/lib.rs | 22 +++++++- 2 files changed, 97 insertions(+), 24 deletions(-) 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; -- 2.44.1 From 54c4b99ab632efa0c276d5af4d811f1946e4006c Mon Sep 17 00:00:00 2001 From: Savanni D'Gerinel Date: Thu, 14 Dec 2023 22:03:51 -0500 Subject: [PATCH 10/16] Improve the blinker animations and state transitions when switching blinkers --- bike-lights/bike/src/main.rs | 43 ++++++----- bike-lights/core/src/lib.rs | 119 +++++++++++++++++++++---------- bike-lights/core/src/patterns.rs | 2 +- 3 files changed, 102 insertions(+), 62 deletions(-) diff --git a/bike-lights/bike/src/main.rs b/bike-lights/bike/src/main.rs index b309376..48b809a 100644 --- a/bike-lights/bike/src/main.rs +++ b/bike-lights/bike/src/main.rs @@ -11,13 +11,13 @@ use embedded_alloc::Heap; use embedded_hal::{blocking::spi::Write, digital::v2::InputPin}; use fixed::types::I16F16; use fugit::RateExtU32; -use lights_core::{App, BodyPattern, DashboardPattern, Event, Instant, State, FPS, UI}; +use lights_core::{App, BodyPattern, DashboardPattern, Event, Instant, FPS, UI}; use panic_halt as _; use rp_pico::{ entry, hal::{ clocks::init_clocks_and_plls, - gpio::{FunctionSio, Pin, PinId, PullDown, SioInput}, + gpio::{FunctionSio, Pin, PinId, PullUp, SioInput}, pac::{CorePeripherals, Peripherals}, spi::{Enabled, Spi, SpiDevice, ValidSpiPinout}, watchdog::Watchdog, @@ -30,7 +30,8 @@ use rp_pico::{ static HEAP: Heap = Heap::empty(); const LIGHT_SCALE: I16F16 = I16F16::lit("256.0"); -const GLOBAL_BRIGHTESS: u8 = 1; +const DASHBOARD_BRIGHTESS: u8 = 1; +const BODY_BRIGHTNESS: u8 = 8; struct BikeUI< D: SpiDevice, @@ -41,10 +42,10 @@ struct BikeUI< NextId: PinId, > { spi: RefCell>, - left_blinker_button: Pin, PullDown>, - right_blinker_button: Pin, PullDown>, - previous_animation_button: Pin, PullDown>, - next_animation_button: Pin, PullDown>, + left_blinker_button: Pin, PullUp>, + right_blinker_button: Pin, PullUp>, + previous_animation_button: Pin, PullUp>, + next_animation_button: Pin, PullUp>, } impl< @@ -58,10 +59,10 @@ impl< { fn new( spi: Spi, - left_blinker_button: Pin, PullDown>, - right_blinker_button: Pin, PullDown>, - previous_animation_button: Pin, PullDown>, - next_animation_button: Pin, PullDown>, + left_blinker_button: Pin, PullUp>, + right_blinker_button: Pin, PullUp>, + previous_animation_button: Pin, PullUp>, + next_animation_button: Pin, PullUp>, ) -> Self { Self { spi: RefCell::new(spi), @@ -83,13 +84,13 @@ impl< > UI for BikeUI { fn check_event(&self) -> Option { - if self.left_blinker_button.is_high().unwrap_or(false) { + if self.left_blinker_button.is_low().unwrap_or(false) { Some(Event::LeftBlinker) - } else if self.right_blinker_button.is_high().unwrap_or(false) { + } else if self.right_blinker_button.is_low().unwrap_or(false) { Some(Event::RightBlinker) - } else if self.previous_animation_button.is_high().unwrap_or(false) { + } else if self.previous_animation_button.is_low().unwrap_or(false) { Some(Event::PreviousPattern) - } else if self.next_animation_button.is_high().unwrap_or(false) { + } else if self.next_animation_button.is_low().unwrap_or(false) { Some(Event::NextPattern) } else { None @@ -98,14 +99,12 @@ impl< 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; lights[19] = 0xff; for (idx, rgb) in dashboard_lights.iter().enumerate() { - lights[(idx + 1) * 4 + 0] = 0xe0 + GLOBAL_BRIGHTESS; + lights[(idx + 1) * 4 + 0] = 0xe0 + DASHBOARD_BRIGHTESS; lights[(idx + 1) * 4 + 1] = (I16F16::from(rgb.r) * LIGHT_SCALE).saturating_as(); lights[(idx + 1) * 4 + 2] = (I16F16::from(rgb.b) * LIGHT_SCALE).saturating_as(); lights[(idx + 1) * 4 + 3] = (I16F16::from(rgb.g) * LIGHT_SCALE).saturating_as(); @@ -159,10 +158,10 @@ fn main() -> ! { embedded_hal::spi::MODE_1, ); - 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 left_blinker_button = pins.gpio18.into_pull_up_input(); + let right_blinker_button = pins.gpio19.into_pull_up_input(); + let previous_animation_button = pins.gpio20.into_pull_up_input(); + let next_animation_button = pins.gpio21.into_pull_up_input(); let ui = BikeUI::new( spi, diff --git a/bike-lights/core/src/lib.rs b/bike-lights/core/src/lib.rs index 28e803c..6bdf9b1 100644 --- a/bike-lights/core/src/lib.rs +++ b/bike-lights/core/src/lib.rs @@ -169,6 +169,7 @@ impl Animation for Fade { #[derive(Debug)] pub enum FadeDirection { + Transition, FadeIn, FadeOut, } @@ -179,6 +180,7 @@ pub enum BlinkerDirection { } pub struct Blinker { + transition: Fade, fade_in: Fade, fade_out: Fade, direction: FadeDirection, @@ -191,10 +193,12 @@ 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 = starting_dashboard.clone(); + let mut ending_dashboard = home_dashboard.clone(); match direction { BlinkerDirection::Left => { @@ -209,7 +213,7 @@ impl Blinker { } } - let mut ending_body = starting_body.clone(); + let mut ending_body = home_body.clone(); match direction { BlinkerDirection::Left => { for i in 0..30 { @@ -228,7 +232,7 @@ impl Blinker { } Blinker { - fade_in: Fade::new( + transition: Fade::new( starting_dashboard.clone(), starting_body.clone(), ending_dashboard.clone(), @@ -236,15 +240,23 @@ impl Blinker { BLINKER_FRAMES, time, ), + fade_in: Fade::new( + home_dashboard.clone(), + home_body.clone(), + ending_dashboard.clone(), + ending_body.clone(), + BLINKER_FRAMES, + time, + ), fade_out: Fade::new( ending_dashboard.clone(), ending_body.clone(), - starting_dashboard.clone(), - starting_body.clone(), + home_dashboard.clone(), + home_body.clone(), BLINKER_FRAMES, time, ), - direction: FadeDirection::FadeIn, + direction: FadeDirection::Transition, start_time: time, frames: BLINKER_FRAMES, } @@ -256,6 +268,10 @@ impl Animation for Blinker { let frames = calculate_frames(self.start_time.0, time.0); if frames > self.frames { match self.direction { + FadeDirection::Transition => { + self.direction = FadeDirection::FadeOut; + self.fade_out.start_time = time; + } FadeDirection::FadeIn => { self.direction = FadeDirection::FadeOut; self.fade_out.start_time = time; @@ -269,6 +285,7 @@ impl Animation for Blinker { } match self.direction { + FadeDirection::Transition => self.transition.tick(time), FadeDirection::FadeIn => self.fade_in.tick(time), FadeDirection::FadeOut => self.fade_out.tick(time), } @@ -285,9 +302,45 @@ pub enum Event { RightBlinker, } +#[derive(Clone, Copy, PartialEq)] +pub enum Pattern { + GayPride, + TransPride, +} + +impl Pattern { + fn previous(&self) -> Pattern { + match self { + Pattern::GayPride => Pattern::TransPride, + Pattern::TransPride => Pattern::GayPride, + } + } + + fn next(&self) -> Pattern { + match self { + Pattern::GayPride => Pattern::TransPride, + Pattern::TransPride => Pattern::GayPride, + } + } + + fn dashboard(&self) -> DashboardPattern { + match self { + Pattern::GayPride => PRIDE_DASHBOARD, + Pattern::TransPride => TRANS_PRIDE_DASHBOARD, + } + } + + fn body(&self) -> BodyPattern { + match self { + Pattern::GayPride => PRIDE_BODY, + Pattern::TransPride => TRANS_PRIDE_BODY, + } + } +} + #[derive(Clone, PartialEq)] pub enum State { - Pattern(u8), + Pattern(Pattern), Brake, LeftBlinker, RightBlinker, @@ -298,7 +351,7 @@ pub enum State { pub struct App { ui: Box, state: State, - home_state: State, + home_pattern: Pattern, current_animation: Box, dashboard_lights: DashboardPattern, lights: BodyPattern, @@ -308,8 +361,8 @@ impl App { pub fn new(ui: Box) -> Self { Self { ui, - state: State::Pattern(0), - home_state: State::Pattern(0), + state: State::Pattern(Pattern::GayPride), + home_pattern: Pattern::GayPride, current_animation: Box::new(DefaultAnimation {}), dashboard_lights: OFF_DASHBOARD, lights: OFF_BODY, @@ -318,27 +371,16 @@ impl App { fn update_animation(&mut self, time: Instant) { match self.state { - State::Pattern(0) => { + State::Pattern(ref pattern) => { self.current_animation = Box::new(Fade::new( self.dashboard_lights.clone(), self.lights.clone(), - PRIDE_DASHBOARD, - PRIDE_BODY, + pattern.dashboard(), + pattern.body(), DEFAULT_FRAMES, time, )) } - State::Pattern(1) => { - self.current_animation = Box::new(Fade::new( - self.dashboard_lights.clone(), - self.lights.clone(), - TRANS_PRIDE_DASHBOARD, - TRANS_PRIDE_BODY, - DEFAULT_FRAMES, - time, - )) - } - State::Pattern(_) => {} State::Brake => { self.current_animation = Box::new(Fade::new( self.dashboard_lights.clone(), @@ -353,6 +395,8 @@ 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, )); @@ -361,6 +405,8 @@ 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, )); @@ -374,41 +420,36 @@ impl App { match event { Event::Brake => { if self.state == State::Brake { - self.state = self.home_state.clone(); + self.state = State::Pattern(self.home_pattern); } else { self.state = State::Brake; } } - Event::BrakeRelease => self.state = self.home_state.clone(), + Event::BrakeRelease => self.state = State::Pattern(self.home_pattern), Event::LeftBlinker => match self.state { State::Brake => self.state = State::BrakeLeftBlinker, State::BrakeLeftBlinker => self.state = State::Brake, - State::LeftBlinker => self.state = self.home_state.clone(), + State::LeftBlinker => self.state = State::Pattern(self.home_pattern), _ => self.state = State::LeftBlinker, }, Event::NextPattern => match self.state { - State::Pattern(i) => { - let next = i + 1; - self.state = State::Pattern(if next > 1 { 0 } else { next }); - self.home_state = self.state.clone(); + State::Pattern(ref pattern) => { + self.home_pattern = pattern.next(); + self.state = State::Pattern(self.home_pattern); } _ => (), }, Event::PreviousPattern => match self.state { - State::Pattern(i) => { - if i == 0 { - self.state = State::Pattern(1); - } else { - self.state = State::Pattern(i - 1); - } - self.home_state = self.state.clone(); + State::Pattern(ref pattern) => { + self.home_pattern = pattern.previous(); + self.state = State::Pattern(self.home_pattern); } _ => (), }, Event::RightBlinker => match self.state { State::Brake => self.state = State::BrakeRightBlinker, State::BrakeRightBlinker => self.state = State::Brake, - State::RightBlinker => self.state = self.home_state.clone(), + State::RightBlinker => self.state = State::Pattern(self.home_pattern), _ => self.state = State::RightBlinker, }, } diff --git a/bike-lights/core/src/patterns.rs b/bike-lights/core/src/patterns.rs index 0c8f609..fbaab4e 100644 --- a/bike-lights/core/src/patterns.rs +++ b/bike-lights/core/src/patterns.rs @@ -21,7 +21,7 @@ pub const BRAKES_RED: RGB = RGB { pub const BLINKER_AMBER: RGB = RGB { r: I8F8::lit("1"), - g: I8F8::lit("0.74"), + g: I8F8::lit("0.15"), b: I8F8::lit("0"), }; -- 2.44.1 From d7a70119c8beb16c72c1d04351fb7c5c97222dfc Mon Sep 17 00:00:00 2001 From: Savanni D'Gerinel Date: Sun, 17 Dec 2023 10:42:47 -0500 Subject: [PATCH 11/16] Send out the full set of lights --- bike-lights/bike/src/main.rs | 16 +++++++++++----- 1 file changed, 11 insertions(+), 5 deletions(-) diff --git a/bike-lights/bike/src/main.rs b/bike-lights/bike/src/main.rs index 48b809a..a683804 100644 --- a/bike-lights/bike/src/main.rs +++ b/bike-lights/bike/src/main.rs @@ -98,17 +98,23 @@ impl< } fn update_lights(&self, dashboard_lights: DashboardPattern, body_lights: BodyPattern) { - let mut lights: [u8; 20] = [0; 20]; - lights[16] = 0xff; - lights[17] = 0xff; - lights[18] = 0xff; - lights[19] = 0xff; + let mut lights: [u8; 260] = [0; 260]; + lights[256] = 0xff; + lights[257] = 0xff; + lights[258] = 0xff; + lights[259] = 0xff; for (idx, rgb) in dashboard_lights.iter().enumerate() { lights[(idx + 1) * 4 + 0] = 0xe0 + DASHBOARD_BRIGHTESS; lights[(idx + 1) * 4 + 1] = (I16F16::from(rgb.r) * LIGHT_SCALE).saturating_as(); lights[(idx + 1) * 4 + 2] = (I16F16::from(rgb.b) * LIGHT_SCALE).saturating_as(); lights[(idx + 1) * 4 + 3] = (I16F16::from(rgb.g) * LIGHT_SCALE).saturating_as(); } + 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(); + } let mut spi = self.spi.borrow_mut(); spi.write(lights.as_slice()); } -- 2.44.1 From 80d8dedbaff568cde7aa1ea157c58487422d3506 Mon Sep 17 00:00:00 2001 From: Savanni D'Gerinel Date: Fri, 29 Dec 2023 16:15:25 -0500 Subject: [PATCH 12/16] Adjust colors and the blinker patterns --- bike-lights/bike/src/main.rs | 61 +++++++++++++++++++++++-------- bike-lights/core/src/lib.rs | 24 +++++------- bike-lights/core/src/patterns.rs | 20 +++++----- bike-lights/simulator/src/main.rs | 2 +- 4 files changed, 65 insertions(+), 42 deletions(-) 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, -- 2.44.1 From 2b0fc7639efc11cb86481a55dfa3fab961de57ca Mon Sep 17 00:00:00 2001 From: Savanni D'Gerinel Date: Fri, 29 Dec 2023 17:51:15 -0500 Subject: [PATCH 13/16] Debounce buttons, fix colors, and add a new water pattern --- bike-lights/bike/src/main.rs | 2 +- bike-lights/core/src/lib.rs | 31 +++++++++++++++++++++++-------- bike-lights/core/src/patterns.rs | 22 ++++++++++++++++++++++ 3 files changed, 46 insertions(+), 9 deletions(-) diff --git a/bike-lights/bike/src/main.rs b/bike-lights/bike/src/main.rs index 962e0dc..c9fa1ad 100644 --- a/bike-lights/bike/src/main.rs +++ b/bike-lights/bike/src/main.rs @@ -54,7 +54,7 @@ impl DebouncedButton

{ } fn set_debounce(&mut self, time: Instant) { - self.debounce = time + Instant((100 as u32).into()); + self.debounce = time + Instant((250 as u32).into()); } } diff --git a/bike-lights/core/src/lib.rs b/bike-lights/core/src/lib.rs index b686d83..3bc79be 100644 --- a/bike-lights/core/src/lib.rs +++ b/bike-lights/core/src/lib.rs @@ -69,13 +69,15 @@ pub trait Animation { fn tick(&mut self, time: Instant) -> (DashboardPattern, BodyPattern); } +/* pub struct DefaultAnimation {} impl Animation for DefaultAnimation { fn tick(&mut self, _: Instant) -> (DashboardPattern, BodyPattern) { - (PRIDE_DASHBOARD, PRIDE_BODY) + (WATER_DASHBOARD, WATER_BODY) } } +*/ pub struct Fade { starting_dashboard: DashboardPattern, @@ -300,8 +302,9 @@ pub enum Event { RightBlinker, } -#[derive(Clone, Copy, PartialEq)] +#[derive(Clone, Copy, Debug, PartialEq)] pub enum Pattern { + Water, GayPride, TransPride, } @@ -309,20 +312,23 @@ pub enum Pattern { impl Pattern { fn previous(&self) -> Pattern { match self { - Pattern::GayPride => Pattern::TransPride, + Pattern::Water => Pattern::TransPride, + Pattern::GayPride => Pattern::Water, Pattern::TransPride => Pattern::GayPride, } } fn next(&self) -> Pattern { match self { + Pattern::Water => Pattern::GayPride, Pattern::GayPride => Pattern::TransPride, - Pattern::TransPride => Pattern::GayPride, + Pattern::TransPride => Pattern::Water, } } fn dashboard(&self) -> DashboardPattern { match self { + Pattern::Water => WATER_DASHBOARD, Pattern::GayPride => PRIDE_DASHBOARD, Pattern::TransPride => TRANS_PRIDE_DASHBOARD, } @@ -330,13 +336,14 @@ impl Pattern { fn body(&self) -> BodyPattern { match self { + Pattern::Water => OFF_BODY, Pattern::GayPride => PRIDE_BODY, Pattern::TransPride => TRANS_PRIDE_BODY, } } } -#[derive(Clone, PartialEq)] +#[derive(Clone, Debug, PartialEq)] pub enum State { Pattern(Pattern), Brake, @@ -357,11 +364,19 @@ pub struct App { impl App { pub fn new(ui: Box) -> Self { + let pattern = Pattern::Water; Self { ui, - state: State::Pattern(Pattern::GayPride), - home_pattern: Pattern::GayPride, - current_animation: Box::new(DefaultAnimation {}), + state: State::Pattern(pattern), + home_pattern: pattern, + current_animation: Box::new(Fade::new( + OFF_DASHBOARD, + OFF_BODY, + pattern.dashboard(), + pattern.body(), + DEFAULT_FRAMES, + Instant((0 as u32).into()), + )), dashboard_lights: OFF_DASHBOARD, lights: OFF_BODY, } diff --git a/bike-lights/core/src/patterns.rs b/bike-lights/core/src/patterns.rs index 41b9f99..12fb7ed 100644 --- a/bike-lights/core/src/patterns.rs +++ b/bike-lights/core/src/patterns.rs @@ -73,11 +73,33 @@ pub const TRANS_PINK: RGB = RGB { b: I8F8::lit("0.32"), }; +pub const WATER_1: RGB = RGB { + r: I8F8::lit("0.0"), + g: I8F8::lit("0.0"), + b: I8F8::lit("0.75"), +}; + +pub const WATER_2: RGB = RGB { + r: I8F8::lit("0.8"), + g: I8F8::lit("0.8"), + b: I8F8::lit("0.8"), +}; + +pub const WATER_3: RGB = RGB { + r: I8F8::lit("0.00"), + g: I8F8::lit("0.75"), + b: I8F8::lit("0.75"), +}; + pub const OFF_DASHBOARD: DashboardPattern = [RGB_OFF; 3]; pub const OFF_BODY: BodyPattern = [RGB_OFF; 60]; pub const DEFAULT_FRAMES: U16F0 = U16F0::lit("30"); +pub const WATER_DASHBOARD: DashboardPattern = [WATER_1, WATER_2, WATER_3]; + +pub const WATER_BODY: BodyPattern = [RGB_OFF; 60]; + pub const PRIDE_DASHBOARD: DashboardPattern = [PRIDE_RED, PRIDE_GREEN, PRIDE_INDIGO]; pub const PRIDE_BODY: BodyPattern = [ -- 2.44.1 From 291663d4a3249c3e4b9493ff71fcc96a6c6a06e0 Mon Sep 17 00:00:00 2001 From: Savanni D'Gerinel Date: Mon, 8 Jul 2024 09:35:44 -0400 Subject: [PATCH 14/16] Re-add the armv6 toolchain --- rust-toolchain | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/rust-toolchain b/rust-toolchain index 09aa8a4..10e3c69 100644 --- a/rust-toolchain +++ b/rust-toolchain @@ -1,3 +1,3 @@ [toolchain] channel = "1.77.0" -targets = [ "wasm32-unknown-unknown" ] +targets = [ "wasm32-unknown-unknown", "thumbv6m-none-eabi" ] -- 2.44.1 From 37c7e048203a4fb8849ec1f1e7af62ba681d8de6 Mon Sep 17 00:00:00 2001 From: Savanni D'Gerinel Date: Sat, 20 Jul 2024 11:21:16 -0400 Subject: [PATCH 15/16] Turn on the built-in LED when software starts up --- bike-lights/bike/src/main.rs | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/bike-lights/bike/src/main.rs b/bike-lights/bike/src/main.rs index c9fa1ad..a6e9d7f 100644 --- a/bike-lights/bike/src/main.rs +++ b/bike-lights/bike/src/main.rs @@ -8,7 +8,7 @@ use az::*; use core::cell::RefCell; use cortex_m::delay::Delay; use embedded_alloc::Heap; -use embedded_hal::{blocking::spi::Write, digital::v2::InputPin}; +use embedded_hal::{blocking::spi::Write, digital::v2::InputPin, digital::v2::OutputPin}; use fixed::types::I16F16; use fugit::RateExtU32; use lights_core::{App, BodyPattern, DashboardPattern, Event, Instant, FPS, UI}; @@ -209,6 +209,7 @@ fn main() -> ! { let mut app = App::new(Box::new(ui)); let mut led_pin = pins.led.into_push_pull_output(); + led_pin.set_high(); let mut time = Instant::default(); let delay_ms = 1000 / (FPS as u32); -- 2.44.1 From 70c013218af24459e551180685a45fe12edd6298 Mon Sep 17 00:00:00 2001 From: Savanni D'Gerinel Date: Tue, 30 Jul 2024 14:50:14 -0400 Subject: [PATCH 16/16] Update pins for the realities of the board layout --- bike-lights/bike/src/main.rs | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/bike-lights/bike/src/main.rs b/bike-lights/bike/src/main.rs index a6e9d7f..8bd6779 100644 --- a/bike-lights/bike/src/main.rs +++ b/bike-lights/bike/src/main.rs @@ -193,10 +193,10 @@ fn main() -> ! { embedded_hal::spi::MODE_1, ); - let left_blinker_button = pins.gpio18.into_pull_up_input(); - let right_blinker_button = pins.gpio19.into_pull_up_input(); - let previous_animation_button = pins.gpio20.into_pull_up_input(); - let next_animation_button = pins.gpio21.into_pull_up_input(); + let left_blinker_button = pins.gpio17.into_pull_up_input(); + let right_blinker_button = pins.gpio16.into_pull_up_input(); + let previous_animation_button = pins.gpio27.into_pull_up_input(); + let next_animation_button = pins.gpio26.into_pull_up_input(); let ui = BikeUI::new( spi, -- 2.44.1