Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

PIO: open-drain/multi-driver support #32

Draft
wants to merge 1 commit into
base: development
Choose a base branch
from
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
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