Skip to content

Commit

Permalink
Add Pull-Up/Pull-Down traits
Browse files Browse the repository at this point in the history
  • Loading branch information
t-moe committed Jan 29, 2024
1 parent 3948972 commit 04b9250
Show file tree
Hide file tree
Showing 5 changed files with 87 additions and 1 deletion.
1 change: 1 addition & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0

## [Unreleased]
### Added
- Added `PortDriverPullDown` and `PortDriverPullUp` traits for port-expander ([#17]).
- Added support for `PI4IOE5V6408` ([#17]).


Expand Down
10 changes: 10 additions & 0 deletions src/common.rs
Original file line number Diff line number Diff line change
Expand Up @@ -39,6 +39,16 @@ pub trait PortDriverTotemPole: PortDriver {
fn set_direction(&mut self, mask: u32, dir: Direction, state: 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>;
}

#[derive(Debug, Clone, Copy, PartialEq, Eq)]
pub enum Direction {
Input,
Expand Down
53 changes: 52 additions & 1 deletion src/dev/pi4ioe5v6408.rs
Original file line number Diff line number Diff line change
Expand Up @@ -204,6 +204,36 @@ impl<I2C: crate::I2cBus> crate::PortDriverTotemPole for Driver<I2C> {
}
}

impl<I2C: crate::I2cBus> crate::PortDriverPullDown for Driver<I2C> {
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<I2C: crate::I2cBus> crate::PortDriverPullUp for Driver<I2C> {
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 super::PullMode;
Expand Down Expand Up @@ -233,6 +263,22 @@ mod tests {
// io0 reads
mock_i2c::Transaction::write_read(0x43, vec![0x0f], vec![0x01]),
mock_i2c::Transaction::write_read(0x43, vec![0x0f], vec![0x00]),
// 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);

Expand All @@ -242,7 +288,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();
Expand All @@ -251,6 +297,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();
}

Expand Down
2 changes: 2 additions & 0 deletions src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand Down
22 changes: 22 additions & 0 deletions src/pin.rs
Original file line number Diff line number Diff line change
Expand Up @@ -119,6 +119,28 @@ where
}
}

impl<'a, MODE: crate::mode::HasInput, MUTEX, PD> Pin<'a, MODE, MUTEX>
where
PD: crate::PortDriver + crate::PortDriverPullUp,
MUTEX: shared_bus::BusMutex<Bus = PD>,
{
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<Bus = PD>,
{
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,
Expand Down

0 comments on commit 04b9250

Please sign in to comment.