From 789aeecec296d7d3301509d32153022927ff33e4 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Franti=C5=A1ek=20Boh=C3=A1=C4=8Dek?= Date: Fri, 28 Jul 2023 21:24:30 +0200 Subject: [PATCH] feat(src): add basic button representation --- src/button.rs | 99 +++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 99 insertions(+) create mode 100644 src/button.rs diff --git a/src/button.rs b/src/button.rs new file mode 100644 index 0000000..26a4f6b --- /dev/null +++ b/src/button.rs @@ -0,0 +1,99 @@ +use core::convert::Infallible; + +use alloc::boxed::Box; +use core::marker::PhantomData; +use embedded_hal::digital::v2::InputPin; + +pub struct ActiveHigh; +pub struct ActiveLow; + +const DEBOUNCE: u8 = 2; +const LONG_PRESS: u8 = 5; + +#[derive(PartialEq, Eq)] +pub enum ButtonState { + Off, + JustPressed, + LongPress, + Click, + DoubleClick, + Released, +} + +pub struct Button { + pin: Box>, + debounce: u8, + prev_state: bool, + level: PhantomData, +} + +pub trait ActiveLevel { + fn raw_is_pressed(pin_state: bool) -> bool; +} + +impl ActiveLevel for ActiveHigh { + fn raw_is_pressed(pin_state: bool) -> bool { + pin_state + } +} + +impl ActiveLevel for ActiveLow { + fn raw_is_pressed(pin_state: bool) -> bool { + !pin_state + } +} + +impl Button { + pub fn new(pin: Box>) -> Self { + Self { + pin, + debounce: 0, + prev_state: false, + level: PhantomData::, + } + } + + pub fn raw_is_pressed(&self) -> bool { + ACTIVELEVEL::raw_is_pressed(self.pin.is_high().unwrap()) + } + + pub fn is_just_pressed(&self) -> bool { + self.raw_is_pressed() && self.debounce == DEBOUNCE + } + + pub fn is_pressed(&self) -> bool { + self.raw_is_pressed() && self.debounce >= DEBOUNCE + } + + pub fn is_long_pressed(&self) -> bool { + self.raw_is_pressed() && self.debounce >= LONG_PRESS + } + + pub fn state(&self) -> ButtonState { + if !self.raw_is_pressed() { + ButtonState::Off + } else if self.is_just_pressed() { + ButtonState::JustPressed + } else if self.is_long_pressed() { + ButtonState::LongPress + } else { + ButtonState::Off + } + } + + pub fn update(&mut self) { + let raw_pressed = self.raw_is_pressed(); + + if raw_pressed != self.prev_state { + self.debounce = 0; + } else if self.debounce < u8::MAX { + self.debounce += 1; + } + + self.prev_state = raw_pressed; + } + + pub fn reset() { + // resets is_clicked etc. + } +} -- 2.48.1