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

#![cfg_attr(docsrs, feature(doc_cfg))]
#![no_std]

/// Re-export of the linked embedded-hal `v0.2.x` version for convenience
pub use eh0_2;

/// Re-export of the linked embedded-hal `v1.0.x` version for convenience
pub use eh1_0;

/// Re-export of the linked embedded-io version for convenience
#[cfg(feature = "embedded-io")]
#[cfg_attr(docsrs, doc(cfg(feature = "embedded-io")))]
pub use embedded_io;

mod forward;
pub mod markers;
mod reverse;

// Forward compatibility wrapper trait, access using `.forward()`
pub use forward::{Forward, ForwardCompat};

// Reverse compatibility wrapper trait, access using `.reverse()`
pub use reverse::{Reverse, ReverseCompat};