diff --git a/CHANGELOG.md b/CHANGELOG.md index 1470504..b4dec2c 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -7,6 +7,7 @@ - [Integration](https://crates.io/crates/mcan-core) with the [`mcan`](https://crates.io/crates/mcan) crate. - Implementation of blocking::i2c::Transactional trait from [embedded-hal](https://crates.io/crates/embedded-hal) for TWI device. +- PIO: open-drain/multi-driver support ### Changed diff --git a/hal/src/pio/dynpin.rs b/hal/src/pio/dynpin.rs index d0d1774..c35ce8e 100644 --- a/hal/src/pio/dynpin.rs +++ b/hal/src/pio/dynpin.rs @@ -73,6 +73,7 @@ pub enum DynPinMode { Reset, Peripheral(DynPeripheral), Output, + OpenDrain, Input, } diff --git a/hal/src/pio/pin.rs b/hal/src/pio/pin.rs index 231db6e..23a59e1 100644 --- a/hal/src/pio/pin.rs +++ b/hal/src/pio/pin.rs @@ -55,6 +55,10 @@ impl generics::Sealed for Input {} pub enum Output {} impl generics::Sealed for Output {} +/// Type indicating that the [`Pin`] is an open drain +pub enum OpenDrain {} +impl generics::Sealed for OpenDrain {} + //================================================================================ // Peripheral configurations //================================================================================ @@ -117,6 +121,10 @@ impl PinMode for Output { const DYN: DynPinMode = DynPinMode::Output; } +impl PinMode for OpenDrain { + const DYN: DynPinMode = DynPinMode::OpenDrain; +} + impl PinMode for Input { const DYN: DynPinMode = DynPinMode::Input; } @@ -207,6 +215,15 @@ where pin } + /// Configures tis pin to operate as an [`OpenDrain`] [`Pin`]. + #[inline] + pub fn into_opendrain(self, cfg: PullDir) -> Pin { + let mut pin: Pin = self.into_mode(); + pin.set_pull_dir(cfg); + + pin + } + /// Configures this [`Pin`] to operate as an [`Input`] [`Pin`]. #[inline] pub fn into_input(self, cfg: PullDir) -> Pin { @@ -423,6 +440,25 @@ where } } +impl OutputPin for Pin +where + I: PinId, +{ + type Error = Infallible; + + #[inline] + fn set_high(&mut self) -> Result<(), Self::Error> { + self.set_pull_dir(PullDir::PullUp); + Ok(()) + } + + #[inline] + fn set_low(&mut self) -> Result<(), Self::Error> { + self.set_pull_dir(PullDir::Floating); + Ok(()) + } +} + #[cfg(feature = "unproven")] impl ToggleableOutputPin for Pin where diff --git a/hal/src/pio/reg.rs b/hal/src/pio/reg.rs index 84b792d..ae62059 100644 --- a/hal/src/pio/reg.rs +++ b/hal/src/pio/reg.rs @@ -23,6 +23,7 @@ pub(in crate::pio) trait RegisterInterface { DynPinMode::Reset => unimplemented!(), DynPinMode::Peripheral(a) => self.as_peripheral(a), DynPinMode::Output => self.as_output(), + DynPinMode::OpenDrain => self.as_opendrain(), DynPinMode::Input => self.as_input(), } } @@ -67,6 +68,18 @@ pub(in crate::pio) trait RegisterInterface { self.reg().oer.write(|w| unsafe { w.bits(self.mask()) }); } + #[inline] + fn as_opendrain(&mut self) { + // take pin from peripheral + self.reg().per.write(|w| unsafe { w.bits(self.mask()) }); + + // Enable multidrive + self.reg().mder.write(|w| unsafe { w.bits(self.mask()) }); + + // disable pin output, driver should not be connected + self.reg().odr.write(|w| unsafe { w.bits(self.mask()) }); + } + #[inline] fn as_input(&mut self) { // take pin from peripheral