embedded_hal/
digital.rs

1//! Digital I/O.
2
3use core::{convert::From, ops::Not};
4
5#[cfg(feature = "defmt-03")]
6use crate::defmt;
7
8/// Error.
9pub trait Error: core::fmt::Debug {
10    /// Convert error to a generic error kind
11    ///
12    /// By using this method, errors freely defined by HAL implementations
13    /// can be converted to a set of generic errors upon which generic
14    /// code can act.
15    fn kind(&self) -> ErrorKind;
16}
17
18impl Error for core::convert::Infallible {
19    fn kind(&self) -> ErrorKind {
20        match *self {}
21    }
22}
23
24/// Error kind.
25///
26/// This represents a common set of operation errors. HAL implementations are
27/// free to define more specific or additional error types. However, by providing
28/// a mapping to these common errors, generic code can still react to them.
29#[derive(Debug, Copy, Clone, Eq, PartialEq, Ord, PartialOrd, Hash)]
30#[cfg_attr(feature = "defmt-03", derive(defmt::Format))]
31#[non_exhaustive]
32pub enum ErrorKind {
33    /// A different error occurred. The original error may contain more information.
34    Other,
35}
36
37impl Error for ErrorKind {
38    #[inline]
39    fn kind(&self) -> ErrorKind {
40        *self
41    }
42}
43
44impl core::fmt::Display for ErrorKind {
45    #[inline]
46    fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
47        match self {
48            Self::Other => write!(
49                f,
50                "A different error occurred. The original error may contain more information"
51            ),
52        }
53    }
54}
55
56/// Error type trait.
57///
58/// This just defines the error type, to be used by the other traits.
59pub trait ErrorType {
60    /// Error type
61    type Error: Error;
62}
63
64impl<T: ErrorType + ?Sized> ErrorType for &T {
65    type Error = T::Error;
66}
67
68impl<T: ErrorType + ?Sized> ErrorType for &mut T {
69    type Error = T::Error;
70}
71
72/// Digital output pin state.
73///
74/// Conversion from `bool` and logical negation are also implemented
75/// for this type.
76/// ```rust
77/// # use embedded_hal::digital::PinState;
78/// let state = PinState::from(false);
79/// assert_eq!(state, PinState::Low);
80/// assert_eq!(!state, PinState::High);
81/// ```
82#[derive(Debug, PartialEq, Eq, Clone, Copy)]
83#[cfg_attr(feature = "defmt-03", derive(defmt::Format))]
84pub enum PinState {
85    /// Low pin state.
86    Low,
87    /// High pin state.
88    High,
89}
90
91impl From<bool> for PinState {
92    #[inline]
93    fn from(value: bool) -> Self {
94        match value {
95            false => PinState::Low,
96            true => PinState::High,
97        }
98    }
99}
100
101impl Not for PinState {
102    type Output = PinState;
103
104    #[inline]
105    fn not(self) -> Self::Output {
106        match self {
107            PinState::High => PinState::Low,
108            PinState::Low => PinState::High,
109        }
110    }
111}
112
113impl From<PinState> for bool {
114    #[inline]
115    fn from(value: PinState) -> bool {
116        match value {
117            PinState::Low => false,
118            PinState::High => true,
119        }
120    }
121}
122
123/// Single digital push-pull output pin.
124pub trait OutputPin: ErrorType {
125    /// Drives the pin low.
126    ///
127    /// *NOTE* the actual electrical state of the pin may not actually be low, e.g. due to external
128    /// electrical sources.
129    fn set_low(&mut self) -> Result<(), Self::Error>;
130
131    /// Drives the pin high.
132    ///
133    /// *NOTE* the actual electrical state of the pin may not actually be high, e.g. due to external
134    /// electrical sources.
135    fn set_high(&mut self) -> Result<(), Self::Error>;
136
137    /// Drives the pin high or low depending on the provided value.
138    ///
139    /// *NOTE* the actual electrical state of the pin may not actually be high or low, e.g. due to external
140    /// electrical sources.
141    #[inline]
142    fn set_state(&mut self, state: PinState) -> Result<(), Self::Error> {
143        match state {
144            PinState::Low => self.set_low(),
145            PinState::High => self.set_high(),
146        }
147    }
148}
149
150impl<T: OutputPin + ?Sized> OutputPin for &mut T {
151    #[inline]
152    fn set_low(&mut self) -> Result<(), Self::Error> {
153        T::set_low(self)
154    }
155
156    #[inline]
157    fn set_high(&mut self) -> Result<(), Self::Error> {
158        T::set_high(self)
159    }
160
161    #[inline]
162    fn set_state(&mut self, state: PinState) -> Result<(), Self::Error> {
163        T::set_state(self, state)
164    }
165}
166
167/// Push-pull output pin that can read its output state.
168pub trait StatefulOutputPin: OutputPin {
169    /// Is the pin in drive high mode?
170    ///
171    /// *NOTE* this does *not* read the electrical state of the pin.
172    fn is_set_high(&mut self) -> Result<bool, Self::Error>;
173
174    /// Is the pin in drive low mode?
175    ///
176    /// *NOTE* this does *not* read the electrical state of the pin.
177    fn is_set_low(&mut self) -> Result<bool, Self::Error>;
178
179    /// Toggle pin output.
180    fn toggle(&mut self) -> Result<(), Self::Error> {
181        let was_low: bool = self.is_set_low()?;
182        self.set_state(PinState::from(was_low))
183    }
184}
185
186impl<T: StatefulOutputPin + ?Sized> StatefulOutputPin for &mut T {
187    #[inline]
188    fn is_set_high(&mut self) -> Result<bool, Self::Error> {
189        T::is_set_high(self)
190    }
191
192    #[inline]
193    fn is_set_low(&mut self) -> Result<bool, Self::Error> {
194        T::is_set_low(self)
195    }
196
197    #[inline]
198    fn toggle(&mut self) -> Result<(), Self::Error> {
199        T::toggle(self)
200    }
201}
202
203/// Single digital input pin.
204pub trait InputPin: ErrorType {
205    /// Is the input pin high?
206    fn is_high(&mut self) -> Result<bool, Self::Error>;
207
208    /// Is the input pin low?
209    fn is_low(&mut self) -> Result<bool, Self::Error>;
210}
211
212impl<T: InputPin + ?Sized> InputPin for &mut T {
213    #[inline]
214    fn is_high(&mut self) -> Result<bool, Self::Error> {
215        T::is_high(self)
216    }
217
218    #[inline]
219    fn is_low(&mut self) -> Result<bool, Self::Error> {
220        T::is_low(self)
221    }
222}