diff --git a/examples/button_interrupt.rs b/examples/button_interrupt.rs new file mode 100644 index 00000000000..97c7bf0ed67 --- /dev/null +++ b/examples/button_interrupt.rs @@ -0,0 +1,60 @@ +//! Toggle an LED on/off with a button +//! +//! This assumes that a LED is connected to GPIO4. +//! Additionally this assumes a button connected to GPIO9. +//! On an ESP32C3 development board this is the BOOT button. +//! +//! Depending on your target and the board you are using you should change the pins. +//! If your board doesn't have on-board LEDs don't forget to add an appropriate resistor. + +use core::num::NonZero; +use esp_idf_hal::delay::FreeRtos; +use esp_idf_hal::gpio::{InterruptType, PinDriver, Pull}; +use esp_idf_hal::peripherals::Peripherals; +use esp_idf_hal::task::notification::Notification; + +fn main() -> anyhow::Result<()> { + esp_idf_hal::sys::link_patches(); + + let peripherals = Peripherals::take()?; + let mut led = PinDriver::output(peripherals.pins.gpio4)?; + let mut button = PinDriver::input(peripherals.pins.gpio9)?; + + button.set_pull(Pull::Down)?; + button.set_interrupt_type(InterruptType::PosEdge)?; + + let mut led_state = false; + led.set_low()?; + + loop { + // prepare communication channel + let notification = Notification::new(); + let waker = notification.notifier(); + + // register interrupt callback, here it's a closure on stack + unsafe { + button + .subscribe_nonstatic(move || { + waker.notify(NonZero::new(1).unwrap()); + }) + .unwrap(); + } + + // enable interrupt, will be automatically disabled after being triggered + button.enable_interrupt()?; + // block until notified + notification.wait_any(); + + // toggle the LED + if led_state { + led.set_low()?; + led_state = false; + } else { + led.set_high()?; + led_state = true; + } + + // debounce + FreeRtos::delay_ms(200); + } +}