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]) -> Result<(), Error>;
187
188 fn raw_stop(&mut self) -> Result<(), Error>;
195}
196
197pub struct I2c<H, I2C: I2cOps<H, SDA, SCL>, SDA, SCL, CLOCK> {
215 p: I2C,
216 #[allow(dead_code)]
217 sda: SDA,
218 #[allow(dead_code)]
219 scl: SCL,
220 _clock: PhantomData<CLOCK>,
221 _h: PhantomData<H>,
222}
223
224impl<H, I2C, SDAPIN, SCLPIN, CLOCK>
225 I2c<H, I2C, port::Pin<port::mode::Input, SDAPIN>, port::Pin<port::mode::Input, SCLPIN>, CLOCK>
226where
227 I2C: I2cOps<H, port::Pin<port::mode::Input, SDAPIN>, port::Pin<port::mode::Input, SCLPIN>>,
228 SDAPIN: port::PinOps,
229 SCLPIN: port::PinOps,
230 CLOCK: crate::clock::Clock,
231{
232 pub fn new(
241 p: I2C,
242 sda: port::Pin<port::mode::Input<port::mode::PullUp>, SDAPIN>,
243 scl: port::Pin<port::mode::Input<port::mode::PullUp>, SCLPIN>,
244 speed: u32,
245 ) -> Self {
246 let mut i2c = Self {
247 p,
248 sda: sda.forget_imode(),
249 scl: scl.forget_imode(),
250 _clock: PhantomData,
251 _h: PhantomData,
252 };
253 i2c.p.raw_setup::<CLOCK>(speed);
254 i2c
255 }
256
257 pub fn with_external_pullup(
264 p: I2C,
265 sda: port::Pin<port::mode::Input<port::mode::Floating>, SDAPIN>,
266 scl: port::Pin<port::mode::Input<port::mode::Floating>, SCLPIN>,
267 speed: u32,
268 ) -> Self {
269 let mut i2c = Self {
270 p,
271 sda: sda.forget_imode(),
272 scl: scl.forget_imode(),
273 _clock: PhantomData,
274 _h: PhantomData,
275 };
276 i2c.p.raw_setup::<CLOCK>(speed);
277 i2c
278 }
279}
280
281impl<H, I2C: I2cOps<H, SDA, SCL>, SDA, SCL, CLOCK> I2c<H, I2C, SDA, SCL, CLOCK>
282where
283 CLOCK: crate::clock::Clock,
284 crate::delay::Delay<CLOCK>: embedded_hal_v0::blocking::delay::DelayMs<u16>,
285{
286 pub fn ping_device(&mut self, address: u8, direction: Direction) -> Result<bool, Error> {
288 match self.p.raw_start(address, direction) {
289 Ok(_) => {
290 self.p.raw_stop()?;
291 Ok(true)
292 }
293 Err(Error::AddressNack) => Ok(false),
294 Err(e) => Err(e),
295 }
296 }
297
298 pub fn i2cdetect<W: ufmt::uWrite>(
315 &mut self,
316 w: &mut W,
317 direction: Direction,
318 ) -> Result<(), W::Error> {
319 use embedded_hal_v0::blocking::delay::DelayMs;
320 let mut delay = crate::delay::Delay::<CLOCK>::new();
321
322 w.write_str(
323 "\
324- 0 1 2 3 4 5 6 7 8 9 a b c d e f\r\n\
32500: ",
326 )?;
327
328 fn u4_to_hex(b: u8) -> char {
329 match b {
330 x if x < 0xa => (0x30 + x).into(),
331 x if x < 0x10 => (0x57 + x).into(),
332 _ => '?',
333 }
334 }
335
336 for address in 0x02..=0x77 {
337 let (ah, al) = (u4_to_hex(address >> 4), u4_to_hex(address & 0xf));
338
339 if address % 0x10 == 0 {
340 w.write_str("\r\n")?;
341 w.write_char(ah)?;
342 w.write_str("0:")?;
343 }
344
345 match self.ping_device(address, direction) {
346 Ok(true) => {
347 w.write_char(' ')?;
348 w.write_char(ah)?;
349 w.write_char(al)?;
350 }
351 Ok(false) => {
352 w.write_str(" --")?;
353 }
354 Err(e) => {
355 w.write_str(" E")?;
356 w.write_char(u4_to_hex(e as u8))?;
357 }
358 }
359
360 delay.delay_ms(10u16);
361 }
362
363 w.write_str("\r\n")?;
364
365 Ok(())
366 }
367}
368
369impl<H, I2C: I2cOps<H, SDA, SCL>, SDA, SCL, CLOCK> embedded_hal_v0::blocking::i2c::Write
370 for I2c<H, I2C, SDA, SCL, CLOCK>
371{
372 type Error = Error;
373
374 fn write(&mut self, address: u8, bytes: &[u8]) -> Result<(), Self::Error> {
375 self.p.raw_start(address, Direction::Write)?;
376 self.p.raw_write(bytes)?;
377 self.p.raw_stop()?;
378 Ok(())
379 }
380}
381
382impl<H, I2C: I2cOps<H, SDA, SCL>, SDA, SCL, CLOCK> embedded_hal_v0::blocking::i2c::Read
383 for I2c<H, I2C, SDA, SCL, CLOCK>
384{
385 type Error = Error;
386
387 fn read(&mut self, address: u8, buffer: &mut [u8]) -> Result<(), Self::Error> {
388 self.p.raw_start(address, Direction::Read)?;
389 self.p.raw_read(buffer)?;
390 self.p.raw_stop()?;
391 Ok(())
392 }
393}
394
395impl<H, I2C: I2cOps<H, SDA, SCL>, SDA, SCL, CLOCK> embedded_hal_v0::blocking::i2c::WriteRead
396 for I2c<H, I2C, SDA, SCL, CLOCK>
397{
398 type Error = Error;
399
400 fn write_read(
401 &mut self,
402 address: u8,
403 bytes: &[u8],
404 buffer: &mut [u8],
405 ) -> Result<(), Self::Error> {
406 self.p.raw_start(address, Direction::Write)?;
407 self.p.raw_write(bytes)?;
408 self.p.raw_start(address, Direction::Read)?;
409 self.p.raw_read(buffer)?;
410 self.p.raw_stop()?;
411 Ok(())
412 }
413}
414
415impl<H, I2C: I2cOps<H, SDA, SCL>, SDA, SCL, CLOCK> embedded_hal::i2c::I2c<SevenBitAddress>
416 for I2c<H, I2C, SDA, SCL, CLOCK>
417{
418 fn transaction(
419 &mut self,
420 address: u8,
421 operations: &mut [embedded_hal::i2c::Operation<'_>],
422 ) -> Result<(), Self::Error> {
423 let mut previous_direction = Direction::Read;
424 for (idx, operation) in operations.iter_mut().enumerate() {
425 match operation {
426 embedded_hal::i2c::Operation::Read(buffer) => {
427 if idx == 0 || previous_direction != Direction::Read {
428 self.p.raw_start(address, Direction::Read)?;
429 }
430 self.p.raw_read(buffer)?;
431 previous_direction = Direction::Read;
432 }
433 embedded_hal::i2c::Operation::Write(bytes) => {
434 if idx == 0 || previous_direction != Direction::Write {
435 self.p.raw_start(address, Direction::Write)?;
436 }
437 self.p.raw_write(bytes)?;
438 previous_direction = Direction::Write;
439 }
440 }
441 }
442 if operations.len() > 0 {
443 self.p.raw_stop()?;
444 }
445
446 Ok(())
447 }
448}
449
450#[macro_export]
451macro_rules! impl_i2c_twi {
452 (
453 hal: $HAL:ty,
454 peripheral: $I2C:ty,
455 sda: $sdapin:ty,
456 scl: $sclpin:ty,
457 ) => {
458 impl
459 $crate::i2c::I2cOps<
460 $HAL,
461 $crate::port::Pin<$crate::port::mode::Input, $sdapin>,
462 $crate::port::Pin<$crate::port::mode::Input, $sclpin>,
463 > for $I2C
464 {
465 #[inline]
466 fn raw_setup<CLOCK: $crate::clock::Clock>(&mut self, speed: u32) {
467 let twbr = ((CLOCK::FREQ / speed) - 16) / 2;
469 self.twbr.write(|w| unsafe { w.bits(twbr as u8) });
470
471 self.twsr.write(|w| w.twps().prescaler_1());
473 }
474
475 #[inline]
476 fn raw_start(&mut self, address: u8, direction: Direction) -> Result<(), Error> {
477 self.twcr
479 .write(|w| w.twen().set_bit().twint().set_bit().twsta().set_bit());
480 while self.twcr.read().twint().bit_is_clear() {}
482
483 match self.twsr.read().tws().bits() {
485 $crate::i2c::twi_status::TW_START | $crate::i2c::twi_status::TW_REP_START => (),
486 $crate::i2c::twi_status::TW_MT_ARB_LOST
487 | $crate::i2c::twi_status::TW_MR_ARB_LOST => {
488 return Err($crate::i2c::Error::ArbitrationLost);
489 }
490 $crate::i2c::twi_status::TW_BUS_ERROR => {
491 return Err($crate::i2c::Error::BusError);
492 }
493 _ => {
494 return Err($crate::i2c::Error::Unknown);
495 }
496 }
497
498 let dirbit = if direction == $crate::i2c::Direction::Read {
500 1
501 } else {
502 0
503 };
504 let rawaddr = (address << 1) | dirbit;
505 self.twdr.write(|w| unsafe { w.bits(rawaddr) });
506 self.twcr.write(|w| w.twen().set_bit().twint().set_bit());
508 while self.twcr.read().twint().bit_is_clear() {}
509
510 match self.twsr.read().tws().bits() {
512 $crate::i2c::twi_status::TW_MT_SLA_ACK
513 | $crate::i2c::twi_status::TW_MR_SLA_ACK => (),
514 $crate::i2c::twi_status::TW_MT_SLA_NACK
515 | $crate::i2c::twi_status::TW_MR_SLA_NACK => {
516 self.raw_stop()?;
518 return Err($crate::i2c::Error::AddressNack);
519 }
520 $crate::i2c::twi_status::TW_MT_ARB_LOST
521 | $crate::i2c::twi_status::TW_MR_ARB_LOST => {
522 return Err($crate::i2c::Error::ArbitrationLost);
523 }
524 $crate::i2c::twi_status::TW_BUS_ERROR => {
525 return Err($crate::i2c::Error::BusError);
526 }
527 _ => {
528 return Err($crate::i2c::Error::Unknown);
529 }
530 }
531
532 Ok(())
533 }
534
535 #[inline]
536 fn raw_write(&mut self, bytes: &[u8]) -> Result<(), Error> {
537 for byte in bytes {
538 self.twdr.write(|w| unsafe { w.bits(*byte) });
539 self.twcr.write(|w| w.twen().set_bit().twint().set_bit());
541 while self.twcr.read().twint().bit_is_clear() {}
542
543 match self.twsr.read().tws().bits() {
544 $crate::i2c::twi_status::TW_MT_DATA_ACK => (),
545 $crate::i2c::twi_status::TW_MT_DATA_NACK => {
546 self.raw_stop()?;
547 return Err($crate::i2c::Error::DataNack);
548 }
549 $crate::i2c::twi_status::TW_MT_ARB_LOST => {
550 return Err($crate::i2c::Error::ArbitrationLost);
551 }
552 $crate::i2c::twi_status::TW_BUS_ERROR => {
553 return Err($crate::i2c::Error::BusError);
554 }
555 _ => {
556 return Err($crate::i2c::Error::Unknown);
557 }
558 }
559 }
560 Ok(())
561 }
562
563 #[inline]
564 fn raw_read(&mut self, buffer: &mut [u8]) -> Result<(), Error> {
565 let last = buffer.len() - 1;
566 for (i, byte) in buffer.iter_mut().enumerate() {
567 if i != last {
568 self.twcr
569 .write(|w| w.twint().set_bit().twen().set_bit().twea().set_bit());
570 while self.twcr.read().twint().bit_is_clear() {}
572 } else {
573 self.twcr.write(|w| w.twint().set_bit().twen().set_bit());
574 while self.twcr.read().twint().bit_is_clear() {}
576 }
577
578 match self.twsr.read().tws().bits() {
579 $crate::i2c::twi_status::TW_MR_DATA_ACK
580 | $crate::i2c::twi_status::TW_MR_DATA_NACK => (),
581 $crate::i2c::twi_status::TW_MR_ARB_LOST => {
582 return Err($crate::i2c::Error::ArbitrationLost);
583 }
584 $crate::i2c::twi_status::TW_BUS_ERROR => {
585 return Err($crate::i2c::Error::BusError);
586 }
587 _ => {
588 return Err($crate::i2c::Error::Unknown);
589 }
590 }
591
592 *byte = self.twdr.read().bits();
593 }
594 Ok(())
595 }
596
597 #[inline]
598 fn raw_stop(&mut self) -> Result<(), Error> {
599 self.twcr
600 .write(|w| w.twen().set_bit().twint().set_bit().twsto().set_bit());
601 Ok(())
602 }
603 }
604 };
605}