diff --git a/CHANGELOG.md b/CHANGELOG.md index 274b0f41f..652088367 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -8,6 +8,8 @@ and this project adheres to [Semantic Versioning](http://semver.org/). ## [Unreleased] ### Added +- Added `IoPin` trait for pins that can change between being inputs or outputs + dynamically. ### Changed - Swap PWM channel arguments to references diff --git a/src/digital.rs b/src/digital.rs index 7edd92a57..2e0735a09 100644 --- a/src/digital.rs +++ b/src/digital.rs @@ -174,3 +174,49 @@ pub trait InputPin { /// Is the input pin low? fn try_is_low(&self) -> Result; } + +/// Single pin that can switch from input to output mode, and vice-versa. +/// +/// Example use (assumes the `Error` type is the same for the `IoPin`, +/// `InputPin`, and `OutputPin`): +/// +/// ``` +/// use core::time::Duration; +/// use embedded_hal::digital::{IoPin, InputPin, OutputPin}; +/// +/// pub fn ping_and_read( +/// mut pin: TOutputPin, delay_fn: &dyn Fn(Duration) -> ()) -> Result +/// where +/// TInputPin : InputPin + IoPin, +/// TOutputPin : OutputPin + IoPin, +/// { +/// // Ping +/// pin.try_set_low()?; +/// delay_fn(Duration::from_millis(10)); +/// pin.try_set_high()?; +/// +/// // Read +/// let pin = pin.try_into_input_pin()?; +/// delay_fn(Duration::from_millis(10)); +/// pin.try_is_high() +/// } +/// ``` +pub trait IoPin +where + TInput: InputPin + IoPin, + TOutput: OutputPin + IoPin, +{ + /// Error type. + type Error; + + /// Tries to convert this pin to input mode. + /// + /// If the pin is already in input mode, this method should succeed. + fn try_into_input_pin(self) -> Result; + + /// Tries to convert this pin to output mode with the given initial state. + /// + /// If the pin is already in the requested state, this method should + /// succeed. + fn try_into_output_pin(self, state: PinState) -> Result; +}