M5Unit-KEYBOARD 0.1.0 git rev:b58d024
Loading...
Searching...
No Matches
button_event_detector.hpp
Go to the documentation of this file.
1/*
2 * SPDX-FileCopyrightText: 2026 M5Stack Technology CO LTD
3 *
4 * SPDX-License-Identifier: MIT
5 */
12#ifndef M5_UNIT_KEYBOARD_UTILITY_BUTTON_EVENT_DETECTOR_HPP
13#define M5_UNIT_KEYBOARD_UTILITY_BUTTON_EVENT_DETECTOR_HPP
14
15#include <cstdint>
16
17namespace m5 {
18namespace unit {
19namespace keyboard_bitwise {
20
22enum class ButtonEvent : uint8_t {
23 None,
24 PressDown,
25 PressUp,
26 SingleClick,
27 DoubleClick,
28 LongPressStart,
29 LongPressUp,
30};
31
39public:
40 struct config_t {
41 uint32_t short_press_ms{200};
42 uint32_t long_press_ms{400};
43 };
44
45 ButtonEventDetector() : _cfg()
46 {
47 }
48
49 explicit ButtonEventDetector(const config_t& cfg) : _cfg(cfg)
50 {
51 }
52
53 inline void reset()
54 {
55 _state = State::Idle;
56 _repeat = 0;
57 _t0 = 0U;
58 }
59
63 ButtonEvent edge(const bool pressed, const uint32_t now_ms)
64 {
65 switch (_state) {
66 case State::Idle:
67 if (pressed) {
68 _repeat = 1;
69 _t0 = now_ms;
70 _state = State::Down;
71 return ButtonEvent::PressDown;
72 }
73 return ButtonEvent::None;
74
75 case State::Down:
76 if (!pressed) {
77 _t0 = now_ms;
78 _state = State::WaitRepeat;
79 return ButtonEvent::PressUp;
80 }
81 return ButtonEvent::None; // hardware repeat — ignore
82
83 case State::WaitRepeat:
84 if (pressed) {
85 ++_repeat;
86 _t0 = now_ms;
87 _state = State::RepeatDown;
88 return ButtonEvent::PressDown;
89 }
90 return ButtonEvent::None;
91
92 case State::RepeatDown:
93 if (!pressed) {
94 _t0 = now_ms;
95 _state = State::WaitRepeat;
96 return ButtonEvent::PressUp;
97 }
98 return ButtonEvent::None;
99
100 case State::LongHold:
101 if (!pressed) {
102 _state = State::Idle;
103 return ButtonEvent::LongPressUp;
104 }
105 return ButtonEvent::None;
106 }
107 return ButtonEvent::None;
108 }
109
112 ButtonEvent poll(const uint32_t now_ms)
113 {
114 switch (_state) {
115 case State::Down:
116 if (now_ms - _t0 >= _cfg.long_press_ms) {
117 _state = State::LongHold;
118 return ButtonEvent::LongPressStart;
119 }
120 return ButtonEvent::None;
121
122 case State::WaitRepeat:
123 if (now_ms - _t0 > _cfg.short_press_ms) {
124 const uint8_t repeat = _repeat;
125 _repeat = 0;
126 _state = State::Idle;
127 if (repeat == 1) return ButtonEvent::SingleClick;
128 if (repeat == 2) return ButtonEvent::DoubleClick;
129 return ButtonEvent::None;
130 }
131 return ButtonEvent::None;
132
133 default:
134 return ButtonEvent::None;
135 }
136 }
137
138private:
139 enum class State : uint8_t { Idle, Down, WaitRepeat, RepeatDown, LongHold };
140
141 config_t _cfg{};
142 State _state{State::Idle};
143 uint8_t _repeat{0};
144 uint32_t _t0{0};
145};
147
148} // namespace keyboard_bitwise
149} // namespace unit
150} // namespace m5
151
152#endif
ButtonEvent
Semantic button events (subset of iot_button needed for CardKB2 modifiers)
Definition button_event_detector.hpp:22
Per-key click/long-press recognizer mirroring iot_button v4.1.4 timing.
Top level namespace of M5Stack.
Unit-related namespace.