diff --git a/justfile b/justfile index 8d6b6be..e133eaf 100644 --- a/justfile +++ b/justfile @@ -1,13 +1,13 @@ -all: check-all \ - build-all \ - check-fmt-all \ +all: check \ + build \ + check-fmt \ clippy-all \ docs-all -check-all: check-va108xx check-va416xx -build-all: build-va108xx build-va416xx -check-fmt-all: check-fmt-va108xx check-fmt-va416xx -fmt-all: fmt-va108xx fmt-va416xx fmt-shared-hal +check: check-va108xx check-va416xx +build: build-va108xx build-va416xx +check-fmt: check-fmt-va108xx check-fmt-va416xx +fmt: fmt-va108xx fmt-va416xx fmt-shared-hal clippy-all: clippy-va108xx clippy-va416xx clippy-shared-hal docs-all: docs-va108xx docs-va416xx docs-shared-hal clean-all: clean-va108xx clean-va416xx diff --git a/vorago-shared-hal/CHANGELOG.md b/vorago-shared-hal/CHANGELOG.md index dbdb8c9..1382150 100644 --- a/vorago-shared-hal/CHANGELOG.md +++ b/vorago-shared-hal/CHANGELOG.md @@ -10,6 +10,9 @@ and this project adheres to [Semantic Versioning](http://semver.org/). ### Added +- Add `is_high` and `is_low` for `InputPinAsync`. +- Add `InputPin` impl for `InputPinAsync`. + ### Changed - Added `RxWithInterrupt::steal`. @@ -20,6 +23,7 @@ and this project adheres to [Semantic Versioning](http://semver.org/). - Removed HW CS pin provider implementation for PA23, PA22 and PA21, which are multi HW CS pins. - Added missing `AnyPin` trait impl for Multi HW CS pins. +- Expose inner `Input` pin for `InputPinAsync`. ## [v0.2.0] 2025-09-03 diff --git a/vorago-shared-hal/src/gpio/asynch.rs b/vorago-shared-hal/src/gpio/asynch.rs index 46e349e..5531bb5 100644 --- a/vorago-shared-hal/src/gpio/asynch.rs +++ b/vorago-shared-hal/src/gpio/asynch.rs @@ -6,6 +6,7 @@ //! which must be provided for async support to work. However, it provides the //! [on_interrupt_for_async_gpio_for_port] generic interrupt handler. This should be called in all //! IRQ functions which handle any GPIO interrupts with the corresponding [Port] argument. +#![deny(missing_docs)] use core::future::Future; use embassy_sync::waitqueue::AtomicWaker; @@ -97,6 +98,14 @@ fn pin_group_to_waker_and_edge_detection_group( pub fn on_interrupt_for_async_gpio_for_port(port: Port) { on_interrupt_for_async_gpio_for_port_generic(port); } + +/// Generic interrupt handler for GPIO interrupts on a specific port to support async functionalities +/// +/// This function should be called in all interrupt handlers which handle any GPIO interrupts +/// matching the [Port] argument. +/// The handler will wake the corresponding wakers for the pins that triggered an interrupts +/// as well as update the static edge detection structures. This allows the pin future to complete +/// complete async operations. #[cfg(feature = "vor4x")] pub fn on_interrupt_for_async_gpio_for_port( port: Port, @@ -152,6 +161,7 @@ pub struct InputPinFuture { } impl InputPinFuture { + /// Create a new input pin future from mutable reference to an [Input] pin. #[cfg(feature = "vor1x")] pub fn new_with_input_pin(pin: &mut Input, irq: pac::Interrupt, edge: InterruptEdge) -> Self { let (waker_group, edge_detection_group) = @@ -166,6 +176,8 @@ impl InputPinFuture { edge_detection_group, } } + + /// Create a new input pin future from mutable reference to an [Input] pin. #[cfg(feature = "vor4x")] pub fn new_with_input_pin( pin: &mut Input, @@ -208,6 +220,7 @@ impl Future for InputPinFuture { } } +/// Input pin which has additional asynchronous support. pub struct InputPinAsync { pin: Input, #[cfg(feature = "vor1x")] @@ -225,6 +238,13 @@ impl InputPinAsync { pub fn new(pin: Input, irq: va108xx::Interrupt) -> Self { Self { pin, irq } } + + /// Create a new asynchronous input pin from an [Input] pin. The interrupt ID to be used must be + /// passed as well and is used to route and enable the interrupt. + /// + /// Please note that the interrupt handler itself must be provided by the user and the + /// generic [on_interrupt_for_async_gpio_for_port] function must be called inside that function + /// for the asynchronous functionality to work. #[cfg(feature = "vor4x")] pub fn new(pin: Input) -> Result { if pin.id().port() == Port::G { @@ -250,6 +270,30 @@ impl InputPinAsync { fut.await; } + /// Check whether pin is high. + #[inline] + pub fn is_high(&self) -> bool { + self.pin.is_high() + } + + /// Check whether pin is low. + #[inline] + pub fn is_low(&self) -> bool { + self.pin.is_low() + } + + /// Shared access to [Input] pin. + #[inline] + pub fn inner(&self) -> &Input { + &self.pin + } + + /// Mutable access to [Input] pin. + #[inline] + pub fn inner_mut(&mut self) -> &mut Input { + &mut self.pin + } + /// Asynchronously wait until the pin is low. /// /// This returns immediately if the pin is already high. @@ -296,6 +340,8 @@ impl InputPinAsync { .await; } + /// Release the contained [Input] pin. + #[inline] pub fn release(self) -> Input { self.pin } @@ -331,3 +377,13 @@ impl Wait for InputPinAsync { Ok(()) } } + +impl embedded_hal::digital::InputPin for InputPinAsync { + fn is_low(&mut self) -> Result { + Ok(self.inner().is_low()) + } + + fn is_high(&mut self) -> Result { + Ok(self.inner().is_high()) + } +}