embedded_c_sdk_bind_hal/
i2c.rs

1pub use crate::ll_api::I2CBusId;
2use crate::ll_api::{ll_cmd::*, I2CBusAddrBits};
3use embedded_hal::i2c::{NoAcknowledgeSource, SevenBitAddress, TenBitAddress};
4
5pub const FREQ_I2C_SCL_100K: u32 = 100_000;
6pub const FREQ_I2C_SCL_400K: u32 = 400_000;
7
8/// Represents errors that can occur during I2C communication.
9#[derive(Debug, PartialEq, Eq, Clone, Copy)]
10pub enum I2CError {
11    Code(i32),
12}
13
14/// Represents I2C addresses.
15#[derive(Debug, Clone, Copy)]
16pub enum I2CAddr {
17    /// A 7-bit address.
18    SevenBitAddress(u8),
19    /// A 10-bit address.
20    TenBitAddress(u16),
21}
22
23/// Implementation of the I2C interface.
24#[derive(Clone, Debug)]
25pub struct I2C<const CLK_HZ: u32> {
26    bus: I2CBusId,
27}
28
29impl<const CLK_HZ: u32> I2C<CLK_HZ> {
30    /// Creates a new `I2C` instance.
31    pub fn new(bus: I2CBusId, flags: Option<u32>) -> Self {
32        let flag_param = if let Some(flags) = flags { flags } else { 0 };
33
34        ll_invoke_inner!(INVOKE_ID_I2C_INIT, bus, CLK_HZ, flag_param);
35
36        I2C { bus }
37    }
38
39    /// Writes bytes and reads bytes over the I2C bus.
40    ///
41    /// # Examples
42    /// ```
43    /// let mut buffer = [0; 4];
44    /// i2c.blocking_write_read(I2CAddr::SevenBitAddress(0x48), &[0x00, 0x01], &mut buffer)?;
45    /// assert_eq!(buffer, [0x02, 0x03, 0x04, 0x05]);
46    /// ```
47    /// ``` text
48    /// Master: ST SAD+W     O0     O1     ... OM     SR SAD+R        MAK    MAK ...    NMAK SP
49    /// Slave:           SAK    SAK    SAK ...    SAK          SAK I0     I1     ... IN
50    /// ```
51    pub fn blocking_write_read(
52        &mut self,
53        address: I2CAddr,
54        write: &[u8],
55        read: &mut [u8],
56    ) -> Result<(), I2CError> {
57        let (bus_addr_bits, addr) = match address {
58            I2CAddr::SevenBitAddress(addr) => (I2CBusAddrBits::SevenBitAddr, addr as u16),
59            I2CAddr::TenBitAddress(addr) => (I2CBusAddrBits::TenBitAddr, addr),
60        };
61        let result = ll_invoke_inner!(
62            INVOKE_ID_I2C_WRITE_READ,
63            self.bus,
64            bus_addr_bits,
65            addr,
66            write.as_ptr(),
67            write.len(),
68            read.as_mut_ptr(),
69            read.len()
70        );
71
72        if result < 0 {
73            return Err(I2CError::Code(result));
74        }
75
76        Ok(())
77    }
78
79    /// Writes bytes over the I2C bus.
80    ///
81    /// # Examples
82    /// ```
83    /// i2c.blocking_write(I2CAddr::SevenBitAddress(0x48), &[0x00, 0x01])?;
84    /// ```
85    ///  ``` text
86    /// Master: ST SAD+W     B0     B1     ... BN     SP
87    /// Slave:           SAK    SAK    SAK ...    SAK
88    /// ```
89    pub fn blocking_write(&mut self, address: I2CAddr, write: &[u8]) -> Result<(), I2CError> {
90        let (bus_addr_bits, addr) = match address {
91            I2CAddr::SevenBitAddress(addr) => (I2CBusAddrBits::SevenBitAddr, addr as u16),
92            I2CAddr::TenBitAddress(addr) => (I2CBusAddrBits::TenBitAddr, addr),
93        };
94        let result = ll_invoke_inner!(
95            INVOKE_ID_I2C_WRITE,
96            self.bus,
97            bus_addr_bits,
98            addr,
99            write.as_ptr(),
100            write.len()
101        );
102
103        if result < 0 {
104            return Err(I2CError::Code(result));
105        }
106        Ok(())
107    }
108
109    /// Reads bytes over the I2C bus.
110    ///
111    /// # Examples
112    /// ```
113    /// let mut buffer = [0; 4];
114    /// i2c.blocking_read(I2CAddr::SevenBitAddress(0x48), &mut buffer)?;
115    /// assert_eq!(buffer, [0x02, 0x03, 0x04, 0x05]);
116    /// ```
117    /// ``` text
118    /// Master: ST SAD+R        MAK    MAK ...    NMAK SP
119    /// Slave:           SAK B0     B1     ... BN
120    /// ```
121    pub fn blocking_read(&mut self, address: I2CAddr, read: &mut [u8]) -> Result<(), I2CError> {
122        let (bus_addr_bits, addr) = match address {
123            I2CAddr::SevenBitAddress(addr) => (I2CBusAddrBits::SevenBitAddr, addr as u16),
124            I2CAddr::TenBitAddress(addr) => (I2CBusAddrBits::TenBitAddr, addr),
125        };
126        let result = ll_invoke_inner!(
127            INVOKE_ID_I2C_READ,
128            self.bus,
129            bus_addr_bits,
130            addr,
131            read.as_mut_ptr(),
132            read.len()
133        );
134
135        if result < 0 {
136            return Err(I2CError::Code(result));
137        }
138        Ok(())
139    }
140}
141
142impl<const CLK_HZ: u32> Drop for I2C<CLK_HZ> {
143    fn drop(&mut self) {
144        ll_invoke_inner!(INVOKE_ID_I2C_DEINIT, self.bus);
145    }
146}
147
148impl embedded_hal::i2c::Error for I2CError {
149    fn kind(&self) -> embedded_hal::i2c::ErrorKind {
150        match *self {
151            I2CError::Code(code) => match code {
152                -1 => embedded_hal::i2c::ErrorKind::NoAcknowledge(NoAcknowledgeSource::Address),
153                -2 => embedded_hal::i2c::ErrorKind::NoAcknowledge(NoAcknowledgeSource::Data),
154                -3 => embedded_hal::i2c::ErrorKind::Bus,
155                -4 => embedded_hal::i2c::ErrorKind::ArbitrationLoss,
156                -5 => embedded_hal::i2c::ErrorKind::Overrun,
157                _ => embedded_hal::i2c::ErrorKind::Other,
158            },
159        }
160    }
161}
162
163impl<const CLK_HZ: u32> embedded_hal::i2c::ErrorType for I2C<CLK_HZ> {
164    type Error = I2CError;
165}
166
167impl<const CLK_HZ: u32> embedded_hal::i2c::I2c<SevenBitAddress> for I2C<CLK_HZ> {
168    fn read(&mut self, address: u8, read: &mut [u8]) -> Result<(), Self::Error> {
169        self.blocking_read(I2CAddr::SevenBitAddress(address), read)
170    }
171
172    fn write(&mut self, address: u8, write: &[u8]) -> Result<(), Self::Error> {
173        self.blocking_write(I2CAddr::SevenBitAddress(address), write)
174    }
175
176    fn write_read(
177        &mut self,
178        address: u8,
179        write: &[u8],
180        read: &mut [u8],
181    ) -> Result<(), Self::Error> {
182        self.blocking_write_read(I2CAddr::SevenBitAddress(address), write, read)
183    }
184
185    fn transaction(
186        &mut self,
187        address: u8,
188        operations: &mut [embedded_hal::i2c::Operation<'_>],
189    ) -> Result<(), Self::Error> {
190        for op in operations {
191            match op {
192                embedded_hal::i2c::Operation::Write(data) => {
193                    self.blocking_write(I2CAddr::SevenBitAddress(address), data)?;
194                }
195                embedded_hal::i2c::Operation::Read(data) => {
196                    self.blocking_read(I2CAddr::SevenBitAddress(address), data)?;
197                }
198            }
199        }
200        Ok(())
201    }
202}
203
204impl<const CLK_HZ: u32> embedded_hal::i2c::I2c<TenBitAddress> for I2C<CLK_HZ> {
205    fn read(&mut self, address: u16, read: &mut [u8]) -> Result<(), Self::Error> {
206        self.blocking_read(I2CAddr::TenBitAddress(address), read)
207    }
208
209    fn write(&mut self, address: u16, write: &[u8]) -> Result<(), Self::Error> {
210        self.blocking_write(I2CAddr::TenBitAddress(address), write)
211    }
212
213    fn write_read(
214        &mut self,
215        address: u16,
216        write: &[u8],
217        read: &mut [u8],
218    ) -> Result<(), Self::Error> {
219        self.blocking_write_read(I2CAddr::TenBitAddress(address), write, read)
220    }
221
222    fn transaction(
223        &mut self,
224        address: u16,
225        operations: &mut [embedded_hal::i2c::Operation<'_>],
226    ) -> Result<(), Self::Error> {
227        for op in operations {
228            match op {
229                embedded_hal::i2c::Operation::Write(data) => {
230                    self.blocking_write(I2CAddr::TenBitAddress(address), data)?;
231                }
232                embedded_hal::i2c::Operation::Read(data) => {
233                    self.blocking_read(I2CAddr::TenBitAddress(address), data)?;
234                }
235            }
236        }
237        Ok(())
238    }
239}