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 if direction == Direction::Read {
293 self.p.raw_read(&mut [0], true)?
294 }
295 self.p.raw_stop()?;
296 Ok(true)
297 }
298 Err(Error::AddressNack) => Ok(false),
299 Err(e) => Err(e),
300 }
301 }
302
303 pub fn i2cdetect<W: ufmt::uWrite>(
320 &mut self,
321 w: &mut W,
322 direction: Direction,
323 ) -> Result<(), W::Error> {
324 use embedded_hal_v0::blocking::delay::DelayMs;
325 let mut delay = crate::delay::Delay::<CLOCK>::new();
326
327 w.write_str(
328 "\
329- 0 1 2 3 4 5 6 7 8 9 a b c d e f\r\n\
33000: ",
331 )?;
332
333 fn u4_to_hex(b: u8) -> char {
334 match b {
335 x if x < 0xa => (0x30 + x).into(),
336 x if x < 0x10 => (0x57 + x).into(),
337 _ => '?',
338 }
339 }
340
341 for address in 0x02..=0x77 {
342 let (ah, al) = (u4_to_hex(address >> 4), u4_to_hex(address & 0xf));
343
344 if address % 0x10 == 0 {
345 w.write_str("\r\n")?;
346 w.write_char(ah)?;
347 w.write_str("0:")?;
348 }
349
350 match self.ping_device(address, direction) {
351 Ok(true) => {
352 w.write_char(' ')?;
353 w.write_char(ah)?;
354 w.write_char(al)?;
355 }
356 Ok(false) => {
357 w.write_str(" --")?;
358 }
359 Err(e) => {
360 w.write_str(" E")?;
361 w.write_char(u4_to_hex(e as u8))?;
362 }
363 }
364
365 delay.delay_ms(10u16);
366 }
367
368 w.write_str("\r\n")?;
369
370 Ok(())
371 }
372}
373
374impl<H, I2C: I2cOps<H, SDA, SCL>, SDA, SCL, CLOCK> embedded_hal_v0::blocking::i2c::Write
375 for I2c<H, I2C, SDA, SCL, CLOCK>
376{
377 type Error = Error;
378
379 fn write(&mut self, address: u8, bytes: &[u8]) -> Result<(), Self::Error> {
380 self.p.raw_start(address, Direction::Write)?;
381 self.p.raw_write(bytes)?;
382 self.p.raw_stop()?;
383 Ok(())
384 }
385}
386
387impl<H, I2C: I2cOps<H, SDA, SCL>, SDA, SCL, CLOCK> embedded_hal_v0::blocking::i2c::Read
388 for I2c<H, I2C, SDA, SCL, CLOCK>
389{
390 type Error = Error;
391
392 fn read(&mut self, address: u8, buffer: &mut [u8]) -> Result<(), Self::Error> {
393 self.p.raw_start(address, Direction::Read)?;
394 self.p.raw_read(buffer, true)?;
395 self.p.raw_stop()?;
396 Ok(())
397 }
398}
399
400impl<H, I2C: I2cOps<H, SDA, SCL>, SDA, SCL, CLOCK> embedded_hal_v0::blocking::i2c::WriteRead
401 for I2c<H, I2C, SDA, SCL, CLOCK>
402{
403 type Error = Error;
404
405 fn write_read(
406 &mut self,
407 address: u8,
408 bytes: &[u8],
409 buffer: &mut [u8],
410 ) -> Result<(), Self::Error> {
411 self.p.raw_start(address, Direction::Write)?;
412 self.p.raw_write(bytes)?;
413 self.p.raw_start(address, Direction::Read)?;
414 self.p.raw_read(buffer, true)?;
415 self.p.raw_stop()?;
416 Ok(())
417 }
418}
419
420impl<H, I2C: I2cOps<H, SDA, SCL>, SDA, SCL, CLOCK> embedded_hal::i2c::I2c<SevenBitAddress>
421 for I2c<H, I2C, SDA, SCL, CLOCK>
422{
423 fn transaction(
424 &mut self,
425 address: u8,
426 operations: &mut [embedded_hal::i2c::Operation<'_>],
427 ) -> Result<(), Self::Error> {
428 let mut previous_direction = Direction::Read;
429 let mut ops_iter = operations.iter_mut().enumerate().peekable();
430 while let Some((idx, operation)) = ops_iter.next() {
431 match operation {
432 embedded_hal::i2c::Operation::Read(buffer) => {
433 if idx == 0 || previous_direction != Direction::Read {
434 self.p.raw_start(address, Direction::Read)?;
435 }
436
437 let next_op_is_read = matches!(
438 ops_iter.peek(),
439 Some((_, embedded_hal::i2c::Operation::Read(_)))
440 );
441
442 self.p.raw_read(buffer, !next_op_is_read)?;
443 previous_direction = Direction::Read;
444 }
445 embedded_hal::i2c::Operation::Write(bytes) => {
446 if idx == 0 || previous_direction != Direction::Write {
447 self.p.raw_start(address, Direction::Write)?;
448 }
449 self.p.raw_write(bytes)?;
450 previous_direction = Direction::Write;
451 }
452 }
453 }
454 if operations.len() > 0 {
455 self.p.raw_stop()?;
456 }
457
458 Ok(())
459 }
460}
461
462#[macro_export]
463macro_rules! impl_i2c_twi {
464 (
465 hal: $HAL:ty,
466 peripheral: $I2C:ty,
467 sda: $sdapin:ty,
468 scl: $sclpin:ty,
469 ) => {
470 impl
471 $crate::i2c::I2cOps<
472 $HAL,
473 $crate::port::Pin<$crate::port::mode::Input, $sdapin>,
474 $crate::port::Pin<$crate::port::mode::Input, $sclpin>,
475 > for $I2C
476 {
477 #[inline]
478 fn raw_setup<CLOCK: $crate::clock::Clock>(&mut self, speed: u32) {
479 let twbr = ((CLOCK::FREQ / speed) - 16) / 2;
481 self.twbr()
482 .write(|w| unsafe { w.bits(twbr.try_into().unwrap()) });
483
484 self.twsr().write(|w| w.twps().prescaler_1());
486 }
487
488 #[inline]
489 fn raw_start(&mut self, address: u8, direction: Direction) -> Result<(), Error> {
490 self.twcr()
492 .write(|w| w.twen().set_bit().twint().set_bit().twsta().set_bit());
493 while self.twcr().read().twint().bit_is_clear() {}
495
496 match self.twsr().read().tws().bits() {
498 $crate::i2c::twi_status::TW_START | $crate::i2c::twi_status::TW_REP_START => (),
499 $crate::i2c::twi_status::TW_MT_ARB_LOST
500 | $crate::i2c::twi_status::TW_MR_ARB_LOST => {
501 return Err($crate::i2c::Error::ArbitrationLost);
502 }
503 $crate::i2c::twi_status::TW_BUS_ERROR => {
504 return Err($crate::i2c::Error::BusError);
505 }
506 _ => {
507 return Err($crate::i2c::Error::Unknown);
508 }
509 }
510
511 let dirbit = if direction == $crate::i2c::Direction::Read {
513 1
514 } else {
515 0
516 };
517 let rawaddr = (address << 1) | dirbit;
518 self.twdr().write(|w| unsafe { w.bits(rawaddr) });
519 self.twcr().write(|w| w.twen().set_bit().twint().set_bit());
521 while self.twcr().read().twint().bit_is_clear() {}
522
523 match self.twsr().read().tws().bits() {
525 $crate::i2c::twi_status::TW_MT_SLA_ACK
526 | $crate::i2c::twi_status::TW_MR_SLA_ACK => (),
527 $crate::i2c::twi_status::TW_MT_SLA_NACK
528 | $crate::i2c::twi_status::TW_MR_SLA_NACK => {
529 self.raw_stop()?;
531 return Err($crate::i2c::Error::AddressNack);
532 }
533 $crate::i2c::twi_status::TW_MT_ARB_LOST
534 | $crate::i2c::twi_status::TW_MR_ARB_LOST => {
535 return Err($crate::i2c::Error::ArbitrationLost);
536 }
537 $crate::i2c::twi_status::TW_BUS_ERROR => {
538 return Err($crate::i2c::Error::BusError);
539 }
540 _ => {
541 return Err($crate::i2c::Error::Unknown);
542 }
543 }
544
545 Ok(())
546 }
547
548 #[inline]
549 fn raw_write(&mut self, bytes: &[u8]) -> Result<(), Error> {
550 for byte in bytes {
551 self.twdr().write(|w| unsafe { w.bits(*byte) });
552 self.twcr().write(|w| w.twen().set_bit().twint().set_bit());
554 while self.twcr().read().twint().bit_is_clear() {}
555
556 match self.twsr().read().tws().bits() {
557 $crate::i2c::twi_status::TW_MT_DATA_ACK => (),
558 $crate::i2c::twi_status::TW_MT_DATA_NACK => {
559 self.raw_stop()?;
560 return Err($crate::i2c::Error::DataNack);
561 }
562 $crate::i2c::twi_status::TW_MT_ARB_LOST => {
563 return Err($crate::i2c::Error::ArbitrationLost);
564 }
565 $crate::i2c::twi_status::TW_BUS_ERROR => {
566 return Err($crate::i2c::Error::BusError);
567 }
568 _ => {
569 return Err($crate::i2c::Error::Unknown);
570 }
571 }
572 }
573 Ok(())
574 }
575
576 #[inline]
577 fn raw_read(&mut self, buffer: &mut [u8], last_read: bool) -> Result<(), Error> {
578 let last = buffer.len() - 1;
579 for (i, byte) in buffer.iter_mut().enumerate() {
580 if i != last || !last_read {
581 self.twcr()
582 .write(|w| w.twint().set_bit().twen().set_bit().twea().set_bit());
583 while self.twcr().read().twint().bit_is_clear() {}
585 } else {
586 self.twcr().write(|w| w.twint().set_bit().twen().set_bit());
587 while self.twcr().read().twint().bit_is_clear() {}
589 }
590
591 match self.twsr().read().tws().bits() {
592 $crate::i2c::twi_status::TW_MR_DATA_ACK
593 | $crate::i2c::twi_status::TW_MR_DATA_NACK => (),
594 $crate::i2c::twi_status::TW_MR_ARB_LOST => {
595 return Err($crate::i2c::Error::ArbitrationLost);
596 }
597 $crate::i2c::twi_status::TW_BUS_ERROR => {
598 return Err($crate::i2c::Error::BusError);
599 }
600 _ => {
601 return Err($crate::i2c::Error::Unknown);
602 }
603 }
604
605 *byte = self.twdr().read().bits();
606 }
607 Ok(())
608 }
609
610 #[inline]
611 fn raw_stop(&mut self) -> Result<(), Error> {
612 self.twcr()
613 .write(|w| w.twen().set_bit().twint().set_bit().twsto().set_bit());
614 Ok(())
615 }
616 }
617 };
618}