7 static constexpr uint32_t MS_DEBOUNCE
= 25; // how long the switch must change state to be considered
8 static constexpr uint32_t MS_LONG
= 500; // duration held to be considered a long press (repeats)
9 static constexpr uint32_t MS_MULTI_TIMEOUT
= 500; // duration without a press before the short count is reset
11 static constexpr unsigned STATE_IDLE
= 0b111;
12 static constexpr unsigned STATE_FALL
= 0b100;
13 static constexpr unsigned STATE_RISE
= 0b011;
14 static constexpr unsigned STATE_HELD
= 0b000;
19 uint32_t _lastCheck
; // millis of last pin read
20 uint32_t _lastFallingEdge
; // millis of last debounced falling edge
21 uint8_t _state
; // pin history
22 bool _isLongPress
; // true if last press was a long
23 uint8_t _longCount
; // number of times long press has repeated
24 uint8_t _pressCount
; // number of short presses before timeout
27 void (*OnShortPress
)();
28 void (*OnLongPress
)();
30 uint8_t getCount() const { return _pressCount
; }
31 uint8_t getLongCount() const { return _longCount
; }
34 _lastCheck(0), _lastFallingEdge(0), _state(STATE_IDLE
),
35 _isLongPress(false), _longCount(0), _pressCount(0)
39 void init(uint8_t pin
, bool idlelow
= false)
43 pinMode(_pin
, _idlelow
? INPUT
: INPUT_PULLUP
);
46 // Call this in loop()
49 const uint32_t now
= millis();
51 // Reset press count if it has been too long since last rising edge
52 if (now
- _lastFallingEdge
> MS_MULTI_TIMEOUT
)
55 _state
= (_state
<< 1) & 0b110;
56 _state
|= digitalRead(_pin
) ^ _idlelow
;
58 // If rising edge (release)
59 if (_state
== STATE_RISE
)
63 DBGVLN("Button short");
71 else if (_state
== STATE_FALL
)
73 _lastFallingEdge
= now
;
76 // Three or more low in a row
77 else if (_state
== STATE_HELD
)
79 if (now
- _lastFallingEdge
> MS_LONG
)
81 DBGVLN("Button long %d", _longCount
);
85 // Reset time so long can fire again
86 _lastFallingEdge
= now
;