An applicaiton and simulator for a bike lighting system #245
|
@ -2337,6 +2337,10 @@ 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"
|
||||||
|
|
|
@ -6,3 +6,5 @@ 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" }
|
||||||
|
|
|
@ -2,16 +2,33 @@
|
||||||
|
|
||||||
extern crate alloc;
|
extern crate alloc;
|
||||||
use alloc::boxed::Box;
|
use alloc::boxed::Box;
|
||||||
|
use az::*;
|
||||||
use core::{clone::Clone, cmp::PartialEq, ops::Sub, option::Option};
|
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::{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)]
|
#[derive(Clone, Copy)]
|
||||||
pub struct Instant(pub u128);
|
pub struct Instant(pub U128F0);
|
||||||
|
|
||||||
impl Sub for Instant {
|
impl Sub for Instant {
|
||||||
type Output = Self;
|
type Output = Self;
|
||||||
|
@ -25,56 +42,56 @@ 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, lights: Pattern);
|
fn update_lights(&self, dashboard_lights: DashboardPattern, body_lights: BodyPattern);
|
||||||
}
|
}
|
||||||
|
|
||||||
pub trait Animation {
|
pub trait Animation {
|
||||||
fn tick(&mut self, time: Instant) -> (DashboardPattern, Pattern);
|
fn tick(&mut self, time: Instant) -> (DashboardPattern, BodyPattern);
|
||||||
}
|
}
|
||||||
|
|
||||||
pub struct DefaultAnimation {}
|
pub struct DefaultAnimation {}
|
||||||
|
|
||||||
impl Animation for DefaultAnimation {
|
impl Animation for DefaultAnimation {
|
||||||
fn tick(&mut self, _: Instant) -> (DashboardPattern, Pattern) {
|
fn tick(&mut self, _: Instant) -> (DashboardPattern, BodyPattern) {
|
||||||
(PRIDE_DASHBOARD, PRIDE)
|
(PRIDE_DASHBOARD, PRIDE_BODY)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub struct Fade {
|
pub struct Fade {
|
||||||
starting_dashboard: DashboardPattern,
|
starting_dashboard: DashboardPattern,
|
||||||
starting_lights: Pattern,
|
starting_lights: BodyPattern,
|
||||||
|
|
||||||
start_time: Instant,
|
start_time: Instant,
|
||||||
dashboard_slope: [RGB<f64>; 3],
|
dashboard_slope: [RGB<I8F8>; 3],
|
||||||
body_slope: [RGB<f64>; 60],
|
body_slope: [RGB<I8F8>; 60],
|
||||||
frames: u8,
|
frames: U16F0,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Fade {
|
impl Fade {
|
||||||
fn new(
|
fn new(
|
||||||
dashboard: DashboardPattern,
|
dashboard: DashboardPattern,
|
||||||
lights: Pattern,
|
lights: BodyPattern,
|
||||||
ending_dashboard: DashboardPattern,
|
ending_dashboard: DashboardPattern,
|
||||||
ending_lights: Pattern,
|
ending_lights: BodyPattern,
|
||||||
frames: u8,
|
frames: U16F0,
|
||||||
time: Instant,
|
time: Instant,
|
||||||
) -> Self {
|
) -> Self {
|
||||||
let mut dashboard_slope = [Default::default(); 3];
|
let mut dashboard_slope = [Default::default(); 3];
|
||||||
let mut body_slope = [Default::default(); 60];
|
let mut body_slope = [Default::default(); 60];
|
||||||
for i in 0..3 {
|
for i in 0..3 {
|
||||||
let slope = RGB {
|
let slope = RGB {
|
||||||
r: (ending_dashboard[i].r as f64 - dashboard[i].r as f64) / frames as f64,
|
r: calculate_slope(dashboard[i].r, ending_dashboard[i].r, frames),
|
||||||
g: (ending_dashboard[i].g as f64 - dashboard[i].g as f64) / frames as f64,
|
g: calculate_slope(dashboard[i].g, ending_dashboard[i].g, frames),
|
||||||
b: (ending_dashboard[i].b as f64 - dashboard[i].b as f64) / frames as f64,
|
b: calculate_slope(dashboard[i].b, ending_dashboard[i].b, frames),
|
||||||
};
|
};
|
||||||
dashboard_slope[i] = slope;
|
dashboard_slope[i] = slope;
|
||||||
}
|
}
|
||||||
|
|
||||||
for i in 0..60 {
|
for i in 0..60 {
|
||||||
let slope = RGB {
|
let slope = RGB {
|
||||||
r: (ending_lights[i].r as f64 - lights[i].r as f64) / frames as f64,
|
r: calculate_slope(lights[i].r, ending_lights[i].r, frames),
|
||||||
g: (ending_lights[i].g as f64 - lights[i].g as f64) / frames as f64,
|
g: calculate_slope(lights[i].g, ending_lights[i].g, frames),
|
||||||
b: (ending_lights[i].b as f64 - lights[i].b as f64) / frames as f64,
|
b: calculate_slope(lights[i].b, ending_lights[i].b, frames),
|
||||||
};
|
};
|
||||||
body_slope[i] = slope;
|
body_slope[i] = slope;
|
||||||
}
|
}
|
||||||
|
@ -91,50 +108,39 @@ impl Fade {
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Animation for Fade {
|
impl Animation for Fade {
|
||||||
fn tick(&mut self, time: Instant) -> (DashboardPattern, Pattern) {
|
fn tick(&mut self, time: Instant) -> (DashboardPattern, BodyPattern) {
|
||||||
let mut frames: u8 = ((time - self.start_time).0 as f64 / FPS as f64) as u8;
|
let mut frames = calculate_frames(self.start_time.0, time.0);
|
||||||
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: Pattern = OFF;
|
let mut body_pattern: BodyPattern = OFF_BODY;
|
||||||
|
|
||||||
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 = apply(
|
dashboard_pattern[i].r = linear_ease(
|
||||||
self.starting_dashboard[i].r as f64,
|
self.starting_dashboard[i].r,
|
||||||
frames as f64,
|
frames,
|
||||||
self.dashboard_slope[i].r as f64,
|
self.dashboard_slope[i].r,
|
||||||
) as u8;
|
);
|
||||||
dashboard_pattern[i].g = apply(
|
dashboard_pattern[i].g = linear_ease(
|
||||||
self.starting_dashboard[i].g as f64,
|
self.starting_dashboard[i].g,
|
||||||
frames as f64,
|
frames,
|
||||||
self.dashboard_slope[i].g as f64,
|
self.dashboard_slope[i].g,
|
||||||
) as u8;
|
);
|
||||||
dashboard_pattern[i].b = apply(
|
dashboard_pattern[i].b = linear_ease(
|
||||||
self.starting_dashboard[i].b as f64,
|
self.starting_dashboard[i].b,
|
||||||
frames as f64,
|
frames,
|
||||||
self.dashboard_slope[i].b as f64,
|
self.dashboard_slope[i].b,
|
||||||
) as u8;
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
for i in 0..60 {
|
for i in 0..60 {
|
||||||
body_pattern[i].r = apply(
|
body_pattern[i].r =
|
||||||
self.starting_lights[i].r as f64,
|
linear_ease(self.starting_lights[i].r, frames, self.body_slope[i].r);
|
||||||
frames as f64,
|
body_pattern[i].g =
|
||||||
self.body_slope[i].r as f64,
|
linear_ease(self.starting_lights[i].g, frames, self.body_slope[i].g);
|
||||||
) as u8;
|
body_pattern[i].b =
|
||||||
body_pattern[i].g = apply(
|
linear_ease(self.starting_lights[i].b, frames, self.body_slope[i].b);
|
||||||
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)
|
||||||
|
@ -158,13 +164,13 @@ pub struct Blinker {
|
||||||
direction: FadeDirection,
|
direction: FadeDirection,
|
||||||
|
|
||||||
start_time: Instant,
|
start_time: Instant,
|
||||||
frames: u8,
|
frames: U16F0,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Blinker {
|
impl Blinker {
|
||||||
fn new(
|
fn new(
|
||||||
starting_dashboard: DashboardPattern,
|
starting_dashboard: DashboardPattern,
|
||||||
starting_body: Pattern,
|
starting_body: BodyPattern,
|
||||||
direction: BlinkerDirection,
|
direction: BlinkerDirection,
|
||||||
time: Instant,
|
time: Instant,
|
||||||
) -> Self {
|
) -> Self {
|
||||||
|
@ -172,14 +178,14 @@ impl Blinker {
|
||||||
|
|
||||||
match direction {
|
match direction {
|
||||||
BlinkerDirection::Left => {
|
BlinkerDirection::Left => {
|
||||||
ending_dashboard[0].r = LEFT_DASHBOARD[0].r;
|
ending_dashboard[0].r = LEFT_BLINKER_DASHBOARD[0].r;
|
||||||
ending_dashboard[0].g = LEFT_DASHBOARD[0].g;
|
ending_dashboard[0].g = LEFT_BLINKER_DASHBOARD[0].g;
|
||||||
ending_dashboard[0].b = LEFT_DASHBOARD[0].b;
|
ending_dashboard[0].b = LEFT_BLINKER_DASHBOARD[0].b;
|
||||||
}
|
}
|
||||||
BlinkerDirection::Right => {
|
BlinkerDirection::Right => {
|
||||||
ending_dashboard[2].r = RIGHT_DASHBOARD[2].r;
|
ending_dashboard[2].r = RIGHT_BLINKER_DASHBOARD[2].r;
|
||||||
ending_dashboard[2].g = RIGHT_DASHBOARD[2].g;
|
ending_dashboard[2].g = RIGHT_BLINKER_DASHBOARD[2].g;
|
||||||
ending_dashboard[2].b = RIGHT_DASHBOARD[2].b;
|
ending_dashboard[2].b = RIGHT_BLINKER_DASHBOARD[2].b;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -187,16 +193,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[i].r;
|
ending_body[i].r = LEFT_BLINKER_BODY[i].r;
|
||||||
ending_body[i].g = LEFT[i].g;
|
ending_body[i].g = LEFT_BLINKER_BODY[i].g;
|
||||||
ending_body[i].b = LEFT[i].b;
|
ending_body[i].b = LEFT_BLINKER_BODY[i].b;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
BlinkerDirection::Right => {
|
BlinkerDirection::Right => {
|
||||||
for i in 30..60 {
|
for i in 30..60 {
|
||||||
ending_body[i].r = RIGHT[i].r;
|
ending_body[i].r = RIGHT_BLINKER_BODY[i].r;
|
||||||
ending_body[i].g = RIGHT[i].g;
|
ending_body[i].g = RIGHT_BLINKER_BODY[i].g;
|
||||||
ending_body[i].b = RIGHT[i].b;
|
ending_body[i].b = RIGHT_BLINKER_BODY[i].b;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -226,8 +232,8 @@ impl Blinker {
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Animation for Blinker {
|
impl Animation for Blinker {
|
||||||
fn tick(&mut self, time: Instant) -> (DashboardPattern, Pattern) {
|
fn tick(&mut self, time: Instant) -> (DashboardPattern, BodyPattern) {
|
||||||
let frames: u8 = ((time - self.start_time).0 as f64 / FPS as f64) as u8;
|
let frames = calculate_frames(self.start_time.0, time.0);
|
||||||
if frames > self.frames {
|
if frames > self.frames {
|
||||||
match self.direction {
|
match self.direction {
|
||||||
FadeDirection::FadeIn => {
|
FadeDirection::FadeIn => {
|
||||||
|
@ -275,7 +281,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: Pattern,
|
lights: BodyPattern,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl App {
|
impl App {
|
||||||
|
@ -286,7 +292,7 @@ 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,
|
lights: OFF_BODY,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -297,7 +303,7 @@ impl App {
|
||||||
self.dashboard_lights.clone(),
|
self.dashboard_lights.clone(),
|
||||||
self.lights.clone(),
|
self.lights.clone(),
|
||||||
PRIDE_DASHBOARD,
|
PRIDE_DASHBOARD,
|
||||||
PRIDE,
|
PRIDE_BODY,
|
||||||
DEFAULT_FRAMES,
|
DEFAULT_FRAMES,
|
||||||
time,
|
time,
|
||||||
))
|
))
|
||||||
|
@ -307,7 +313,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,
|
TRANS_PRIDE_BODY,
|
||||||
DEFAULT_FRAMES,
|
DEFAULT_FRAMES,
|
||||||
time,
|
time,
|
||||||
))
|
))
|
||||||
|
@ -317,9 +323,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(),
|
||||||
BRAKE_DASHBOARD,
|
BRAKES_DASHBOARD,
|
||||||
BRAKES,
|
BRAKES_BODY,
|
||||||
BRAKE_FRAMES,
|
BRAKES_FRAMES,
|
||||||
time,
|
time,
|
||||||
));
|
));
|
||||||
}
|
}
|
||||||
|
|
File diff suppressed because it is too large
Load Diff
|
@ -1,4 +1,5 @@
|
||||||
use core::default::Default;
|
use core::default::Default;
|
||||||
|
use fixed::types::I8F8;
|
||||||
|
|
||||||
#[derive(Clone, Copy, Default, Debug)]
|
#[derive(Clone, Copy, Default, Debug)]
|
||||||
pub struct RGB<T> {
|
pub struct RGB<T> {
|
||||||
|
@ -7,35 +8,10 @@ pub struct RGB<T> {
|
||||||
pub b: T,
|
pub b: T,
|
||||||
}
|
}
|
||||||
|
|
||||||
pub type DashboardPattern = [RGB<u8>; 3];
|
const DASHBOARD_LIGHT_COUNT: usize = 3;
|
||||||
/*
|
|
||||||
#[derive(Clone)]
|
|
||||||
pub struct DashboardPattern(pub [RGB<u8>; 3]);
|
|
||||||
*/
|
|
||||||
|
|
||||||
/*
|
pub type DashboardPattern = [RGB<I8F8>; DASHBOARD_LIGHT_COUNT];
|
||||||
impl Clone for DashboardPattern {
|
|
||||||
fn clone(&self) -> Self {
|
|
||||||
let mut v: [RGB<u8>; 3] = Default::default();
|
|
||||||
for i in 0..3 {
|
|
||||||
v[i] = self.0[i]
|
|
||||||
}
|
|
||||||
Self(v)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
*/
|
|
||||||
|
|
||||||
pub type Pattern = [RGB<u8>; 60];
|
const BODY_LIGHT_COUNT: usize = 60;
|
||||||
/*
|
|
||||||
pub struct Pattern(pub [RGB<u8>; 60]);
|
|
||||||
|
|
||||||
impl Pattern {
|
pub type BodyPattern = [RGB<I8F8>; BODY_LIGHT_COUNT];
|
||||||
pub fn clone(&self) -> Self {
|
|
||||||
let mut v: [RGB<u8>; 60] = [Default::default(); 60];
|
|
||||||
for i in 0..60 {
|
|
||||||
v[i] = self.0[i]
|
|
||||||
}
|
|
||||||
Self(v)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
*/
|
|
||||||
|
|
|
@ -1,7 +1,10 @@
|
||||||
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::{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::{
|
use std::{
|
||||||
cell::RefCell,
|
cell::RefCell,
|
||||||
env,
|
env,
|
||||||
|
@ -14,7 +17,7 @@ const HEIGHT: i32 = 480;
|
||||||
|
|
||||||
pub struct Update {
|
pub struct Update {
|
||||||
dashboard: DashboardPattern,
|
dashboard: DashboardPattern,
|
||||||
lights: Pattern,
|
lights: BodyPattern,
|
||||||
}
|
}
|
||||||
|
|
||||||
pub struct DashboardLightsPrivate {
|
pub struct DashboardLightsPrivate {
|
||||||
|
@ -29,11 +32,7 @@ impl ObjectSubclass for DashboardLightsPrivate {
|
||||||
|
|
||||||
fn new() -> Self {
|
fn new() -> Self {
|
||||||
Self {
|
Self {
|
||||||
lights: Rc::new(RefCell::new([
|
lights: Rc::new(RefCell::new(OFF_DASHBOARD)),
|
||||||
RGB { r: 0, g: 0, b: 0 },
|
|
||||||
RGB { r: 0, g: 0, b: 0 },
|
|
||||||
RGB { r: 0, g: 0, b: 0 },
|
|
||||||
])),
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -60,9 +59,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 as f64 / 256.,
|
lights[i].r.into(),
|
||||||
lights[i].g as f64 / 256.,
|
lights[i].g.into(),
|
||||||
lights[i].b as f64 / 256.,
|
lights[i].b.into(),
|
||||||
);
|
);
|
||||||
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();
|
||||||
|
@ -73,14 +72,14 @@ impl DashboardLights {
|
||||||
s
|
s
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn set_lights(&self, lights: [RGB<u8>; 3]) {
|
pub fn set_lights(&self, lights: DashboardPattern) {
|
||||||
*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<Pattern>>,
|
lights: Rc<RefCell<BodyPattern>>,
|
||||||
}
|
}
|
||||||
|
|
||||||
#[glib::object_subclass]
|
#[glib::object_subclass]
|
||||||
|
@ -91,68 +90,7 @@ impl ObjectSubclass for BikeLightsPrivate {
|
||||||
|
|
||||||
fn new() -> Self {
|
fn new() -> Self {
|
||||||
Self {
|
Self {
|
||||||
lights: Rc::new(RefCell::new([
|
lights: Rc::new(RefCell::new(OFF_BODY)),
|
||||||
RGB { r: 0, g: 0, b: 0 },
|
|
||||||
RGB { r: 0, g: 0, b: 0 },
|
|
||||||
RGB { r: 0, g: 0, b: 0 },
|
|
||||||
RGB { r: 0, g: 0, b: 0 },
|
|
||||||
RGB { r: 0, g: 0, b: 0 },
|
|
||||||
RGB { r: 0, g: 0, b: 0 },
|
|
||||||
RGB { r: 0, g: 0, b: 0 },
|
|
||||||
RGB { r: 0, g: 0, b: 0 },
|
|
||||||
RGB { r: 0, g: 0, b: 0 },
|
|
||||||
RGB { r: 0, g: 0, b: 0 },
|
|
||||||
RGB { r: 0, g: 0, b: 0 },
|
|
||||||
RGB { r: 0, g: 0, b: 0 },
|
|
||||||
RGB { r: 0, g: 0, b: 0 },
|
|
||||||
RGB { r: 0, g: 0, b: 0 },
|
|
||||||
RGB { r: 0, g: 0, b: 0 },
|
|
||||||
RGB { r: 0, g: 0, b: 0 },
|
|
||||||
RGB { r: 0, g: 0, b: 0 },
|
|
||||||
RGB { r: 0, g: 0, b: 0 },
|
|
||||||
RGB { r: 0, g: 0, b: 0 },
|
|
||||||
RGB { r: 0, g: 0, b: 0 },
|
|
||||||
RGB { r: 0, g: 0, b: 0 },
|
|
||||||
RGB { r: 0, g: 0, b: 0 },
|
|
||||||
RGB { r: 0, g: 0, b: 0 },
|
|
||||||
RGB { r: 0, g: 0, b: 0 },
|
|
||||||
RGB { r: 0, g: 0, b: 0 },
|
|
||||||
RGB { r: 0, g: 0, b: 0 },
|
|
||||||
RGB { r: 0, g: 0, b: 0 },
|
|
||||||
RGB { r: 0, g: 0, b: 0 },
|
|
||||||
RGB { r: 0, g: 0, b: 0 },
|
|
||||||
RGB { r: 0, g: 0, b: 0 },
|
|
||||||
RGB { r: 0, g: 0, b: 0 },
|
|
||||||
RGB { r: 0, g: 0, b: 0 },
|
|
||||||
RGB { r: 0, g: 0, b: 0 },
|
|
||||||
RGB { r: 0, g: 0, b: 0 },
|
|
||||||
RGB { r: 0, g: 0, b: 0 },
|
|
||||||
RGB { r: 0, g: 0, b: 0 },
|
|
||||||
RGB { r: 0, g: 0, b: 0 },
|
|
||||||
RGB { r: 0, g: 0, b: 0 },
|
|
||||||
RGB { r: 0, g: 0, b: 0 },
|
|
||||||
RGB { r: 0, g: 0, b: 0 },
|
|
||||||
RGB { r: 0, g: 0, b: 0 },
|
|
||||||
RGB { r: 0, g: 0, b: 0 },
|
|
||||||
RGB { r: 0, g: 0, b: 0 },
|
|
||||||
RGB { r: 0, g: 0, b: 0 },
|
|
||||||
RGB { r: 0, g: 0, b: 0 },
|
|
||||||
RGB { r: 0, g: 0, b: 0 },
|
|
||||||
RGB { r: 0, g: 0, b: 0 },
|
|
||||||
RGB { r: 0, g: 0, b: 0 },
|
|
||||||
RGB { r: 0, g: 0, b: 0 },
|
|
||||||
RGB { r: 0, g: 0, b: 0 },
|
|
||||||
RGB { r: 0, g: 0, b: 0 },
|
|
||||||
RGB { r: 0, g: 0, b: 0 },
|
|
||||||
RGB { r: 0, g: 0, b: 0 },
|
|
||||||
RGB { r: 0, g: 0, b: 0 },
|
|
||||||
RGB { r: 0, g: 0, b: 0 },
|
|
||||||
RGB { r: 0, g: 0, b: 0 },
|
|
||||||
RGB { r: 0, g: 0, b: 0 },
|
|
||||||
RGB { r: 0, g: 0, b: 0 },
|
|
||||||
RGB { r: 0, g: 0, b: 0 },
|
|
||||||
RGB { r: 0, g: 0, b: 0 },
|
|
||||||
])),
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -180,18 +118,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 as f64 / 256.,
|
lights[i].r.into(),
|
||||||
lights[i].g as f64 / 256.,
|
lights[i].g.into(),
|
||||||
lights[i].b as f64 / 256.,
|
lights[i].b.into(),
|
||||||
);
|
);
|
||||||
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 as f64 / 256.,
|
lights[i + 30].r.into(),
|
||||||
lights[i + 30].g as f64 / 256.,
|
lights[i + 30].g.into(),
|
||||||
lights[i + 30].b as f64 / 256.,
|
lights[i + 30].b.into(),
|
||||||
);
|
);
|
||||||
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();
|
||||||
|
@ -202,7 +140,7 @@ impl BikeLights {
|
||||||
s
|
s
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn set_lights(&self, lights: [RGB<u8>; 60]) {
|
pub fn set_lights(&self, lights: [RGB<I8F8>; 60]) {
|
||||||
*self.imp().lights.borrow_mut() = lights;
|
*self.imp().lights.borrow_mut() = lights;
|
||||||
self.queue_draw();
|
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
|
self.tx
|
||||||
.send(Update {
|
.send(Update {
|
||||||
dashboard: dashboard_lights,
|
dashboard: dashboard_lights,
|
||||||
|
@ -248,12 +186,12 @@ fn main() {
|
||||||
rx: event_rx,
|
rx: event_rx,
|
||||||
}));
|
}));
|
||||||
loop {
|
loop {
|
||||||
bike_app.tick(Instant(
|
bike_app.tick(Instant(U128F0::from(
|
||||||
(std::time::SystemTime::now()
|
std::time::SystemTime::now()
|
||||||
.duration_since(std::time::UNIX_EPOCH)
|
.duration_since(std::time::UNIX_EPOCH)
|
||||||
.unwrap())
|
.unwrap()
|
||||||
.as_millis(),
|
.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)));
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
Loading…
Reference in New Issue