1use crate::peripherals::{I2c0, I2c1};
6use core::marker::PhantomData;
7
8pub struct I2c<'d, T> {
9 idx: u8,
10 _peripheral: PhantomData<&'d T>,
11}
12
13fn i2c_regs(idx: u8) -> &'static ws63_pac::i2c0::RegisterBlock {
14 unsafe {
15 match idx {
16 0 => &*I2c0::ptr(),
17 1 => &*I2c1::ptr(),
18 _ => unreachable!(),
19 }
20 }
21}
22
23impl<'d> I2c<'d, I2c0<'d>> {
24 pub fn new_i2c0(_i2c: I2c0<'d>, freq: u32) -> Self {
25 configure_i2c(0, freq);
26 Self { idx: 0, _peripheral: PhantomData }
27 }
28}
29
30impl<'d> I2c<'d, I2c1<'d>> {
31 pub fn new_i2c1(_i2c: I2c1<'d>, freq: u32) -> Self {
32 configure_i2c(1, freq);
33 Self { idx: 1, _peripheral: PhantomData }
34 }
35}
36
37fn configure_i2c(idx: u8, freq: u32) {
38 let r = i2c_regs(idx);
39 let pclk = crate::soc::ws63::SYSTEM_CLOCK_HZ;
40 let freq = if freq == 0 { 1 } else { freq };
41 let period = pclk / (2 * freq);
42 let half = period / 2;
43 r.i2c_scl_h().write(|w| unsafe { w.bits(half) });
44 r.i2c_scl_l().write(|w| unsafe { w.bits(half) });
45 r.i2c_ctrl().write(|w| unsafe {
47 w.bits(0);
48 w.i2c_en().set_bit();
49 w.mode_ctrl().set_bit();
50 w.int_ack_err_mask().set_bit()
52 });
53}
54
55const I2C_WAIT_LOOPS: u32 = 1_000_000;
60
61#[inline]
62fn wait_until(mut ready: impl FnMut() -> bool) -> Result<(), I2cError> {
63 let mut n = I2C_WAIT_LOOPS;
64 while !ready() {
65 n -= 1;
66 if n == 0 {
67 return Err(I2cError::Timeout);
68 }
69 }
70 Ok(())
71}
72
73impl<T> I2c<'_, T> {
74 #[allow(dead_code)]
75 fn wait_not_busy(&self) -> Result<(), I2cError> {
76 let r = i2c_regs(self.idx);
77 wait_until(|| !r.i2c_sr().read().bus_busy().bit_is_set())
78 }
79
80 fn clear_interrupts(&self) {
81 let r = i2c_regs(self.idx);
82 unsafe { r.i2c_icr().write(|w| w.bits(0x7FF)) };
84 }
85
86 fn check_ack(&self) -> Result<(), I2cError> {
88 let r = i2c_regs(self.idx);
89 if r.i2c_sr().read().int_ack_err().bit_is_set() {
90 return Err(I2cError::Ack);
91 }
92 Ok(())
93 }
94
95 fn wait_tx_ack(&self) -> Result<(), I2cError> {
97 let r = i2c_regs(self.idx);
98 wait_until(|| r.i2c_sr().read().int_tx().bit_is_set())?;
99 self.check_ack()
101 }
102
103 fn send_start(&self, addr_byte: u32, is_read: bool) -> Result<(), I2cError> {
106 let r = i2c_regs(self.idx);
107 self.clear_interrupts();
108
109 r.i2c_txr().write(|w| unsafe { w.bits(addr_byte) });
111
112 unsafe {
114 r.i2c_com().write(|w| w.bits(0));
115 }
116 let mut com: u32 = 0;
117 com |= 1 << 3; com |= 1 << 1; if is_read {
120 }
124 unsafe {
125 r.i2c_com().write(|w| w.bits(com));
126 }
127
128 self.wait_tx_ack()
129 }
130
131 pub fn write(&mut self, addr: u8, data: &[u8]) -> Result<(), I2cError> {
132 let r = i2c_regs(self.idx);
133
134 self.send_start((addr as u32) << 1, false)?;
136
137 for &byte in data {
139 r.i2c_txr().write(|w| unsafe { w.bits(byte as u32) });
140 unsafe { r.i2c_com().write(|w| w.bits(1 << 1)) };
142 self.wait_tx_ack()?;
143 self.clear_interrupts();
144 }
145
146 r.i2c_com().write(|w| w.op_stop().set_bit());
148 wait_until(|| r.i2c_sr().read().int_stop().bit_is_set())?;
149 self.clear_interrupts();
150
151 Ok(())
152 }
153
154 pub fn read(&mut self, addr: u8, buf: &mut [u8]) -> Result<(), I2cError> {
155 let r = i2c_regs(self.idx);
156
157 self.send_start(((addr as u32) << 1) | 1, true)?;
159
160 let buf_len = buf.len();
162 for (i, byte) in buf.iter_mut().enumerate() {
163 let is_last = i == buf_len - 1;
164 let mut com: u32 = 1 << 2; if is_last {
167 com |= 1 << 4; }
169 unsafe { r.i2c_com().write(|w| w.bits(com)) };
170
171 wait_until(|| r.i2c_sr().read().int_rx().bit_is_set())?;
172 *byte = r.i2c_rxr().read().bits() as u8;
173 self.clear_interrupts();
174 }
175
176 r.i2c_com().write(|w| w.op_stop().set_bit());
178 wait_until(|| r.i2c_sr().read().int_stop().bit_is_set())?;
179 self.clear_interrupts();
180
181 Ok(())
182 }
183
184 pub fn write_read(&mut self, addr: u8, wr_buf: &[u8], rd_buf: &mut [u8]) -> Result<(), I2cError> {
187 let r = i2c_regs(self.idx);
188
189 if !wr_buf.is_empty() {
190 self.send_start((addr as u32) << 1, false)?;
192
193 for &byte in wr_buf {
195 r.i2c_txr().write(|w| unsafe { w.bits(byte as u32) });
196 unsafe { r.i2c_com().write(|w| w.bits(1 << 1)) }; self.wait_tx_ack()?;
198 self.clear_interrupts();
199 }
200 }
202
203 if !rd_buf.is_empty() {
204 self.send_start(((addr as u32) << 1) | 1, true)?;
206
207 let buf_len = rd_buf.len();
208 for (i, byte) in rd_buf.iter_mut().enumerate() {
209 let is_last = i == buf_len - 1;
210 let mut com: u32 = 1 << 2; if is_last {
212 com |= 1 << 4; }
214 unsafe { r.i2c_com().write(|w| w.bits(com)) };
215 wait_until(|| r.i2c_sr().read().int_rx().bit_is_set())?;
216 *byte = r.i2c_rxr().read().bits() as u8;
217 self.clear_interrupts();
218 }
219 }
220
221 r.i2c_com().write(|w| w.op_stop().set_bit());
223 wait_until(|| r.i2c_sr().read().int_stop().bit_is_set())?;
224 self.clear_interrupts();
225
226 Ok(())
227 }
228
229 fn transaction_impl(
234 &mut self,
235 address: u8,
236 operations: &mut [embedded_hal::i2c::Operation<'_>],
237 ) -> Result<(), I2cError> {
238 let r = i2c_regs(self.idx);
239 let addr_w = (address as u32) << 1; let addr_r = ((address as u32) << 1) | 1; for op in operations.iter_mut() {
243 match op {
244 embedded_hal::i2c::Operation::Write(data) => {
245 self.send_start(addr_w, false)?;
246 self.clear_interrupts();
247
248 for &byte in data.iter() {
249 r.i2c_txr().write(|w| unsafe { w.bits(byte as u32) });
250 unsafe { r.i2c_com().write(|w| w.bits(1 << 1)) }; self.wait_tx_ack()?;
252 self.clear_interrupts();
253 }
254 }
256 embedded_hal::i2c::Operation::Read(buf) => {
257 self.send_start(addr_r, true)?;
258 self.clear_interrupts();
259
260 let buf_len = buf.len();
261 for (i, byte) in buf.iter_mut().enumerate() {
262 let is_last = i == buf_len - 1;
263 let mut com: u32 = 1 << 2; if is_last {
265 com |= 1 << 4; }
267 unsafe { r.i2c_com().write(|w| w.bits(com)) };
268 wait_until(|| r.i2c_sr().read().int_rx().bit_is_set())?;
269 *byte = r.i2c_rxr().read().bits() as u8;
270 self.clear_interrupts();
271 }
272 }
274 }
275 }
276
277 r.i2c_com().write(|w| w.op_stop().set_bit());
279 wait_until(|| r.i2c_sr().read().int_stop().bit_is_set())?;
280 self.clear_interrupts();
281
282 Ok(())
283 }
284}
285
286#[derive(Debug)]
287pub enum I2cError {
288 Ack,
289 BusError,
290 Timeout,
291}
292
293impl embedded_hal::i2c::Error for I2cError {
294 fn kind(&self) -> embedded_hal::i2c::ErrorKind {
295 match self {
296 I2cError::Ack => {
297 embedded_hal::i2c::ErrorKind::NoAcknowledge(embedded_hal::i2c::NoAcknowledgeSource::Unknown)
298 }
299 I2cError::BusError => embedded_hal::i2c::ErrorKind::Bus,
300 I2cError::Timeout => embedded_hal::i2c::ErrorKind::Other,
301 }
302 }
303}
304
305impl embedded_hal::i2c::ErrorType for I2c<'_, I2c0<'_>> {
308 type Error = I2cError;
309}
310
311impl embedded_hal::i2c::I2c for I2c<'_, I2c0<'_>> {
312 fn transaction(
313 &mut self,
314 address: u8,
315 operations: &mut [embedded_hal::i2c::Operation<'_>],
316 ) -> Result<(), Self::Error> {
317 self.transaction_impl(address, operations)
318 }
319}
320
321impl embedded_hal::i2c::ErrorType for I2c<'_, I2c1<'_>> {
322 type Error = I2cError;
323}
324
325impl embedded_hal::i2c::I2c for I2c<'_, I2c1<'_>> {
326 fn transaction(
327 &mut self,
328 address: u8,
329 operations: &mut [embedded_hal::i2c::Operation<'_>],
330 ) -> Result<(), Self::Error> {
331 self.transaction_impl(address, operations)
332 }
333}
334
335#[cfg(test)]
338mod tests {
339 #[test]
340 fn test_i2c_address_write_encoding() {
341 assert_eq!((0x50u32 << 1), 0xA0);
343 assert_eq!((0x50u32 << 1) & 0xFE, 0xA0); }
345
346 #[test]
347 fn test_i2c_address_read_encoding() {
348 assert_eq!(((0x50u32 << 1) | 1), 0xA1);
350 }
351
352 #[test]
353 fn test_i2c_address_write_read_differ_by_one_bit() {
354 let addr_w = (0x48u32) << 1; let addr_r = ((0x48u32) << 1) | 1; assert_eq!(addr_r, addr_w | 1);
357 assert_eq!(addr_w & 0x01, 0); assert_eq!(addr_r & 0x01, 1); }
360
361 #[test]
362 fn test_i2c_10bit_high_address_encoding() {
363 let addr: u32 = 0x78;
365 let addr_w = addr << 1;
366 assert_eq!(addr_w, 0xF0); }
368}