use core::{convert::From, ops::Not};
#[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 trait OutputPin {
type Error;
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(),
}
}
}
#[cfg(feature = "unproven")]
pub trait StatefulOutputPin: OutputPin {
fn is_set_high(&self) -> Result<bool, Self::Error>;
fn is_set_low(&self) -> Result<bool, Self::Error>;
}
#[cfg(feature = "unproven")]
pub trait ToggleableOutputPin {
type Error;
fn toggle(&mut self) -> Result<(), Self::Error>;
}
#[cfg(feature = "unproven")]
pub mod toggleable {
use super::{OutputPin, StatefulOutputPin, ToggleableOutputPin};
pub trait Default: OutputPin + StatefulOutputPin {}
impl<P> ToggleableOutputPin for P
where
P: Default,
{
type Error = P::Error;
fn toggle(&mut self) -> Result<(), Self::Error> {
if self.is_set_low()? {
self.set_high()
} else {
self.set_low()
}
}
}
}
#[cfg(feature = "unproven")]
pub trait InputPin {
type Error;
fn is_high(&self) -> Result<bool, Self::Error>;
fn is_low(&self) -> Result<bool, Self::Error>;
}
#[cfg(feature = "unproven")]
pub trait IoPin<TInput, TOutput>
where
TInput: InputPin + IoPin<TInput, TOutput>,
TOutput: OutputPin + IoPin<TInput, TOutput>,
{
type Error;
fn into_input_pin(self) -> Result<TInput, Self::Error>;
fn into_output_pin(self, state: PinState) -> Result<TOutput, Self::Error>;
}