1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109
//! Support for detecting button 'hold' events. //! //! This is part of the implementation of the [`single_with_hold`] and //! [`dual_with_hold`] button monitors, public so that it's possible to make //! variants with different timings. //! //! [`single_with_hold`]: crate::buttons::monitors::single_with_hold //! [`dual_with_hold`]: crate::buttons::monitors::dual_with_hold use core::ops::AddAssign; use crate::buttons::core::Transition; /// Description of the number of ticks to treat as a 'hold'. pub trait HoldDescriptor: { /// Integer type wide enough to hold the tick count type width: PartialOrd + AddAssign + Copy; /// Zero of the `width` type const HOLD_START: Self::width; /// One of the `width` type const HOLD_INCREMENT: Self::width; /// The number of ticks const HOLD_TICKS: Self::width; } /// The default `HoldDescriptor`. /// /// Represents 250 ticks (which is 1.5s for 6ms ticks). pub struct DefaultHoldDescriptor (); impl HoldDescriptor for DefaultHoldDescriptor { type width = u8; const HOLD_START: u8 = 0; const HOLD_INCREMENT: u8 = 1; const HOLD_TICKS: u8 = 250; } /// Variant of [`TransitionEvent`] with an additional `Hold` /// event. /// /// [`TransitionEvent`]: crate::buttons::core::TransitionEvent #[derive(Debug)] pub enum Event { Press, Release, Hold, } /// A hold-detection algorithm and associated state. #[derive(Debug)] pub struct HoldAnnotator<T: HoldDescriptor> { counter: T::width, } impl<T: HoldDescriptor> HoldAnnotator<T> { /// Returns a new `HoldAnnotator`. pub fn new() -> HoldAnnotator<T> { HoldAnnotator { counter: T::HOLD_START } } /// Convert the result of a button poll to an event. /// /// Returns [events] similar to those from [`PollButton::poll_event`], but /// with `Hold` as possibility as well as `Press` and `Release`. /// /// If the button has been down for longer than `HOLD_TICKS`, immediately /// reports `Hold`, and reports no event when the button is next released. /// /// See [`DefaultHoldDescriptor`] for the default `HOLD_TICKS`. /// /// # Example /// ```ignore /// match hold_annotator.annotate(button.poll_transition()) { /// Some(holding::Event::Press) => ..., /// Some(holding::Event::Release) => ..., /// Some(holding::Event::Hold) => ..., /// None => ..., /// } /// ``` /// [events]: Event /// [`PollButton::poll_event`]: crate::buttons::core::PollButton::poll_event pub fn annotate(&mut self, transition: Transition) -> Option<Event> { match transition { Transition {was_pressed: false, is_pressed: true} => { self.counter = T::HOLD_START; Some(Event::Press) }, Transition {was_pressed: true, is_pressed: false} => { Some(Event::Release) }, Transition {was_pressed: true, is_pressed: true} => { if self.counter <= T::HOLD_TICKS { self.counter += T::HOLD_INCREMENT; } if self.counter == T::HOLD_TICKS { Some(Event::Hold) } else { None } }, Transition {was_pressed: false, is_pressed: false} => None, } } }