From 97fac7697cf52968796534542aab76a95e32d433 Mon Sep 17 00:00:00 2001 From: Astro Date: Sun, 8 Apr 2018 00:11:07 +0200 Subject: [PATCH 1/4] Remove reading functions from OutputPin trait --- src/digital.rs | 6 ------ 1 file changed, 6 deletions(-) diff --git a/src/digital.rs b/src/digital.rs index 88b0c3c4a..4bf49d178 100644 --- a/src/digital.rs +++ b/src/digital.rs @@ -2,12 +2,6 @@ /// Single digital output pin pub trait OutputPin { - /// Is the output pin high? - fn is_high(&self) -> bool; - - /// Is the output pin low? - fn is_low(&self) -> bool; - /// Sets the pin low fn set_low(&mut self); From 3f61ef25d9244fcf37226f1b7948f08e5eca89b9 Mon Sep 17 00:00:00 2001 From: Astro Date: Sun, 8 Apr 2018 01:17:31 +0200 Subject: [PATCH 2/4] Add StatefulOutputPin to read and toggle the state of OutputPin --- src/digital.rs | 19 +++++++++++++++++++ 1 file changed, 19 insertions(+) diff --git a/src/digital.rs b/src/digital.rs index 4bf49d178..6a40f073f 100644 --- a/src/digital.rs +++ b/src/digital.rs @@ -9,6 +9,25 @@ pub trait OutputPin { fn set_high(&mut self); } +/// Output pin that can read its output state +#[cfg(feature = "unproven")] +trait StatefulOutputPin: OutputPin { + /// Is the pin set to high? + fn is_set_high(&self) -> bool; + + /// Is the pin set to low? + fn is_set_low(&self) -> bool; + + /// Toggle pin output + fn toggle(&mut self) { + if self.is_set_low() { + self.set_high(); + } else { + self.set_low(); + } + } +} + /// Single digital input pin #[cfg(feature = "unproven")] pub trait InputPin { From ac965a3fe89800c0e9df08f7b36515001f96aa2c Mon Sep 17 00:00:00 2001 From: Astro Date: Thu, 12 Apr 2018 17:32:13 +0200 Subject: [PATCH 3/4] separate OutputPin.toggle() into ToggleableOutputPin, provide default impl for StatefulOutputPin --- src/digital.rs | 15 ++++++++++++++- 1 file changed, 14 insertions(+), 1 deletion(-) diff --git a/src/digital.rs b/src/digital.rs index 6a40f073f..492596844 100644 --- a/src/digital.rs +++ b/src/digital.rs @@ -11,13 +11,26 @@ pub trait OutputPin { /// Output pin that can read its output state #[cfg(feature = "unproven")] -trait StatefulOutputPin: OutputPin { +trait StatefulOutputPin { /// Is the pin set to high? fn is_set_high(&self) -> bool; /// Is the pin set to low? fn is_set_low(&self) -> bool; +} + +/// Output pin that can be toggled +#[cfg(feature = "unproven")] +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() { From 6549d73cbedbcc465c58f9ca03c512697d6b3747 Mon Sep 17 00:00:00 2001 From: Astro Date: Thu, 12 Apr 2018 19:23:24 +0200 Subject: [PATCH 4/4] move ToggleableOutputPin default impl to opt-in trait + doc --- src/digital.rs | 75 ++++++++++++++++++++++++++++++++++++++++++-------- 1 file changed, 63 insertions(+), 12 deletions(-) diff --git a/src/digital.rs b/src/digital.rs index 492596844..897c1525d 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,74 @@ 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. +/// 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()); +/// ``` #[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(); +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(); + } } } }