AceButton 1.10.0 An adjustable, compact, event-driven button library for Arduino.

AceButton.cpp
1 /*
2 MIT License
3
4 Copyright (c) 2018 Brian T. Park
5
6 Permission is hereby granted, free of charge, to any person obtaining a copy
7 of this software and associated documentation files (the "Software"), to deal
8 in the Software without restriction, including without limitation the rights
9 to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
10 copies of the Software, and to permit persons to whom the Software is
11 furnished to do so, subject to the following conditions:
12
13 The above copyright notice and this permission notice shall be included in all
14 copies or substantial portions of the Software.
15
16 THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
17 IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
18 FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
19 AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
20 LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
21 OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
22 SOFTWARE.
23 */
24
25 #include "AceButton.h"
26
27 namespace ace_button {
28
29 //-----------------------------------------------------------------------------
30
31 // Macros to perform compile-time assertions. See
32 // https://www.embedded.com/electronics-blogs/programming-pointers/4025549/Catching-errors-early-with-compile-time-assertions
33 // and https://gcc.gnu.org/onlinedocs/gcc/Common-Function-Attributes.html
34 #define CONCAT_(x, y) x##y
35 #define CONCAT(x,y) CONCAT_(x,y)
36 #define COMPILE_TIME_ASSERT(cond, msg) \
37 extern char CONCAT(compile_time_assert, __LINE__)[(cond) ? 1 : -1];
38
39 // Check that the Arduino constants HIGH and LOW are defined to be 1 and 0,
40 // respectively. Otherwise, this library won't work.
41 COMPILE_TIME_ASSERT(HIGH == 1, "HIGH must be 1")
42 COMPILE_TIME_ASSERT(LOW == 0, "LOW must be 0")
43
44 // On boards using the new PinStatus API, check that kButtonStateUnknown is
45 // different from all other PinStatus enums.
46 #if ARDUINO_API_VERSION >= 10000
47 COMPILE_TIME_ASSERT(\
48 AceButton::kButtonStateUnknown != LOW \
49 && AceButton::kButtonStateUnknown != HIGH \
50 && AceButton::kButtonStateUnknown != CHANGE \
51 && AceButton::kButtonStateUnknown != FALLING \
52 && AceButton::kButtonStateUnknown != RISING, \
53 "kButtonStateUnknown conflicts with PinStatus enum")
54 #endif
55
56 //-----------------------------------------------------------------------------
57
58 static const char sEventPressed[] PROGMEM = "Pressed";
59 static const char sEventReleased[] PROGMEM = "Released";
60 static const char sEventClicked[] PROGMEM = "Clicked";
61 static const char sEventDoubleClicked[] PROGMEM = "DoubleClicked";
62 static const char sEventLongPressed[] PROGMEM = "LongPressed";
63 static const char sEventRepeatPressed[] PROGMEM = "RepeatPressed";
64 static const char sEventLongReleased[] PROGMEM = "LongReleased";
65 static const char sEventHeartBeat[] PROGMEM = "HeartBeat";
66 static const char sEventUnknown[] PROGMEM = "(unknown)";
67
68 static const char* const sEventNames[] PROGMEM = {
69 sEventPressed,
70 sEventReleased,
71 sEventClicked,
72 sEventDoubleClicked,
73 sEventLongPressed,
74 sEventRepeatPressed,
75 sEventLongReleased,
76 sEventHeartBeat,
77 };
78
79 __FlashStringHelper* AceButton::eventName(uint8_t event) {
80 const char* name = (event >= sizeof(sEventNames) / sizeof(const char*))
81 ? sEventUnknown
82 : (const char*) pgm_read_ptr(sEventNames + event);
83 return (__FlashStringHelper*) name;
84 }
85
86 //-----------------------------------------------------------------------------
87
88 void AceButton::init(uint8_t pin, uint8_t defaultReleasedState, uint8_t id) {
89 mPin = pin;
90 mId = id;
91 mFlags = 0;
92 mLastButtonState = kButtonStateUnknown;
93 setDefaultReleasedState(defaultReleasedState);
94 }
95
96 void AceButton::init(ButtonConfig* buttonConfig, uint8_t pin,
97 uint8_t defaultReleasedState, uint8_t id) {
98 mButtonConfig = buttonConfig;
99 init(pin, defaultReleasedState, id);
100 }
101
102 void AceButton::setDefaultReleasedState(uint8_t state) {
103 if (state == HIGH) {
104 mFlags |= kFlagDefaultReleasedState;
105 } else {
106 mFlags &= ~kFlagDefaultReleasedState;
107 }
108 }
109
110 uint8_t AceButton::getDefaultReleasedState() const {
111 return (mFlags & kFlagDefaultReleasedState) ? HIGH : LOW;
112 }
113
114 // NOTE: It would be interesting to rewrite the check() method using a Finite
115 // State Machine.
116 void AceButton::check() {
117 uint8_t buttonState = mButtonConfig->readButton(mPin);
118 checkState(buttonState);
119 }
120
121 void AceButton::checkState(uint8_t buttonState) {
122 // Retrieve the current time just once and use that in the various checkXxx()
123 // functions below. This provides some robustness of the various timing
124 // algorithms even if one of the event handlers takes more time than the
125 // threshold time limits such as 'debounceDelay' or longPressDelay'.
126 uint16_t now = mButtonConfig->getClock();
127
128 // Send heart beat if enabled and needed. Purposely placed outside of the
129 // checkDebounced() guard so that it can fire regardless of the state of the
130 // debouncing logic.
131 checkHeartBeat(now);
132
133 // Debounce the button, and send any events detected.
134 if (checkDebounced(now, buttonState)) {
135 // check if the button was initialized (i.e. UNKNOWN state)
136 if (checkInitialized(buttonState)) {
137 checkEvent(now, buttonState);
138 }
139 }
140 }
141
142 void AceButton::checkEvent(uint16_t now, uint8_t buttonState) {
143 // We need to remove orphaned clicks even if just Click is enabled. It is not
144 // sufficient to do this for just DoubleClick. That's because it's possible
145 // for a Clicked event to be generated, then 65.536 seconds later, the
146 // ButtonConfig could be changed to enable DoubleClick. (Such real-time change
147 // of ButtonConfig is not recommended, but is sometimes convenient.) If the
148 // orphaned click is not cleared, then the next Click would be errorneously
149 // considered to be a DoubleClick. Therefore, we must clear the orphaned click
150 // even if just the Clicked event is enabled.
151 //
152 // We also need to check of any postponed clicks that got generated when
153 // kFeatureSuppressClickBeforeDoubleClick was enabled.
154 if (mButtonConfig->isFeature(ButtonConfig::kFeatureClick) ||
155 mButtonConfig->isFeature(ButtonConfig::kFeatureDoubleClick)) {
156 checkPostponedClick(now);
157 checkOrphanedClick(now);
158 }
159
160 if (mButtonConfig->isFeature(ButtonConfig::kFeatureLongPress)) {
161 checkLongPress(now, buttonState);
162 }
163 if (mButtonConfig->isFeature(ButtonConfig::kFeatureRepeatPress)) {
164 checkRepeatPress(now, buttonState);
165 }
166 if (buttonState != getLastButtonState()) {
167 checkChanged(now, buttonState);
168 }
169 }
170
171 bool AceButton::checkDebounced(uint16_t now, uint8_t buttonState) {
172 if (isFlag(kFlagDebouncing)) {
173
174 // NOTE: This is a bit tricky. The elapsedTime will be valid even if the
175 // uint16_t representation of 'now' rolls over so that (now <
176 // mLastDebounceTime). This is true as long as the 'unsigned long'
177 // representation of 'now' is < (65536 + mLastDebounceTime). We need to cast
178 // this expression into an uint16_t before doing the '>=' comparison below
179 // for compatability with processors whose sizeof(int) == 4 instead of 2.
180 // For those processors, the expression (now - mLastDebounceTime >=
181 // getDebounceDelay()) won't work because the terms in the expression get
182 // promoted to an (int).
183 uint16_t elapsedTime = now - mLastDebounceTime;
184
185 bool isDebouncingTimeOver =
186 (elapsedTime >= mButtonConfig->getDebounceDelay());
187
188 if (isDebouncingTimeOver) {
189 clearFlag(kFlagDebouncing);
190 return true;
191 } else {
192 return false;
193 }
194 } else {
195 // Currently not in debouncing phase. Check for a button state change. This
196 // will also detect a transition from kButtonStateUnknown to HIGH or LOW.
197 if (buttonState == getLastButtonState()) {
198 // no change, return immediately
199 return true;
200 }
201
202 // button has changed so, enter debouncing phase
203 setFlag(kFlagDebouncing);
204 mLastDebounceTime = now;
205 return false;
206 }
207 }
208
209 bool AceButton::checkInitialized(uint16_t buttonState) {
210 if (mLastButtonState != kButtonStateUnknown) {
211 return true;
212 }
213
214 // If transitioning from the initial "unknown" button state, just set the last
215 // valid button state, but don't fire off the event handler. This handles the
216 // case where a momentary switch is pressed down, then the board is rebooted.
217 // When the board comes up, it should not fire off the event handler. This
218 // also handles the case of a 2-position switch set to the "pressed"
219 // position, and the board is rebooted.
220 mLastButtonState = buttonState;
221 return false;
222 }
223
224 void AceButton::checkLongPress(uint16_t now, uint8_t buttonState) {
225 if (buttonState == getDefaultReleasedState()) {
226 return;
227 }
228
229 if (isFlag(kFlagPressed) && !isFlag(kFlagLongPressed)) {
230 uint16_t elapsedTime = now - mLastPressTime;
231 if (elapsedTime >= mButtonConfig->getLongPressDelay()) {
232 setFlag(kFlagLongPressed);
233 handleEvent(kEventLongPressed);
234 }
235 }
236 }
237
238 void AceButton::checkRepeatPress(uint16_t now, uint8_t buttonState) {
239 if (buttonState == getDefaultReleasedState()) {
240 return;
241 }
242
243 if (isFlag(kFlagPressed)) {
244 if (isFlag(kFlagRepeatPressed)) {
245 uint16_t elapsedTime = now - mLastRepeatPressTime;
246 if (elapsedTime >= mButtonConfig->getRepeatPressInterval()) {
247 handleEvent(kEventRepeatPressed);
248 mLastRepeatPressTime = now;
249 }
250 } else {
251 uint16_t elapsedTime = now - mLastPressTime;
252 if (elapsedTime >= mButtonConfig->getRepeatPressDelay()) {
253 setFlag(kFlagRepeatPressed);
254 // Trigger the RepeatPressed immedidately, instead of waiting until the
255 // first getRepeatPressInterval() has passed.
256 handleEvent(kEventRepeatPressed);
257 mLastRepeatPressTime = now;
258 }
259 }
260 }
261 }
262
263 void AceButton::checkChanged(uint16_t now, uint8_t buttonState) {
264 mLastButtonState = buttonState;
265 checkPressed(now, buttonState);
266 checkReleased(now, buttonState);
267 }
268
269 void AceButton::checkPressed(uint16_t now, uint8_t buttonState) {
270 if (buttonState == getDefaultReleasedState()) {
271 return;
272 }
273
274 // button was pressed
275 mLastPressTime = now;
276 setFlag(kFlagPressed);
277 handleEvent(kEventPressed);
278 }
279
280 void AceButton::checkReleased(uint16_t now, uint8_t buttonState) {
281 if (buttonState != getDefaultReleasedState()) {
282 return;
283 }
284
285 // Check for click (before sending off the Released event).
286 // Make sure that we don't clearPressed() before calling this.
287 if (mButtonConfig->isFeature(ButtonConfig::kFeatureClick)
288 || mButtonConfig->isFeature(ButtonConfig::kFeatureDoubleClick)) {
289 checkClicked(now);
290 }
291
292 // Save whether this was generated from a long press.
293 bool wasLongPressed = isFlag(kFlagLongPressed);
294
295 // Check if Released events are suppressed.
296 bool suppress =
297 ((isFlag(kFlagLongPressed) &&
298 mButtonConfig->
299 isFeature(ButtonConfig::kFeatureSuppressAfterLongPress)) ||
300 (isFlag(kFlagRepeatPressed) &&
301 mButtonConfig->
302 isFeature(ButtonConfig::kFeatureSuppressAfterRepeatPress)) ||
303 (isFlag(kFlagClicked) &&
304 mButtonConfig->isFeature(ButtonConfig::kFeatureSuppressAfterClick)) ||
305 (isFlag(kFlagDoubleClicked) &&
306 mButtonConfig->
307 isFeature(ButtonConfig::kFeatureSuppressAfterDoubleClick)));
308
309 // Button was released, so clear current flags. Note that the compiler will
310 // optimize the following 4 statements to be equivalent to this single one:
311 // mFlags &= ~kFlagPressed & ~kFlagDoubleClicked & ~kFlagLongPressed
312 // & ~kFlagRepeatPressed;
313 clearFlag(kFlagPressed);
314 clearFlag(kFlagDoubleClicked);
315 clearFlag(kFlagLongPressed);
316 clearFlag(kFlagRepeatPressed);
317
318 // Fire off a Released event, unless suppressed. Replace Released with
319 // LongReleased if this was a LongPressed.
320 if (suppress) {
321 if (wasLongPressed) {
322 handleEvent(kEventLongReleased);
323 }
324 } else {
325 handleEvent(kEventReleased);
326 }
327 }
328
329 void AceButton::checkClicked(uint16_t now) {
330 if (!isFlag(kFlagPressed)) {
331 // Not a Click unless the previous state was a Pressed state.
332 // This can happen if the chip was rebooted with the button Pressed. Upon
333 // Release, it shouldn't generated a click, even accidentally due to a
334 // spurious value in mLastPressTime.
335 clearFlag(kFlagClicked);
336 return;
337 }
338 uint16_t elapsedTime = now - mLastPressTime;
339 if (elapsedTime >= mButtonConfig->getClickDelay()) {
340 clearFlag(kFlagClicked);
341 return;
342 }
343
344 // check for double click
345 if (mButtonConfig->isFeature(ButtonConfig::kFeatureDoubleClick)) {
346 checkDoubleClicked(now);
347 }
348
349 // Suppress a second click (both buttonState change and event message) if
350 // double-click detected, which has the side-effect of preventing 3 clicks
351 // from generating another double-click at the third click.
352 if (isFlag(kFlagDoubleClicked)) {
353 clearFlag(kFlagClicked);
354 return;
355 }
356
357 // we got a single click
358 mLastClickTime = now;
359 setFlag(kFlagClicked);
360 if (mButtonConfig->isFeature(
361 ButtonConfig::kFeatureSuppressClickBeforeDoubleClick)) {
362 setFlag(kFlagClickPostponed);
363 } else {
364 handleEvent(kEventClicked);
365 }
366 }
367
368 void AceButton::checkDoubleClicked(uint16_t now) {
369 if (!isFlag(kFlagClicked)) {
370 clearFlag(kFlagDoubleClicked);
371 return;
372 }
373
374 uint16_t elapsedTime = now - mLastClickTime;
375 if (elapsedTime >= mButtonConfig->getDoubleClickDelay()) {
376 clearFlag(kFlagDoubleClicked);
377 // There should be no postponed Click at this point because
378 // checkPostponedClick() should have taken care of it.
379 return;
380 }
381
382 // If there was a postponed click, suppress it because it could only have been
383 // postponed if kFeatureSuppressClickBeforeDoubleClick was enabled. If we got
384 // to this point, there was a DoubleClick, so we must suppress the first
385 // Click as requested.
386 if (isFlag(kFlagClickPostponed)) {
387 clearFlag(kFlagClickPostponed);
388 }
389 setFlag(kFlagDoubleClicked);
390 handleEvent(kEventDoubleClicked);
391 }
392
393 void AceButton::checkOrphanedClick(uint16_t now) {
394 // The amount of time which must pass before a click is determined to be
395 // orphaned and reclaimed. If only DoubleClicked is supported, then I think
396 // just getDoubleClickDelay() is correct. No other higher level event uses the
397 // first Clicked event. If TripleClicked becomes supported, I think
398 // orphanedClickDelay will be either (2 * getDoubleClickDelay()) or
399 // (getDoubleClickDelay() + getTripleClickDelay()), depending on whether the
400 // TripleClick has an independent delay time, or reuses the DoubleClick delay
401 // time. But I'm not sure that I've thought through all the details.
402 uint16_t orphanedClickDelay = mButtonConfig->getDoubleClickDelay();
403
404 uint16_t elapsedTime = now - mLastClickTime;
405 if (isFlag(kFlagClicked) && (elapsedTime >= orphanedClickDelay)) {
406 clearFlag(kFlagClicked);
407 }
408 }
409
410 void AceButton::checkPostponedClick(uint16_t now) {
411 uint16_t postponedClickDelay = mButtonConfig->getDoubleClickDelay();
412 uint16_t elapsedTime = now - mLastClickTime;
413 if (isFlag(kFlagClickPostponed) && elapsedTime >= postponedClickDelay) {
414 handleEvent(kEventClicked);
415 clearFlag(kFlagClickPostponed);
416 }
417 }
418
419 void AceButton::checkHeartBeat(uint16_t now) {
420 if (! mButtonConfig->isFeature(ButtonConfig::kFeatureHeartBeat)) return;
421
422 // On first call, set the last heart beat time.
423 if (! isFlag(kFlagHeartRunning)) {
424 setFlag(kFlagHeartRunning);
425 mLastHeartBeatTime = now;
426 return;
427 }
428
429 uint16_t elapsedTime = now - mLastHeartBeatTime;
430 if (elapsedTime >= mButtonConfig->getHeartBeatInterval()) {
431 // This causes the kEventHeartBeat to be sent with the last validated button
432 // state, not the current button state. I think that makes more sense, but
433 // there might be situations where it doesn't.
434 handleEvent(kEventHeartBeat);
435 mLastHeartBeatTime = now;
436 }
437 }
438
439 void AceButton::handleEvent(uint8_t eventType) {
440 mButtonConfig->dispatchEvent(this, eventType, getLastButtonState());
441 }
442
443 }
ace_button::AceButton::kEventDoubleClicked
static const uint8_t kEventDoubleClicked
Button was double-clicked.
Definition: AceButton.h:74
ace_button::AceButton::init
void init(uint8_t pin=0, uint8_t defaultReleasedState=HIGH, uint8_t id=0)
Reset the button to the initial constructed state.
Definition: AceButton.cpp:88
ace_button::AceButton::kEventClicked
static const uint8_t kEventClicked
Button was clicked (Pressed and Released within ButtonConfig::getClickDelay()).
Definition: AceButton.h:68
ace_button::AceButton::eventName
static __FlashStringHelper * eventName(uint8_t event)
Return the human-readable name of the event.
Definition: AceButton.cpp:79
ace_button::AceButton::checkState
void checkState(uint8_t buttonState)
Version of check() used by EncodedButtonConfig.
Definition: AceButton.cpp:121
ace_button::AceButton::getDefaultReleasedState
uint8_t getDefaultReleasedState() const
Get the initial released state of the button, HIGH or LOW.
Definition: AceButton.cpp:110
ace_button::AceButton::kEventLongPressed
static const uint8_t kEventLongPressed
Button was held down for longer than ButtonConfig::getLongPressDelay()).
Definition: AceButton.h:80
ace_button::AceButton::kEventRepeatPressed
static const uint8_t kEventRepeatPressed
Button was held down and auto generated multiple presses.
Definition: AceButton.h:88
ace_button::AceButton::kEventLongReleased
static const uint8_t kEventLongReleased
Button was released after a long press.
Definition: AceButton.h:99
ace_button::AceButton::getLastButtonState
uint8_t getLastButtonState() const
Return the button state that was last valid.
Definition: AceButton.h:292
ace_button::AceButton::kEventHeartBeat
static const uint8_t kEventHeartBeat
An event that fires every time interval defined by getHeartBeatInterval().
Definition: AceButton.h:111
ace_button::AceButton::kEventReleased
static const uint8_t kEventReleased
Button was released.
Definition: AceButton.h:62
ace_button::AceButton::kEventPressed
static const uint8_t kEventPressed
Button was pressed.
Definition: AceButton.h:59
ace_button::AceButton::check
void check()
Check state of button and trigger event processing.
Definition: AceButton.cpp:116
ace_button::AceButton::kButtonStateUnknown
static const uint8_t kButtonStateUnknown
Button state is unknown.
Definition: AceButton.h:119
ace_button::ButtonConfig
Class that defines the timing parameters and event handler of an AceButton or a group of AceButton in...
Definition: ButtonConfig.h:66
ace_button::ButtonConfig::getDoubleClickDelay
uint16_t getDoubleClickDelay() const
Milliseconds between the first and second click to register as a double-click.
Definition: ButtonConfig.h:231
ace_button::ButtonConfig::kFeatureSuppressAfterLongPress
static const FeatureFlagType kFeatureSuppressAfterLongPress
Flag to suppress kEventReleased after a kEventLongPressed.
Definition: ButtonConfig.h:139
ace_button::ButtonConfig::getDebounceDelay
uint16_t getDebounceDelay() const
Milliseconds to wait for debouncing.
Definition: ButtonConfig.h:222
ace_button::ButtonConfig::getClickDelay
uint16_t getClickDelay() const
Milliseconds to wait for a possible click.
Definition: ButtonConfig.h:225
ace_button::ButtonConfig::getLongPressDelay
uint16_t getLongPressDelay() const
Milliseconds for a long press event.
Definition: ButtonConfig.h:236
ace_button::ButtonConfig::getClock
virtual unsigned long getClock()
Return the milliseconds of the internal clock.
Definition: ButtonConfig.h:307
ace_button::ButtonConfig::kFeatureLongPress
static const FeatureFlagType kFeatureLongPress
Flag to activate the AceButton::kEventLongPress event.
Definition: ButtonConfig.h:123
ace_button::ButtonConfig::kFeatureSuppressAfterClick
static const FeatureFlagType kFeatureSuppressAfterClick
Flag to suppress kEventReleased after a kEventClicked.
Definition: ButtonConfig.h:129
ace_button::ButtonConfig::getRepeatPressInterval
uint16_t getRepeatPressInterval() const
Milliseconds between two successive RepeatPressed events.
Definition: ButtonConfig.h:251
ace_button::ButtonConfig::readButton
virtual int readButton(uint8_t pin)
Return the HIGH or LOW state of the button.
Definition: ButtonConfig.h:317
ace_button::ButtonConfig::kFeatureDoubleClick
static const FeatureFlagType kFeatureDoubleClick
Flag to activate the AceButton::kEventDoubleClicked event.
Definition: ButtonConfig.h:120
ace_button::ButtonConfig::kFeatureSuppressAfterRepeatPress
static const FeatureFlagType kFeatureSuppressAfterRepeatPress
Flag to suppress kEventReleased after a kEventRepeatPressed.
Definition: ButtonConfig.h:142
ace_button::ButtonConfig::kFeatureSuppressAfterDoubleClick
static const FeatureFlagType kFeatureSuppressAfterDoubleClick
Flag to suppress kEventReleased after a kEventDoubleClicked.
Definition: ButtonConfig.h:136
ace_button::ButtonConfig::kFeatureSuppressClickBeforeDoubleClick
static const FeatureFlagType kFeatureSuppressClickBeforeDoubleClick
Flag to suppress kEventClicked before a kEventDoubleClicked.
Definition: ButtonConfig.h:150
ace_button::ButtonConfig::dispatchEvent
void dispatchEvent(AceButton *button, uint8_t eventType, uint8_t buttonState) const
Dispatch the event to the handler.
Definition: ButtonConfig.h:370
ace_button::ButtonConfig::kFeatureClick
static const FeatureFlagType kFeatureClick
Flag to activate the AceButton::kEventClicked event.
Definition: ButtonConfig.h:113
ace_button::ButtonConfig::kFeatureRepeatPress
static const FeatureFlagType kFeatureRepeatPress
Flag to activate the AceButton::kEventRepeatPressed event.
Definition: ButtonConfig.h:126
ace_button::ButtonConfig::isFeature
bool isFeature(FeatureFlagType features) const
Check if the given features are enabled.
Definition: ButtonConfig.h:325
ace_button::ButtonConfig::getRepeatPressDelay
uint16_t getRepeatPressDelay() const
Milliseconds that a button needs to be Pressed down before the start of the sequence of RepeatPressed...
Definition: ButtonConfig.h:246
ace_button::ButtonConfig::kFeatureHeartBeat
static const FeatureFlagType kFeatureHeartBeat
Flag to enable periodic kEventHeartBeat.
Definition: ButtonConfig.h:153
ace_button::ButtonConfig::getHeartBeatInterval
uint16_t getHeartBeatInterval() const
Milliseconds between two successive HeartBeat events.
Definition: ButtonConfig.h:256