Skip to content

Commit

Permalink
Allow configuring default pull mode for inputs
Browse files Browse the repository at this point in the history
  • Loading branch information
t-moe committed Jan 29, 2024
1 parent 756aabf commit 3948972
Showing 1 changed file with 71 additions and 8 deletions.
79 changes: 71 additions & 8 deletions src/dev/pi4ioe5v6408.rs
Original file line number Diff line number Diff line change
Expand Up @@ -13,8 +13,9 @@ where
/// # Arguments
/// - `i2c` - The I2C bus the device is connected to
/// - `addr` - The address of the device. The address is 0x43 if `addr` is `false` and 0x44 if `addr` is `true`
pub fn new(i2c: I2C, addr: bool) -> Result<Self, I2C::BusError> {
Self::with_mutex(i2c, addr)
/// - `default_pull_mode` - The default pull mode for all pins (The pins are configured as inputs on reset)
pub fn new(i2c: I2C, addr: bool, default_pull_mode: PullMode) -> Result<Self, I2C::BusError> {
Self::with_mutex(i2c, addr, default_pull_mode)
}
}

Expand All @@ -29,8 +30,17 @@ where
/// # Arguments
/// - `i2c` - The I2C bus the device is connected to
/// - `addr` - The address of the device. The address is 0x43 if `addr` is `false` and 0x44 if `addr` is `true`
pub fn with_mutex(i2c: I2C, addr: bool) -> Result<Self, I2C::BusError> {
Ok(Self(shared_bus::BusMutex::create(Driver::new(i2c, addr)?)))
/// - `default_pull_mode` - The default pull mode for all pins (The pins are configured as inputs on reset)
pub fn with_mutex(
i2c: I2C,
addr: bool,
default_pull_mode: PullMode,
) -> Result<Self, I2C::BusError> {
Ok(Self(shared_bus::BusMutex::create(Driver::new(
i2c,
addr,
default_pull_mode,
)?)))
}

pub fn split<'a>(&'a mut self) -> Parts<'a, I2C, M> {
Expand Down Expand Up @@ -83,14 +93,28 @@ impl From<Regs> for u8 {
}
}

/// The pull mode for an input pin
pub enum PullMode {
/// Pull the pin up
PullUp,
/// Pull the pin down
PullDown,
/// Don't activate pull-up or pull-down resistors and leave the pin floating
Floating,
}

pub struct Driver<I2C> {
i2c: I2C,
addr: u8,
out: u8,
}

impl<I2C: crate::I2cBus> Driver<I2C> {
pub fn new(mut i2c: I2C, addr: bool) -> Result<Self, I2C::BusError> {
pub fn new(
mut i2c: I2C,
addr: bool,
default_pull_mode: PullMode,
) -> Result<Self, I2C::BusError> {
let addr = if addr { 0x44 } else { 0x43 };

let device_id = i2c.read_reg(addr, Regs::DeviceIdControl)?; // Reset the "(Power on) Reset Interrupt" bit (and validate the device ID)
Expand All @@ -113,9 +137,18 @@ impl<I2C: crate::I2cBus> Driver<I2C> {

// Change reset values we don't want
i2c.write_reg(addr, Regs::OutputHighImpedance, 0)?; // Disable high impedance mode on all outputs
i2c.write_reg(addr, Regs::PullUpPullDownSelection, 0xff)?; // Enable Pull-Ups on all inputs
i2c.write_reg(addr, Regs::InterruptMaskRegister, 0xff)?; // Disable interrupts on all inputs

match default_pull_mode {
PullMode::PullUp => {
i2c.write_reg(addr, Regs::PullUpPullDownSelection, 0xff)?; // Pull-Ups on all inputs
}
PullMode::PullDown => {} // Nothing to do, as this is the default
PullMode::Floating => {
i2c.write_reg(addr, Regs::PullUpPullDownEnable, 0)?; // Disable pull-up/pull-down on all inputs
}
}

Ok(Self { i2c, addr, out: 0 })
}
}
Expand Down Expand Up @@ -173,6 +206,7 @@ impl<I2C: crate::I2cBus> crate::PortDriverTotemPole for Driver<I2C> {

#[cfg(test)]
mod tests {
use super::PullMode;
use embedded_hal_mock::i2c as mock_i2c;

#[test]
Expand All @@ -181,7 +215,6 @@ mod tests {
// driver setup
mock_i2c::Transaction::write_read(0x43, vec![0x01], vec![0xa2]),
mock_i2c::Transaction::write(0x43, vec![0x07, 0]),
mock_i2c::Transaction::write(0x43, vec![0x0d, 0xff]),
mock_i2c::Transaction::write(0x43, vec![0x11, 0xff]),
// pin setup io0
mock_i2c::Transaction::write_read(0x43, vec![0x03], vec![0]),
Expand All @@ -203,7 +236,7 @@ mod tests {
];
let mut bus = mock_i2c::Mock::new(&expectations);

let mut pca = super::Pi4ioe5v6408::new(bus.clone(), false).unwrap();
let mut pca = super::Pi4ioe5v6408::new(bus.clone(), false, PullMode::PullDown).unwrap();
let pca_pins = pca.split();

let io0 = pca_pins.io0.into_output().unwrap();
Expand All @@ -220,4 +253,34 @@ mod tests {

bus.done();
}

#[test]
fn pi4ioe5v6408_setup_pullup() {
let expectations = [
// driver setup
mock_i2c::Transaction::write_read(0x43, vec![0x01], vec![0xa2]),
mock_i2c::Transaction::write(0x43, vec![0x07, 0]),
mock_i2c::Transaction::write(0x43, vec![0x11, 0xff]),
mock_i2c::Transaction::write(0x43, vec![0x0d, 0xff]),
];
let mut bus = mock_i2c::Mock::new(&expectations);

let _pca = super::Pi4ioe5v6408::new(bus.clone(), false, PullMode::PullUp).unwrap();
bus.done();
}

#[test]
fn pi4ioe5v6408_setup_floating() {
let expectations = [
// driver setup
mock_i2c::Transaction::write_read(0x44, vec![0x01], vec![0xa2]),
mock_i2c::Transaction::write(0x44, vec![0x07, 0]),
mock_i2c::Transaction::write(0x44, vec![0x11, 0xff]),
mock_i2c::Transaction::write(0x44, vec![0x0b, 0]),
];
let mut bus = mock_i2c::Mock::new(&expectations);

let _pca = super::Pi4ioe5v6408::new(bus.clone(), true, PullMode::Floating).unwrap();
bus.done();
}
}

0 comments on commit 3948972

Please sign in to comment.