#![no_std]
pub mod prelude;
use core::marker::PhantomData;
use embedded_hal::digital::v2::InputPin;
pub struct ActiveLow;
pub struct ActiveHigh;
#[derive(PartialEq, Clone, Copy, Debug)]
pub enum DebounceState {
Debouncing,
Reset,
NotActive,
Active,
}
pub struct DebouncedInputPin<T: InputPin, A> {
pub pin: T,
activeness: PhantomData<A>,
debounce_state: DebounceState,
counter: i8,
}
pub trait Debounce {
type Error;
type State;
fn update(&mut self) -> Result<Self::State, Self::Error>;
}
impl<T: InputPin, A> DebouncedInputPin<T, A> {
pub fn new(pin: T, _activeness: A) -> Self {
Self {
pin,
activeness: PhantomData,
counter: 0,
debounce_state: DebounceState::NotActive,
}
}
pub fn is_active(&self) -> bool {
self.debounce_state == DebounceState::Active
}
}
impl<T: InputPin> Debounce for DebouncedInputPin<T, ActiveHigh> {
type Error = T::Error;
type State = DebounceState;
fn update(&mut self) -> Result<Self::State, Self::Error> {
if self.pin.is_low()? {
if self.debounce_state == Self::State::Active {
self.counter = 0;
self.debounce_state = Self::State::Reset;
} else {
self.debounce_state = Self::State::NotActive;
}
} else if self.counter < 10 {
self.counter += 1;
self.debounce_state = Self::State::Debouncing;
} else {
self.debounce_state = Self::State::Active;
}
Ok(self.debounce_state)
}
}
impl<T: InputPin> Debounce for DebouncedInputPin<T, ActiveLow> {
type Error = T::Error;
type State = DebounceState;
fn update(&mut self) -> Result<Self::State, Self::Error> {
if self.pin.is_high()? {
if self.debounce_state == Self::State::Active {
self.counter = 0;
self.debounce_state = Self::State::Reset;
} else {
self.debounce_state = Self::State::NotActive;
}
} else if self.counter < 10 {
self.counter += 1;
self.debounce_state = Self::State::Debouncing;
} else {
self.debounce_state = Self::State::Active;
}
Ok(self.debounce_state)
}
}
impl<T: InputPin> InputPin for DebouncedInputPin<T, ActiveHigh> {
type Error = T::Error;
fn is_high(&self) -> Result<bool, Self::Error> {
Ok(self.debounce_state == DebounceState::Active)
}
fn is_low(&self) -> Result<bool, Self::Error> {
Ok(self.debounce_state != DebounceState::Active)
}
}
impl<T: InputPin> InputPin for DebouncedInputPin<T, ActiveLow> {
type Error = T::Error;
fn is_high(&self) -> Result<bool, Self::Error> {
Ok(self.debounce_state != DebounceState::Active)
}
fn is_low(&self) -> Result<bool, Self::Error> {
Ok(self.debounce_state == DebounceState::Active)
}
}
#[cfg(test)]
mod tests;