1
- // -----
2
- // OneButton.cpp - Library for detecting button clicks, doubleclicks and long press pattern on a single button.
3
- // This class is implemented for use with the Arduino environment.
4
- // Copyright (c) by Matthias Hertel, http://www.mathertel.de
5
- // This work is licensed under a BSD style license. See http://www.mathertel.de/License.aspx
6
- // More information on: http://www.mathertel.de/Arduino
7
- // -----
8
- // Changelog: see OneButton.h
9
- // -----
1
+ /* *
2
+ * @file OneButton.cpp
3
+ *
4
+ * @brief Library for detecting button clicks, doubleclicks and long press
5
+ * pattern on a single button.
6
+ *
7
+ * @author Matthias Hertel, https://www.mathertel.de
8
+ * @Copyright Copyright (c) by Matthias Hertel, https://www.mathertel.de.
9
+ *
10
+ * This work is licensed under a BSD style license. See
11
+ * http://www.mathertel.de/License.aspx
12
+ *
13
+ * More information on: https://www.mathertel.de/Arduino/OneButtonLibrary.aspx
14
+ *
15
+ * Changelog: see OneButton.h
16
+ */
10
17
11
18
#include " OneButton.h"
12
19
13
20
// ----- Initialization and Default Values -----
14
21
22
+ /* *
23
+ * @brief Construct a new OneButton object but not (yet) initialize the IO pin.
24
+ */
25
+ OneButton::OneButton ()
26
+ {
27
+ _pin = -1 ;
28
+ // further initialization has moved to OneButton.h
29
+ }
30
+
15
31
OneButton::OneButton (int pin, int activeLow, bool pullupActive)
16
32
{
33
+ // OneButton();
17
34
_pin = pin;
18
35
19
- _debounceTicks = 50 ; // number of millisec that have to pass by before a click is assumed as safe.
20
- _clickTicks = 600 ; // number of millisec that have to pass by before a click is detected.
21
- _pressTicks = 1000 ; // number of millisec that have to pass by before a long button press is detected.
22
-
23
- _state = 0 ; // starting with state 0: waiting for button to be pressed
24
- _isLongPressed = false ; // Keep track of long press state
25
-
26
36
if (activeLow) {
27
37
// the button connects the input pin to GND when pressed.
28
- _buttonReleased = HIGH; // notPressed
29
38
_buttonPressed = LOW;
30
39
31
- // use the given pin as input and activate internal PULLUP resistor.
32
- if (pullupActive)
33
- pinMode ( pin, INPUT_PULLUP );
34
- else
35
- pinMode ( pin, INPUT );
36
-
37
40
} else {
38
41
// the button connects the input pin to VCC when pressed.
39
- _buttonReleased = LOW;
40
42
_buttonPressed = HIGH;
43
+ } // if
41
44
45
+ if (pullupActive) {
46
+ // use the given pin as input and activate internal PULLUP resistor.
47
+ pinMode (pin, INPUT_PULLUP);
48
+ } else {
42
49
// use the given pin as input
43
50
pinMode (pin, INPUT);
44
51
} // if
45
-
46
- // no functions attached yet: clear all function pointers.
47
- _clickFunc = NULL ;
48
- _doubleClickFunc = NULL ;
49
- _pressFunc = NULL ;
50
- _longPressStartFunc = NULL ;
51
- _longPressStopFunc = NULL ;
52
- _duringLongPressFunc = NULL ;
53
52
} // OneButton
54
53
55
54
56
- // explicitly set the number of millisec that have to pass by before a click is assumed as safe.
57
- void OneButton::setDebounceTicks (int ticks) {
55
+ // explicitly set the number of millisec that have to pass by before a click is
56
+ // assumed as safe.
57
+ void OneButton::setDebounceTicks (int ticks)
58
+ {
58
59
_debounceTicks = ticks;
59
60
} // setDebounceTicks
60
61
61
- // explicitly set the number of millisec that have to pass by before a click is detected.
62
- void OneButton::setClickTicks (int ticks) {
62
+ // explicitly set the number of millisec that have to pass by before a click is
63
+ // detected.
64
+ void OneButton::setClickTicks (int ticks)
65
+ {
63
66
_clickTicks = ticks;
64
67
} // setClickTicks
65
68
66
69
67
- // explicitly set the number of millisec that have to pass by before a long button press is detected.
68
- void OneButton::setPressTicks (int ticks) {
70
+ // explicitly set the number of millisec that have to pass by before a long
71
+ // button press is detected.
72
+ void OneButton::setPressTicks (int ticks)
73
+ {
69
74
_pressTicks = ticks;
70
75
} // setPressTicks
71
76
@@ -85,7 +90,8 @@ void OneButton::attachDoubleClick(callbackFunction newFunction)
85
90
86
91
87
92
// save function for press event
88
- // DEPRECATED, is replaced by attachLongPressStart, attachLongPressStop, attachDuringLongPress,
93
+ // DEPRECATED, is replaced by attachLongPressStart, attachLongPressStop,
94
+ // attachDuringLongPress,
89
95
void OneButton::attachPress (callbackFunction newFunction)
90
96
{
91
97
_pressFunc = newFunction;
@@ -125,73 +131,101 @@ void OneButton::reset(void){
125
131
_isLongPressed = false ;
126
132
}
127
133
134
+
135
+ /* *
136
+ * @brief Check input of the configured pin and then advance the finite state
137
+ * machine (FSM).
138
+ */
128
139
void OneButton::tick (void )
129
140
{
130
- // Detect the input information
131
- int buttonLevel = digitalRead (_pin); // current button signal.
141
+ if (_pin >= 0 ) {
142
+ tick (digitalRead (_pin) == _buttonPressed);
143
+ }
144
+ }
145
+
146
+
147
+ /* *
148
+ * @brief Advance the finite state machine (FSM) using the given level.
149
+ */
150
+ void OneButton::tick (bool activeLevel)
151
+ {
132
152
unsigned long now = millis (); // current (relative) time in msecs.
133
153
134
154
// Implementation of the state machine
155
+
135
156
if (_state == 0 ) { // waiting for menu pin being pressed.
136
- if (buttonLevel == _buttonPressed ) {
157
+ if (activeLevel ) {
137
158
_state = 1 ; // step to state 1
138
159
_startTime = now; // remember starting time
139
160
} // if
140
161
141
162
} else if (_state == 1 ) { // waiting for menu pin being released.
142
163
143
- if ((buttonLevel == _buttonReleased) && ((unsigned long )(now - _startTime) < _debounceTicks)) {
164
+ if ((!activeLevel) &&
165
+ ((unsigned long )(now - _startTime) < _debounceTicks)) {
144
166
// button was released to quickly so I assume some debouncing.
145
- // go back to state 0 without calling a function.
167
+ // go back to state 0 without calling a function.
146
168
_state = 0 ;
147
169
148
- } else if (buttonLevel == _buttonReleased ) {
170
+ } else if (!activeLevel ) {
149
171
_state = 2 ; // step to state 2
150
172
_stopTime = now; // remember stopping time
151
173
152
- } else if ((buttonLevel == _buttonPressed) && ((unsigned long )(now - _startTime) > _pressTicks)) {
153
- _isLongPressed = true ; // Keep track of long press state
154
- if (_pressFunc) _pressFunc ();
155
- if (_longPressStartFunc) _longPressStartFunc ();
156
- if (_duringLongPressFunc) _duringLongPressFunc ();
174
+ } else if ((activeLevel) &&
175
+ ((unsigned long )(now - _startTime) > _pressTicks)) {
176
+ _isLongPressed = true ; // Keep track of long press state
177
+ if (_pressFunc)
178
+ _pressFunc ();
179
+ if (_longPressStartFunc)
180
+ _longPressStartFunc ();
181
+ if (_duringLongPressFunc)
182
+ _duringLongPressFunc ();
157
183
_state = 6 ; // step to state 6
158
184
_stopTime = now; // remember stopping time
159
185
} else {
160
186
// wait. Stay in this state.
161
187
} // if
162
188
163
- } else if (_state == 2 ) { // waiting for menu pin being pressed the second time or timeout.
164
- if (_doubleClickFunc == NULL || (unsigned long )(now - _startTime) > _clickTicks) {
189
+ } else if (_state == 2 ) {
190
+ // waiting for menu pin being pressed the second time or timeout.
191
+ if (_doubleClickFunc == NULL ||
192
+ (unsigned long )(now - _startTime) > _clickTicks) {
165
193
// this was only a single short click
166
- if (_clickFunc) _clickFunc ();
194
+ if (_clickFunc)
195
+ _clickFunc ();
167
196
_state = 0 ; // restart.
168
197
169
- } else if ((buttonLevel == _buttonPressed) && ((unsigned long )(now - _stopTime) > _debounceTicks)) {
198
+ } else if ((activeLevel) &&
199
+ ((unsigned long )(now - _stopTime) > _debounceTicks)) {
170
200
_state = 3 ; // step to state 3
171
201
_startTime = now; // remember starting time
172
202
} // if
173
203
174
204
} else if (_state == 3 ) { // waiting for menu pin being released finally.
175
- // Stay here for at least _debounceTicks because else we might end up in state 1 if the
176
- // button bounces for too long.
177
- if (buttonLevel == _buttonReleased && ((unsigned long )(now - _startTime) > _debounceTicks)) {
205
+ // Stay here for at least _debounceTicks because else we might end up in
206
+ // state 1 if the button bounces for too long.
207
+ if ((!activeLevel) &&
208
+ ((unsigned long )(now - _startTime) > _debounceTicks)) {
178
209
// this was a 2 click sequence.
179
- if (_doubleClickFunc) _doubleClickFunc ();
210
+ if (_doubleClickFunc)
211
+ _doubleClickFunc ();
180
212
_state = 0 ; // restart.
181
213
_stopTime = now; // remember stopping time
182
-
183
214
} // if
184
215
185
- } else if (_state == 6 ) { // waiting for menu pin being release after long press.
186
- if (buttonLevel == _buttonReleased) {
187
- _isLongPressed = false ; // Keep track of long press state
188
- if (_longPressStopFunc) _longPressStopFunc ();
216
+ } else if (_state == 6 ) {
217
+ // waiting for menu pin being release after long press.
218
+ if (!activeLevel) {
219
+ _isLongPressed = false ; // Keep track of long press state
220
+ if (_longPressStopFunc)
221
+ _longPressStopFunc ();
189
222
_state = 0 ; // restart.
190
223
_stopTime = now; // remember stopping time
191
224
} else {
192
- // button is being long pressed
193
- _isLongPressed = true ; // Keep track of long press state
194
- if (_duringLongPressFunc) _duringLongPressFunc ();
225
+ // button is being long pressed
226
+ _isLongPressed = true ; // Keep track of long press state
227
+ if (_duringLongPressFunc)
228
+ _duringLongPressFunc ();
195
229
} // if
196
230
197
231
} // if
0 commit comments