embedded_platform/i2c.rs
1//! Definitions for I²C peripherals.
2use crate::io;
3use core::fmt;
4use core::pin;
5use core::task;
6
7pub mod begin_read;
8pub mod begin_write;
9pub mod initialize;
10
11/// A peripheral that can perform I²C read operations.
12// TODO: this should maybe capture the lifetime of self and let it flow into Self::Read
13pub trait I2cRead: fmt::Debug {
14 /// The common error type for I²C read operations.
15 ///
16 /// A single error type for all operations is enforced for simplicity.
17 type Error;
18 /// An object that can be used to complete the read operation.
19 type Read: io::Read + Unpin;
20
21 /// Polls the start of a read operation to completion.
22 fn poll_begin_read(
23 self: pin::Pin<&mut Self>,
24 cx: &mut task::Context<'_>,
25 addr: u8,
26 ) -> task::Poll<Result<Self::Read, Self::Error>>;
27}
28
29/// Extension functions for instances of [`I2cRead`].
30// TODO: this should maybe capture the lifetime of self and let it flow into Self::Read
31pub trait I2cReadExt: I2cRead {
32 /// Initiates a read operation on the specified address.
33 ///
34 /// The returned object can be used to read the actual data from the address. The user must
35 /// read the data until completion, or else it might leave this I²C peripheral in an incomplete
36 /// state.
37 fn begin_read(&mut self, address: u8) -> begin_read::BeginRead<Self>
38 where
39 Self: Unpin,
40 {
41 begin_read::begin_read(self, address)
42 }
43}
44
45impl<'r, A> I2cReadExt for A where A: I2cRead {}
46
47/// A peripheral that can perform I²C write operations.
48pub trait I2cWrite: fmt::Debug {
49 /// The common error type for I²C write operations.
50 ///
51 /// A single error type for all operations is enforced for simplicity.
52 type Error;
53 /// An object that can be used to complete the write operation.
54 type Write: io::Write + Unpin;
55
56 /// Polls the start of a write operation to completion.
57 fn poll_begin_write(
58 self: pin::Pin<&mut Self>,
59 cx: &mut task::Context<'_>,
60 addr: u8,
61 ) -> task::Poll<Result<Self::Write, Self::Error>>;
62}
63
64/// Extension functions for instances of [`I2cWrite`].
65pub trait I2cWriteExt: I2cWrite {
66 /// Initiates a write operation on the specified address.
67 ///
68 /// The returned object can be used to write the actual data to the address. The user must call
69 /// `shutdown` when done writing, or else it might leave this I²C peripheral in an incomplete
70 /// state. For example, the I²C peripheral might decide to flush remaining data in the [`Drop`]
71 /// implementation, which will be blocking.
72 fn begin_write(&mut self, address: u8) -> begin_write::BeginWrite<Self>
73 where
74 Self: Unpin,
75 {
76 begin_write::begin_write(self, address)
77 }
78}
79
80impl<A> I2cWriteExt for A where A: I2cWrite {}
81
82/// Defines a mapping for two GPIO pins that can be used to create an I²C bus.
83pub trait I2cBusMapping<SDA, SCL> {
84 /// The common error type for I²C operations.
85 ///
86 /// A single error type for all operations is enforced for simplicity.
87 type Error;
88 /// The I²C bus that will be produced once initialization based off of this mapping succeeds.
89 type Bus: I2cRead<Error = Self::Error> + I2cWrite<Error = Self::Error>;
90
91 /// Polls the initialization operation to completion.
92 fn poll_initialize(
93 self: pin::Pin<&mut Self>,
94 cx: &mut task::Context<'_>,
95 sda: &mut SDA,
96 scl: &mut SCL,
97 ) -> task::Poll<Result<Self::Bus, Self::Error>>
98 where
99 Self: Sized;
100}
101
102/// Extension functions for instances of [`I2cBusMapping`].
103pub trait I2cBusMappingExt<SDA, SCL>: I2cBusMapping<SDA, SCL>
104where
105 SDA: Unpin,
106 SCL: Unpin,
107{
108 /// Initializes a new I²C bus based off of the two provided SDA (data) and SCL (clock) pins.
109 fn initialize(self, sda: SDA, scl: SCL) -> initialize::Initialize<Self, SDA, SCL>
110 where
111 Self: Sized + Unpin,
112 {
113 initialize::initialize(self, sda, scl)
114 }
115}
116
117impl<A, SDA, SCL> I2cBusMappingExt<SDA, SCL> for A
118where
119 A: I2cBusMapping<SDA, SCL>,
120 SDA: Unpin,
121 SCL: Unpin,
122{
123}