1use crate::peripherals::{I2c0, I2c1};
9use core::marker::PhantomData;
10
11pub struct I2c<'d, T> {
12 idx: u8,
13 _peripheral: PhantomData<&'d T>,
14}
15
16fn i2c_regs(idx: u8) -> &'static ws63_pac::i2c0::RegisterBlock {
17 unsafe {
18 match idx {
19 0 => &*I2c0::ptr(),
20 1 => &*I2c1::ptr(),
21 _ => unreachable!(),
22 }
23 }
24}
25
26impl<'d> I2c<'d, I2c0<'d>> {
27 pub fn new_i2c0(_i2c: I2c0<'d>, freq: u32) -> Self {
28 configure_i2c(0, freq);
29 Self { idx: 0, _peripheral: PhantomData }
30 }
31}
32
33impl<'d> I2c<'d, I2c1<'d>> {
34 pub fn new_i2c1(_i2c: I2c1<'d>, freq: u32) -> Self {
35 configure_i2c(1, freq);
36 Self { idx: 1, _peripheral: PhantomData }
37 }
38}
39
40fn configure_i2c(idx: u8, freq: u32) {
41 let r = i2c_regs(idx);
42 let pclk = crate::soc::ws63::I2C_CLOCK_HZ;
43 let freq = if freq == 0 { 1 } else { freq };
44 let period = pclk / (2 * freq);
45 let half = period / 2;
46 r.i2c_scl_h().write(|w| unsafe { w.bits(half) });
47 r.i2c_scl_l().write(|w| unsafe { w.bits(half) });
48 r.i2c_ctrl().write(|w| unsafe {
50 w.bits(0);
51 w.i2c_en().set_bit();
52 w.mode_ctrl().set_bit();
53 w.int_ack_err_mask().set_bit()
55 });
56}
57
58const I2C_WAIT_LOOPS: u32 = 1_000_000;
63
64#[inline]
65fn wait_until(mut ready: impl FnMut() -> bool) -> Result<(), I2cError> {
66 let mut n = I2C_WAIT_LOOPS;
67 while !ready() {
68 n -= 1;
69 if n == 0 {
70 return Err(I2cError::Timeout);
71 }
72 }
73 Ok(())
74}
75
76impl<T> I2c<'_, T> {
77 #[allow(dead_code)]
78 fn wait_not_busy(&self) -> Result<(), I2cError> {
79 let r = i2c_regs(self.idx);
80 wait_until(|| !r.i2c_sr().read().bus_busy().bit_is_set())
81 }
82
83 fn clear_interrupts(&self) {
84 let r = i2c_regs(self.idx);
85 unsafe { r.i2c_icr().write(|w| w.bits(0x7FF)) };
87 }
88
89 fn check_ack(&self) -> Result<(), I2cError> {
91 let r = i2c_regs(self.idx);
92 if r.i2c_sr().read().int_ack_err().bit_is_set() {
93 return Err(I2cError::Ack);
94 }
95 Ok(())
96 }
97
98 fn wait_tx_ack(&self) -> Result<(), I2cError> {
100 let r = i2c_regs(self.idx);
101 wait_until(|| r.i2c_sr().read().int_tx().bit_is_set())?;
102 self.check_ack()
104 }
105
106 fn send_start(&self, addr_byte: u32, is_read: bool) -> Result<(), I2cError> {
109 let r = i2c_regs(self.idx);
110 self.clear_interrupts();
111
112 r.i2c_txr().write(|w| unsafe { w.bits(addr_byte) });
114
115 unsafe {
117 r.i2c_com().write(|w| w.bits(0));
118 }
119 let mut com: u32 = 0;
120 com |= 1 << 3; com |= 1 << 1; if is_read {
123 }
127 unsafe {
128 r.i2c_com().write(|w| w.bits(com));
129 }
130
131 self.wait_tx_ack()
132 }
133
134 pub fn write(&mut self, addr: u8, data: &[u8]) -> Result<(), I2cError> {
135 let r = i2c_regs(self.idx);
136
137 self.send_start((addr as u32) << 1, false)?;
139
140 for &byte in data {
142 r.i2c_txr().write(|w| unsafe { w.bits(byte as u32) });
143 unsafe { r.i2c_com().write(|w| w.bits(1 << 1)) };
145 self.wait_tx_ack()?;
146 self.clear_interrupts();
147 }
148
149 r.i2c_com().write(|w| w.op_stop().set_bit());
151 wait_until(|| r.i2c_sr().read().int_stop().bit_is_set())?;
152 self.clear_interrupts();
153
154 Ok(())
155 }
156
157 pub fn read(&mut self, addr: u8, buf: &mut [u8]) -> Result<(), I2cError> {
158 let r = i2c_regs(self.idx);
159
160 self.send_start(((addr as u32) << 1) | 1, true)?;
162
163 let buf_len = buf.len();
165 for (i, byte) in buf.iter_mut().enumerate() {
166 let is_last = i == buf_len - 1;
167 let mut com: u32 = 1 << 2; if is_last {
170 com |= 1 << 4; }
172 unsafe { r.i2c_com().write(|w| w.bits(com)) };
173
174 wait_until(|| r.i2c_sr().read().int_rx().bit_is_set())?;
175 *byte = r.i2c_rxr().read().bits() as u8;
176 self.clear_interrupts();
177 }
178
179 r.i2c_com().write(|w| w.op_stop().set_bit());
181 wait_until(|| r.i2c_sr().read().int_stop().bit_is_set())?;
182 self.clear_interrupts();
183
184 Ok(())
185 }
186
187 pub fn write_read(&mut self, addr: u8, wr_buf: &[u8], rd_buf: &mut [u8]) -> Result<(), I2cError> {
190 let r = i2c_regs(self.idx);
191
192 if !wr_buf.is_empty() {
193 self.send_start((addr as u32) << 1, false)?;
195
196 for &byte in wr_buf {
198 r.i2c_txr().write(|w| unsafe { w.bits(byte as u32) });
199 unsafe { r.i2c_com().write(|w| w.bits(1 << 1)) }; self.wait_tx_ack()?;
201 self.clear_interrupts();
202 }
203 }
205
206 if !rd_buf.is_empty() {
207 self.send_start(((addr as u32) << 1) | 1, true)?;
209
210 let buf_len = rd_buf.len();
211 for (i, byte) in rd_buf.iter_mut().enumerate() {
212 let is_last = i == buf_len - 1;
213 let mut com: u32 = 1 << 2; if is_last {
215 com |= 1 << 4; }
217 unsafe { r.i2c_com().write(|w| w.bits(com)) };
218 wait_until(|| r.i2c_sr().read().int_rx().bit_is_set())?;
219 *byte = r.i2c_rxr().read().bits() as u8;
220 self.clear_interrupts();
221 }
222 }
223
224 r.i2c_com().write(|w| w.op_stop().set_bit());
226 wait_until(|| r.i2c_sr().read().int_stop().bit_is_set())?;
227 self.clear_interrupts();
228
229 Ok(())
230 }
231
232 fn transaction_impl(
237 &mut self,
238 address: u8,
239 operations: &mut [embedded_hal::i2c::Operation<'_>],
240 ) -> Result<(), I2cError> {
241 let r = i2c_regs(self.idx);
242 let addr_w = (address as u32) << 1; let addr_r = ((address as u32) << 1) | 1; for op in operations.iter_mut() {
246 match op {
247 embedded_hal::i2c::Operation::Write(data) => {
248 self.send_start(addr_w, false)?;
249 self.clear_interrupts();
250
251 for &byte in data.iter() {
252 r.i2c_txr().write(|w| unsafe { w.bits(byte as u32) });
253 unsafe { r.i2c_com().write(|w| w.bits(1 << 1)) }; self.wait_tx_ack()?;
255 self.clear_interrupts();
256 }
257 }
259 embedded_hal::i2c::Operation::Read(buf) => {
260 self.send_start(addr_r, true)?;
261 self.clear_interrupts();
262
263 let buf_len = buf.len();
264 for (i, byte) in buf.iter_mut().enumerate() {
265 let is_last = i == buf_len - 1;
266 let mut com: u32 = 1 << 2; if is_last {
268 com |= 1 << 4; }
270 unsafe { r.i2c_com().write(|w| w.bits(com)) };
271 wait_until(|| r.i2c_sr().read().int_rx().bit_is_set())?;
272 *byte = r.i2c_rxr().read().bits() as u8;
273 self.clear_interrupts();
274 }
275 }
277 }
278 }
279
280 r.i2c_com().write(|w| w.op_stop().set_bit());
282 wait_until(|| r.i2c_sr().read().int_stop().bit_is_set())?;
283 self.clear_interrupts();
284
285 Ok(())
286 }
287}
288
289#[derive(Debug)]
290pub enum I2cError {
291 Ack,
292 BusError,
293 Timeout,
294}
295
296impl embedded_hal::i2c::Error for I2cError {
297 fn kind(&self) -> embedded_hal::i2c::ErrorKind {
298 match self {
299 I2cError::Ack => {
300 embedded_hal::i2c::ErrorKind::NoAcknowledge(embedded_hal::i2c::NoAcknowledgeSource::Unknown)
301 }
302 I2cError::BusError => embedded_hal::i2c::ErrorKind::Bus,
303 I2cError::Timeout => embedded_hal::i2c::ErrorKind::Other,
304 }
305 }
306}
307
308impl embedded_hal::i2c::ErrorType for I2c<'_, I2c0<'_>> {
311 type Error = I2cError;
312}
313
314impl embedded_hal::i2c::I2c for I2c<'_, I2c0<'_>> {
315 fn transaction(
316 &mut self,
317 address: u8,
318 operations: &mut [embedded_hal::i2c::Operation<'_>],
319 ) -> Result<(), Self::Error> {
320 self.transaction_impl(address, operations)
321 }
322}
323
324impl embedded_hal::i2c::ErrorType for I2c<'_, I2c1<'_>> {
325 type Error = I2cError;
326}
327
328impl embedded_hal::i2c::I2c for I2c<'_, I2c1<'_>> {
329 fn transaction(
330 &mut self,
331 address: u8,
332 operations: &mut [embedded_hal::i2c::Operation<'_>],
333 ) -> Result<(), Self::Error> {
334 self.transaction_impl(address, operations)
335 }
336}
337
338#[cfg(test)]
341mod tests {
342 #[test]
343 fn test_i2c_address_write_encoding() {
344 assert_eq!((0x50u32 << 1), 0xA0);
346 assert_eq!((0x50u32 << 1) & 0xFE, 0xA0); }
348
349 #[test]
350 fn test_i2c_address_read_encoding() {
351 assert_eq!(((0x50u32 << 1) | 1), 0xA1);
353 }
354
355 #[test]
356 fn test_i2c_address_write_read_differ_by_one_bit() {
357 let addr_w = (0x48u32) << 1; let addr_r = ((0x48u32) << 1) | 1; assert_eq!(addr_r, addr_w | 1);
360 assert_eq!(addr_w & 0x01, 0); assert_eq!(addr_r & 0x01, 1); }
363
364 #[test]
365 fn test_i2c_10bit_high_address_encoding() {
366 let addr: u32 = 0x78;
368 let addr_w = addr << 1;
369 assert_eq!(addr_w, 0xF0); }
371}
372
373#[cfg(feature = "async")]
376mod asynch_impl {
377 use super::{I2c, I2c0, I2c1};
378 use embedded_hal::i2c::Operation;
379
380 macro_rules! async_i2c {
381 ($inst:ty) => {
382 impl embedded_hal_async::i2c::I2c for I2c<'_, $inst> {
383 async fn transaction(&mut self, addr: u8, ops: &mut [Operation<'_>]) -> Result<(), Self::Error> {
384 embedded_hal::i2c::I2c::transaction(self, addr, ops)
385 }
386 }
387 };
388 }
389 async_i2c!(I2c0<'_>);
390 async_i2c!(I2c1<'_>);
391}