@@ 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<mode::Input>,
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{