makes GPIO_PIN_RST optional for the sx1276
[ExpressLRS.git] / src / lib / BUTTON / button.h
bloba8d3b1de4ac8352c95b8c1b7f42e87f5a67e2cab
1 #pragma once
3 #include <functional>
5 template <uint8_t PIN, bool IDLELOW>
6 class Button
8 private:
9 // Constants
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;
19 // State
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
26 public:
27 // Callbacks
28 std::function<void ()>OnShortPress;
29 std::function<void ()>OnLongPress;
30 // Properties
31 uint8_t getCount() const { return _pressCount; }
32 uint8_t getLongCount() const { return _longCount; }
34 Button() :
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()
42 int update()
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)
48 _pressCount = 0;
50 _state = (_state << 1) & 0b110;
51 _state |= digitalRead(PIN) ^ IDLELOW;
53 // If rising edge (release)
54 if (_state == STATE_RISE)
56 if (!_isLongPress)
58 DBGLN("Button short");
59 ++_pressCount;
60 if (OnShortPress)
61 OnShortPress();
63 _isLongPress = false;
65 // Two low in a row
66 else if (_state == STATE_FALL)
68 _lastFallingEdge = now;
69 _longCount = 0;
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);
77 _isLongPress = true;
78 if (OnLongPress)
79 OnLongPress();
80 // Reset time so long can fire again
81 _lastFallingEdge = now;
82 _longCount++;
85 return MS_DEBOUNCE;