From e263c35b465abd9cd0879fab0aed874a6580442f Mon Sep 17 00:00:00 2001 From: Markus Reiter Date: Sat, 23 Jul 2022 11:38:40 +0200 Subject: [PATCH 1/3] Add I2C `AddressingMode`. --- src/i2c.rs | 81 +++++++++++++++++++++++++++++++++++++++++++----------- 1 file changed, 65 insertions(+), 16 deletions(-) diff --git a/src/i2c.rs b/src/i2c.rs index 998ec765..35beaa68 100644 --- a/src/i2c.rs +++ b/src/i2c.rs @@ -73,12 +73,26 @@ pub struct I2c { pins: PINS, } +#[derive(Debug)] +pub enum AddressingMode { + SevenBit, + TenBit, +} + +impl Default for AddressingMode { + fn default() -> Self { + Self::SevenBit + } +} + +#[derive(Debug)] pub struct Config { presc: u8, sclh: u8, scll: u8, scldel: u8, sdadel: u8, + addressing_mode: AddressingMode, } impl Config { @@ -160,6 +174,7 @@ impl Config { scll, scldel, sdadel, + addressing_mode: Default::default(), } } @@ -171,8 +186,14 @@ impl Config { sdadel: ((timing_bits >> 16) & 0xf) as u8, sclh: ((timing_bits >> 8) & 0xff) as u8, scll: (timing_bits & 0xff) as u8, + addressing_mode: Default::default(), } } + + pub fn addressing_mode(mut self, addressing_mode: AddressingMode) -> Self { + self.addressing_mode = addressing_mode; + self + } } macro_rules! hal { @@ -228,7 +249,13 @@ where SDA: SdaPin, { // Make sure the I2C unit is disabled so we can configure it - i2c.cr1.modify(|_, w| w.pe().clear_bit()); + i2c.cr1.modify(|_, w| w.pe().disabled()); + + i2c.cr2.write(|w| match config.addressing_mode { + AddressingMode::SevenBit => w.add10().bit7(), + AddressingMode::TenBit => w.add10().bit10(), + }); + // Configure for "fast mode" (400 KHz) i2c.timingr.write(|w| { w.presc() @@ -244,7 +271,7 @@ where }); // Enable the peripheral - i2c.cr1.write(|w| w.pe().set_bit()); + i2c.cr1.write(|w| w.pe().enabled()); I2c { i2c, pins } } @@ -313,13 +340,18 @@ where // Set START and prepare to send `bytes`. The // START bit can be set even if the bus is BUSY or // I2C is in slave mode. - self.i2c.cr2.write(|w| { + self.i2c.cr2.modify(|r, w| { + // In 7-bit addressing mode, the address is at [7:1]. + let addr = if r.add10().is_bit7() { + u16(addr << 1) + } else { + addr.into() + }; + w.start() .set_bit() .sadd() - .bits(u16(addr << 1 | 0)) - .add10() - .clear_bit() + .bits(addr) .rd_wrn() .write() .nbytes() @@ -342,7 +374,7 @@ where busy_wait!(self.i2c, tc, is_complete); // Stop - self.i2c.cr2.write(|w| w.stop().set_bit()); + self.i2c.cr2.modify(|r, w| w.stop().set_bit()); Ok(()) // Tx::new(&self.i2c)?.write(addr, bytes) @@ -367,9 +399,16 @@ where // Set START and prepare to receive bytes into // `buffer`. The START bit can be set even if the bus // is BUSY or I2C is in slave mode. - self.i2c.cr2.write(|w| { + self.i2c.cr2.modify(|r, w| { + // In 7-bit addressing mode, the address is at [7:1]. + let addr = if r.add10().is_bit7() { + u16(addr << 1) + } else { + addr.into() + }; + w.sadd() - .bits((addr << 1 | 0) as u16) + .bits(addr) .rd_wrn() .read() .nbytes() @@ -413,13 +452,18 @@ where // Set START and prepare to send `bytes`. The // START bit can be set even if the bus is BUSY or // I2C is in slave mode. - self.i2c.cr2.write(|w| { + self.i2c.cr2.modify(|r, w| { + // In 7-bit addressing mode, the address is at [7:1]. + let addr = if r.add10().is_bit7() { + u16(addr << 1) + } else { + addr.into() + }; + w.start() .set_bit() .sadd() - .bits(u16(addr << 1 | 0)) - .add10() - .clear_bit() + .bits(addr) .rd_wrn() .write() .nbytes() @@ -441,11 +485,16 @@ where busy_wait!(self.i2c, tc, is_complete); // reSTART and prepare to receive bytes into `buffer` - self.i2c.cr2.write(|w| { + self.i2c.cr2.modify(|r, w| { + // In 7-bit addressing mode, the address is at [7:1]. + let addr = if r.add10().is_bit7() { + u16(addr << 1) + } else { + addr.into() + }; + w.sadd() .bits(u16(addr << 1 | 1)) - .add10() - .clear_bit() .rd_wrn() .read() .nbytes() From b5ac6cf605cb311bba5a2ba3bc43bd5d1b0d9728 Mon Sep 17 00:00:00 2001 From: Markus Reiter Date: Fri, 5 Aug 2022 01:53:34 +0200 Subject: [PATCH 2/3] Fix `I2c::write_read`. --- src/i2c.rs | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/src/i2c.rs b/src/i2c.rs index 35beaa68..2e831dcb 100644 --- a/src/i2c.rs +++ b/src/i2c.rs @@ -494,7 +494,7 @@ where }; w.sadd() - .bits(u16(addr << 1 | 1)) + .bits(addr) .rd_wrn() .read() .nbytes() @@ -512,6 +512,8 @@ where *byte = self.i2c.rxdr.read().rxdata().bits(); } + // automatic STOP + Ok(()) } } From 86708dccc843a6df0b787f5e34626f0ad16e0575 Mon Sep 17 00:00:00 2001 From: Markus Reiter Date: Fri, 5 Aug 2022 02:07:53 +0200 Subject: [PATCH 3/3] Remove unused variable. --- src/i2c.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/i2c.rs b/src/i2c.rs index 2e831dcb..a115cf47 100644 --- a/src/i2c.rs +++ b/src/i2c.rs @@ -374,7 +374,7 @@ where busy_wait!(self.i2c, tc, is_complete); // Stop - self.i2c.cr2.modify(|r, w| w.stop().set_bit()); + self.i2c.cr2.modify(|_, w| w.stop().set_bit()); Ok(()) // Tx::new(&self.i2c)?.write(addr, bytes)