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#[derive(Debug, PartialEq, Eq, Clone, Copy)]
10pub enum I2CError {
11 Code(i32),
12}
13
14#[derive(Debug, Clone, Copy)]
16pub enum I2CAddr {
17 SevenBitAddress(u8),
19 TenBitAddress(u16),
21}
22
23#[derive(Clone, Debug)]
25pub struct I2C<const CLK_HZ: u32> {
26 bus: I2CBusId,
27}
28
29impl<const CLK_HZ: u32> I2C<CLK_HZ> {
30 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 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 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 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}