main: first implementation of a way to handle interrupts from sensors. untested!!

This commit is contained in:
2026-03-11 13:59:56 +01:00
parent 94144ab4b3
commit ccb2680954
4 changed files with 89 additions and 5 deletions

View File

@@ -12,17 +12,17 @@ use embassy_executor::Spawner;
use embassy_time::{Duration, Instant, Timer, WithTimeout};
use enum_map::EnumMap;
use esp_hal::{gpio::{Output, OutputConfig, Pin}, time::Rate};
use esp_hal::{gpio::{Event, Input, InputConfig, Output, OutputConfig, Pin}, handler, time::Rate};
use esp_hal::{
clock::CpuClock, timer::{systimer::SystemTimer, timg::{TimerGroup, Wdt}}
};
use embassy_sync::{
blocking_mutex::raw::NoopRawMutex, channel::DynamicReceiver, pubsub::PubSubChannel
blocking_mutex::raw::NoopRawMutex, channel::DynamicReceiver, once_lock::OnceLock, pubsub::PubSubChannel, signal::Signal
};
use esp_storage::FlashStorage;
use log::*;
use renderbug_bike::{events::{Prediction, SensorSource, SensorState}, graphics::display::DisplayControls, logging::RenderbugLogger, simdata::IMUReading, storage::{SharedFlash, SimDataRecorder}, tasks::{oled::{OledUI, OledUiSurfacePool, oled_ui}, safetyui::{SafetyUi, safety_ui_main}, ui::UiSurfacePool}, tracing::Tracer};
use renderbug_bike::{events::{Prediction, SensorSource, SensorState}, gpio_interrupt::{InterruptDispatch, PinInterrupt}, graphics::display::DisplayControls, logging::RenderbugLogger, simdata::IMUReading, storage::{SharedFlash, SimDataRecorder}, tasks::{oled::{OledUI, OledUiSurfacePool, oled_ui}, safetyui::{SafetyUi, safety_ui_main}, ui::UiSurfacePool}, tracing::Tracer};
use renderbug_bike::events::Measurement;
use static_cell::StaticCell;
use esp_backtrace as _;
@@ -45,6 +45,12 @@ static WIFI_INIT: StaticCell<esp_radio::Controller<'static>> = StaticCell::new()
rtos_trace::global_trace!(Tracer);
static INTERRUPTS: OnceLock<InterruptDispatch<'static, 4>> = OnceLock::new();
#[handler]
fn gpio_interrupt_handler() {
INTERRUPTS.try_get().unwrap().process_interrupts();
}
#[esp_rtos::main]
async fn main(spawner: Spawner) {
// If we aren't using the second CPU, we can use the bootloader space for the heap instead
@@ -94,6 +100,20 @@ async fn main(spawner: Spawner) {
// Spawn the rendering task as soon as possible so it can start pushing pixels
spawner.must_spawn(renderbug_bike::tasks::render::render(peripherals.SPI2.degrade(), peripherals.DMA_CH2.degrade(), peripherals.GPIO5.degrade(), surfaces, safety_surfaces, display_controls, wdt));
let imu_interrupt = PinInterrupt::new(Input::new(peripherals.GPIO36.degrade(), InputConfig::default()), Event::RisingEdge);
let pd_interrupt = PinInterrupt::new(Input::new(peripherals.GPIO16.degrade(), InputConfig::default()), Event::RisingEdge);
let sd_detect_interrupt = PinInterrupt::new(Input::new(peripherals.GPIO42.degrade(), InputConfig::default()), Event::RisingEdge);
let gps_pulse_interrupt = PinInterrupt::new(Input::new(peripherals.GPIO45.degrade(), InputConfig::default()), Event::RisingEdge);
INTERRUPTS.init(InterruptDispatch::new([
imu_interrupt.clone(),
pd_interrupt.clone(),
sd_detect_interrupt.clone(),
gps_pulse_interrupt.clone()
])).ok();
let mut io = esp_hal::gpio::Io::new(peripherals.IO_MUX);
io.set_interrupt_handler(gpio_interrupt_handler);
#[cfg(feature="motion")]
{
use embassy_embedded_hal::shared_bus::asynch::i2c::I2cDevice;
@@ -108,7 +128,7 @@ async fn main(spawner: Spawner) {
let i2c = I2c::new(peripherals.I2C1, Config::default()).unwrap().with_scl(scl).with_sda(sda).into_async();
let i2c_bus = I2C_BUS.init(Mutex::new(i2c));
#[cfg(feature="mpu")]
spawner.must_spawn(renderbug_bike::tasks::mpu::mpu_task(motion_bus.dyn_sender(), I2cDevice::new(i2c_bus)));
spawner.must_spawn(renderbug_bike::tasks::mpu::mpu_task(motion_bus.dyn_sender(), I2cDevice::new(i2c_bus), imu_interrupt));
#[cfg(feature="gps")]
spawner.must_spawn(renderbug_bike::tasks::gps::gps_task(motion_bus.dyn_sender(), I2cDevice::new(i2c_bus)));
}