5 template <uint8_t PIN
, bool IDLELOW
>
10 static constexpr uint32_t MS_DEBOUNCE
= 25; // how long the switch must change state to be considered
11 static constexpr uint32_t MS_LONG
= 500; // duration held to be considered a long press (repeats)
12 static constexpr uint32_t MS_MULTI_TIMEOUT
= 500; // duration without a press before the short count is reset
14 static constexpr unsigned STATE_IDLE
= 0b111;
15 static constexpr unsigned STATE_FALL
= 0b100;
16 static constexpr unsigned STATE_RISE
= 0b011;
17 static constexpr unsigned STATE_HELD
= 0b000;
20 uint32_t _lastCheck
; // millis of last pin read
21 uint32_t _lastFallingEdge
; // millis of last debounced falling edge
22 uint8_t _state
; // pin history
23 bool _isLongPress
; // true if last press was a long
24 uint8_t _longCount
; // number of times long press has repeated
25 uint8_t _pressCount
; // number of short presses before timeout
28 std::function
<void ()>OnShortPress
;
29 std::function
<void ()>OnLongPress
;
31 uint8_t getCount() const { return _pressCount
; }
32 uint8_t getLongCount() const { return _longCount
; }
35 _lastCheck(0), _lastFallingEdge(0), _state(STATE_IDLE
),
36 _isLongPress(false), _longCount(0), _pressCount(0)
38 pinMode(PIN
, IDLELOW
? INPUT
: INPUT_PULLUP
);
41 // Call this in loop()
44 const uint32_t now
= millis();
46 // Reset press count if it has been too long since last rising edge
47 if (now
- _lastFallingEdge
> MS_MULTI_TIMEOUT
)
50 _state
= (_state
<< 1) & 0b110;
51 _state
|= digitalRead(PIN
) ^ IDLELOW
;
53 // If rising edge (release)
54 if (_state
== STATE_RISE
)
58 DBGLN("Button short");
66 else if (_state
== STATE_FALL
)
68 _lastFallingEdge
= now
;
71 // Three or more low in a row
72 else if (_state
== STATE_HELD
)
74 if (now
- _lastFallingEdge
> MS_LONG
)
76 DBGLN("Button long %d", _longCount
);
80 // Reset time so long can fire again
81 _lastFallingEdge
= now
;