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

Wrap errors for embedded-hal trait implementations #30

Merged
merged 3 commits into from
Apr 6, 2024
Merged
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
91 changes: 65 additions & 26 deletions src/pin.rs
Original file line number Diff line number Diff line change
Expand Up @@ -40,14 +40,46 @@ where
self.port_driver.lock(|pd| f(pd))
}
}

/// Error type for [`Pin`] which implements [`embedded_hal::digital::Error`].
#[derive(Debug)]
pub struct PinError<PDE> {
driver_error: PDE,
}

impl<PDE> PinError<PDE> {
/// The upstream port driver error that occurred
pub fn driver_error(&self) -> &PDE {
&self.driver_error
}
}

impl<PDE> hal_digital::Error for PinError<PDE>
where
PDE: core::fmt::Debug,
{
fn kind(&self) -> hal_digital::ErrorKind {
hal_digital::ErrorKind::Other
}
}

impl<PDE> From<PDE> for PinError<PDE> {
fn from(value: PDE) -> Self {
Self {
driver_error: value,
}
}
}

impl<'a, MODE, MUTEX, PD> ErrorType for Pin<'a, MODE, MUTEX>
where
PD: crate::PortDriver + crate::PortDriverTotemPole,
PD::Error: embedded_hal::digital::Error,
PD::Error: core::fmt::Debug,
MUTEX: crate::PortMutex<Port = PD>,
{
type Error = PD::Error;
type Error = PinError<PD::Error>;
}

impl<'a, MODE, MUTEX, PD> Pin<'a, MODE, MUTEX>
where
PD: crate::PortDriver + crate::PortDriverTotemPole,
Expand All @@ -56,7 +88,7 @@ where
/// Configure this pin as an input.
///
/// The exact electrical details depend on the port-expander device which is used.
pub fn into_input(self) -> Result<Pin<'a, crate::mode::Input, MUTEX>, PD::Error> {
pub fn into_input(self) -> Result<Pin<'a, crate::mode::Input, MUTEX>, PinError<PD::Error>> {
self.port_driver
.lock(|drv| drv.set_direction(self.pin_mask, crate::Direction::Input, false))?;
Ok(Pin {
Expand All @@ -70,7 +102,7 @@ where
///
/// The LOW state is, as long as he port-expander chip allows this, entered without any
/// electrical glitch.
pub fn into_output(self) -> Result<Pin<'a, crate::mode::Output, MUTEX>, PD::Error> {
pub fn into_output(self) -> Result<Pin<'a, crate::mode::Output, MUTEX>, PinError<PD::Error>> {
self.port_driver
.lock(|drv| drv.set_direction(self.pin_mask, crate::Direction::Output, false))?;
Ok(Pin {
Expand All @@ -84,7 +116,9 @@ where
///
/// The HIGH state is, as long as he port-expander chip allows this, entered without any
/// electrical glitch.
pub fn into_output_high(self) -> Result<Pin<'a, crate::mode::Output, MUTEX>, PD::Error> {
pub fn into_output_high(
self,
) -> Result<Pin<'a, crate::mode::Output, MUTEX>, PinError<PD::Error>> {
self.port_driver
.lock(|drv| drv.set_direction(self.pin_mask, crate::Direction::Output, true))?;
Ok(Pin {
Expand All @@ -101,14 +135,14 @@ where
MUTEX: crate::PortMutex<Port = PD>,
{
/// Turn on hardware polarity inversion for this pin.
pub fn into_inverted(self) -> Result<Self, PD::Error> {
pub fn into_inverted(self) -> Result<Self, PinError<PD::Error>> {
self.port_driver
.lock(|drv| drv.set_polarity(self.pin_mask, true))?;
Ok(self)
}

/// Set hardware polarity inversion for this pin.
pub fn set_inverted(&mut self, inverted: bool) -> Result<(), PD::Error> {
pub fn set_inverted(&mut self, inverted: bool) -> Result<(), PinError<PD::Error>> {
self.port_driver
.lock(|drv| drv.set_polarity(self.pin_mask, inverted))?;
Ok(())
Expand All @@ -121,13 +155,13 @@ where
MUTEX: crate::PortMutex<Port = PD>,
{
/// Read the pin's input state and return `true` if it is HIGH.
pub fn is_high(&self) -> Result<bool, PD::Error> {
pub fn is_high(&self) -> Result<bool, PinError<PD::Error>> {
self.port_driver
.lock(|drv| Ok(drv.get(self.pin_mask, 0)? == self.pin_mask))
}

/// Read the pin's input state and return `true` if it is LOW.
pub fn is_low(&self) -> Result<bool, PD::Error> {
pub fn is_low(&self) -> Result<bool, PinError<PD::Error>> {
self.port_driver
.lock(|drv| Ok(drv.get(0, self.pin_mask)? == self.pin_mask))
}
Expand All @@ -141,9 +175,10 @@ where
/// Enable/Disable pull-up resistors for this pin.
///
/// If `enable` is `true`, the pull-up resistor is enabled, otherwise the pin is configured as floating input.
pub fn enable_pull_up(&mut self, enable: bool) -> Result<(), PD::Error> {
pub fn enable_pull_up(&mut self, enable: bool) -> Result<(), PinError<PD::Error>> {
self.port_driver
.lock(|drv| drv.set_pull_up(self.pin_mask, enable))
.lock(|drv| drv.set_pull_up(self.pin_mask, enable))?;
Ok(())
}
}

Expand All @@ -155,23 +190,24 @@ where
/// Enable/Disable pull-down resistors for this pin.
///
/// If `enable` is `true`, the pull-down resistor is enabled, otherwise the pin is configured as floating input.
pub fn enable_pull_down(&mut self, enable: bool) -> Result<(), PD::Error> {
pub fn enable_pull_down(&mut self, enable: bool) -> Result<(), PinError<PD::Error>> {
self.port_driver
.lock(|drv| drv.set_pull_down(self.pin_mask, enable))
.lock(|drv| drv.set_pull_down(self.pin_mask, enable))?;
Ok(())
}
}

impl<'a, MODE: crate::mode::HasInput, MUTEX, PD> hal_digital::InputPin for Pin<'a, MODE, MUTEX>
where
PD: crate::PortDriver + crate::PortDriverTotemPole,
<PD as crate::PortDriver>::Error: embedded_hal::digital::Error,
<PD as crate::PortDriver>::Error: core::fmt::Debug,
MUTEX: crate::PortMutex<Port = PD>,
{
fn is_high(&mut self) -> Result<bool, <PD as crate::PortDriver>::Error> {
fn is_high(&mut self) -> Result<bool, Self::Error> {
Pin::is_high(self)
}

fn is_low(&mut self) -> Result<bool, <PD as crate::PortDriver>::Error> {
fn is_low(&mut self) -> Result<bool, Self::Error> {
Pin::is_low(self)
}
}
Expand All @@ -184,43 +220,46 @@ where
/// Set the pin's output state to HIGH.
///
/// Note that this can have different electrical meanings depending on the port-expander chip.
pub fn set_high(&mut self) -> Result<(), PD::Error> {
self.port_driver.lock(|drv| drv.set(self.pin_mask, 0))
pub fn set_high(&mut self) -> Result<(), PinError<PD::Error>> {
self.port_driver.lock(|drv| drv.set(self.pin_mask, 0))?;
Ok(())
}

/// Set the pin's output state to LOW.
///
/// Note that this can have different electrical meanings depending on the port-expander chip.
pub fn set_low(&mut self) -> Result<(), PD::Error> {
self.port_driver.lock(|drv| drv.set(0, self.pin_mask))
pub fn set_low(&mut self) -> Result<(), PinError<PD::Error>> {
self.port_driver.lock(|drv| drv.set(0, self.pin_mask))?;
Ok(())
}

/// Return `true` if the pin's output state is HIGH.
///
/// This method does **not** read the pin's electrical state.
pub fn is_set_high(&self) -> Result<bool, PD::Error> {
pub fn is_set_high(&self) -> Result<bool, PinError<PD::Error>> {
self.port_driver
.lock(|drv| Ok(drv.is_set(self.pin_mask, 0)? == self.pin_mask))
}

/// Return `true` if the pin's output state is LOW.
///
/// This method does **not** read the pin's electrical state.
pub fn is_set_low(&self) -> Result<bool, PD::Error> {
pub fn is_set_low(&self) -> Result<bool, PinError<PD::Error>> {
self.port_driver
.lock(|drv| Ok(drv.is_set(0, self.pin_mask)? == self.pin_mask))
}

/// Toggle the pin's output state.
pub fn toggle(&mut self) -> Result<(), PD::Error> {
self.port_driver.lock(|drv| drv.toggle(self.pin_mask))
pub fn toggle(&mut self) -> Result<(), PinError<PD::Error>> {
self.port_driver.lock(|drv| drv.toggle(self.pin_mask))?;
Ok(())
}
}

impl<'a, MODE: crate::mode::HasOutput, MUTEX, PD> hal_digital::OutputPin for Pin<'a, MODE, MUTEX>
where
PD: crate::PortDriver + crate::PortDriverTotemPole,
<PD as crate::PortDriver>::Error: embedded_hal::digital::Error,
<PD as crate::PortDriver>::Error: core::fmt::Debug,
MUTEX: crate::PortMutex<Port = PD>,
{
fn set_low(&mut self) -> Result<(), Self::Error> {
Expand All @@ -236,7 +275,7 @@ impl<'a, MODE: crate::mode::HasOutput, MUTEX, PD> hal_digital::StatefulOutputPin
for Pin<'a, MODE, MUTEX>
where
PD: crate::PortDriver + crate::PortDriverTotemPole,
<PD as crate::PortDriver>::Error: embedded_hal::digital::Error,
<PD as crate::PortDriver>::Error: core::fmt::Debug,
MUTEX: crate::PortMutex<Port = PD>,
{
fn is_set_high(&mut self) -> Result<bool, Self::Error> {
Expand Down
Loading