use core::cell::RefCell; use alloc::sync::Arc; use critical_section::Mutex; use embassy_sync::{blocking_mutex::raw::CriticalSectionRawMutex, signal::Signal}; use esp_hal::gpio::Input; pub struct InterruptDispatch<'a, const COUNT: usize> { interrupts: [PinInterrupt<'a>; COUNT] } impl<'a, const COUNT: usize> InterruptDispatch<'a, COUNT> { pub fn new(interrupts: [PinInterrupt<'a>; COUNT]) -> Self { Self { interrupts } } pub fn process_interrupts(&self) { for interrupt in &self.interrupts { interrupt.handle_interrupt(); } } } #[derive(Clone)] pub struct PinInterrupt<'a> { pin: Arc>>>, signal: Arc>, event: esp_hal::gpio::Event } impl<'a> PinInterrupt<'a> { pub fn new(pin: Input<'a>, event: esp_hal::gpio::Event) -> Self { Self { pin: Arc::new(Mutex::new(RefCell::new(pin))), signal: Arc::new(Signal::new()), event } } pub fn handle_interrupt(&self) { critical_section::with(|cs| { let locked = self.pin.borrow(cs); let mut pin = locked.borrow_mut(); if pin.is_interrupt_set() { pin.clear_interrupt(); self.signal.signal(pin.level()); } }); } pub fn listen(&self) { critical_section::with(|cs| { let locked = self.pin.borrow(cs); let mut pin = locked.borrow_mut(); pin.listen(self.event); }); } pub async fn wait_for_interrupt(&self) -> esp_hal::gpio::Level { self.signal.wait().await } }