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}
223