diff --git a/src/bin/main.rs b/src/bin/main.rs index cf5995e..16546ba 100644 --- a/src/bin/main.rs +++ b/src/bin/main.rs @@ -18,9 +18,14 @@ use esp_hal::{ clock::CpuClock, system::{AppCoreGuard, CpuControl, Stack}, timer::{systimer::SystemTimer, timg::{TimerGroup, Wdt}} }; +use embassy_sync::{ + pubsub::PubSubChannel, + blocking_mutex::raw::NoopRawMutex +}; + use log::*; -use renderbug_embassy::{graphics::display::DisplayControls, logging::RenderbugLogger, tasks::{oled::{OledUI, OledUiSurfacePool, oled_ui}, safetyui::{SafetyUi, safety_ui_main}, ui::UiSurfacePool}}; -use renderbug_embassy::events::{BusGarage, Measurement}; +use renderbug_embassy::{events::Prediction, graphics::display::DisplayControls, logging::RenderbugLogger, tasks::{oled::{OledUI, OledUiSurfacePool, oled_ui}, safetyui::{SafetyUi, safety_ui_main}, ui::UiSurfacePool}}; +use renderbug_embassy::events::Measurement; use static_cell::StaticCell; use esp_backtrace as _; use esp_rtos::embassy::{Executor, InterruptExecutor}; @@ -31,7 +36,7 @@ use renderbug_embassy::tasks::{ ui::{Ui, ui_main} }; -use embassy_sync::blocking_mutex::raw::CriticalSectionRawMutex; +use embassy_sync::{blocking_mutex::raw::CriticalSectionRawMutex, pubsub::DynSubscriber}; use embassy_sync::channel::Channel; extern crate alloc; @@ -42,8 +47,6 @@ esp_bootloader_esp_idf::esp_app_desc!(); static STATIC_HI_EXEC: StaticCell> = StaticCell::new(); static CORE2_EXEC: StaticCell = StaticCell::new(); - -static BUS_GARAGE: StaticCell = StaticCell::new(); static mut CORE2_STACK: Stack<16384> = Stack::new(); #[cfg(feature="radio")] static WIFI_INIT: StaticCell> = StaticCell::new(); @@ -83,13 +86,13 @@ async fn main(spawner: Spawner) { let timer0 = TimerGroup::new(peripherals.TIMG0); let mut wdt = timer0.wdt; wdt.set_timeout(esp_hal::timer::timg::MwdtStage::Stage0, esp_hal::time::Duration::from_secs(5)); - wdt.enable(); + //wdt.enable(); let swi = SoftwareInterruptControl::new(peripherals.SW_INTERRUPT); - let hi_exec = STATIC_HI_EXEC.init(InterruptExecutor::new(swi.software_interrupt2)); - let hi_spawn = hi_exec.start(esp_hal::interrupt::Priority::max()); + //let hi_exec = STATIC_HI_EXEC.init(InterruptExecutor::new(swi.software_interrupt2)); + //let hi_spawn = hi_exec.start(esp_hal::interrupt::Priority::max()); - hi_spawn.must_spawn(renderbug_embassy::tasks::render::render(peripherals.RMT, peripherals.GPIO5.degrade(), surfaces, safety_surfaces, display_controls, wdt)); + spawner.must_spawn(renderbug_embassy::tasks::render::render(peripherals.RMT, peripherals.GPIO5.degrade(), surfaces, safety_surfaces, display_controls, wdt)); #[cfg(feature="motion")] { @@ -149,28 +152,32 @@ async fn main(spawner: Spawner) { info!("Starting core 2"); let core2_main = |spawner: Spawner| { - let garage = BUS_GARAGE.init_with(|| { Default::default() }); + static PREDICTIONS: StaticCell> = StaticCell::new(); + let predictions = PREDICTIONS.init(PubSubChannel::new()); - info!("Launching motion engine"); - spawner.must_spawn(motion_task(motion_bus.dyn_receiver(), garage.predict.dyn_publisher().unwrap())); - - info!("Launching Safety UI"); - spawner.must_spawn(safety_ui_main(garage.predict.dyn_subscriber().unwrap(), safety_ui)); - info!("Launching UI"); - spawner.must_spawn(ui_main(garage.predict.dyn_subscriber().unwrap(), ui)); - info!("Launching OLED UI"); - spawner.must_spawn(oled_ui(garage.predict.dyn_subscriber().unwrap(), oledui)); - - #[cfg(feature="radio")] + #[cfg(not(feature="demo"))] { - info!("Launching networking stack"); - spawner.must_spawn(renderbug_embassy::tasks::wifi::wireless_task(garage.predict.dyn_subscriber().unwrap(), wifi_init, peripherals.WIFI)); + info!("Launching motion engine"); + spawner.must_spawn(motion_task(motion_bus.dyn_receiver(), predictions.dyn_publisher().unwrap())); } #[cfg(feature="demo")] { warn!("Launching with demo sequencer"); - spawner.must_spawn(renderbug_embassy::tasks::demo::demo_task(garage.notify.dyn_publisher().unwrap())); + spawner.must_spawn(renderbug_embassy::tasks::demo::demo_task(predictions.dyn_publisher().unwrap())); + } + + info!("Launching Safety UI"); + spawner.must_spawn(safety_ui_main(predictions.dyn_subscriber().unwrap(), safety_ui)); + info!("Launching UI"); + spawner.must_spawn(ui_main(predictions.dyn_subscriber().unwrap(), ui)); + info!("Launching OLED UI"); + spawner.must_spawn(oled_ui(predictions.dyn_subscriber().unwrap(), oledui)); + + #[cfg(feature="radio")] + { + info!("Launching networking stack"); + spawner.must_spawn(renderbug_embassy::tasks::wifi::wireless_task(predictions.dyn_subscriber().unwrap(), wifi_init, peripherals.WIFI)); } #[cfg(feature="dual-core")] @@ -184,6 +191,8 @@ async fn main(spawner: Spawner) { spawner.must_spawn(wdt_task(ui_wdt)); } + spawner.must_spawn(print_telemetry(predictions.dyn_subscriber().unwrap())); + info!("System is ready in {}ms", Instant::now().as_millis()); }; @@ -206,4 +215,11 @@ async fn wdt_task(mut wdt: Wdt>) { wdt.feed(); Timer::after_secs(3).await; } +} + +#[embassy_executor::task] +async fn print_telemetry(mut events: DynSubscriber<'static, Prediction>) { + loop { + info!("predict={:?}", events.next_message_pure().await); + } } \ No newline at end of file diff --git a/src/events.rs b/src/events.rs index 0f72220..38036ef 100644 --- a/src/events.rs +++ b/src/events.rs @@ -1,5 +1,4 @@ -use embassy_sync::{blocking_mutex::raw::NoopRawMutex, pubsub::PubSubChannel}; use embassy_time::Duration; use enum_map::Enum; use enumset::EnumSetType; @@ -67,26 +66,6 @@ pub enum Prediction { SetPersonality(Personality) } -#[derive(Clone, Copy, Debug)] -pub enum Notification { - // The prediction engine has decided the UI should switch to another scene - SceneChange(Scene), - - // States of external connections to the world - SensorStatus(SensorSource, SensorState), - // 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), - - // TODO: BPM detection via bluetooth - Beat, -} - // GPS data = 2, motion data = 1 #[derive(Debug, EnumSetType, Enum)] pub enum SensorSource { @@ -116,19 +95,4 @@ impl From for SensorSource { StreamType::IMU => Self::IMU } } -} - -#[derive(Debug)] -pub struct BusGarage { - pub notify: PubSubChannel, - pub predict: PubSubChannel, -} - -impl Default for BusGarage { - fn default() -> Self { - Self { - notify: PubSubChannel::new(), - predict: PubSubChannel::new(), - } - } } \ No newline at end of file diff --git a/src/tasks/demo.rs b/src/tasks/demo.rs index 3821cab..dfae930 100644 --- a/src/tasks/demo.rs +++ b/src/tasks/demo.rs @@ -1,25 +1,27 @@ use embassy_sync::pubsub::DynPublisher; use embassy_time::Timer; -use crate::events::{Notification, Scene, SensorSource, SensorState}; +use crate::{ego::engine::MotionState, events::{Personality, Prediction, SensorSource, SensorState}}; #[embassy_executor::task] -pub async fn demo_task(ui: DynPublisher<'static, Notification>) { +pub async fn demo_task(ui: DynPublisher<'static, Prediction>) { + ui.publish(Prediction::SensorStatus(SensorSource::Demo, SensorState::AcquiringFix)).await; Timer::after_secs(10).await; - ui.publish(Notification::SceneChange(Scene::Idle)).await; - ui.publish(Notification::SetBrakelight(true)).await; - ui.publish(Notification::SetHeadlight(true)).await; + ui.publish(Prediction::SetPersonality(crate::events::Personality::Active)).await; Timer::after_secs(10).await; - ui.publish(Notification::SensorStatus(SensorSource::Demo, SensorState::AcquiringFix)).await; + ui.publish(Prediction::SensorStatus(SensorSource::Demo, SensorState::Online)).await; loop { - for scene in [Scene::Accelerating, Scene::Ready, Scene::Decelerating, Scene::Ready] { - ui.publish(Notification::SceneChange(scene)).await; + for personality in [Personality::Active, Personality::Parked] { + ui.publish(Prediction::SetPersonality(personality)).await; for state in [SensorState::Offline, SensorState::AcquiringFix, SensorState::Degraded, SensorState::Offline] { - for sensor in [SensorSource::ForwardsReference, SensorSource::GPS, SensorSource::GravityReference, SensorSource::IMU, SensorSource::Location] { - ui.publish(Notification::SensorStatus(sensor, state)).await; - } - Timer::after_secs(1).await; + for motion in [MotionState::Accelerating, MotionState::Steady, MotionState::Decelerating, MotionState::Stationary] { + ui.publish(Prediction::Motion { prev: motion, next: motion }).await; + for sensor in [SensorSource::ForwardsReference, SensorSource::GPS, SensorSource::GravityReference, SensorSource::IMU, SensorSource::Location] { + ui.publish(Prediction::SensorStatus(sensor, state)).await; + } + Timer::after_secs(1).await; + } } } }