11//! Blocking I2C API
22//!
3- //! Slave addresses used by this API are 7-bit I2C addresses ranging from 0 to 127.
3+ //! This API supports 7-bit and 10-bit addresses. Traits feature an `AddressMode`
4+ //! marker type parameter. Two implementation of the `AddressMode` exist:
5+ //! `SevenBitAddress` and `TenBitAddress`.
46//!
5- //! Operations on 10-bit slave addresses are not supported by the API yet (but applications might
6- //! be able to emulate some operations).
7+ //! Through this marker types it is possible to implement each address mode for
8+ //! the traits independently in `embedded-hal` implementations and device drivers
9+ //! can depend only on the mode that they support.
10+ //!
11+ //! Additionally, the I2C 10-bit address mode has been developed to be fully
12+ //! backwards compatible with the 7-bit address mode. This allows for a
13+ //! software-emulated 10-bit addressing implementation if the address mode
14+ //! is not supported by the hardware.
15+ //!
16+ //! Since 7-bit addressing is the mode of the majority of I2C devices,
17+ //! `SevenBitAddress` has been set as default mode and thus can be omitted if desired.
18+ //!
19+ //! ## Examples
20+ //!
21+ //! ### `embedded-hal` implementation for an MCU
22+ //! Here is an example of an embedded-hal implementation of the `Write` trait
23+ //! for both modes:
24+ //! ```
25+ //! # use embedded_hal::blocking::i2c::{SevenBitAddress, TenBitAddress, Write};
26+ //! /// I2C0 hardware peripheral which supports both 7-bit and 10-bit addressing.
27+ //! pub struct I2c0;
28+ //!
29+ //! impl Write<SevenBitAddress> for I2c0
30+ //! {
31+ //! # type Error = ();
32+ //! #
33+ //! fn try_write(&mut self, addr: u8, output: &[u8]) -> Result<(), Self::Error> {
34+ //! // ...
35+ //! # Ok(())
36+ //! }
37+ //! }
38+ //!
39+ //! impl Write<TenBitAddress> for I2c0
40+ //! {
41+ //! # type Error = ();
42+ //! #
43+ //! fn try_write(&mut self, addr: u16, output: &[u8]) -> Result<(), Self::Error> {
44+ //! // ...
45+ //! # Ok(())
46+ //! }
47+ //! }
48+ //! ```
49+ //!
50+ //! ### Device driver compatible only with 7-bit addresses
51+ //!
52+ //! For demonstration purposes the address mode parameter has been omitted in this example.
53+ //!
54+ //! ```
55+ //! # use embedded_hal::blocking::i2c::WriteRead;
56+ //! const ADDR: u8 = 0x15;
57+ //! # const TEMP_REGISTER: u8 = 0x1;
58+ //! pub struct TemperatureSensorDriver<I2C> {
59+ //! i2c: I2C,
60+ //! }
61+ //!
62+ //! impl<I2C, E> TemperatureSensorDriver<I2C>
63+ //! where
64+ //! I2C: WriteRead<Error = E>,
65+ //! {
66+ //! pub fn read_temperature(&mut self) -> Result<u8, E> {
67+ //! let mut temp = [0];
68+ //! self.i2c
69+ //! .try_write_read(ADDR, &[TEMP_REGISTER], &mut temp)
70+ //! .and(Ok(temp[0]))
71+ //! }
72+ //! }
73+ //! ```
74+ //!
75+ //! ### Device driver compatible only with 10-bit addresses
76+ //!
77+ //! ```
78+ //! # use embedded_hal::blocking::i2c::{TenBitAddress, WriteRead};
79+ //! const ADDR: u16 = 0x158;
80+ //! # const TEMP_REGISTER: u8 = 0x1;
81+ //! pub struct TemperatureSensorDriver<I2C> {
82+ //! i2c: I2C,
83+ //! }
84+ //!
85+ //! impl<I2C, E> TemperatureSensorDriver<I2C>
86+ //! where
87+ //! I2C: WriteRead<TenBitAddress, Error = E>,
88+ //! {
89+ //! pub fn read_temperature(&mut self) -> Result<u8, E> {
90+ //! let mut temp = [0];
91+ //! self.i2c
92+ //! .try_write_read(ADDR, &[TEMP_REGISTER], &mut temp)
93+ //! .and(Ok(temp[0]))
94+ //! }
95+ //! }
96+ //! ```
97+
98+ use crate :: private;
99+
100+ /// Address mode (7-bit / 10-bit)
101+ ///
102+ /// Note: This trait is sealed and should not be implemented outside of this crate.
103+ pub trait AddressMode : private:: Sealed {
104+ /// Address value type
105+ type Address ;
106+ }
107+
108+ /// 7-bit address mode type
109+ pub struct SevenBitAddress ;
110+
111+ /// 10-bit address mode type
112+ pub struct TenBitAddress ;
113+
114+ impl AddressMode for SevenBitAddress {
115+ type Address = u8 ;
116+ }
117+
118+ impl AddressMode for TenBitAddress {
119+ type Address = u16 ;
120+ }
7121
8122/// Blocking read
9- pub trait Read {
123+ pub trait Read < A : AddressMode = SevenBitAddress > {
10124 /// Error type
11125 type Error ;
12126
@@ -28,11 +142,11 @@ pub trait Read {
28142 /// - `MAK` = master acknowledge
29143 /// - `NMAK` = master no acknowledge
30144 /// - `SP` = stop condition
31- fn try_read ( & mut self , address : u8 , buffer : & mut [ u8 ] ) -> Result < ( ) , Self :: Error > ;
145+ fn try_read ( & mut self , address : A :: Address , buffer : & mut [ u8 ] ) -> Result < ( ) , Self :: Error > ;
32146}
33147
34148/// Blocking write
35- pub trait Write {
149+ pub trait Write < A : AddressMode = SevenBitAddress > {
36150 /// Error type
37151 type Error ;
38152
@@ -52,11 +166,11 @@ pub trait Write {
52166 /// - `SAK` = slave acknowledge
53167 /// - `Bi` = ith byte of data
54168 /// - `SP` = stop condition
55- fn try_write ( & mut self , address : u8 , bytes : & [ u8 ] ) -> Result < ( ) , Self :: Error > ;
169+ fn try_write ( & mut self , address : A :: Address , bytes : & [ u8 ] ) -> Result < ( ) , Self :: Error > ;
56170}
57171
58172/// Blocking write (iterator version)
59- pub trait WriteIter {
173+ pub trait WriteIter < A : AddressMode = SevenBitAddress > {
60174 /// Error type
61175 type Error ;
62176
@@ -65,13 +179,13 @@ pub trait WriteIter {
65179 /// # I2C Events (contract)
66180 ///
67181 /// Same as `Write`
68- fn try_write_iter < B > ( & mut self , address : u8 , bytes : B ) -> Result < ( ) , Self :: Error >
182+ fn try_write_iter < B > ( & mut self , address : A :: Address , bytes : B ) -> Result < ( ) , Self :: Error >
69183 where
70184 B : IntoIterator < Item = u8 > ;
71185}
72186
73187/// Blocking write + read
74- pub trait WriteRead {
188+ pub trait WriteRead < A : AddressMode = SevenBitAddress > {
75189 /// Error type
76190 type Error ;
77191
@@ -99,14 +213,14 @@ pub trait WriteRead {
99213 /// - `SP` = stop condition
100214 fn try_write_read (
101215 & mut self ,
102- address : u8 ,
216+ address : A :: Address ,
103217 bytes : & [ u8 ] ,
104218 buffer : & mut [ u8 ] ,
105219 ) -> Result < ( ) , Self :: Error > ;
106220}
107221
108222/// Blocking write (iterator version) + read
109- pub trait WriteIterRead {
223+ pub trait WriteIterRead < A : AddressMode = SevenBitAddress > {
110224 /// Error type
111225 type Error ;
112226
@@ -118,7 +232,7 @@ pub trait WriteIterRead {
118232 /// Same as the `WriteRead` trait
119233 fn try_write_iter_read < B > (
120234 & mut self ,
121- address : u8 ,
235+ address : A :: Address ,
122236 bytes : B ,
123237 buffer : & mut [ u8 ] ,
124238 ) -> Result < ( ) , Self :: Error >
0 commit comments