diff --git a/src/digital.rs b/src/digital.rs index 492596844..3f6be4449 100644 --- a/src/digital.rs +++ b/src/digital.rs @@ -11,7 +11,7 @@ pub trait OutputPin { /// Output pin that can read its output state #[cfg(feature = "unproven")] -trait StatefulOutputPin { +pub trait StatefulOutputPin { /// Is the pin set to high? fn is_set_high(&self) -> bool; @@ -20,23 +20,73 @@ trait StatefulOutputPin { } /// Output pin that can be toggled +/// +/// See [toggleable](toggleable) to use a software implementation if +/// both [OutputPin](trait.OutputPin.html) and +/// [StatefulOutputPin](trait.StatefulOutputPin.html) are +/// implemented. Otherwise, implement this using hardware mechanisms. #[cfg(feature = "unproven")] -trait ToggleableOutputPin { - /// Toggle pin output +pub trait ToggleableOutputPin { + /// Toggle pin output. fn toggle(&mut self); } /// If you can read **and** write the output state, a pin is -/// toggleable by software. You may override the `toggle()` method -/// with a hardware implementation. -#[cfg(feature = "unproven")] -impl ToggleableOutputPin for PIN { - /// Toggle pin output - fn toggle(&mut self) { - if self.is_set_low() { - self.set_high(); - } else { - self.set_low(); +/// toggleable by software. +/// +/// ``` +/// use embedded_hal::digital::{OutputPin, StatefulOutputPin, ToggleableOutputPin}; +/// use embedded_hal::digital::toggleable; +/// +/// /// A virtual output pin that exists purely in software +/// struct MyPin { +/// state: bool +/// } +/// +/// impl OutputPin for MyPin { +/// fn set_low(&mut self) { +/// self.state = false; +/// } +/// fn set_high(&mut self) { +/// self.state = true; +/// } +/// } +/// +/// impl StatefulOutputPin for MyPin { +/// fn is_set_low(&self) -> bool { +/// !self.state +/// } +/// fn is_set_high(&self) -> bool { +/// self.state +/// } +/// } +/// +/// /// Opt-in to the software implementation. +/// impl toggleable::Default for MyPin {} +/// +/// let mut pin = MyPin { state: false }; +/// pin.toggle(); +/// assert!(pin.is_set_high()); +/// pin.toggle(); +/// assert!(pin.is_set_low()); +/// ``` +pub mod toggleable { + use super::{OutputPin, StatefulOutputPin, ToggleableOutputPin}; + + /// Software-driven `toggle()` implementation. + pub trait Default: OutputPin + StatefulOutputPin {} + + impl

ToggleableOutputPin for P + where + P: Default, + { + /// Toggle pin output + fn toggle(&mut self) { + if self.is_set_low() { + self.set_high(); + } else { + self.set_low(); + } } } }