From 009f77986b5650a7d297ba633edd74ed1788bf51 Mon Sep 17 00:00:00 2001 From: Timo Date: Tue, 6 Feb 2024 16:53:06 +0100 Subject: [PATCH] Add Pull-Up/Pull-Down traits and implement them for the PI4IOE5V6408 --- src/common.rs | 10 ++++++++ src/dev/pi4ioe5v6408.rs | 53 ++++++++++++++++++++++++++++++++++++++++- src/lib.rs | 2 ++ src/pin.rs | 22 +++++++++++++++++ 4 files changed, 86 insertions(+), 1 deletion(-) diff --git a/src/common.rs b/src/common.rs index 5f22ebc..6147bfe 100644 --- a/src/common.rs +++ b/src/common.rs @@ -50,6 +50,16 @@ pub trait PortDriverPolarity: PortDriver { fn set_polarity(&mut self, mask: u32, inverted: bool) -> Result<(), Self::Error>; } +pub trait PortDriverPullDown: PortDriver { + /// Enable pull-downs for pins in mask or set the pin to floating if enable is false. + fn set_pull_down(&mut self, mask: u32, enable: bool) -> Result<(), Self::Error>; +} + +pub trait PortDriverPullUp: PortDriver { + /// Enable pull-ups for pins in mask or set the pin to floating if enable is false. + fn set_pull_up(&mut self, mask: u32, enable: bool) -> Result<(), Self::Error>; +} + /// Pin Modes pub mod mode { /// Trait for pin-modes which can be used to set a logic level. diff --git a/src/dev/pi4ioe5v6408.rs b/src/dev/pi4ioe5v6408.rs index bc2fef0..1fd58a4 100644 --- a/src/dev/pi4ioe5v6408.rs +++ b/src/dev/pi4ioe5v6408.rs @@ -195,6 +195,36 @@ impl crate::PortDriverTotemPole for Driver { } } +impl crate::PortDriverPullDown for Driver { + fn set_pull_down(&mut self, mask: u32, enable: bool) -> Result<(), Self::Error> { + if enable { + self.i2c + .update_reg(self.addr, Regs::PullUpPullDownSelection, 0, mask as u8)?; + self.i2c + .update_reg(self.addr, Regs::PullUpPullDownEnable, mask as u8, 0)?; + } else { + self.i2c + .update_reg(self.addr, Regs::PullUpPullDownEnable, 0, mask as u8)?; + } + Ok(()) + } +} + +impl crate::PortDriverPullUp for Driver { + fn set_pull_up(&mut self, mask: u32, enable: bool) -> Result<(), Self::Error> { + if enable { + self.i2c + .update_reg(self.addr, Regs::PullUpPullDownSelection, mask as u8, 0)?; + self.i2c + .update_reg(self.addr, Regs::PullUpPullDownEnable, mask as u8, 0)?; + } else { + self.i2c + .update_reg(self.addr, Regs::PullUpPullDownEnable, 0, mask as u8)?; + } + Ok(()) + } +} + #[cfg(test)] mod tests { use embedded_hal_mock::eh1::i2c as mock_i2c; @@ -225,6 +255,22 @@ mod tests { // io0 reads mock_i2c::Transaction::write_read(0x43, vec![0x0f], vec![0b00000001]), mock_i2c::Transaction::write_read(0x43, vec![0x0f], vec![0b00000000]), + // io0 activate pull-up + mock_i2c::Transaction::write_read(0x43, vec![0x0d], vec![0b10101010]), + mock_i2c::Transaction::write(0x43, vec![0x0d, 0b10101011]), + mock_i2c::Transaction::write_read(0x43, vec![0x0b], vec![0b00001010]), + mock_i2c::Transaction::write(0x43, vec![0x0b, 0b00001011]), + // io0 disable pull-up + mock_i2c::Transaction::write_read(0x43, vec![0x0b], vec![0b00001011]), + mock_i2c::Transaction::write(0x43, vec![0x0b, 0b00001010]), + // io0 activate pull-down + mock_i2c::Transaction::write_read(0x43, vec![0x0d], vec![0b10101011]), + mock_i2c::Transaction::write(0x43, vec![0x0d, 0b10101010]), + mock_i2c::Transaction::write_read(0x43, vec![0x0b], vec![0b00001010]), + mock_i2c::Transaction::write(0x43, vec![0x0b, 0b00001011]), + // io0 disable pull-down + mock_i2c::Transaction::write_read(0x43, vec![0x0b], vec![0b00001011]), + mock_i2c::Transaction::write(0x43, vec![0x0b, 0b00001010]), ]; let mut bus = mock_i2c::Mock::new(&expectations); @@ -234,7 +280,7 @@ mod tests { let io0 = pca_pins.io0.into_output().unwrap(); let mut io1 = pca_pins.io1.into_output_high().unwrap(); - let io0 = io0.into_input().unwrap(); + let mut io0 = io0.into_input().unwrap(); io1.set_low().unwrap(); io1.set_high().unwrap(); @@ -243,6 +289,11 @@ mod tests { assert!(io0.is_high().unwrap()); assert!(io0.is_low().unwrap()); + io0.enable_pull_up(true).unwrap(); + io0.enable_pull_up(false).unwrap(); + io0.enable_pull_down(true).unwrap(); + io0.enable_pull_down(false).unwrap(); + bus.done(); } diff --git a/src/lib.rs b/src/lib.rs index e232e67..9eebb42 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -73,6 +73,8 @@ pub(crate) use bus::I2cExt; pub(crate) use common::Direction; pub(crate) use common::PortDriver; pub(crate) use common::PortDriverPolarity; +pub(crate) use common::PortDriverPullDown; +pub(crate) use common::PortDriverPullUp; pub(crate) use common::PortDriverTotemPole; pub use dev::max7321::Max7321; diff --git a/src/pin.rs b/src/pin.rs index 9561e55..dc0ac4b 100644 --- a/src/pin.rs +++ b/src/pin.rs @@ -126,6 +126,28 @@ where } } +impl<'a, MODE: crate::mode::HasInput, MUTEX, PD> Pin<'a, MODE, MUTEX> +where + PD: crate::PortDriver + crate::PortDriverPullUp, + MUTEX: shared_bus::BusMutex, +{ + pub fn enable_pull_up(&mut self, enable: bool) -> Result<(), PD::Error> { + self.port_driver + .lock(|drv| drv.set_pull_up(self.pin_mask, enable)) + } +} + +impl<'a, MODE: crate::mode::HasInput, MUTEX, PD> Pin<'a, MODE, MUTEX> +where + PD: crate::PortDriver + crate::PortDriverPullDown, + MUTEX: shared_bus::BusMutex, +{ + pub fn enable_pull_down(&mut self, enable: bool) -> Result<(), PD::Error> { + self.port_driver + .lock(|drv| drv.set_pull_down(self.pin_mask, enable)) + } +} + impl<'a, MODE: crate::mode::HasInput, MUTEX, PD> hal_digital::InputPin for Pin<'a, MODE, MUTEX> where PD: crate::PortDriver + crate::PortDriverTotemPole,