embedded_hal_compat/
forward.rs

1//! Embedded HAL Forward Compat Later
2//! A compatibility layer to alleviate (some) of the issues resolving from changes to embedded-hal
3// Copyright 2021 Ryan Kurte
4
5use core::marker::PhantomData;
6
7/// Forward compatibility container object.
8/// This is generic over different E-H types and will provide adaption
9/// depending on the bound type.
10pub struct Forward<T, M = ()> {
11    inner: T,
12    _marker: PhantomData<M>,
13}
14
15/// Helper trait to convert a type for forward compatibility
16/// call `.forward()` on `e-h@0.2.x` types to create an `e-h@1.x.x` compatible wrapper object
17pub trait ForwardCompat<T, M = ()> {
18    /// Create an e-h-c forward compatibility wrapper around and e-h object
19    /// Available methods depend on the wrapped type
20    fn forward(self) -> Forward<T, M>;
21}
22
23/// Blanket [ForwardCompat] implementation
24/// (note input/output/io pins may require type annotations)
25impl<T, M> ForwardCompat<T, M> for T {
26    fn forward(self) -> Forward<T, M> {
27        Forward::new(self)
28    }
29}
30
31impl<T, M> Forward<T, M> {
32    /// Create a new compatibility wrapper object
33    pub fn new(inner: T) -> Forward<T, M> {
34        Forward {
35            inner,
36            _marker: PhantomData,
37        }
38    }
39
40    /// Fetch a reference to the wrapped object
41    pub fn inner(&self) -> &T {
42        &self.inner
43    }
44
45    /// Fetch a mutable reference to the wrapped object
46    pub fn inner_mut(&mut self) -> &mut T {
47        &mut self.inner
48    }
49
50    /// Destroy the compatibility wrapper, returning the wrapped object
51    pub fn unwrap(self) -> T {
52        self.inner
53    }
54}
55
56/// Fake SPI error type for forward compatibility.
57///
58/// This fulfils error trait bounds but `.kind()` always returns `Other`
59#[derive(Debug, Clone, PartialEq)]
60#[cfg_attr(feature = "defmt-03", derive(defmt::Format))]
61pub struct ForwardError<E>(pub E);
62
63// note that implementations over Forward cannot be generic over word type
64// etc. due to orphan rules (ie. what happens if someone else defines a word type?)
65
66// Digital / GPIOs
67mod digital {
68    use super::{Forward, ForwardError};
69    use crate::markers::{ForwardInputPin, ForwardIoPin, ForwardOutputPin};
70
71    impl<E: core::fmt::Debug> eh1_0::digital::Error for ForwardError<E> {
72        fn kind(&self) -> eh1_0::digital::ErrorKind {
73            eh1_0::digital::ErrorKind::Other
74        }
75    }
76
77    impl<T, E> eh1_0::digital::ErrorType for Forward<T, ForwardInputPin>
78    where
79        T: eh0_2::digital::v2::InputPin<Error = E>,
80        E: core::fmt::Debug,
81    {
82        type Error = super::ForwardError<E>;
83    }
84
85    impl<T, E> eh1_0::digital::InputPin for Forward<T, ForwardInputPin>
86    where
87        T: eh0_2::digital::v2::InputPin<Error = E>,
88        E: core::fmt::Debug,
89    {
90        /// Is the input pin high?
91        fn is_high(&mut self) -> Result<bool, Self::Error> {
92            self.inner.is_high().map_err(ForwardError)
93        }
94
95        /// Is the input pin low?
96        fn is_low(&mut self) -> Result<bool, Self::Error> {
97            self.inner.is_low().map_err(ForwardError)
98        }
99    }
100
101    impl<T, E> eh1_0::digital::ErrorType for Forward<T, ForwardOutputPin>
102    where
103        T: eh0_2::digital::v2::OutputPin<Error = E>,
104        E: core::fmt::Debug,
105    {
106        type Error = super::ForwardError<E>;
107    }
108
109    impl<T, E> eh1_0::digital::OutputPin for Forward<T, ForwardOutputPin>
110    where
111        T: eh0_2::digital::v2::OutputPin<Error = E>,
112        E: core::fmt::Debug,
113    {
114        /// Set the output as high
115        fn set_high(&mut self) -> Result<(), Self::Error> {
116            self.inner.set_high().map_err(ForwardError)
117        }
118
119        /// Set the output as low
120        fn set_low(&mut self) -> Result<(), Self::Error> {
121            self.inner.set_low().map_err(ForwardError)
122        }
123    }
124
125    impl<T, E> eh1_0::digital::ErrorType for Forward<T, ForwardIoPin>
126    where
127        T: eh0_2::digital::v2::OutputPin<Error = E> + eh0_2::digital::v2::InputPin<Error = E>,
128        E: core::fmt::Debug,
129    {
130        type Error = super::ForwardError<E>;
131    }
132
133    impl<T, E> eh1_0::digital::InputPin for Forward<T, ForwardIoPin>
134    where
135        T: eh0_2::digital::v2::InputPin<Error = E> + eh0_2::digital::v2::OutputPin<Error = E>,
136        E: core::fmt::Debug,
137    {
138        /// Is the input pin high?
139        fn is_high(&mut self) -> Result<bool, Self::Error> {
140            self.inner.is_high().map_err(ForwardError)
141        }
142
143        /// Is the input pin low?
144        fn is_low(&mut self) -> Result<bool, Self::Error> {
145            self.inner.is_low().map_err(ForwardError)
146        }
147    }
148
149    impl<T, E> eh1_0::digital::OutputPin for Forward<T, ForwardIoPin>
150    where
151        T: eh0_2::digital::v2::InputPin<Error = E> + eh0_2::digital::v2::OutputPin<Error = E>,
152        E: core::fmt::Debug,
153    {
154        /// Set the output as high
155        fn set_high(&mut self) -> Result<(), Self::Error> {
156            self.inner.set_high().map_err(ForwardError)
157        }
158
159        /// Set the output as low
160        fn set_low(&mut self) -> Result<(), Self::Error> {
161            self.inner.set_low().map_err(ForwardError)
162        }
163    }
164}
165
166/// Delays (blocking)
167mod delay {
168    use super::Forward;
169
170    impl<T> eh1_0::delay::DelayNs for Forward<T>
171    where
172        T: eh0_2::blocking::delay::DelayUs<u32>,
173    {
174        fn delay_ns(&mut self, ns: u32) {
175            self.inner.delay_us(ns.div_ceil(1000))
176        }
177
178        fn delay_us(&mut self, us: u32) {
179            self.inner.delay_us(us)
180        }
181    }
182}
183
184/// SPI (blocking)
185mod spi {
186    use super::{Forward, ForwardError};
187
188    impl<E: core::fmt::Debug> eh1_0::spi::Error for ForwardError<E> {
189        fn kind(&self) -> eh1_0::spi::ErrorKind {
190            eh1_0::spi::ErrorKind::Other
191        }
192    }
193
194    impl<T, E> eh1_0::spi::ErrorType for Forward<T>
195    where
196        T: eh0_2::blocking::spi::Transfer<u8, Error = E>,
197        E: core::fmt::Debug,
198    {
199        type Error = ForwardError<E>;
200    }
201
202    impl<T, E> eh1_0::spi::SpiBus<u8> for Forward<T>
203    where
204        T: eh0_2::blocking::spi::Transfer<u8, Error = E>
205            + eh0_2::blocking::spi::Write<u8, Error = E>,
206        E: core::fmt::Debug,
207    {
208        fn read(&mut self, words: &mut [u8]) -> Result<(), Self::Error> {
209            // Clear buffer to send empty bytes
210            for word in words.iter_mut() {
211                *word = 0x00;
212            }
213            self.inner.transfer(words).map_err(ForwardError)?;
214            Ok(())
215        }
216
217        fn write(&mut self, words: &[u8]) -> Result<(), Self::Error> {
218            self.inner.write(words).map_err(ForwardError)
219        }
220
221        fn transfer(&mut self, read: &mut [u8], write: &[u8]) -> Result<(), Self::Error> {
222            read.copy_from_slice(&write[..read.len()]);
223            self.inner.transfer(read).map_err(ForwardError)?;
224            Ok(())
225        }
226
227        fn transfer_in_place(&mut self, words: &mut [u8]) -> Result<(), Self::Error> {
228            self.inner.transfer(words).map_err(ForwardError)?;
229            Ok(())
230        }
231
232        fn flush(&mut self) -> Result<(), Self::Error> {
233            // TODO: This API doesn't exist in 0.2.7
234            Ok(())
235        }
236    }
237}
238
239// I2C (blocking)
240mod i2c {
241    use super::{Forward, ForwardError};
242    use eh1_0::i2c::SevenBitAddress;
243
244    use eh0_2::blocking::i2c::{self as eh0_2_i2c};
245
246    impl<E: core::fmt::Debug> eh1_0::i2c::Error for ForwardError<E> {
247        fn kind(&self) -> eh1_0::i2c::ErrorKind {
248            eh1_0::i2c::ErrorKind::Other
249        }
250    }
251
252    impl<T, E> eh1_0::i2c::ErrorType for Forward<T>
253    where
254        T: eh0_2::blocking::i2c::Read<Error = E>,
255        E: core::fmt::Debug,
256    {
257        type Error = ForwardError<E>;
258    }
259
260    impl<T, E> eh1_0::i2c::I2c<SevenBitAddress> for Forward<T>
261    where
262        T: eh0_2_i2c::Write<Error = E>
263            + eh0_2_i2c::WriteIter<Error = E>
264            + eh0_2_i2c::Read<Error = E>
265            + eh0_2_i2c::WriteRead<Error = E>
266            + eh0_2_i2c::WriteIterRead<Error = E>
267            + eh0_2_i2c::Transactional<Error = E>
268            + eh0_2_i2c::TransactionalIter<Error = E>,
269        E: core::fmt::Debug,
270    {
271        fn read(&mut self, address: SevenBitAddress, words: &mut [u8]) -> Result<(), Self::Error> {
272            self.inner.read(address, words).map_err(ForwardError)
273        }
274
275        fn write(&mut self, address: SevenBitAddress, words: &[u8]) -> Result<(), Self::Error> {
276            eh0_2_i2c::Write::write(&mut self.inner, address, words).map_err(ForwardError)
277        }
278
279        fn write_read(
280            &mut self,
281            address: SevenBitAddress,
282            bytes: &[u8],
283            buffer: &mut [u8],
284        ) -> Result<(), Self::Error> {
285            self.inner
286                .write_read(address, bytes, buffer)
287                .map_err(ForwardError)
288        }
289
290        fn transaction(
291            &mut self,
292            address: SevenBitAddress,
293            operations: &mut [eh1_0::i2c::Operation],
294        ) -> Result<(), Self::Error> {
295            let ops = operations.iter_mut().map(|op| match op {
296                eh1_0::i2c::Operation::Read(ref mut buff) => {
297                    eh0_2::blocking::i2c::Operation::Read(buff)
298                }
299                eh1_0::i2c::Operation::Write(buff) => eh0_2::blocking::i2c::Operation::Write(buff),
300            });
301
302            self.inner.exec_iter(address, ops).map_err(ForwardError)
303        }
304    }
305}
306
307/// Serial (UART etc.)
308#[cfg(feature = "embedded-io")]
309#[cfg_attr(docsrs, doc(cfg(feature = "embedded-io")))]
310mod serial {
311    use super::{Forward, ForwardError};
312
313    impl<E: core::fmt::Debug> embedded_io::Error for ForwardError<E> {
314        fn kind(&self) -> embedded_io::ErrorKind {
315            embedded_io::ErrorKind::Other
316        }
317    }
318
319    impl<T, E> embedded_io::ErrorType for Forward<T>
320    where
321        T: eh0_2::blocking::serial::Write<u8, Error = E>,
322        E: core::fmt::Debug,
323    {
324        type Error = ForwardError<E>;
325    }
326
327    impl<T, E> embedded_io::Write for Forward<T>
328    where
329        T: eh0_2::blocking::serial::Write<u8, Error = E>,
330        E: core::fmt::Debug,
331    {
332        fn write(&mut self, words: &[u8]) -> Result<usize, Self::Error> {
333            self.inner
334                .bwrite_all(words)
335                .map_err(ForwardError)
336                .and(Ok(words.len()))
337        }
338
339        fn flush(&mut self) -> Result<(), Self::Error> {
340            self.inner.bflush().map_err(ForwardError)
341        }
342    }
343}