62 lines
1.6 KiB
Rust
62 lines
1.6 KiB
Rust
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<Mutex<RefCell<Input<'a>>>>,
|
|
signal: Arc<Signal<CriticalSectionRawMutex, esp_hal::gpio::Level>>,
|
|
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
|
|
}
|
|
} |