1use embedded_hal::i2c::SevenBitAddress;
6
7use crate::port;
8use core::marker::PhantomData;
9
10pub mod twi_status {
12 pub const TW_START: u8 = 0x08 >> 3;
19
20 pub const TW_REP_START: u8 = 0x10 >> 3;
22
23 pub const TW_MT_SLA_ACK: u8 = 0x18 >> 3;
26
27 pub const TW_MT_SLA_NACK: u8 = 0x20 >> 3;
29
30 pub const TW_MT_DATA_ACK: u8 = 0x28 >> 3;
32
33 pub const TW_MT_DATA_NACK: u8 = 0x30 >> 3;
35
36 pub const TW_MT_ARB_LOST: u8 = 0x38 >> 3;
38
39 pub const TW_MR_ARB_LOST: u8 = 0x38 >> 3;
42
43 pub const TW_MR_SLA_ACK: u8 = 0x40 >> 3;
45
46 pub const TW_MR_SLA_NACK: u8 = 0x48 >> 3;
48
49 pub const TW_MR_DATA_ACK: u8 = 0x50 >> 3;
51
52 pub const TW_MR_DATA_NACK: u8 = 0x58 >> 3;
54
55 pub const TW_ST_SLA_ACK: u8 = 0xA8 >> 3;
58
59 pub const TW_ST_ARB_LOST_SLA_ACK: u8 = 0xB0 >> 3;
61
62 pub const TW_ST_DATA_ACK: u8 = 0xB8 >> 3;
64
65 pub const TW_ST_DATA_NACK: u8 = 0xC0 >> 3;
67
68 pub const TW_ST_LAST_DATA: u8 = 0xC8 >> 3;
70
71 pub const TW_SR_SLA_ACK: u8 = 0x60 >> 3;
74
75 pub const TW_SR_ARB_LOST_SLA_ACK: u8 = 0x68 >> 3;
77
78 pub const TW_SR_GCALL_ACK: u8 = 0x70 >> 3;
80
81 pub const TW_SR_ARB_LOST_GCALL_ACK: u8 = 0x78 >> 3;
83
84 pub const TW_SR_DATA_ACK: u8 = 0x80 >> 3;
86
87 pub const TW_SR_DATA_NACK: u8 = 0x88 >> 3;
89
90 pub const TW_SR_GCALL_DATA_ACK: u8 = 0x90 >> 3;
92
93 pub const TW_SR_GCALL_DATA_NACK: u8 = 0x98 >> 3;
95
96 pub const TW_SR_STOP: u8 = 0xA0 >> 3;
98
99 pub const TW_NO_INFO: u8 = 0xF8 >> 3;
102
103 pub const TW_BUS_ERROR: u8 = 0x00 >> 3;
105}
106
107#[derive(ufmt::derive::uDebug, Debug, Clone, Copy, Eq, PartialEq)]
109#[repr(u8)]
110pub enum Error {
111 ArbitrationLost,
113 AddressNack,
115 DataNack,
117 BusError,
119 Unknown,
121}
122
123impl embedded_hal::i2c::Error for Error {
124 fn kind(&self) -> embedded_hal::i2c::ErrorKind {
125 match *self {
126 Error::ArbitrationLost => embedded_hal::i2c::ErrorKind::ArbitrationLoss,
127 Error::AddressNack => embedded_hal::i2c::ErrorKind::NoAcknowledge(
128 embedded_hal::i2c::NoAcknowledgeSource::Address,
129 ),
130 Error::DataNack => embedded_hal::i2c::ErrorKind::NoAcknowledge(
131 embedded_hal::i2c::NoAcknowledgeSource::Data,
132 ),
133 Error::BusError => embedded_hal::i2c::ErrorKind::Bus,
134 Error::Unknown => embedded_hal::i2c::ErrorKind::Other,
135 }
136 }
137}
138
139impl<H, I2C: I2cOps<H, SDA, SCL>, SDA, SCL, CLOCK> embedded_hal::i2c::ErrorType
140 for I2c<H, I2C, SDA, SCL, CLOCK>
141{
142 type Error = Error;
143}
144
145#[derive(ufmt::derive::uDebug, Debug, Clone, Copy, Eq, PartialEq)]
147#[repr(u8)]
148pub enum Direction {
149 Write,
151 Read,
153}
154
155pub trait I2cOps<H, SDA, SCL> {
161 fn raw_setup<CLOCK: crate::clock::Clock>(&mut self, speed: u32);
165
166 fn raw_start(&mut self, address: u8, direction: Direction) -> Result<(), Error>;
173
174 fn raw_write(&mut self, bytes: &[u8]) -> Result<(), Error>;
180
181 fn raw_read(&mut self, buffer: &mut [u8], last_read: bool) -> Result<(), Error>;
189
190 fn raw_stop(&mut self) -> Result<(), Error>;
197}
198
199pub struct I2c<H, I2C: I2cOps<H, SDA, SCL>, SDA, SCL, CLOCK> {
217 p: I2C,
218 #[allow(dead_code)]
219 sda: SDA,
220 #[allow(dead_code)]
221 scl: SCL,
222 _clock: PhantomData<CLOCK>,
223 _h: PhantomData<H>,
224}
225
226impl<H, I2C, SDAPIN, SCLPIN, CLOCK>
227 I2c<H, I2C, port::Pin<port::mode::Input, SDAPIN>, port::Pin<port::mode::Input, SCLPIN>, CLOCK>
228where
229 I2C: I2cOps<H, port::Pin<port::mode::Input, SDAPIN>, port::Pin<port::mode::Input, SCLPIN>>,
230 SDAPIN: port::PinOps,
231 SCLPIN: port::PinOps,
232 CLOCK: crate::clock::Clock,
233{
234 pub fn new(
243 p: I2C,
244 sda: port::Pin<port::mode::Input<port::mode::PullUp>, SDAPIN>,
245 scl: port::Pin<port::mode::Input<port::mode::PullUp>, SCLPIN>,
246 speed: u32,
247 ) -> Self {
248 let mut i2c = Self {
249 p,
250 sda: sda.forget_imode(),
251 scl: scl.forget_imode(),
252 _clock: PhantomData,
253 _h: PhantomData,
254 };
255 i2c.p.raw_setup::<CLOCK>(speed);
256 i2c
257 }
258
259 pub fn with_external_pullup(
266 p: I2C,
267 sda: port::Pin<port::mode::Input<port::mode::Floating>, SDAPIN>,
268 scl: port::Pin<port::mode::Input<port::mode::Floating>, SCLPIN>,
269 speed: u32,
270 ) -> Self {
271 let mut i2c = Self {
272 p,
273 sda: sda.forget_imode(),
274 scl: scl.forget_imode(),
275 _clock: PhantomData,
276 _h: PhantomData,
277 };
278 i2c.p.raw_setup::<CLOCK>(speed);
279 i2c
280 }
281}
282
283impl<H, I2C: I2cOps<H, SDA, SCL>, SDA, SCL, CLOCK> I2c<H, I2C, SDA, SCL, CLOCK>
284where
285 CLOCK: crate::clock::Clock,
286 crate::delay::Delay<CLOCK>: embedded_hal_v0::blocking::delay::DelayMs<u16>,
287{
288 pub fn ping_device(&mut self, address: u8, direction: Direction) -> Result<bool, Error> {
290 match self.p.raw_start(address, direction) {
291 Ok(_) => {
292 self.p.raw_stop()?;
293 Ok(true)
294 }
295 Err(Error::AddressNack) => Ok(false),
296 Err(e) => Err(e),
297 }
298 }
299
300 pub fn i2cdetect<W: ufmt::uWrite>(
317 &mut self,
318 w: &mut W,
319 direction: Direction,
320 ) -> Result<(), W::Error> {
321 use embedded_hal_v0::blocking::delay::DelayMs;
322 let mut delay = crate::delay::Delay::<CLOCK>::new();
323
324 w.write_str(
325 "\
326- 0 1 2 3 4 5 6 7 8 9 a b c d e f\r\n\
32700: ",
328 )?;
329
330 fn u4_to_hex(b: u8) -> char {
331 match b {
332 x if x < 0xa => (0x30 + x).into(),
333 x if x < 0x10 => (0x57 + x).into(),
334 _ => '?',
335 }
336 }
337
338 for address in 0x02..=0x77 {
339 let (ah, al) = (u4_to_hex(address >> 4), u4_to_hex(address & 0xf));
340
341 if address % 0x10 == 0 {
342 w.write_str("\r\n")?;
343 w.write_char(ah)?;
344 w.write_str("0:")?;
345 }
346
347 match self.ping_device(address, direction) {
348 Ok(true) => {
349 w.write_char(' ')?;
350 w.write_char(ah)?;
351 w.write_char(al)?;
352 }
353 Ok(false) => {
354 w.write_str(" --")?;
355 }
356 Err(e) => {
357 w.write_str(" E")?;
358 w.write_char(u4_to_hex(e as u8))?;
359 }
360 }
361
362 delay.delay_ms(10u16);
363 }
364
365 w.write_str("\r\n")?;
366
367 Ok(())
368 }
369}
370
371impl<H, I2C: I2cOps<H, SDA, SCL>, SDA, SCL, CLOCK> embedded_hal_v0::blocking::i2c::Write
372 for I2c<H, I2C, SDA, SCL, CLOCK>
373{
374 type Error = Error;
375
376 fn write(&mut self, address: u8, bytes: &[u8]) -> Result<(), Self::Error> {
377 self.p.raw_start(address, Direction::Write)?;
378 self.p.raw_write(bytes)?;
379 self.p.raw_stop()?;
380 Ok(())
381 }
382}
383
384impl<H, I2C: I2cOps<H, SDA, SCL>, SDA, SCL, CLOCK> embedded_hal_v0::blocking::i2c::Read
385 for I2c<H, I2C, SDA, SCL, CLOCK>
386{
387 type Error = Error;
388
389 fn read(&mut self, address: u8, buffer: &mut [u8]) -> Result<(), Self::Error> {
390 self.p.raw_start(address, Direction::Read)?;
391 self.p.raw_read(buffer, true)?;
392 self.p.raw_stop()?;
393 Ok(())
394 }
395}
396
397impl<H, I2C: I2cOps<H, SDA, SCL>, SDA, SCL, CLOCK> embedded_hal_v0::blocking::i2c::WriteRead
398 for I2c<H, I2C, SDA, SCL, CLOCK>
399{
400 type Error = Error;
401
402 fn write_read(
403 &mut self,
404 address: u8,
405 bytes: &[u8],
406 buffer: &mut [u8],
407 ) -> Result<(), Self::Error> {
408 self.p.raw_start(address, Direction::Write)?;
409 self.p.raw_write(bytes)?;
410 self.p.raw_start(address, Direction::Read)?;
411 self.p.raw_read(buffer, true)?;
412 self.p.raw_stop()?;
413 Ok(())
414 }
415}
416
417impl<H, I2C: I2cOps<H, SDA, SCL>, SDA, SCL, CLOCK> embedded_hal::i2c::I2c<SevenBitAddress>
418 for I2c<H, I2C, SDA, SCL, CLOCK>
419{
420 fn transaction(
421 &mut self,
422 address: u8,
423 operations: &mut [embedded_hal::i2c::Operation<'_>],
424 ) -> Result<(), Self::Error> {
425 let mut previous_direction = Direction::Read;
426 let mut ops_iter = operations.iter_mut().enumerate().peekable();
427 while let Some((idx, operation)) = ops_iter.next() {
428 match operation {
429 embedded_hal::i2c::Operation::Read(buffer) => {
430 if idx == 0 || previous_direction != Direction::Read {
431 self.p.raw_start(address, Direction::Read)?;
432 }
433
434 let next_op_is_read = matches!(
435 ops_iter.peek(),
436 Some((_, embedded_hal::i2c::Operation::Read(_)))
437 );
438
439 self.p.raw_read(buffer, !next_op_is_read)?;
440 previous_direction = Direction::Read;
441 }
442 embedded_hal::i2c::Operation::Write(bytes) => {
443 if idx == 0 || previous_direction != Direction::Write {
444 self.p.raw_start(address, Direction::Write)?;
445 }
446 self.p.raw_write(bytes)?;
447 previous_direction = Direction::Write;
448 }
449 }
450 }
451 if operations.len() > 0 {
452 self.p.raw_stop()?;
453 }
454
455 Ok(())
456 }
457}
458
459#[macro_export]
460macro_rules! impl_i2c_twi {
461 (
462 hal: $HAL:ty,
463 peripheral: $I2C:ty,
464 sda: $sdapin:ty,
465 scl: $sclpin:ty,
466 ) => {
467 impl
468 $crate::i2c::I2cOps<
469 $HAL,
470 $crate::port::Pin<$crate::port::mode::Input, $sdapin>,
471 $crate::port::Pin<$crate::port::mode::Input, $sclpin>,
472 > for $I2C
473 {
474 #[inline]
475 fn raw_setup<CLOCK: $crate::clock::Clock>(&mut self, speed: u32) {
476 let twbr = ((CLOCK::FREQ / speed) - 16) / 2;
478 self.twbr.write(|w| unsafe { w.bits(twbr as u8) });
479
480 self.twsr.write(|w| w.twps().prescaler_1());
482 }
483
484 #[inline]
485 fn raw_start(&mut self, address: u8, direction: Direction) -> Result<(), Error> {
486 self.twcr
488 .write(|w| w.twen().set_bit().twint().set_bit().twsta().set_bit());
489 while self.twcr.read().twint().bit_is_clear() {}
491
492 match self.twsr.read().tws().bits() {
494 $crate::i2c::twi_status::TW_START | $crate::i2c::twi_status::TW_REP_START => (),
495 $crate::i2c::twi_status::TW_MT_ARB_LOST
496 | $crate::i2c::twi_status::TW_MR_ARB_LOST => {
497 return Err($crate::i2c::Error::ArbitrationLost);
498 }
499 $crate::i2c::twi_status::TW_BUS_ERROR => {
500 return Err($crate::i2c::Error::BusError);
501 }
502 _ => {
503 return Err($crate::i2c::Error::Unknown);
504 }
505 }
506
507 let dirbit = if direction == $crate::i2c::Direction::Read {
509 1
510 } else {
511 0
512 };
513 let rawaddr = (address << 1) | dirbit;
514 self.twdr.write(|w| unsafe { w.bits(rawaddr) });
515 self.twcr.write(|w| w.twen().set_bit().twint().set_bit());
517 while self.twcr.read().twint().bit_is_clear() {}
518
519 match self.twsr.read().tws().bits() {
521 $crate::i2c::twi_status::TW_MT_SLA_ACK
522 | $crate::i2c::twi_status::TW_MR_SLA_ACK => (),
523 $crate::i2c::twi_status::TW_MT_SLA_NACK
524 | $crate::i2c::twi_status::TW_MR_SLA_NACK => {
525 self.raw_stop()?;
527 return Err($crate::i2c::Error::AddressNack);
528 }
529 $crate::i2c::twi_status::TW_MT_ARB_LOST
530 | $crate::i2c::twi_status::TW_MR_ARB_LOST => {
531 return Err($crate::i2c::Error::ArbitrationLost);
532 }
533 $crate::i2c::twi_status::TW_BUS_ERROR => {
534 return Err($crate::i2c::Error::BusError);
535 }
536 _ => {
537 return Err($crate::i2c::Error::Unknown);
538 }
539 }
540
541 Ok(())
542 }
543
544 #[inline]
545 fn raw_write(&mut self, bytes: &[u8]) -> Result<(), Error> {
546 for byte in bytes {
547 self.twdr.write(|w| unsafe { w.bits(*byte) });
548 self.twcr.write(|w| w.twen().set_bit().twint().set_bit());
550 while self.twcr.read().twint().bit_is_clear() {}
551
552 match self.twsr.read().tws().bits() {
553 $crate::i2c::twi_status::TW_MT_DATA_ACK => (),
554 $crate::i2c::twi_status::TW_MT_DATA_NACK => {
555 self.raw_stop()?;
556 return Err($crate::i2c::Error::DataNack);
557 }
558 $crate::i2c::twi_status::TW_MT_ARB_LOST => {
559 return Err($crate::i2c::Error::ArbitrationLost);
560 }
561 $crate::i2c::twi_status::TW_BUS_ERROR => {
562 return Err($crate::i2c::Error::BusError);
563 }
564 _ => {
565 return Err($crate::i2c::Error::Unknown);
566 }
567 }
568 }
569 Ok(())
570 }
571
572 #[inline]
573 fn raw_read(&mut self, buffer: &mut [u8], last_read: bool) -> Result<(), Error> {
574 let last = buffer.len() - 1;
575 for (i, byte) in buffer.iter_mut().enumerate() {
576 if i != last || !last_read {
577 self.twcr
578 .write(|w| w.twint().set_bit().twen().set_bit().twea().set_bit());
579 while self.twcr.read().twint().bit_is_clear() {}
581 } else {
582 self.twcr.write(|w| w.twint().set_bit().twen().set_bit());
583 while self.twcr.read().twint().bit_is_clear() {}
585 }
586
587 match self.twsr.read().tws().bits() {
588 $crate::i2c::twi_status::TW_MR_DATA_ACK
589 | $crate::i2c::twi_status::TW_MR_DATA_NACK => (),
590 $crate::i2c::twi_status::TW_MR_ARB_LOST => {
591 return Err($crate::i2c::Error::ArbitrationLost);
592 }
593 $crate::i2c::twi_status::TW_BUS_ERROR => {
594 return Err($crate::i2c::Error::BusError);
595 }
596 _ => {
597 return Err($crate::i2c::Error::Unknown);
598 }
599 }
600
601 *byte = self.twdr.read().bits();
602 }
603 Ok(())
604 }
605
606 #[inline]
607 fn raw_stop(&mut self) -> Result<(), Error> {
608 self.twcr
609 .write(|w| w.twen().set_bit().twint().set_bit().twsto().set_bit());
610 Ok(())
611 }
612 }
613 };
614}