Hello,
I am trying to implement reading the state of a button using embassy and the embassy_nrf crate. The idea is to distinguish if the button was pressed shortly or long. The idea is to start two actions
- A non blocking gpio state listen action
- A non blocking timer timeout
When the timer timed out, it is a long press. Otherwise a short. The problem is that I didn't find an example how to reimplement the interrupts by my self, without disturbing the embassy framework.
use embassy_time::Timer;
use embassy_nrf::{
bind_interrupts,
gpio::{self, AnyPin},
peripherals, interrupt,
Peripheral,
timer,
};
use embassy_sync::{
blocking_mutex::{raw::ThreadModeRawMutex},
signal::Signal,
};
// Enable interrupt executor
#[interrupt]
unsafe fn GPIOTE() {
// Disable interrupts
BUTTON1_WAIT_SIGNAL.signal(true);
// Clear interrupt flag
}
// TODO: allowed to use TIMER0?
#[interrupt]
unsafe fn TIMER1() {
// Disable interrupts
BUTTON1_WAIT_SIGNAL.signal(false);
// Clear interrupt flag
}
pub enum ButtonState {
ShortPress,
LongPress,
}
pub (crate) static BUTTON1_STATE: Signal<ThreadModeRawMutex, ButtonState> = Signal::new();
static BUTTON1_WAIT_SIGNAL: Signal<ThreadModeRawMutex, bool> = Signal::new();
#[embassy_executor::task]
pub async fn button1(pin: AnyPin, pull: gpio::Pull, timer: peripherals::TIMER1) -> ! {
let mut button = gpio::Input::new(pin, pull);
button_generic(&mut button, timer, &BUTTON1_STATE, &BUTTON1_WAIT_SIGNAL).await
}
pub async fn button_generic<'d, T: timer::Instance>(button: &mut gpio::Input<'_>, timer: impl Peripheral<P = T> + 'd, signal: & Signal<ThreadModeRawMutex, ButtonState>, s: &Signal<ThreadModeRawMutex, bool>) -> ! {
loop {
button.wait_for_falling_edge().await;
Timer::after_millis(10).await; // Debounce
if button.is_high() {
continue;
}
// TODO: Start timer
// TODO: Set GPIOTE to trigger on rising edge
if s.wait().await {
// If signal comes from gpiote, the button was released before the timer timed out
signal.signal(ButtonState::ShortPress);
} else {
// If signal comes from timer a timeout occured which means a long press happened
signal.signal(ButtonState::LongPress);
}
}
}