diff --git a/Cargo.lock b/Cargo.lock index 62c76b1..d95e44e 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -137,12 +137,6 @@ dependencies = [ "syn 2.0.106", ] -[[package]] -name = "bitflags" -version = "1.3.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "bef38d45163c2f1dde094a7dfd33ccf595c92905c8f8f4fdc18d06fb1037718a" - [[package]] name = "bitflags" version = "2.9.4" @@ -343,6 +337,18 @@ dependencies = [ "typenum", ] +[[package]] +name = "csv" +version = "1.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "52cd9d68cf7efc6ddfaaee42e7288d3a99d613d4b50f76ce9827ae0c6e14f938" +dependencies = [ + "csv-core", + "itoa", + "ryu", + "serde_core", +] + [[package]] name = "csv-core" version = "0.1.12" @@ -576,24 +582,6 @@ dependencies = [ "num-traits", ] -[[package]] -name = "embassy-net" -version = "0.7.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0558a231a47e7d4a06a28b5278c92e860f1200f24821d2f365a2f40fe3f3c7b2" -dependencies = [ - "document-features", - "embassy-net-driver", - "embassy-sync 0.7.2", - "embassy-time 0.5.0", - "embedded-io-async", - "embedded-nal-async", - "heapless", - "log", - "managed", - "smoltcp", -] - [[package]] name = "embassy-net-driver" version = "0.2.0" @@ -773,25 +761,6 @@ dependencies = [ "embedded-io", ] -[[package]] -name = "embedded-nal" -version = "0.9.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c56a28be191a992f28f178ec338a0bf02f63d7803244add736d026a471e6ed77" -dependencies = [ - "nb 1.1.0", -] - -[[package]] -name = "embedded-nal-async" -version = "0.8.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "76959917cd2b86f40a98c28dd5624eddd1fa69d746241c8257eac428d83cb211" -dependencies = [ - "embedded-io-async", - "embedded-nal", -] - [[package]] name = "embedded-storage" version = "0.3.1" @@ -916,7 +885,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "f3887eda2917deef3d99e7a5c324f9190714e99055361ad36890dffd0a995b49" dependencies = [ "bitfield 0.19.2", - "bitflags 2.9.4", + "bitflags", "bytemuck", "cfg-if", "critical-section", @@ -1110,7 +1079,6 @@ dependencies = [ "portable-atomic", "portable_atomic_enum", "rand_core 0.9.3", - "smoltcp", "xtensa-lx-rt", ] @@ -1623,15 +1591,6 @@ dependencies = [ "wasm-bindgen", ] -[[package]] -name = "kfilter" -version = "0.4.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1d320a64bfb4ff8e33add1458241eff87b02a29abf9c19549a02500795928afa" -dependencies = [ - "nalgebra 0.33.2", -] - [[package]] name = "lebe" version = "0.5.3" @@ -1709,12 +1668,6 @@ dependencies = [ "imgref", ] -[[package]] -name = "managed" -version = "0.8.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0ca88d725a0a943b096803bd34e73a4437208b6077654cc4ecb2947a5f91618d" - [[package]] name = "maybe-async-cfg" version = "0.2.4" @@ -1995,7 +1948,7 @@ version = "0.18.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "97baced388464909d42d89643fe4361939af9b7ce7a31ee32a168f832a70f2a0" dependencies = [ - "bitflags 2.9.4", + "bitflags", "crc32fast", "fdeflate", "flate2", @@ -2114,7 +2067,7 @@ version = "0.11.3" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "679341d22c78c6c649893cbd6c3278dcbe9fc4faa62fea3a9296ae2b50c14625" dependencies = [ - "bitflags 2.9.4", + "bitflags", "memchr", "unicase", ] @@ -2280,19 +2233,15 @@ dependencies = [ name = "renderbug-embassy" version = "0.1.0" dependencies = [ - "anyhow", "bleps", "critical-section", - "csv-core", + "csv", "embassy-embedded-hal 0.5.0", "embassy-executor", - "embassy-net", "embassy-sync 0.7.2", "embassy-time 0.5.0", "embedded-graphics", "embedded-hal-async", - "embedded-io", - "embedded-io-async", "esp-alloc", "esp-backtrace", "esp-bootloader-esp-idf", @@ -2305,18 +2254,14 @@ dependencies = [ "figments-render", "futures", "image", - "kfilter", "log", + "micromath", "mpu6050-dmp", "nalgebra 0.33.2", "nmea", "rgb", "rmp", - "serde", - "serde_json", "smart-leds", - "smart-leds-trait", - "smoltcp", "ssd1306", "static_cell", "xtensa-lx-rt", @@ -2447,19 +2392,6 @@ dependencies = [ "syn 2.0.106", ] -[[package]] -name = "serde_json" -version = "1.0.145" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "402a6f66d8c709116cf22f558eab210f5a50187f702eb4d7e5ef38d9a7f1c79c" -dependencies = [ - "itoa", - "memchr", - "ryu", - "serde", - "serde_core", -] - [[package]] name = "serde_spanned" version = "0.6.9" @@ -2551,20 +2483,6 @@ dependencies = [ "rgb", ] -[[package]] -name = "smoltcp" -version = "0.12.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "dad095989c1533c1c266d9b1e8d70a1329dd3723c3edac6d03bbd67e7bf6f4bb" -dependencies = [ - "bitflags 1.3.2", - "byteorder", - "cfg-if", - "heapless", - "log", - "managed", -] - [[package]] name = "ssd1306" version = "0.10.0" diff --git a/Cargo.toml b/Cargo.toml index eaf4daf..7eb5d99 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -9,26 +9,23 @@ name = "renderbug-embassy" path = "./src/bin/main.rs" [features] -default = [] -simulation = ["dep:csv-core", "dep:rmp"] +default = ["real-output"] +real-output = [] +simulation = ["dep:rmp"] radio = [ - "dep:embassy-net", - "dep:smoltcp", "dep:bleps", - "dep:serde_json", - "dep:serde", "dep:esp-wifi" ] motion = ["mpu", "gps"] max-usb-power = [] wokwi = ["max-usb-power"] -headless = [] mpu = ["dep:mpu6050-dmp"] gps = ["dep:nmea"] -oled = [] +oled = ["dep:ssd1306", "dep:embedded-graphics"] demo = [] [dependencies] +# The basic requirements for all features figments = { path = "../figments/figments/", features = ["alloc"] } figments-render = { path = "../figments/figments-render/", features = ["smart-leds", "micromath"], default-features = false } esp-bootloader-esp-idf = { version = "0.2.0", features = ["esp32s3"] } @@ -37,17 +34,6 @@ esp-hal = { version = "=1.0.0-rc.0", features = [ "log-04", "unstable", ] } -log = "0.4.27" - -embassy-net = { version = "0.7.0", optional = true, features = [ - "dhcpv4", - "log", - "medium-ethernet", - "tcp", - "udp", -] } -embedded-io = "0.6.1" -embedded-io-async = "0.6.1" esp-alloc = "0.8.0" esp-backtrace = { version = "0.17.0", features = [ "esp32s3", @@ -67,33 +53,34 @@ esp-hal-embassy = { version = "0.9.0", features = [ "esp32s3", "log-04" ] } +log = "0.4.27" +static_cell = "2.1.1" +rgb = "0.8.52" +# esp-hal-smartled = { version = "0.15.0", features = ["esp32c3"] } +esp-hal-smartled = { git = "https://github.com/esp-rs/esp-hal-community.git", features = ["esp32s3"] } +smart-leds = "0.4.0" +embassy-sync = "0.7.2" +embassy-embedded-hal = "0.5.0" +embedded-hal-async = "1.0.0" +nalgebra = { version = "0.33.2", default-features = false, features = ["alloc", "libm"] } +xtensa-lx-rt = { version = "*", features = ["float-save-restore"] } +futures = { version = "0.3.31", default-features = false, features = ["async-await"] } +micromath = "2.1.0" + +# Telemetry outputs esp-wifi = { version = "0.15.0", optional = true, features = [ "builtin-scheduler", "esp-alloc", "esp32s3", "log-04", - "smoltcp", "wifi", "ble" ] } -smoltcp = { version = "0.12.0", optional = true, default-features = false, features = [ - "log", - "medium-ethernet", - "multicast", - "proto-dhcpv4", - "proto-dns", - "proto-ipv4", - "socket-dns", - "socket-icmp", - "socket-raw", - "socket-tcp", - "socket-udp", -] } -static_cell = "2.1.1" -# esp-hal-smartled = { version = "0.15.0", features = ["esp32c3"] } -esp-hal-smartled = { git = "https://github.com/esp-rs/esp-hal-community.git", features = ["esp32s3"] } -smart-leds = "0.4.0" -rgb = "0.8.52" +bleps = { git = "https://github.com/bjoernQ/bleps", optional = true, package = "bleps", rev = "a5148d8ae679e021b78f53fd33afb8bb35d0b62e", features = [ "macros", "async"] } +embedded-graphics = { version = "0.8.1", features = ["nalgebra_support"], optional = true} +ssd1306 = { version = "0.10.0", features = ["async"], optional = true } + +# Sensors nmea = { version = "0.7.0", optional = true, default-features = false, features = [ "GGA", "GSA", @@ -104,23 +91,10 @@ nmea = { version = "0.7.0", optional = true, default-features = false, features "GLL", "GST", ] } -embassy-sync = "0.7.2" mpu6050-dmp = { version = "0.6.1", features = ["async"], optional = true } -embassy-embedded-hal = "0.5.0" -embedded-hal-async = "1.0.0" -smart-leds-trait = "0.3.1" -anyhow = { version = "1.0.99", default-features = false } -nalgebra = { version = "0.33.2", default-features = false } -bleps = { git = "https://github.com/bjoernQ/bleps", optional = true, package = "bleps", rev = "a5148d8ae679e021b78f53fd33afb8bb35d0b62e", features = [ "macros", "async"] } -serde_json = {version = "1.0.145", optional = true, default-features = false, features = ["alloc"] } -csv-core = {version = "0.1.12", optional = true } -serde = { version = "1.0.228", optional = true, default-features = false, features = ["derive"] } -kfilter = "0.4.0" + +# Simulation rmp = { version = "0.8.14", optional = true, default-features = false } -xtensa-lx-rt = { version = "*", features = ["float-save-restore"] } -futures = { version = "0.3.31", default-features = false, features = ["async-await"] } -ssd1306 = { version = "0.10.0", features = ["async"] } -embedded-graphics = { version = "0.8.1", features = ["nalgebra_support"] } [profile.dev] # Rust debug is too slow. @@ -137,5 +111,6 @@ opt-level = 's' overflow-checks = false [build-dependencies] -image = "0.25.8" -rmp = "0.8" \ No newline at end of file +image = "0.25" +rmp = "0.8" +csv = "1.3" diff --git a/build.rs b/build.rs index f78d992..b094135 100644 --- a/build.rs +++ b/build.rs @@ -3,13 +3,22 @@ use std::io::Write; use std::path::Path; use std::fs::File; use image::GenericImageView; -use rmp; +use csv::Reader; fn main() { linker_be_nice(); // make sure linkall.x is the last linker script (otherwise might cause problems with flip-link) println!("cargo:rustc-link-arg=-Tlinkall.x"); + #[cfg(feature="simulation")] + write_sim_data(); + + #[cfg(feature="oled")] + compile_assets(); + +} + +fn compile_assets() { let asset_path = Path::new("assets"); let mut image_output = File::create(Path::new("target/images.rs")).unwrap(); @@ -55,13 +64,100 @@ fn main() { println!("cargo::rerun-if-changed={fname_str}"); } } +} - /*let test_data_path = Path::new("test-data"); - let gps_data = File::open(test_data_path.join("LocationGps.csv")).unwrap(); - let accel_data = File::open(test_data_path.join("AccelerometerUncalibrated.csv")).unwrap(); - let gyro_data = File::open(test_data_path.join("GyroscopeUncalibrated.csv")).unwrap(); - let mut test_data_output = File::create(Path::new("target/test_data.rs")).unwrap();*/ +fn write_sim_data() { + let test_data_path = Path::new("test-data"); + let output_path = Path::new("target"); + let gps_input = test_data_path.join("LocationGps.csv"); + let gyro_input = test_data_path.join("GyroscopeUncalibrated.csv"); + let accel_input = test_data_path.join("AccelerometerUncalibrated.csv"); + let gps_output = output_path.join("gps_test_data.msgpack"); + let motion_output = output_path.join("motion_test_data.msgpack"); + + println!("cargo::rerun-if-changed={}", gps_input.to_str().unwrap()); + if !gps_output.exists() || gps_output.metadata().unwrap().modified().unwrap() < gps_input.metadata().unwrap().modified().unwrap() { + let mut gps_data = Reader::from_reader(File::open(gps_input).unwrap()); + let headers = gps_data.headers().unwrap(); + let (timestamp_idx, lat_idx, lon_idx) = ( + headers.iter().position(|x| { x == "seconds_elapsed" }).unwrap(), + headers.iter().position(|x| { x == "longitude" }).unwrap(), + headers.iter().position(|x| { x == "latitude" }).unwrap(), + ); + let mut gps_output = File::create(gps_output).unwrap(); + let mut last_stamp = 0.0; + for record in gps_data.records().flatten() { + let (timestamp, lat, lon) = ( + record.get(timestamp_idx).unwrap().parse().unwrap(), + record.get(lat_idx).unwrap().parse().unwrap(), + record.get(lon_idx).unwrap().parse().unwrap() + ); + let next_delay = timestamp - last_stamp; + last_stamp = timestamp; + rmp::encode::write_array_len(&mut gps_output, 3).unwrap(); + rmp::encode::write_f64(&mut gps_output, next_delay).unwrap(); + rmp::encode::write_f64(&mut gps_output, lat).unwrap(); + rmp::encode::write_f64(&mut gps_output, lon).unwrap(); + } + } + + println!("cargo::rerun-if-changed={}", accel_input.to_str().unwrap()); + println!("cargo::rerun-if-changed={}", gyro_input.to_str().unwrap()); + let rebuild_motion = { + if motion_output.exists() { + let motion_stamp = motion_output.metadata().unwrap().modified().unwrap(); + motion_stamp < accel_input.metadata().unwrap().modified().unwrap() || motion_stamp < gyro_input.metadata().unwrap().modified().unwrap() + } else { + true + } + }; + if rebuild_motion { + let mut accel_data = Reader::from_reader(File::open(accel_input).unwrap()); + let mut gyro_data = Reader::from_reader(File::open(gyro_input).unwrap()); + let headers = accel_data.headers().unwrap(); + let (timestamp_idx, accel_x_idx, accel_y_idx, accel_z_idx) = ( + headers.iter().position(|x| { x == "seconds_elapsed" }).unwrap(), + headers.iter().position(|x| { x == "x" }).unwrap(), + headers.iter().position(|x| { x == "y" }).unwrap(), + headers.iter().position(|x| { x == "z" }).unwrap(), + ); + + let headers = gyro_data.headers().unwrap(); + let (gyro_x_idx, gyro_y_idx, gyro_z_idx) = ( + headers.iter().position(|x| { x == "x" }).unwrap(), + headers.iter().position(|x| { x == "y" }).unwrap(), + headers.iter().position(|x| { x == "z" }).unwrap(), + ); + + let mut motion_output = File::create(motion_output).unwrap(); + let mut last_stamp = 0.0; + for (accel_record, gyro_record) in accel_data.records().flatten().zip(gyro_data.records().flatten()) { + let (timestamp, accel_x, accel_y, accel_z) = ( + accel_record.get(timestamp_idx).unwrap().parse().unwrap(), + accel_record.get(accel_x_idx).unwrap().parse().unwrap(), + accel_record.get(accel_y_idx).unwrap().parse().unwrap(), + accel_record.get(accel_z_idx).unwrap().parse().unwrap() + ); + let (gyro_x, gyro_y, gyro_z) = ( + gyro_record.get(gyro_x_idx).unwrap().parse().unwrap(), + gyro_record.get(gyro_y_idx).unwrap().parse().unwrap(), + gyro_record.get(gyro_z_idx).unwrap().parse().unwrap() + ); + let next_delay = timestamp - last_stamp; + if next_delay >= 0.02 { + last_stamp = timestamp; + rmp::encode::write_array_len(&mut motion_output, 7).unwrap(); + rmp::encode::write_f64(&mut motion_output, next_delay).unwrap(); + rmp::encode::write_f64(&mut motion_output, accel_x).unwrap(); + rmp::encode::write_f64(&mut motion_output, accel_y).unwrap(); + rmp::encode::write_f64(&mut motion_output, accel_z).unwrap(); + rmp::encode::write_f64(&mut motion_output, gyro_x).unwrap(); + rmp::encode::write_f64(&mut motion_output, gyro_y).unwrap(); + rmp::encode::write_f64(&mut motion_output, gyro_z).unwrap(); + } + } + } } fn linker_be_nice() { diff --git a/src/bin/main.rs b/src/bin/main.rs index 4235be9..339bfe0 100644 --- a/src/bin/main.rs +++ b/src/bin/main.rs @@ -79,13 +79,8 @@ async fn main(spawner: Spawner) { #[allow(unused_variables)] let hi_spawn = hi_exec.start(esp_hal::interrupt::Priority::max()); - #[cfg(not(feature="headless"))] - { - wdt.enable(); - hi_spawn.must_spawn(renderbug_embassy::tasks::render::render(peripherals.RMT, peripherals.GPIO5.degrade(), surfaces, safety_surfaces, garage.display.clone(), wdt)); - } - #[cfg(feature="headless")] - garage.display.notify_render_is_running(true); + wdt.enable(); + hi_spawn.must_spawn(renderbug_embassy::tasks::render::render(peripherals.RMT, peripherals.GPIO5.degrade(), surfaces, safety_surfaces, garage.display.clone(), wdt)); #[cfg(feature="motion")] { diff --git a/src/display.rs b/src/display.rs index 466079b..dbf9f64 100644 --- a/src/display.rs +++ b/src/display.rs @@ -8,9 +8,11 @@ use figments_render::{ gamma::{GammaCurve, WithGamma}, output::{Brightness, GammaCorrected, OutputAsync}, power::AsMilliwatts, smart_leds::PowerManagedWriterAsync }; use smart_leds::SmartLedsWriteAsync; + +pub const NUM_PIXELS: usize = 178; // FIXME: We need a way to specify a different buffer format from the 'native' hardware output, due to sometimes testing with GRB strips instead of RGB pub struct BikeOutput { - pixbuf: [T::Color; 178], + pixbuf: [T::Color; NUM_PIXELS], writer: PowerManagedWriterAsync, controls: DisplayControls } @@ -24,18 +26,18 @@ impl GammaCorrected for BikeOutput where T::Color: Pix impl BikeOutput where T::Color: PixelBlend> + PixelFormat + WithGamma + 'static, T::Error: core::fmt::Debug { pub fn new(target: T, max_mw: u32, controls: DisplayControls) -> Self { Self { - pixbuf: [Default::default(); 178], + pixbuf: [Default::default(); NUM_PIXELS], writer: PowerManagedWriterAsync::new(target, max_mw), controls } } pub fn blank(&mut self) { - self.pixbuf = [Default::default(); 178]; + self.pixbuf = [Default::default(); NUM_PIXELS]; } } -impl<'a, T: SmartLedsWriteAsync + 'a> OutputAsync<'a, SegmentSpace> for BikeOutput where T::Color: PixelBlend> + Debug + 'static + AsMilliwatts + PixelFormat + WithGamma, [T::Color; 178]: AsMilliwatts + WithGamma + Copy, T::Error: core::fmt::Debug { +impl<'a, T: SmartLedsWriteAsync + 'a> OutputAsync<'a, SegmentSpace> for BikeOutput where T::Color: PixelBlend> + Debug + 'static + AsMilliwatts + PixelFormat + WithGamma, [T::Color; NUM_PIXELS]: AsMilliwatts + WithGamma + Copy, T::Error: core::fmt::Debug { async fn commit_async(&mut self) -> Result<(), T::Error> { self.writer.controls().set_brightness(self.controls.brightness()); self.writer.controls().set_on(self.controls.is_on()); @@ -52,7 +54,7 @@ impl<'a, T: SmartLedsWriteAsync + 'a> OutputAsync<'a, SegmentSpace> for BikeOutp } } -impl<'a, T: SmartLedsWriteAsync> Sample<'a, SegmentSpace> for BikeOutput where T::Color: Debug + PixelFormat + 'a, [T::Color; 178]: Sample<'a, SegmentSpace, Output = T::Color> { +impl<'a, T: SmartLedsWriteAsync> Sample<'a, SegmentSpace> for BikeOutput where T::Color: Debug + PixelFormat + 'a, [T::Color; NUM_PIXELS]: Sample<'a, SegmentSpace, Output = T::Color> { type Output = T::Color; fn sample(&mut self, rect: &Rectangle) -> impl Iterator, &'a mut T::Color)> { @@ -74,12 +76,12 @@ pub struct Segment { length: usize, } -impl<'a, T: PixelFormat> Sample<'a, SegmentSpace> for [T; 178] where T: 'static { +impl<'a, T: PixelFormat> Sample<'a, SegmentSpace> for [T; NUM_PIXELS] where T: 'static { type Output = T; fn sample(&mut self, rect: &Rectangle) -> impl Iterator, &'a mut Self::Output)> { let bufref = unsafe { - &mut *(self as *mut [T; 178]) + &mut *(self as *mut [T; NUM_PIXELS]) }; SegmentIter { pixbuf: bufref, @@ -97,7 +99,7 @@ impl CoordinateSpace for SegmentSpace { } pub struct SegmentIter<'a, Format: PixelFormat> { - pixbuf: &'a mut [Format; 178], + pixbuf: &'a mut [Format; NUM_PIXELS], cur: Coordinates, end: Coordinates, } @@ -129,7 +131,7 @@ impl<'a, Format: PixelFormat> Iterator for SegmentIter<'a, Format> { } let bufref = unsafe { - &mut *(self.pixbuf as *mut [Format; 178]) + &mut *(self.pixbuf as *mut [Format; NUM_PIXELS]) }; Some((pixel_coords, &mut bufref[offset])) diff --git a/src/ego/engine.rs b/src/ego/engine.rs index bb6ed26..6e4dd66 100644 --- a/src/ego/engine.rs +++ b/src/ego/engine.rs @@ -1,9 +1,7 @@ use embassy_sync::{channel::DynamicSender, pubsub::DynPublisher}; use embassy_time::{Duration, Instant}; -use nalgebra::{Rotation3, Vector2, Vector3}; +use nalgebra::{Rotation3, Vector2, Vector3, ComplexField, RealField}; use log::*; -//use micromath::F32Ext; -use nalgebra::{ComplexField, RealField}; use core::fmt::Debug; diff --git a/src/tasks/mod.rs b/src/tasks/mod.rs index eca5cc9..7335e46 100644 --- a/src/tasks/mod.rs +++ b/src/tasks/mod.rs @@ -2,14 +2,20 @@ pub mod mpu; #[cfg(feature="gps")] pub mod gps; -pub mod render; -pub mod motion; -pub mod ui; #[cfg(feature="radio")] pub mod wifi; #[cfg(feature="simulation")] pub mod simulation; -pub mod predict; +#[cfg(feature="demo")] pub mod demo; +#[cfg(feature="oled")] +pub mod oled; + +// Prediction engines +pub mod predict; +pub mod motion; + +// Graphics stack +pub mod ui; pub mod safetyui; -pub mod oled; \ No newline at end of file +pub mod render; \ No newline at end of file diff --git a/src/tasks/render.rs b/src/tasks/render.rs index 4315122..b7699b5 100644 --- a/src/tasks/render.rs +++ b/src/tasks/render.rs @@ -1,25 +1,23 @@ use embassy_time::{Duration, Instant, Timer}; use esp_hal::{gpio::AnyPin, rmt::Rmt, time::Rate, timer::timg::Wdt}; use esp_hal_smartled::{buffer_size_async, SmartLedsAdapterAsync}; -use figments::{prelude::*, surface::{BufferedSurfacePool, Surfaces}}; +use figments::{prelude::*, surface::Surfaces}; use figments_render::gamma::GammaCurve; use figments_render::output::{GammaCorrected, OutputAsync}; use log::{info, warn}; -use rgb::Rgba; -use nalgebra::ComplexField; +use micromath::F32Ext; -use crate::display::{BikeOutput, DisplayControls, SegmentSpace, Uniforms}; - -//TODO: Import the bike surfaces from renderbug-prime, somehow make those surfaces into tasks +use crate::display::NUM_PIXELS; +use crate::{display::{BikeOutput, DisplayControls, Uniforms}, tasks::ui::UiSurfacePool}; #[embassy_executor::task] -pub async fn render(rmt: esp_hal::peripherals::RMT<'static>, gpio: AnyPin<'static>, surfaces: BufferedSurfacePool>, safety_surfaces: BufferedSurfacePool>, mut controls: DisplayControls, mut wdt: Wdt>) { +pub async fn render(rmt: esp_hal::peripherals::RMT<'static>, gpio: AnyPin<'static>, surfaces: UiSurfacePool, safety_surfaces: UiSurfacePool, mut controls: DisplayControls, mut wdt: Wdt>) { let frequency: Rate = Rate::from_mhz(80); let rmt = Rmt::new(rmt, frequency) .expect("Failed to initialize RMT").into_async(); let rmt_channel = rmt.channel0; - let rmt_buffer = [0u32; buffer_size_async(178)]; + let rmt_buffer = [0u32; buffer_size_async(NUM_PIXELS)]; //let target = SmartLedsAdapterAsync::new(rmt_channel, gpio, rmt_buffer); let target = SmartLedsAdapterAsync::new(rmt_channel, gpio, rmt_buffer); @@ -40,8 +38,6 @@ pub async fn render(rmt: esp_hal::peripherals::RMT<'static>, gpio: AnyPin<'stati let mut output = BikeOutput::new(target, MAX_POWER_MW, controls.clone()); output.set_gamma(GammaCurve::new(1.3)); - //#[cfg(not(feature="wokwi"))] - //output.set_gamma(GammaCurve::new(2.1)); info!("Rendering started! {}ms since boot", Instant::now().as_millis()); controls.notify_render_is_running(true); diff --git a/src/tasks/simulation.rs b/src/tasks/simulation.rs index 830753b..f39458c 100644 --- a/src/tasks/simulation.rs +++ b/src/tasks/simulation.rs @@ -8,7 +8,7 @@ use crate::Breaker; #[embassy_executor::task] pub async fn motion_simulation_task(events: DynamicSender<'static, Measurement>) { - let mut rd = rmp::decode::Bytes::new(include_bytes!("../../test-data/motion.msgpack")); + let mut rd = rmp::decode::Bytes::new(include_bytes!("../../target/motion_test_data.msgpack")); let mut runtime_secs = Breaker::default(); let mut runtime = Duration::default(); events.send(Measurement::SensorOnline(SensorSource::IMU)).await; @@ -39,7 +39,7 @@ pub async fn motion_simulation_task(events: DynamicSender<'static, Measurement>) #[embassy_executor::task] pub async fn location_simulation_task(events: DynamicSender<'static, Measurement>) { - let mut rd = rmp::decode::Bytes::new(include_bytes!("../../test-data/gps.msgpack")); + let mut rd = rmp::decode::Bytes::new(include_bytes!("../../target/gps_test_data.msgpack")); let mut runtime_secs = Breaker::default(); let mut runtime = Duration::default(); events.send(Measurement::SensorOnline(SensorSource::GPS)).await; diff --git a/src/tasks/ui.rs b/src/tasks/ui.rs index c5d2a6c..08cf7ef 100644 --- a/src/tasks/ui.rs +++ b/src/tasks/ui.rs @@ -200,9 +200,9 @@ impl>>; -#[cfg(not(feature="headless"))] +#[cfg(feature="real-output")] pub type UiSurfacePool = BufferedSurfacePool>; #[embassy_executor::task] diff --git a/test-data/gps.msgpack b/test-data/gps.msgpack deleted file mode 100644 index 44331f7..0000000 Binary files a/test-data/gps.msgpack and /dev/null differ diff --git a/test-data/motion.msgpack b/test-data/motion.msgpack deleted file mode 100644 index ce7f066..0000000 Binary files a/test-data/motion.msgpack and /dev/null differ diff --git a/test-data/process.py b/test-data/process.py deleted file mode 100644 index 1b8590a..0000000 --- a/test-data/process.py +++ /dev/null @@ -1,39 +0,0 @@ -import click -import csv -import umsgpack - -@click.command -@click.argument('gps-data', type=click.File('r')) -@click.argument('accelerometer-data', type=click.File('r')) -@click.argument('gyro-data', type=click.File('r')) -@click.argument('gps-output', type=click.File('wb')) -@click.argument('motion-output', type=click.File('wb')) -def main(gps_data, accelerometer_data, gyro_data, gps_output, motion_output): - gps_reader = csv.DictReader(gps_data) - last_stamp = 0 - for row in gps_reader: - next_delay = float(row['seconds_elapsed']) - last_stamp - # We only one one update per second, to cut down on size - if next_delay < 1: - continue - last_stamp = float(row['seconds_elapsed']) - umsgpack.pack([float(next_delay), float(row['latitude']), float(row['longitude'])], gps_output) - - accel_reader = csv.DictReader(accelerometer_data) - gyro_reader = csv.DictReader(gyro_data) - #motion_writer = csv.writer(motion_output, SampleDataDialect) - last_stamp = 0 - for (accel_row, gyro_row) in zip(accel_reader, gyro_reader): - next_delay = float(accel_row['seconds_elapsed']) - last_stamp - # Only one update every 100ms, to cut down on size - if next_delay < 0.02: - continue - last_stamp = float(accel_row['seconds_elapsed']) - umsgpack.pack([ - next_delay, - float(accel_row['x']), float(accel_row['y']), float(accel_row['z']), - float(gyro_row['x']), float(gyro_row['y']), float(gyro_row['z']) - ], motion_output) - -if __name__ == "__main__": - main()