Phase 3: STM32 Removal: Shared RX/TX parts (#3016)
[ExpressLRS.git] / src / lib / BUTTON / button.h
blob79bcb8f372cb64ef957a0258b38554f1e9bf82be
1 #pragma once
3 class Button
5 private:
6 // Constants
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;
16 // State
17 uint8_t _pin;
18 bool _idlelow;
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
25 public:
26 // Callbacks
27 void (*OnShortPress)();
28 void (*OnLongPress)();
29 // Properties
30 uint8_t getCount() const { return _pressCount; }
31 uint8_t getLongCount() const { return _longCount; }
33 Button() :
34 _lastCheck(0), _lastFallingEdge(0), _state(STATE_IDLE),
35 _isLongPress(false), _longCount(0), _pressCount(0)
39 void init(uint8_t pin, bool idlelow = false)
41 _pin = pin;
42 _idlelow = idlelow,
43 pinMode(_pin, _idlelow ? INPUT : INPUT_PULLUP);
46 // Call this in loop()
47 int update()
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)
53 _pressCount = 0;
55 _state = (_state << 1) & 0b110;
56 _state |= digitalRead(_pin) ^ _idlelow;
58 // If rising edge (release)
59 if (_state == STATE_RISE)
61 if (!_isLongPress)
63 DBGVLN("Button short");
64 ++_pressCount;
65 if (OnShortPress)
66 OnShortPress();
68 _isLongPress = false;
70 // Two low in a row
71 else if (_state == STATE_FALL)
73 _lastFallingEdge = now;
74 _longCount = 0;
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);
82 _isLongPress = true;
83 if (OnLongPress)
84 OnLongPress();
85 // Reset time so long can fire again
86 _lastFallingEdge = now;
87 _longCount++;
90 return MS_DEBOUNCE;