Compare commits

..

No commits in common. "afd10cff668aafffdb0cbcf4e5f76cb4f013d574" and "9346f4a9b8679f0873faaf16ec485e34a6e16057" have entirely different histories.

10 changed files with 1306 additions and 485 deletions

17
Cargo.lock generated
View File

@ -217,19 +217,6 @@ version = "1.6.0"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "8c3c1a368f70d6cf7302d78f8f7093da241fb8e8807c05cc9e51a125895a6d5b" 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]] [[package]]
name = "bit-set" name = "bit-set"
version = "0.5.3" version = "0.5.3"
@ -2189,10 +2176,6 @@ dependencies = [
[[package]] [[package]]
name = "lights-core" name = "lights-core"
version = "0.1.0" version = "0.1.0"
dependencies = [
"az",
"fixed",
]
[[package]] [[package]]
name = "linux-raw-sys" name = "linux-raw-sys"

View File

@ -2,7 +2,6 @@
resolver = "2" resolver = "2"
members = [ members = [
"authdb", "authdb",
"bike-lights/bike",
"bike-lights/core", "bike-lights/core",
"bike-lights/simulator", "bike-lights/simulator",
"changeset", "changeset",

View File

@ -1,12 +0,0 @@
[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"

View File

@ -1,15 +0,0 @@
[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" }

View File

@ -1,10 +0,0 @@
#![no_main]
#![no_std]
use panic_halt as _;
use rp_pico::entry;
#[entry]
fn main() -> ! {
loop {}
}

View File

@ -6,5 +6,3 @@ edition = "2021"
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html # See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
[dependencies] [dependencies]
az = { version = "1" }
fixed = { version = "1" }

View File

@ -1,101 +1,69 @@
#![no_std]
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; mod patterns;
pub use patterns::*; pub use patterns::*;
mod types; mod types;
pub use types::{BodyPattern, DashboardPattern, RGB}; pub use types::{DashboardPattern, Pattern, 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 U128F0);
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 const FPS: u8 = 30;
pub trait UI { pub trait UI {
fn check_event(&self) -> Option<Event>; fn check_event(&self) -> Option<Event>;
fn update_lights(&self, dashboard_lights: DashboardPattern, body_lights: BodyPattern); fn update_lights(&self, dashboard_lights: DashboardPattern, lights: Pattern);
} }
pub trait Animation { pub trait Animation {
fn tick(&mut self, time: Instant) -> (DashboardPattern, BodyPattern); fn tick(&mut self, time: std::time::Instant) -> (DashboardPattern, Pattern);
} }
pub struct DefaultAnimation {} pub struct DefaultAnimation {}
impl Animation for DefaultAnimation { impl Animation for DefaultAnimation {
fn tick(&mut self, _: Instant) -> (DashboardPattern, BodyPattern) { fn tick(&mut self, _: std::time::Instant) -> (DashboardPattern, Pattern) {
(PRIDE_DASHBOARD, PRIDE_BODY) (PRIDE_DASHBOARD, PRIDE)
} }
} }
pub struct Fade { pub struct Fade {
starting_dashboard: DashboardPattern, starting_dashboard: DashboardPattern,
starting_lights: BodyPattern, starting_lights: Pattern,
start_time: Instant, start_time: std::time::Instant,
dashboard_slope: [RGB<I8F8>; 3], dashboard_slope: Vec<RGB<f64>>,
body_slope: [RGB<I8F8>; 60], body_slope: Vec<RGB<f64>>,
frames: U16F0, frames: u8,
} }
impl Fade { impl Fade {
fn new( fn new(
dashboard: DashboardPattern, dashboard: DashboardPattern,
lights: BodyPattern, lights: Pattern,
ending_dashboard: DashboardPattern, ending_dashboard: DashboardPattern,
ending_lights: BodyPattern, ending_lights: Pattern,
frames: U16F0, frames: u8,
time: Instant, time: std::time::Instant,
) -> Self { ) -> Self {
let mut dashboard_slope = [Default::default(); 3]; let mut dashboard_slope = Vec::new();
let mut body_slope = [Default::default(); 60]; let mut body_slope = Vec::new();
for i in 0..3 { for i in 0..3 {
let slope = RGB { let slope = RGB {
r: calculate_slope(dashboard[i].r, ending_dashboard[i].r, frames), r: (ending_dashboard[i].r as f64 - dashboard[i].r as f64) / frames as f64,
g: calculate_slope(dashboard[i].g, ending_dashboard[i].g, frames), g: (ending_dashboard[i].g as f64 - dashboard[i].g as f64) / frames as f64,
b: calculate_slope(dashboard[i].b, ending_dashboard[i].b, frames), b: (ending_dashboard[i].b as f64 - dashboard[i].b as f64) / frames as f64,
}; };
dashboard_slope[i] = slope; dashboard_slope.push(slope);
} }
for i in 0..60 { for i in 0..60 {
let slope = RGB { let slope = RGB {
r: calculate_slope(lights[i].r, ending_lights[i].r, frames), r: (ending_lights[i].r as f64 - lights[i].r as f64) / frames as f64,
g: calculate_slope(lights[i].g, ending_lights[i].g, frames), g: (ending_lights[i].g as f64 - lights[i].g as f64) / frames as f64,
b: calculate_slope(lights[i].b, ending_lights[i].b, frames), b: (ending_lights[i].b as f64 - lights[i].b as f64) / frames as f64,
}; };
body_slope[i] = slope; body_slope.push(slope);
} }
println!("dashboard slope: {:?}", dashboard_slope);
Self { Self {
starting_dashboard: dashboard, starting_dashboard: dashboard,
starting_lights: lights, starting_lights: lights,
@ -108,39 +76,50 @@ impl Fade {
} }
impl Animation for Fade { impl Animation for Fade {
fn tick(&mut self, time: Instant) -> (DashboardPattern, BodyPattern) { fn tick(&mut self, time: std::time::Instant) -> (DashboardPattern, Pattern) {
let mut frames = calculate_frames(self.start_time.0, time.0); let mut frames: u8 = ((time - self.start_time).as_millis() as f64 / FPS as f64) as u8;
if frames > self.frames { if frames > self.frames {
frames = self.frames frames = self.frames
} }
let mut dashboard_pattern: DashboardPattern = OFF_DASHBOARD; let mut dashboard_pattern: DashboardPattern = OFF_DASHBOARD;
let mut body_pattern: BodyPattern = OFF_BODY; let mut body_pattern: Pattern = OFF;
let apply = |value: f64, frames: f64, slope: f64| -> f64 { value + frames * slope };
for i in 0..3 { for i in 0..3 {
dashboard_pattern[i].r = linear_ease( dashboard_pattern[i].r = apply(
self.starting_dashboard[i].r, self.starting_dashboard[i].r as f64,
frames, frames as f64,
self.dashboard_slope[i].r, self.dashboard_slope[i].r as f64,
); ) as u8;
dashboard_pattern[i].g = linear_ease( dashboard_pattern[i].g = apply(
self.starting_dashboard[i].g, self.starting_dashboard[i].g as f64,
frames, frames as f64,
self.dashboard_slope[i].g, self.dashboard_slope[i].g as f64,
); ) as u8;
dashboard_pattern[i].b = linear_ease( dashboard_pattern[i].b = apply(
self.starting_dashboard[i].b, self.starting_dashboard[i].b as f64,
frames, frames as f64,
self.dashboard_slope[i].b, self.dashboard_slope[i].b as f64,
); ) as u8;
} }
for i in 0..60 { for i in 0..60 {
body_pattern[i].r = body_pattern[i].r = apply(
linear_ease(self.starting_lights[i].r, frames, self.body_slope[i].r); self.starting_lights[i].r as f64,
body_pattern[i].g = frames as f64,
linear_ease(self.starting_lights[i].g, frames, self.body_slope[i].g); self.body_slope[i].r as f64,
body_pattern[i].b = ) as u8;
linear_ease(self.starting_lights[i].b, frames, self.body_slope[i].b); 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) (dashboard_pattern, body_pattern)
@ -163,29 +142,29 @@ pub struct Blinker {
fade_out: Fade, fade_out: Fade,
direction: FadeDirection, direction: FadeDirection,
start_time: Instant, start_time: std::time::Instant,
frames: U16F0, frames: u8,
} }
impl Blinker { impl Blinker {
fn new( fn new(
starting_dashboard: DashboardPattern, starting_dashboard: DashboardPattern,
starting_body: BodyPattern, starting_body: Pattern,
direction: BlinkerDirection, direction: BlinkerDirection,
time: Instant, time: std::time::Instant,
) -> Self { ) -> Self {
let mut ending_dashboard = starting_dashboard.clone(); let mut ending_dashboard = starting_dashboard.clone();
match direction { match direction {
BlinkerDirection::Left => { BlinkerDirection::Left => {
ending_dashboard[0].r = LEFT_BLINKER_DASHBOARD[0].r; ending_dashboard[0].r = LEFT_DASHBOARD[0].r;
ending_dashboard[0].g = LEFT_BLINKER_DASHBOARD[0].g; ending_dashboard[0].g = LEFT_DASHBOARD[0].g;
ending_dashboard[0].b = LEFT_BLINKER_DASHBOARD[0].b; ending_dashboard[0].b = LEFT_DASHBOARD[0].b;
} }
BlinkerDirection::Right => { BlinkerDirection::Right => {
ending_dashboard[2].r = RIGHT_BLINKER_DASHBOARD[2].r; ending_dashboard[2].r = RIGHT_DASHBOARD[2].r;
ending_dashboard[2].g = RIGHT_BLINKER_DASHBOARD[2].g; ending_dashboard[2].g = RIGHT_DASHBOARD[2].g;
ending_dashboard[2].b = RIGHT_BLINKER_DASHBOARD[2].b; ending_dashboard[2].b = RIGHT_DASHBOARD[2].b;
} }
} }
@ -193,16 +172,16 @@ impl Blinker {
match direction { match direction {
BlinkerDirection::Left => { BlinkerDirection::Left => {
for i in 0..30 { for i in 0..30 {
ending_body[i].r = LEFT_BLINKER_BODY[i].r; ending_body[i].r = LEFT[i].r;
ending_body[i].g = LEFT_BLINKER_BODY[i].g; ending_body[i].g = LEFT[i].g;
ending_body[i].b = LEFT_BLINKER_BODY[i].b; ending_body[i].b = LEFT[i].b;
} }
} }
BlinkerDirection::Right => { BlinkerDirection::Right => {
for i in 30..60 { for i in 30..60 {
ending_body[i].r = RIGHT_BLINKER_BODY[i].r; ending_body[i].r = RIGHT[i].r;
ending_body[i].g = RIGHT_BLINKER_BODY[i].g; ending_body[i].g = RIGHT[i].g;
ending_body[i].b = RIGHT_BLINKER_BODY[i].b; ending_body[i].b = RIGHT[i].b;
} }
} }
} }
@ -232,8 +211,8 @@ impl Blinker {
} }
impl Animation for Blinker { impl Animation for Blinker {
fn tick(&mut self, time: Instant) -> (DashboardPattern, BodyPattern) { fn tick(&mut self, time: std::time::Instant) -> (DashboardPattern, Pattern) {
let frames = calculate_frames(self.start_time.0, time.0); let frames: u8 = ((time - self.start_time).as_millis() as f64 / FPS as f64) as u8;
if frames > self.frames { if frames > self.frames {
match self.direction { match self.direction {
FadeDirection::FadeIn => { FadeDirection::FadeIn => {
@ -247,6 +226,7 @@ impl Animation for Blinker {
} }
self.start_time = time; self.start_time = time;
} }
println!("anim: {:?} {}", self.direction, frames);
match self.direction { match self.direction {
FadeDirection::FadeIn => self.fade_in.tick(time), FadeDirection::FadeIn => self.fade_in.tick(time),
@ -281,7 +261,7 @@ pub struct App {
home_state: State, home_state: State,
current_animation: Box<dyn Animation>, current_animation: Box<dyn Animation>,
dashboard_lights: DashboardPattern, dashboard_lights: DashboardPattern,
lights: BodyPattern, lights: Pattern,
} }
impl App { impl App {
@ -292,18 +272,18 @@ impl App {
home_state: State::Pattern(0), home_state: State::Pattern(0),
current_animation: Box::new(DefaultAnimation {}), current_animation: Box::new(DefaultAnimation {}),
dashboard_lights: OFF_DASHBOARD, dashboard_lights: OFF_DASHBOARD,
lights: OFF_BODY, lights: OFF,
} }
} }
fn update_animation(&mut self, time: Instant) { fn update_animation(&mut self, time: std::time::Instant) {
match self.state { match self.state {
State::Pattern(0) => { State::Pattern(0) => {
self.current_animation = Box::new(Fade::new( self.current_animation = Box::new(Fade::new(
self.dashboard_lights.clone(), self.dashboard_lights.clone(),
self.lights.clone(), self.lights.clone(),
PRIDE_DASHBOARD, PRIDE_DASHBOARD,
PRIDE_BODY, PRIDE,
DEFAULT_FRAMES, DEFAULT_FRAMES,
time, time,
)) ))
@ -313,7 +293,7 @@ impl App {
self.dashboard_lights.clone(), self.dashboard_lights.clone(),
self.lights.clone(), self.lights.clone(),
TRANS_PRIDE_DASHBOARD, TRANS_PRIDE_DASHBOARD,
TRANS_PRIDE_BODY, TRANS_PRIDE,
DEFAULT_FRAMES, DEFAULT_FRAMES,
time, time,
)) ))
@ -323,9 +303,9 @@ impl App {
self.current_animation = Box::new(Fade::new( self.current_animation = Box::new(Fade::new(
self.dashboard_lights.clone(), self.dashboard_lights.clone(),
self.lights.clone(), self.lights.clone(),
BRAKES_DASHBOARD, BRAKE_DASHBOARD,
BRAKES_BODY, BRAKES,
BRAKES_FRAMES, BRAKE_FRAMES,
time, time,
)); ));
} }
@ -394,7 +374,7 @@ impl App {
} }
} }
pub fn tick(&mut self, time: Instant) { pub fn tick(&mut self, time: std::time::Instant) {
match self.ui.check_event() { match self.ui.check_event() {
Some(event) => { Some(event) => {
self.update_state(event); self.update_state(event);

File diff suppressed because it is too large Load Diff

View File

@ -1,17 +1,9 @@
use core::default::Default; #[derive(Clone, Default, Debug)]
use fixed::types::I8F8;
#[derive(Clone, Copy, Default, Debug)]
pub struct RGB<T> { pub struct RGB<T> {
pub r: T, pub r: T,
pub g: T, pub g: T,
pub b: T, pub b: T,
} }
const DASHBOARD_LIGHT_COUNT: usize = 3; pub type DashboardPattern = [RGB<u8>; 3];
pub type Pattern = [RGB<u8>; 60];
pub type DashboardPattern = [RGB<I8F8>; DASHBOARD_LIGHT_COUNT];
const BODY_LIGHT_COUNT: usize = 60;
pub type BodyPattern = [RGB<I8F8>; BODY_LIGHT_COUNT];

View File

@ -1,10 +1,7 @@
use adw::prelude::*; use adw::prelude::*;
use fixed::types::{I8F8, U128F0};
use glib::{Object, Sender}; use glib::{Object, Sender};
use gtk::subclass::prelude::*; use gtk::subclass::prelude::*;
use lights_core::{ use lights_core::{App, DashboardPattern, Event, Pattern, FPS, RGB, UI};
App, BodyPattern, DashboardPattern, Event, Instant, FPS, OFF_BODY, OFF_DASHBOARD, RGB, UI,
};
use std::{ use std::{
cell::RefCell, cell::RefCell,
env, env,
@ -17,7 +14,7 @@ const HEIGHT: i32 = 480;
pub struct Update { pub struct Update {
dashboard: DashboardPattern, dashboard: DashboardPattern,
lights: BodyPattern, lights: Pattern,
} }
pub struct DashboardLightsPrivate { pub struct DashboardLightsPrivate {
@ -32,7 +29,11 @@ impl ObjectSubclass for DashboardLightsPrivate {
fn new() -> Self { fn new() -> Self {
Self { Self {
lights: Rc::new(RefCell::new(OFF_DASHBOARD)), 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 },
])),
} }
} }
} }
@ -59,9 +60,9 @@ impl DashboardLights {
let lights = s.imp().lights.borrow(); let lights = s.imp().lights.borrow();
for i in 0..3 { for i in 0..3 {
context.set_source_rgb( context.set_source_rgb(
lights[i].r.into(), lights[i].r as f64 / 256.,
lights[i].g.into(), lights[i].g as f64 / 256.,
lights[i].b.into(), lights[i].b as f64 / 256.,
); );
context.rectangle(start + 100. * i as f64, 10., 80., 80.); context.rectangle(start + 100. * i as f64, 10., 80., 80.);
let _ = context.fill(); let _ = context.fill();
@ -72,14 +73,14 @@ impl DashboardLights {
s s
} }
pub fn set_lights(&self, lights: DashboardPattern) { pub fn set_lights(&self, lights: [RGB<u8>; 3]) {
*self.imp().lights.borrow_mut() = lights; *self.imp().lights.borrow_mut() = lights;
self.queue_draw(); self.queue_draw();
} }
} }
pub struct BikeLightsPrivate { pub struct BikeLightsPrivate {
lights: Rc<RefCell<BodyPattern>>, lights: Rc<RefCell<Pattern>>,
} }
#[glib::object_subclass] #[glib::object_subclass]
@ -90,7 +91,68 @@ impl ObjectSubclass for BikeLightsPrivate {
fn new() -> Self { fn new() -> Self {
Self { Self {
lights: Rc::new(RefCell::new(OFF_BODY)), 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 },
])),
} }
} }
} }
@ -118,18 +180,18 @@ impl BikeLights {
let lights = s.imp().lights.borrow(); let lights = s.imp().lights.borrow();
for i in 0..30 { for i in 0..30 {
context.set_source_rgb( context.set_source_rgb(
lights[i].r.into(), lights[i].r as f64 / 256.,
lights[i].g.into(), lights[i].g as f64 / 256.,
lights[i].b.into(), lights[i].b as f64 / 256.,
); );
context.rectangle(center - 45., 5. + 20. * i as f64, 15., 15.); context.rectangle(center - 45., 5. + 20. * i as f64, 15., 15.);
let _ = context.fill(); let _ = context.fill();
} }
for i in 0..30 { for i in 0..30 {
context.set_source_rgb( context.set_source_rgb(
lights[i + 30].r.into(), lights[i + 30].r as f64 / 256.,
lights[i + 30].g.into(), lights[i + 30].g as f64 / 256.,
lights[i + 30].b.into(), lights[i + 30].b as f64 / 256.,
); );
context.rectangle(center + 15., 5. + 20. * (30. - (i + 1) as f64), 15., 15.); context.rectangle(center + 15., 5. + 20. * (30. - (i + 1) as f64), 15., 15.);
let _ = context.fill(); let _ = context.fill();
@ -140,7 +202,7 @@ impl BikeLights {
s s
} }
pub fn set_lights(&self, lights: [RGB<I8F8>; 60]) { pub fn set_lights(&self, lights: [RGB<u8>; 60]) {
*self.imp().lights.borrow_mut() = lights; *self.imp().lights.borrow_mut() = lights;
self.queue_draw(); self.queue_draw();
} }
@ -160,7 +222,7 @@ impl UI for GTKUI {
} }
} }
fn update_lights(&self, dashboard_lights: DashboardPattern, lights: BodyPattern) { fn update_lights(&self, dashboard_lights: DashboardPattern, lights: Pattern) {
self.tx self.tx
.send(Update { .send(Update {
dashboard: dashboard_lights, dashboard: dashboard_lights,
@ -186,12 +248,7 @@ fn main() {
rx: event_rx, rx: event_rx,
})); }));
loop { loop {
bike_app.tick(Instant(U128F0::from( bike_app.tick(std::time::Instant::now());
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))); std::thread::sleep(std::time::Duration::from_millis(1000 / (FPS as u64)));
} }
}); });