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}