bump a lot of big changes I dont want to break down into individual commits

This commit is contained in:
2025-10-11 16:34:09 +02:00
parent 0e9e0c1b13
commit 8280f38185
48 changed files with 1275467 additions and 394056 deletions

View File

@@ -2,18 +2,19 @@
use core::sync::atomic::{AtomicBool, AtomicU8};
use embassy_sync::{blocking_mutex::raw::{CriticalSectionRawMutex, NoopRawMutex}, channel::Channel, signal::Signal};
use figments::hardware::Brightness;
use embassy_time::Duration;
use nalgebra::{Vector2, Vector3};
use alloc::sync::Arc;
use crate::ego::engine::MotionState;
#[derive(Clone, Copy, Default, Debug)]
pub enum Scene {
#[default]
Startup, // Default state when booting up
ParkedIdle, // Default state when waking up from long term (overnight, eg) parking, or entered when accelerometers and GPS both show zero motion for ~30 seconds
StoplightIdle, // Entered when GPS speed is zero after decelerating
Accelerating, // GPS speed is increasing
Decelerating, // GPS speed is decreasing
ParkedLongTerm, // GPS has not changed location in the last ~5 minutes
Ready, // Default state when booting up, but not when coming out of sleep
Accelerating,
Decelerating,
Idle, // Default state when waking up from sleep, or entered when accelerometers and GPS both show zero motion for ~30 seconds
}
#[derive(Clone, Copy, Debug)]
@@ -22,52 +23,89 @@ pub enum Measurement {
GPS(Option<Vector2<f64>>),
// Accelerometer values in body frame where x=forwards
IMU { accel: Vector3<f32>, gyro: Vector3<f32> },
// Hardware status updates
SensorOnline(SensorSource),
SensorOffline(SensorSource),
// Simulation metadata updates
SimulationProgress(SensorSource, Duration, f32)
}
#[derive(Clone, Copy, Debug)]
pub enum Prediction {
Location(Vector2<f32>),
Velocity(Vector2<f32>)
}
#[derive(Clone, Copy, Debug)]
pub enum Telemetry {
Prediction(Prediction),
Measurement(Measurement),
Notification(Notification)
Motion(MotionState),
Velocity(f32),
Location(Vector2<f64>),
WakeRequested
}
#[derive(Clone, Copy, Debug)]
pub enum Notification {
// The prediction engine has decided the UI should switch to another scene
SceneChange(Scene),
WifiConnected,
WifiDisconnected,
GPSLost,
GPSAcquired,
CalibrationComplete,
// States of external connections to the world
SensorOnline(SensorSource),
SensorOffline(SensorSource),
// TODO: Should be emitted by the prediction engine after it doesn't get any sensor data for some time. Perhaps the threads are somehow deadlocked and a reboot is needed if it doesn't recover
SensorsOffline,
// The prediction engine has decided that the system should be woken up and begin running again
WakeUp,
// The prediction engine has decided that the system is inactive enough and it should go to low-power sleep
Sleep,
// FIXME: Sor safety purposes, we probably want these two events to be combined and act atomic; if the safety lights are ever on, they should both be on.
SetHeadlight(bool),
SetBrakelight(bool)
SetBrakelight(bool),
// TODO: BPM detection via bluetooth
Beat
}
#[derive(Clone, Copy, Debug)]
pub enum SensorSource {
IMU,
GPS
}
// TODO: Make this clone() able, so multiple threads can point to the same underlying atomics for the hardware controls
// FIXME: We only ever hold this behind an Arc and therefore end up storing a Signal inside of an Arc<>... which defeats the whole purpose and can introduce a deadlock
pub struct DisplayControls {
pub on: AtomicBool,
pub brightness: AtomicU8,
pub render_is_running: Signal<CriticalSectionRawMutex, bool>
on: AtomicBool,
brightness: AtomicU8,
// FIXME: This should get turned into a embassy_sync::Watch sender, so multiple tasks can wait on the renderer to be running.
pub render_is_running: Signal<CriticalSectionRawMutex, bool>,
render_pause: Signal<CriticalSectionRawMutex, bool>
}
impl Brightness for DisplayControls {
fn set_brightness(&mut self, brightness: u8) {
impl DisplayControls {
pub fn is_on(&self) -> bool {
self.on.load(core::sync::atomic::Ordering::Relaxed)
}
pub fn brightness(&self) -> u8 {
self.brightness.load(core::sync::atomic::Ordering::Relaxed)
}
pub fn set_brightness(&self, brightness: u8) {
self.brightness.store(brightness, core::sync::atomic::Ordering::Relaxed);
}
fn set_on(&mut self, is_on: bool) {
self.on.store(is_on, core::sync::atomic::Ordering::Relaxed);
// FIXME: its a bit weird we have a pub function for the renderer's privates to wait while hiding render_pause, but directly expose render_is_running for any task to wait on
pub async fn wait_for_on(&self) {
self.render_pause.wait().await;
}
// TODO: Split gamma out from brightness controls
fn set_gamma(&mut self, _gamma: f32) {
unimplemented!()
pub fn set_on(&self, is_on: bool) {
self.on.store(is_on, core::sync::atomic::Ordering::Relaxed);
if is_on {
self.render_pause.signal(true);
} else {
self.render_pause.reset();
}
}
}
@@ -86,7 +124,8 @@ impl Default for DisplayControls {
Self {
on: AtomicBool::new(true),
brightness: AtomicU8::new(255),
render_is_running: Signal::new()
render_is_running: Signal::new(),
render_pause: Signal::new()
}
}
}
@@ -94,17 +133,17 @@ impl Default for DisplayControls {
#[derive(Debug)]
pub struct BusGarage {
pub motion: Channel<NoopRawMutex, Measurement, 5>,
pub scenes: Channel<CriticalSectionRawMutex, Notification, 5>,
pub telemetry: Channel<CriticalSectionRawMutex, Telemetry, 15>,
pub display: DisplayControls
pub notify: Channel<CriticalSectionRawMutex, Notification, 5>,
pub predict: Channel<CriticalSectionRawMutex, Prediction, 15>,
pub display: Arc<DisplayControls>
}
impl Default for BusGarage {
fn default() -> Self {
Self {
motion: Channel::new(),
scenes: Channel::new(),
telemetry: Channel::new(),
notify: Channel::new(),
predict: Channel::new(),
display: Default::default()
}
}