From 017861cd4bf173ebad81ae71feed0ec13c36ff46 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Franti=C5=A1ek=20Boh=C3=A1=C4=8Dek?= Date: Sat, 24 Dec 2022 12:02:26 +0100 Subject: [PATCH] feat: add button events --- src/button.rs | 73 ++++++++++++++++++++++++++++++++++++++++++++++++++- 1 file changed, 72 insertions(+), 1 deletion(-) diff --git a/src/button.rs b/src/button.rs index cd85636..bb3cebf 100644 --- a/src/button.rs +++ b/src/button.rs @@ -8,14 +8,34 @@ pub enum ButtonState { Released // The button was just released } +#[derive(Copy, Clone, PartialEq, Eq)] +pub enum ButtonEvent { + Click, + LongClick, + LongClickContinuous, + DoubleClick, + None +} + const DEBOUNCECYCLES: u8 = 50; +const PRESSED_FOR_MAX: u16 = 65000; +const RELEASED_FOR_MAX: u16 = 65000; + +const PRESSED_FOR_LONG: u16 = 1000; +const RELEASED_FOR_DOUBLE_CLICK: u16 = 1000; + pub struct Button { input: Pin, active_high: bool, last_active: bool, active: bool, - integrator: u8 + integrator: u8, + + pressed_for: u16, + released_for: u16, + + last_event: ButtonEvent, } impl Button { @@ -26,6 +46,9 @@ impl Button { last_active: false, active: false, integrator: 0, + pressed_for: 0, + released_for: 0, + last_event: ButtonEvent::None } } @@ -43,7 +66,55 @@ impl Button { self.integrator += 1; } + let last_active = self.active; self.active = self.pressed(); + + if !last_active && self.active { + self.pressed_for = 0; + } else if last_active && !self.active { + self.released_for = 0; + } + + if self.active { + if self.pressed_for < PRESSED_FOR_MAX { + self.pressed_for += 1; + } + } + else { + if self.released_for < RELEASED_FOR_MAX { + self.released_for += 1; + } + } + + // just pressed and was released just for time it could be double click + // fire double click right away + // that is different to normal click. Normal clicks fire after release, + // double click fires right after the second press + if self.active && self.pressed_for == 1 && self.released_for < RELEASED_FOR_DOUBLE_CLICK { + self.last_event = ButtonEvent::DoubleClick; + self.pressed_for += 1; + } + + // is a long click, fire event until released + if self.active && self.pressed_for == PRESSED_FOR_LONG { + self.last_event = ButtonEvent::LongClick; + } + else if self.active && self.pressed_for % PRESSED_FOR_LONG == 0 && self.last_event == ButtonEvent::None { + self.last_event = ButtonEvent::LongClickContinuous; + } + + // was not long click and period for double click is over + if self.pressed_for < PRESSED_FOR_LONG && self.pressed_for > 1 && self.released_for == RELEASED_FOR_DOUBLE_CLICK { + self.last_event = ButtonEvent::Click; + self.released_for += 1; + } + } + + pub fn event(&mut self) -> ButtonEvent { + let last_event = self.last_event; + self.last_event = ButtonEvent::None; + + last_event } fn pressed(&mut self) -> bool{ -- 2.48.1