use core::{convert::From, ops::Not};
pub trait ErrorType {
type Error: core::fmt::Debug;
}
impl<T: ErrorType> ErrorType for &T {
type Error = T::Error;
}
impl<T: ErrorType> ErrorType for &mut T {
type Error = T::Error;
}
#[derive(Debug, PartialEq, Eq, Clone, Copy)]
pub enum PinState {
Low,
High,
}
impl From<bool> for PinState {
fn from(value: bool) -> Self {
match value {
false => PinState::Low,
true => PinState::High,
}
}
}
impl Not for PinState {
type Output = PinState;
fn not(self) -> Self::Output {
match self {
PinState::High => PinState::Low,
PinState::Low => PinState::High,
}
}
}
pub mod blocking {
use super::PinState;
pub trait OutputPin: super::ErrorType {
fn set_low(&mut self) -> Result<(), Self::Error>;
fn set_high(&mut self) -> Result<(), Self::Error>;
fn set_state(&mut self, state: PinState) -> Result<(), Self::Error> {
match state {
PinState::Low => self.set_low(),
PinState::High => self.set_high(),
}
}
}
impl<T: OutputPin> OutputPin for &mut T {
fn set_low(&mut self) -> Result<(), Self::Error> {
T::set_low(self)
}
fn set_high(&mut self) -> Result<(), Self::Error> {
T::set_high(self)
}
fn set_state(&mut self, state: PinState) -> Result<(), Self::Error> {
T::set_state(self, state)
}
}
pub trait StatefulOutputPin: OutputPin {
fn is_set_high(&self) -> Result<bool, Self::Error>;
fn is_set_low(&self) -> Result<bool, Self::Error>;
}
impl<T: StatefulOutputPin> StatefulOutputPin for &mut T {
fn is_set_high(&self) -> Result<bool, Self::Error> {
T::is_set_high(self)
}
fn is_set_low(&self) -> Result<bool, Self::Error> {
T::is_set_low(self)
}
}
pub trait ToggleableOutputPin: super::ErrorType {
fn toggle(&mut self) -> Result<(), Self::Error>;
}
impl<T: ToggleableOutputPin> ToggleableOutputPin for &mut T {
fn toggle(&mut self) -> Result<(), Self::Error> {
T::toggle(self)
}
}
pub trait InputPin: super::ErrorType {
fn is_high(&self) -> Result<bool, Self::Error>;
fn is_low(&self) -> Result<bool, Self::Error>;
}
impl<T: InputPin> InputPin for &T {
fn is_high(&self) -> Result<bool, Self::Error> {
T::is_high(self)
}
fn is_low(&self) -> Result<bool, Self::Error> {
T::is_low(self)
}
}
pub trait IoPin<TInput, TOutput>
where
TInput: InputPin + IoPin<TInput, TOutput>,
TOutput: OutputPin + IoPin<TInput, TOutput>,
{
type Error: core::fmt::Debug;
fn into_input_pin(self) -> Result<TInput, Self::Error>;
fn into_output_pin(self, state: PinState) -> Result<TOutput, Self::Error>;
}
}