embedded_hal_compat/
lib.rs

1// Embedded HAL Compat
2// Copyright 2021 Ryan Kurte
3//!
4//! A compatibility layer to alleviate (some) of the issues resolving from changes to embedded-hal.
5//! This crate lets you _easily_ mix and match drivers and hal implementations using `v1.x.x` and
6//! `v0.2.x` versions of embedded-hal, just add a `.forward()` or a `.reverse()` wherever you see
7//! trait bounds errors.
8//!
9//! Note that no effort is made to support interoperability between alpha versions, we'll do our
10//! best to keep up with the latest alpha and swap to `1.0.0` on release. In the future these
11//! traits may be renamed to support more hal versions.
12//!
13//!
14//! ## Forward compatibility:
15//!
16//! Calling `ForwardCompat::forward()` (or `.forward()`) on `v0.2.x` types creates a wrapper for
17//! use with `v1.0.x` consumers, so you can drop these wrapped types into drivers expecting
18//! `v1.0.x` types.
19//!
20//! Note that GPIO pins will require annotation with marker types (see [markers]) to select
21//! input / output / combined modes.
22//!
23//!```
24//! # use core::convert::Infallible;
25//! # pub struct OutputPin0_2;
26//! #
27//! # impl eh1_0::digital::ErrorType for OutputPin0_2 {
28//! #     type Error = Infallible;
29//! # }
30//! #
31//! # impl eh0_2::digital::v2::OutputPin for OutputPin0_2 {
32//! #     type Error = Infallible;
33//! #     fn set_high(&mut self) -> Result<(), Self::Error> {
34//! #         Ok(())
35//! #     }
36//! #     fn set_low(&mut self) -> Result<(), Self::Error> {
37//! #         Ok(())
38//! #     }
39//! # }
40//! #
41//! # impl eh0_2::digital::v2::InputPin for OutputPin0_2 {
42//! #     type Error = Infallible;
43//! #     fn is_high(&self) -> Result<bool, Self::Error> {
44//! #         Ok(true)
45//! #     }
46//! #     fn is_low(&self) -> Result<bool, Self::Error> {
47//! #         Ok(false)
48//! #     }
49//! # }
50//! use embedded_hal_compat::{Forward, ForwardCompat, markers::*};
51//!
52//! // Create e-h v0.2.x based type (mock)
53//! let mut old = OutputPin0_2;
54//! // Access via e-h v0.2.x methods
55//! let _ = eh0_2::digital::v2::OutputPin::set_high(&mut old);
56//!
57//! // Apply forward compatibility wrapper
58//! let mut new: Forward<_, ForwardIoPin> = old.forward();
59//! // Access via e-h v1.x.x methods
60//! let _ = eh1_0::digital::OutputPin::set_high(&mut new);
61//!```
62//!
63//!
64//! ## Backwards compatibility:
65//!
66//! Calling `ReverseCompat::reverse()` (or `.reverse()`) on `v1.0.x` types creates a wrapper for
67//! use with `v0.2.x` consumers, so you can drop these wrapped types into drivers expecting
68//! `v0.2.x` types.
69//!
70//! Note that input and output pins require `.reverse_cell()` as a workaround for mutability changes.
71//!
72//!```
73//! # use core::convert::Infallible;
74//! # pub struct OutputPin1_0;
75//! #
76//! # impl eh1_0::digital::ErrorType for OutputPin1_0 {
77//! #     type Error = Infallible;
78//! # }
79//! #
80//! # impl eh1_0::digital::OutputPin for OutputPin1_0 {
81//! #     /// Set the output as high
82//! #     fn set_high(&mut self) -> Result<(), Self::Error> {
83//! #         Ok(())
84//! #     }
85//! #
86//! #     /// Set the output as low
87//! #     fn set_low(&mut self) -> Result<(), Self::Error> {
88//! #         Ok(())
89//! #     }
90//! # }
91//! use embedded_hal_compat::ReverseCompat;
92//!
93//! // Create e-h v1.x.x based type (mock)
94//! let mut new = OutputPin1_0;
95//! // Access via e-h v1.x.x methods
96//! let _ = eh1_0::digital::OutputPin::set_high(&mut new);
97//!
98//! // Apply backwards compatibility wrapper
99//! let mut old = new.reverse_cell();
100//! // Access via e-h v0.2.x methods
101//! let _ = eh0_2::digital::v2::OutputPin::set_high(&mut old);
102//!```
103//!
104//! ```
105//! # use core::convert::Infallible;
106//! # pub struct InputPin1_0;
107//! #
108//! # impl eh1_0::digital::ErrorType for InputPin1_0 {
109//! #     type Error = Infallible;
110//! # }
111//! #
112//! # impl eh1_0::digital::InputPin for InputPin1_0 {
113//! #     /// Set the output as high
114//! #     fn is_high(&mut self) -> Result<bool, Self::Error> {
115//! #         Ok(true)
116//! #     }
117//! #
118//! #     /// Set the output as low
119//! #     fn is_low(&mut self) -> Result<bool, Self::Error> {
120//! #         Ok(false)
121//! #     }
122//! # }
123//! use embedded_hal_compat::ReverseCompat;
124//!
125//! // Create e-h v1.x.x based type (mock)
126//! let mut new = InputPin1_0;
127//! // Access via e-h v1.x.x methods
128//! let _ = eh1_0::digital::InputPin::is_high(&mut new);
129//!
130//! // Apply backwards compatibility wrapper
131//! let mut old = new.reverse_cell();
132//! // Access via e-h v0.2.x methods
133//! let _ = eh0_2::digital::v2::InputPin::is_high(&mut old);
134//!```
135//!
136//! ## Optional features
137//! ### `alloc`
138//! The `alloc` feature enables an implementation of the I2C and SPI `Transactional`
139//! traits from `embedded-hal` `v0.2.x` for the "reverse" direction.
140//!
141//! For example, when your MCU implements the`embedded-hal` `1.0.0` traits
142//! and you want to connect with an I2C or SPI driver that uses
143//! the `Transactional` traits of `embedded-hal` `0.2.x`.
144//!
145//! **For all other cases, this feature is unnecessary**.
146//!
147//! Do not enable it if you do not need it.
148//!
149//! Note that this introduces a dependency on the [core allocation library](https://doc.rust-lang.org/alloc/).
150
151#![cfg_attr(docsrs, feature(doc_cfg))]
152#![no_std]
153
154/// Re-export of the linked embedded-hal `v0.2.x` version for convenience
155pub use eh0_2;
156
157/// Re-export of the linked embedded-hal `v1.0.x` version for convenience
158pub use eh1_0;
159
160/// Re-export of the linked embedded-io version for convenience
161#[cfg(feature = "embedded-io")]
162#[cfg_attr(docsrs, doc(cfg(feature = "embedded-io")))]
163pub use embedded_io;
164
165mod forward;
166pub mod markers;
167mod reverse;
168
169// Forward compatibility wrapper trait, access using `.forward()`
170pub use forward::{Forward, ForwardCompat};
171
172// Reverse compatibility wrapper trait, access using `.reverse()`
173pub use reverse::{Reverse, ReverseCompat};