Skip to content

Commit

Permalink
pio: implement open-drain/multi-drive API
Browse files Browse the repository at this point in the history
  • Loading branch information
sundbom-grepit authored and tmplt committed Aug 6, 2023
1 parent c9fef17 commit 8b18b78
Show file tree
Hide file tree
Showing 4 changed files with 51 additions and 0 deletions.
1 change: 1 addition & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -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

Expand Down
1 change: 1 addition & 0 deletions hal/src/pio/dynpin.rs
Original file line number Diff line number Diff line change
Expand Up @@ -73,6 +73,7 @@ pub enum DynPinMode {
Reset,
Peripheral(DynPeripheral),
Output,
OpenDrain,
Input,
}

Expand Down
36 changes: 36 additions & 0 deletions hal/src/pio/pin.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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
//================================================================================
Expand Down Expand Up @@ -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;
}
Expand Down Expand Up @@ -207,6 +215,15 @@ where
pin
}

/// Configures tis pin to operate as an [`OpenDrain`] [`Pin`].
#[inline]
pub fn into_opendrain(self, cfg: PullDir) -> Pin<I, OpenDrain> {
let mut pin: Pin<I, OpenDrain> = 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<I, Input> {
Expand Down Expand Up @@ -423,6 +440,25 @@ where
}
}

impl<I> OutputPin for Pin<I, OpenDrain>
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<I> ToggleableOutputPin for Pin<I, Output>
where
Expand Down
13 changes: 13 additions & 0 deletions hal/src/pio/reg.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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(),
}
}
Expand Down Expand Up @@ -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
Expand Down

0 comments on commit 8b18b78

Please sign in to comment.