diff --git a/Cargo.toml b/Cargo.toml index f301cf3..f9e2295 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "i2c-pio" -version = "0.6.0" +version = "0.7.0" edition = "2021" license = "Apache-2.0" description = "I2C driver implementation using the RP2040's PIO peripheral." @@ -11,14 +11,11 @@ repository = "https://github.com/rp-rs/i2c-pio-rs" [dependencies] cortex-m = "0.7.3" -eh1_0_alpha = { version = "=1.0.0-alpha.9", package = "embedded-hal", optional = true } +eh1_0_alpha = { version = "=1.0.0-alpha.11", package = "embedded-hal", optional = true } embedded-hal = "0.2.6" nb = "1.0.0" pio = "0.2.0" pio-proc = "0.2.0" -rp2040-hal = "0.8.0" +rp2040-hal = "0.9.0" fugit = "0.3.5" defmt = { version = "0.3.0", optional = true } - -[patch.crates-io] -rp2040-hal = { git = "https://github.com/rp-rs/rp-hal" } diff --git a/src/lib.rs b/src/lib.rs index 39487e2..4141416 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -45,7 +45,7 @@ use embedded_hal::blocking::i2c::{self, AddressMode, Operation, SevenBitAddress, use fugit::HertzU32; use pio::{Instruction, InstructionOperands, SideSet}; use rp2040_hal::{ - gpio::{Disabled, DisabledConfig, Function, FunctionConfig, Pin, PinId, ValidPinMode}, + gpio::{AnyPin, FunctionNull, Pin, PullUp, ValidFunction}, pio::{ PIOExt, PinDir, PinState, Rx, ShiftDirection, StateMachine, StateMachineIndex, Tx, UninitStateMachine, PIO, @@ -102,42 +102,45 @@ pub enum Error { /// Instance of I2C Controller. pub struct I2C<'pio, P, SMI, SDA, SCL> where - P: PIOExt + FunctionConfig, + P: PIOExt, SMI: StateMachineIndex, - SDA: PinId, - SCL: PinId, - Function

: ValidPinMode + ValidPinMode, + SDA: AnyPin, + SCL: AnyPin, { pio: &'pio mut PIO

, sm: StateMachine<(P, SMI), rp2040_hal::pio::Running>, tx: Tx<(P, SMI)>, rx: Rx<(P, SMI)>, - _sda: Pin>, - _scl: Pin>, + _sda: Pin, + _scl: Pin, } impl<'pio, P, SMI, SDA, SCL> I2C<'pio, P, SMI, SDA, SCL> where - P: PIOExt + FunctionConfig, + P: PIOExt, SMI: StateMachineIndex, - SDA: PinId, - SCL: PinId, - Function

: ValidPinMode + ValidPinMode, + SDA: AnyPin, + SCL: AnyPin, { /// Creates a new instance of this driver. /// /// Note: the PIO must have been reset before using this driver. - pub fn new( + pub fn new( pio: &'pio mut PIO

, - sda: rp2040_hal::gpio::Pin>, - scl: rp2040_hal::gpio::Pin>, + sda: SDA, + scl: SCL, sm: UninitStateMachine<(P, SMI)>, bus_freq: HertzU32, clock_freq: HertzU32, ) -> Self where - Function

: ValidPinMode + ValidPinMode, + SDA: AnyPin, + SDA::Id: ValidFunction, + SCL: AnyPin, + SCL::Id: ValidFunction, { + let (sda, scl): (SDA::Type, SCL::Type) = (sda.into(), scl.into()); + let mut program = pio_proc::pio_asm!( ".side_set 1 opt pindirs" @@ -180,8 +183,8 @@ where ) .program; // patch the program to allow scl to be any pin - program.code[7] |= u16::from(SCL::DYN.num); - program.code[12] |= u16::from(SCL::DYN.num); + program.code[7] |= u16::from(scl.id().num); + program.code[12] |= u16::from(scl.id().num); // Install the program into PIO instruction memory. let installed = pio.install(&program).unwrap(); @@ -211,13 +214,13 @@ where // use both RX & TX FIFO .buffers(rp2040_hal::pio::Buffers::RxTx) // Pin configuration - .set_pins(SDA::DYN.num, 1) - .out_pins(SDA::DYN.num, 1) - .in_pin_base(SDA::DYN.num) - .side_set_pin_base(SCL::DYN.num) - .jmp_pin(SDA::DYN.num) + .set_pins(sda.id().num, 1) + .out_pins(sda.id().num, 1) + .in_pin_base(sda.id().num) + .side_set_pin_base(scl.id().num) + .jmp_pin(sda.id().num) // OSR config - .out_shift_direction(rp2040_hal::pio::ShiftDirection::Left) + .out_shift_direction(ShiftDirection::Left) .autopull(true) .pull_threshold(16) // ISR config @@ -228,31 +231,31 @@ where .build(sm); // enable pull up on SDA & SCL: idle bus - let sda = sda.into_pull_up_input(); - let scl = scl.into_pull_up_input(); + let sda = sda.into_pull_type(); + let scl = scl.into_pull_type(); // This will pull the bus high for a little bit of time sm.set_pins([ - (SCL::DYN.num, PinState::High), - (SDA::DYN.num, PinState::High), + (scl.id().num, PinState::High), + (sda.id().num, PinState::High), ]); sm.set_pindirs([ - (SCL::DYN.num, PinDir::Output), - (SDA::DYN.num, PinDir::Output), + (scl.id().num, PinDir::Output), + (sda.id().num, PinDir::Output), ]); // attach SDA pin to pio - let mut sda: Pin> = sda.into_mode(); + let mut sda: Pin = sda.into_function(); // configure SDA pin as inverted sda.set_output_enable_override(rp2040_hal::gpio::OutputEnableOverride::Invert); // attach SCL pin to pio - let mut scl: Pin> = scl.into_mode(); + let mut scl: Pin = scl.into_function(); // configure SCL pin as inverted scl.set_output_enable_override(rp2040_hal::gpio::OutputEnableOverride::Invert); // the PIO now keeps the pin as Input, we can set the pin state to Low. - sm.set_pins([(SDA::DYN.num, PinState::Low), (SCL::DYN.num, PinState::Low)]); + sm.set_pins([(sda.id().num, PinState::Low), (scl.id().num, PinState::Low)]); // Set the state machine on the entry point. sm.exec_instruction(Instruction { @@ -272,8 +275,8 @@ where sm, tx, rx, - _sda: sda, - _scl: scl, + _sda: sda.into(), + _scl: scl.into(), } } @@ -455,11 +458,10 @@ where impl i2c::Read for I2C<'_, P, SMI, SDA, SCL> where A: AddressMode + Into + 'static, - P: PIOExt + FunctionConfig, + P: PIOExt, SMI: StateMachineIndex, - SDA: PinId, - SCL: PinId, - Function

: ValidPinMode + ValidPinMode, + SDA: AnyPin, + SCL: AnyPin, { type Error = Error; @@ -476,11 +478,10 @@ where impl i2c::WriteIter for I2C<'_, P, SMI, SDA, SCL> where A: AddressMode + Into + 'static, - P: PIOExt + FunctionConfig, + P: PIOExt, SMI: StateMachineIndex, - SDA: PinId, - SCL: PinId, - Function

: ValidPinMode + ValidPinMode, + SDA: AnyPin, + SCL: AnyPin, { type Error = Error; @@ -499,11 +500,10 @@ where impl i2c::Write for I2C<'_, P, SMI, SDA, SCL> where A: AddressMode + Into + 'static, - P: PIOExt + FunctionConfig, + P: PIOExt, SMI: StateMachineIndex, - SDA: PinId, - SCL: PinId, - Function

: ValidPinMode + ValidPinMode, + SDA: AnyPin, + SCL: AnyPin, { type Error = Error; @@ -515,11 +515,10 @@ where impl i2c::WriteIterRead for I2C<'_, P, SMI, SDA, SCL> where A: AddressMode + Into + Clone + 'static, - P: PIOExt + FunctionConfig, + P: PIOExt, SMI: StateMachineIndex, - SDA: PinId, - SCL: PinId, - Function

: ValidPinMode + ValidPinMode, + SDA: AnyPin, + SCL: AnyPin, { type Error = Error; @@ -549,11 +548,10 @@ where impl i2c::WriteRead for I2C<'_, P, SMI, SDA, SCL> where A: AddressMode + Into + Clone + 'static, - P: PIOExt + FunctionConfig, + P: PIOExt, SMI: StateMachineIndex, - SDA: PinId, - SCL: PinId, - Function

: ValidPinMode + ValidPinMode, + SDA: AnyPin, + SCL: AnyPin, { type Error = Error; @@ -575,11 +573,10 @@ where impl i2c::TransactionalIter for I2C<'_, P, SMI, SDA, SCL> where A: AddressMode + Into + Clone + 'static, - P: PIOExt + FunctionConfig, + P: PIOExt, SMI: StateMachineIndex, - SDA: PinId, - SCL: PinId, - Function

: ValidPinMode + ValidPinMode, + SDA: AnyPin, + SCL: AnyPin, { type Error = Error; @@ -617,19 +614,14 @@ where impl i2c::Transactional for I2C<'_, P, SMI, SDA, SCL> where A: AddressMode + Into + Clone + 'static, - P: PIOExt + FunctionConfig, + P: PIOExt, SMI: StateMachineIndex, - SDA: PinId, - SCL: PinId, - Function

: ValidPinMode + ValidPinMode, + SDA: AnyPin, + SCL: AnyPin, { type Error = Error; - fn exec<'a>( - &mut self, - address: A, - operations: &mut [Operation<'a>], - ) -> Result<(), Self::Error> { + fn exec(&mut self, address: A, operations: &mut [Operation<'_>]) -> Result<(), Self::Error> { let mut res = Ok(()); let mut first = true; for op in operations { @@ -663,54 +655,18 @@ mod eh1_0_alpha { use crate::Error; - use super::{Function, FunctionConfig, PIOExt, PinId, StateMachineIndex, ValidPinMode, I2C}; + use super::{AnyPin, PIOExt, StateMachineIndex, I2C}; - impl eh1_0_alpha::i2c::Error for super::Error { - fn kind(&self) -> ErrorKind { - match self { - Error::NoAcknowledgeAddress => { - ErrorKind::NoAcknowledge(NoAcknowledgeSource::Address) - } - Error::NoAcknowledgeData => ErrorKind::NoAcknowledge(NoAcknowledgeSource::Data), - } - } - } - - impl eh1_0_alpha::i2c::ErrorType for I2C<'_, P, SMI, SDA, SCL> + impl I2C<'_, P, SMI, SDA, SCL> where - P: PIOExt + FunctionConfig, + P: PIOExt, SMI: StateMachineIndex, - SDA: PinId, - SCL: PinId, - Function

: ValidPinMode + ValidPinMode, + SDA: AnyPin, + SCL: AnyPin, { - type Error = super::Error; - } - - impl eh1_0_alpha::i2c::I2c for I2C<'_, P, SMI, SDA, SCL> - where - A: AddressMode + Into + Clone + 'static, - P: PIOExt + FunctionConfig, - SMI: StateMachineIndex, - SDA: PinId, - SCL: PinId, - Function

: ValidPinMode + ValidPinMode, - { - fn read(&mut self, address: A, buffer: &mut [u8]) -> Result<(), Self::Error> { - let mut res = self.setup(address, true, false); - if res.is_ok() { - res = self.read(buffer); - } - self.stop(); - res - } - - fn write(&mut self, address: A, bytes: &[u8]) -> Result<(), Self::Error> { - self.write_iter(address, bytes.into_iter().cloned()) - } - - fn write_iter(&mut self, address: A, bytes: B) -> Result<(), Self::Error> + pub fn write_iter(&mut self, address: A, bytes: B) -> Result<(), Error> where + A: AddressMode + Into + Clone + 'static, B: IntoIterator, { let mut res = self.setup(address, false, false); @@ -721,22 +677,14 @@ mod eh1_0_alpha { res } - fn write_read( - &mut self, - address: A, - bytes: &[u8], - buffer: &mut [u8], - ) -> Result<(), Self::Error> { - self.write_iter_read(address, bytes.into_iter().cloned(), buffer) - } - - fn write_iter_read( + pub fn write_iter_read( &mut self, address: A, bytes: B, buffer: &mut [u8], - ) -> Result<(), Self::Error> + ) -> Result<(), Error> where + A: AddressMode + Into + Clone + 'static, B: IntoIterator, { let mut res = self.setup(address.clone(), false, false); @@ -753,11 +701,11 @@ mod eh1_0_alpha { res } - fn transaction<'a>( - &mut self, - address: A, - operations: &mut [Operation<'a>], - ) -> Result<(), Self::Error> { + pub fn transaction_iter<'a, A, O>(&mut self, address: A, operations: O) -> Result<(), Error> + where + A: AddressMode + Into + Clone + 'static, + O: IntoIterator>, + { let mut res = Ok(()); let mut first = true; for op in operations { @@ -783,11 +731,64 @@ mod eh1_0_alpha { self.stop(); res } + } - fn transaction_iter<'a, O>(&mut self, address: A, operations: O) -> Result<(), Self::Error> - where - O: IntoIterator>, - { + impl eh1_0_alpha::i2c::Error for super::Error { + fn kind(&self) -> ErrorKind { + match self { + Error::NoAcknowledgeAddress => { + ErrorKind::NoAcknowledge(NoAcknowledgeSource::Address) + } + Error::NoAcknowledgeData => ErrorKind::NoAcknowledge(NoAcknowledgeSource::Data), + } + } + } + + impl eh1_0_alpha::i2c::ErrorType for I2C<'_, P, SMI, SDA, SCL> + where + P: PIOExt, + SMI: StateMachineIndex, + SDA: AnyPin, + SCL: AnyPin, + { + type Error = super::Error; + } + + impl eh1_0_alpha::i2c::I2c for I2C<'_, P, SMI, SDA, SCL> + where + A: AddressMode + Into + Clone + 'static, + P: PIOExt, + SMI: StateMachineIndex, + SDA: AnyPin, + SCL: AnyPin, + { + fn read(&mut self, address: A, buffer: &mut [u8]) -> Result<(), Self::Error> { + let mut res = self.setup(address, true, false); + if res.is_ok() { + res = self.read(buffer); + } + self.stop(); + res + } + + fn write(&mut self, address: A, bytes: &[u8]) -> Result<(), Self::Error> { + self.write_iter(address, bytes.into_iter().cloned()) + } + + fn write_read( + &mut self, + address: A, + bytes: &[u8], + buffer: &mut [u8], + ) -> Result<(), Self::Error> { + self.write_iter_read(address, bytes.into_iter().cloned(), buffer) + } + + fn transaction<'a>( + &mut self, + address: A, + operations: &mut [Operation<'a>], + ) -> Result<(), Self::Error> { let mut res = Ok(()); let mut first = true; for op in operations {