diff --git a/embassy-nrf/src/gpio.rs b/embassy-nrf/src/gpio.rs index 91b2e585..190d8470 100644 --- a/embassy-nrf/src/gpio.rs +++ b/embassy-nrf/src/gpio.rs @@ -1,6 +1,7 @@ #![macro_use] use core::convert::Infallible; +use core::future::Future; use core::hint::unreachable_unchecked; use core::marker::PhantomData; @@ -72,6 +73,54 @@ impl<'d, T: Pin> InputPin for Input<'d, T> { } } +#[cfg(feature = "gpiote")] +impl<'d, T: Pin> embassy::traits::gpio::WaitForHigh for Input<'d, T> { + #[rustfmt::skip] + type Future<'a> where Self: 'a = impl Future + Unpin + 'a; + + fn wait_for_high<'a>(&'a mut self) -> Self::Future<'a> { + self.pin.conf().modify(|_, w| w.sense().high()); + + crate::gpiote::PortInputFuture { + pin_port: self.pin.pin_port(), + phantom: PhantomData, + } + } +} + +#[cfg(feature = "gpiote")] +impl<'d, T: Pin> embassy::traits::gpio::WaitForLow for Input<'d, T> { + #[rustfmt::skip] + type Future<'a> where Self: 'a = impl Future + Unpin + 'a; + + fn wait_for_low<'a>(&'a mut self) -> Self::Future<'a> { + self.pin.conf().modify(|_, w| w.sense().low()); + + crate::gpiote::PortInputFuture { + pin_port: self.pin.pin_port(), + phantom: PhantomData, + } + } +} + +#[cfg(feature = "gpiote")] +impl<'d, T: Pin> embassy::traits::gpio::WaitForAnyEdge for Input<'d, T> { + #[rustfmt::skip] + type Future<'a> where Self: 'a = impl Future + Unpin + 'a; + + fn wait_for_any_edge<'a>(&'a mut self) -> Self::Future<'a> { + if self.is_high().ok().unwrap() { + self.pin.conf().modify(|_, w| w.sense().low()); + } else { + self.pin.conf().modify(|_, w| w.sense().high()); + } + crate::gpiote::PortInputFuture { + pin_port: self.pin.pin_port(), + phantom: PhantomData, + } + } +} + /// Digital input or output level. #[derive(Debug, Eq, PartialEq)] #[cfg_attr(feature = "defmt", derive(defmt::Format))] @@ -277,6 +326,54 @@ impl<'d, T: Pin> StatefulOutputPin for FlexPin<'d, T> { } } +#[cfg(feature = "gpiote")] +impl<'d, T: Pin> embassy::traits::gpio::WaitForHigh for FlexPin<'d, T> { + #[rustfmt::skip] + type Future<'a> where Self: 'a = impl Future + Unpin + 'a; + + fn wait_for_high<'a>(&'a mut self) -> Self::Future<'a> { + self.pin.conf().modify(|_, w| w.sense().high()); + + crate::gpiote::PortInputFuture { + pin_port: self.pin.pin_port(), + phantom: PhantomData, + } + } +} + +#[cfg(feature = "gpiote")] +impl<'d, T: Pin> embassy::traits::gpio::WaitForLow for FlexPin<'d, T> { + #[rustfmt::skip] + type Future<'a> where Self: 'a = impl Future + Unpin + 'a; + + fn wait_for_low<'a>(&'a mut self) -> Self::Future<'a> { + self.pin.conf().modify(|_, w| w.sense().low()); + + crate::gpiote::PortInputFuture { + pin_port: self.pin.pin_port(), + phantom: PhantomData, + } + } +} + +#[cfg(feature = "gpiote")] +impl<'d, T: Pin> embassy::traits::gpio::WaitForAnyEdge for FlexPin<'d, T> { + #[rustfmt::skip] + type Future<'a> where Self: 'a = impl Future + Unpin + 'a; + + fn wait_for_any_edge<'a>(&'a mut self) -> Self::Future<'a> { + if self.is_high().ok().unwrap() { + self.pin.conf().modify(|_, w| w.sense().low()); + } else { + self.pin.conf().modify(|_, w| w.sense().high()); + } + crate::gpiote::PortInputFuture { + pin_port: self.pin.pin_port(), + phantom: PhantomData, + } + } +} + pub(crate) mod sealed { use super::*; diff --git a/embassy-nrf/src/gpiote.rs b/embassy-nrf/src/gpiote.rs index 2e9a7356..4b595c58 100644 --- a/embassy-nrf/src/gpiote.rs +++ b/embassy-nrf/src/gpiote.rs @@ -3,7 +3,6 @@ use core::future::Future; use core::marker::PhantomData; use core::task::{Context, Poll}; use embassy::interrupt::{Interrupt, InterruptExt}; -use embassy::traits::gpio::{WaitForAnyEdge, WaitForHigh, WaitForLow}; use embassy::waitqueue::AtomicWaker; use embassy_hal_common::unsafe_impl_unborrow; use embedded_hal::digital::v2::{InputPin, StatefulOutputPin}; @@ -312,86 +311,12 @@ impl<'d, C: Channel, T: GpioPin> OutputChannel<'d, C, T> { } } -/// GPIOTE port input driver -pub struct PortInput<'d, T: GpioPin> { - pin: Input<'d, T>, +pub(crate) struct PortInputFuture<'a> { + pub(crate) pin_port: u8, + pub(crate) phantom: PhantomData<&'a mut AnyPin>, } -impl<'d, T: GpioPin> Unpin for PortInput<'d, T> {} - -impl<'d, T: GpioPin> PortInput<'d, T> { - pub fn new(pin: Input<'d, T>) -> Self { - Self { pin } - } -} - -impl<'d, T: GpioPin> InputPin for PortInput<'d, T> { - type Error = Infallible; - - fn is_high(&self) -> Result { - self.pin.is_high() - } - - fn is_low(&self) -> Result { - self.pin.is_low() - } -} - -impl<'d, T: GpioPin> WaitForHigh for PortInput<'d, T> { - type Future<'a> - where - Self: 'a, - = PortInputFuture<'a>; - - fn wait_for_high<'a>(&'a mut self) -> Self::Future<'a> { - self.pin.pin.conf().modify(|_, w| w.sense().high()); - - PortInputFuture { - pin_port: self.pin.pin.pin_port(), - phantom: PhantomData, - } - } -} - -impl<'d, T: GpioPin> WaitForLow for PortInput<'d, T> { - type Future<'a> - where - Self: 'a, - = PortInputFuture<'a>; - - fn wait_for_low<'a>(&'a mut self) -> Self::Future<'a> { - self.pin.pin.conf().modify(|_, w| w.sense().low()); - - PortInputFuture { - pin_port: self.pin.pin.pin_port(), - phantom: PhantomData, - } - } -} - -impl<'d, T: GpioPin> WaitForAnyEdge for PortInput<'d, T> { - type Future<'a> - where - Self: 'a, - = PortInputFuture<'a>; - - fn wait_for_any_edge<'a>(&'a mut self) -> Self::Future<'a> { - if self.is_high().ok().unwrap() { - self.pin.pin.conf().modify(|_, w| w.sense().low()); - } else { - self.pin.pin.conf().modify(|_, w| w.sense().high()); - } - PortInputFuture { - pin_port: self.pin.pin.pin_port(), - phantom: PhantomData, - } - } -} - -pub struct PortInputFuture<'a> { - pin_port: u8, - phantom: PhantomData<&'a mut AnyPin>, -} +impl<'a> Unpin for PortInputFuture<'a> {} impl<'a> Drop for PortInputFuture<'a> { fn drop(&mut self) { diff --git a/examples/nrf/src/bin/gpiote_port.rs b/examples/nrf/src/bin/gpiote_port.rs index ba9436ac..76c861d9 100644 --- a/examples/nrf/src/bin/gpiote_port.rs +++ b/examples/nrf/src/bin/gpiote_port.rs @@ -8,12 +8,11 @@ mod example_common; use embassy::executor::Spawner; use embassy::traits::gpio::{WaitForHigh, WaitForLow}; use embassy_nrf::gpio::{AnyPin, Input, Pin as _, Pull}; -use embassy_nrf::gpiote::PortInput; use embassy_nrf::Peripherals; use example_common::*; #[embassy::task(pool_size = 4)] -async fn button_task(n: usize, mut pin: PortInput<'static, AnyPin>) { +async fn button_task(n: usize, mut pin: Input<'static, AnyPin>) { loop { pin.wait_for_low().await; info!("Button {:?} pressed!", n); @@ -26,10 +25,10 @@ async fn button_task(n: usize, mut pin: PortInput<'static, AnyPin>) { async fn main(spawner: Spawner, p: Peripherals) { info!("Starting!"); - let btn1 = PortInput::new(Input::new(p.P0_11.degrade(), Pull::Up)); - let btn2 = PortInput::new(Input::new(p.P0_12.degrade(), Pull::Up)); - let btn3 = PortInput::new(Input::new(p.P0_24.degrade(), Pull::Up)); - let btn4 = PortInput::new(Input::new(p.P0_25.degrade(), Pull::Up)); + let btn1 = Input::new(p.P0_11.degrade(), Pull::Up); + let btn2 = Input::new(p.P0_12.degrade(), Pull::Up); + let btn3 = Input::new(p.P0_24.degrade(), Pull::Up); + let btn4 = Input::new(p.P0_25.degrade(), Pull::Up); unwrap!(spawner.spawn(button_task(1, btn1))); unwrap!(spawner.spawn(button_task(2, btn2))); diff --git a/examples/nrf/src/bin/wdt.rs b/examples/nrf/src/bin/wdt.rs index 76f171cd..78c2205d 100644 --- a/examples/nrf/src/bin/wdt.rs +++ b/examples/nrf/src/bin/wdt.rs @@ -8,7 +8,6 @@ mod example_common; use defmt::*; use embassy::executor::Spawner; use embassy_nrf::gpio::{Input, Pull}; -use embassy_nrf::gpiote::PortInput; use embassy_nrf::wdt::{Config, Watchdog}; use embassy_nrf::Peripherals; use embassy_traits::gpio::{WaitForHigh, WaitForLow}; @@ -32,7 +31,7 @@ async fn main(_spawner: Spawner, p: Peripherals) { } }; - let mut button = PortInput::new(Input::new(p.P0_11, Pull::Up)); + let mut button = Input::new(p.P0_11, Pull::Up); info!("Watchdog started, press button 1 to pet it or I'll reset in 3 seconds!");