AbleButtons V0.4.0
Lightweight button library for Arduino.
 
Loading...
Searching...
No Matches
Pins.h
Go to the documentation of this file.
1/**
2 * @file Pins.h Definition of the Pin class and subclasses (DebouncedPin,
3 * ClickerPin), providing debounce logic when reading from an Arduino pin. Each
4 * sub-class adds features for the pin (e.g. remembering clicks).
5 *
6 * @copyright Copyright (c) 2022 John Scott.
7 */
8#pragma once
9#include <Arduino.h>
10
11namespace able {
12 /**
13 * Pin base class reading direct from the pin (without debouncing). Other pins
14 * inherit directly/indirectly from this base class. This class cannot be
15 * instantiated directly. Instantiation comes through Button sub-classes.
16 */
17 class Pin {
18 protected:
19 //
20 // Static Members...
21 //
22
23 /**
24 * Return the next auto-assigned button identifier.
25 *
26 * @return The next auto-assigned button identifier. Each call increases the
27 * auto-assigned identifier.
28 */
29 inline static uint8_t nextId() {
30 return ++autoId_;
31 }
32
33 protected:
34 //
35 // Creators...
36 //
37
38 /**
39 * Protected constructor used by sub-classes. Use a Button sub-class
40 * instead of this class directly.
41 *
42 * @param pin The pin to read from.
43 * @param initState The initial (un-pushed) state of the button.
44 */
45 inline Pin(uint8_t pin, uint8_t initState)
46 :pin_(pin), currState_(initState) {}
47
48 private:
49 //
50 // Copy and assignment (not supported)...
51 //
52 Pin(const Pin &) = delete; ///< Copying pins is not supported.
53 Pin &operator=(const Pin &) = delete; ///< Assigning pins not supported.
54
55 protected:
56 //
57 // Modifiers...
58 //
59
60 /**
61 * Read the pin directly. In order to save memory, virtual functions are
62 * *not* used (which can consume almost 1K of memory to deal with).
63 * Runtime polymorphism is not required, so avoiding virtual functions
64 * saves memory.
65 */
66 inline void readPin() {
67 currState_ = digitalRead(pin_);
68 }
69
70 protected:
71 //
72 // Accessors...
73 //
74
75 /**
76 * Return the number of clicks.
77 *
78 * @param pressed The pressed state of a button.
79 * @param released The released state of a button.
80 *
81 * @returns Always no clicks (0) as clicks not supported by default.
82 */
83 inline int clicks(uint8_t pressed, uint8_t released) {
84 return 0;
85 }
86
87 protected:
88 //
89 // Data...
90 //
91 static uint8_t autoId_; ///< Auto-assigned button identifier.
92
93 uint8_t pin_; ///< The Arduino pin connected to the button.
94 uint8_t currState_; ///< The reading of the pin.
95 };
96
97 /**
98 * Debouned Pin class. Manages making reliable readings from an input pin.
99 * The readPin() method manages debouncing the pin readings. You cannot use
100 * this class directly. Use one of the Button sub-classes instead.
101 */
102 class DebouncedPin: public Pin {
103 public:
104 //
105 // Static Members...
106 //
107
108 /**
109 * Set the debounce time for input pins. Pins may read noise as buttons
110 * are pressed and released. This noise can be registered as multiple
111 * button presses in a short time period, confusing your program. The
112 * debounce time is the number of milliseconds to wait when a reading
113 * changes before using that reading. See https://docs.arduino.cc/built-in-examples/digital/Debounce
114 * for details on debounce.
115 *
116 * @param debounceTime The number of milliseconds before a button state
117 * change is returned (default 50ms, max 255ms).
118 */
119 inline static void setDebounceTime(uint8_t debounceTime) {
121 };
122
123 /**
124 * Set the held time for input pins. If a button is pressed for longer
125 * than this time, it will be held.
126 *
127 * @param heldTime The number of milliseconds for a held state (default 1s).
128 */
129 inline static void setHeldTime(uint16_t heldTime) {
131 }
132
133 /**
134 * Set the idle time for input pins. If a button is unpressed for longer
135 * than this time, it will be idle.
136 *
137 * @param idleTime The number of milliseconds for an idle state (default 60s).
138 */
139 inline static void setIdleTime(uint32_t idleTime) {
141 }
142
143 protected:
144 //
145 // Creators...
146 //
147
148 /**
149 * Protected constructor used by sub-classes. Use a sub-class of this
150 * class instead of this class directly.
151 *
152 * @param pin The pin to read from.
153 * @param initState The initial (un-pushed) state of the button.
154 */
155 DebouncedPin(uint8_t pin, uint8_t initState)
156 :Pin(pin, initState), prevReading_(initState) {}
157
158 private:
159 //
160 // Copying and assignment (not supported)...
161 //
162 DebouncedPin(const DebouncedPin &) = delete; ///< Copying pins is not supported.
163 DebouncedPin &operator=(const DebouncedPin &) = delete; ///< Assigning pins not supported.
164
165 protected:
166 //
167 // Modifiers...
168 //
169
170 /**
171 * Debounce the pin readings to get a stable state of the pin. In order to
172 * save memory, virtual functions are *not* used (which can consume almost
173 * 1K of memory to deal with). Runtime polymorphism is not required, so
174 * avoiding virtual functions saves memory.
175 */
176 inline void readPin() {
177 byte currReading = digitalRead(pin_);
178
179 // New reading, so start the debounce timer.
180 if (currReading != prevReading_) {
181 millisStart_ = millis();
182 } else if ((millis() - millisStart_) >= debounceTime_) {
183 // Use reading if we have the same reading for >= DELAY ms.
184 currState_ = currReading;
185 }
186
187 prevReading_ = currReading;
188 }
189
190 public:
191 //
192 // Accessors...
193 //
194
195 /**
196 * Return the pin debounce time.
197 *
198 * @returns The number of milliseconds of debounce time.
199 */
200 static inline uint8_t debounceTime() {
201 return debounceTime_;
202 }
203
204 /**
205 * Return the pin held time.
206 *
207 * @returns The number of milliseconds after which a pin is held.
208 */
209 static inline uint16_t heldTime() {
210 return heldTime_;
211 }
212
213 /**
214 * Return the pin idle time.
215 *
216 * @returns The number of milliseconds after which a pin is idle.
217 */
218 static inline uint32_t idleTime() {
219 return idleTime_;
220 }
221
222 protected:
223 //
224 // Data...
225 //
226 static uint8_t debounceTime_; ///< Time required to debounce all input pins.
227 static uint16_t heldTime_; ///< Time required for button to be held.
228 static uint32_t idleTime_; ///< Time required for button to be idle.
229
230 uint8_t prevReading_; ///< The previous pin reading, to monitor state transitions.
231 unsigned long millisStart_; ///< Debounce start timer to handle button transition.
232 };
233
234 /**
235 * Debounced pin class that remembers the previous debounced state. This
236 * allows clicks (a combination of press then release) to be identified.
237 * This class extends the basic DebouncedPin class to add the previous state.
238 */
239 class ClickerPin: public DebouncedPin {
240 protected:
241 //
242 // Creators...
243 //
244
245 /**
246 * Protected constructor used by sub-classes. Use a Button sub-class of
247 * this class instead of this class directly.
248 *
249 * @param pin The pin to read from.
250 * @param initState The initial (un-pushed) state of the button.
251 */
252 ClickerPin(uint8_t pin, uint8_t initState)
253 :DebouncedPin(pin, initState), prevState_(initState) {}
254
255 private:
256 //
257 // Copying and assignment (not supported)...
258 //
259 ClickerPin(const ClickerPin &cpy) = delete; ///< Copying pins is not supported.
260 ClickerPin &operator=(const ClickerPin &) = delete; ///< Assigning pins is not supported.
261
262 protected:
263 //
264 // Modifiers...
265 //
266
267 /**
268 * Debounce the pin readings to get a stable state of the pin. When the
269 * state changes, remember the previous state so clicks (press then
270 * release can be identified). Calls DebouncedPin::readPin() and monitors
271 * for a change in debounced state, remembering the previous state.
272 */
273 inline void readPin() {
274 uint8_t currState = currState_; // Remember current state.
275
277
278 // Save previous state if it changed.
279 if(currState != currState_) {
280 prevState_ = currState;
281 }
282 }
283
284 protected:
285 //
286 // Accessors...
287 //
288
289 /**
290 * Return the number of clicks.
291 *
292 * @param pressed The pressed state of a button.
293 * @param released The released state of a button.
294 *
295 * @returns Always single clicks (1) as double-clicks not supported.
296 */
297 inline int clicks(uint8_t pressed, uint8_t released) {
298 return this->currState_ == released && this->prevState_ == pressed;
299 }
300
301 protected:
302 //
303 // Data...
304 //
305 uint8_t prevState_; ///< Previous debounced reading of the pin.
306 };
307
308 /**
309 * Pin class that counts state changes within a time-period. This enables it
310 * to identify double-clicks.
311 */
313 public:
314 //
315 // Static Members...
316 //
317
318 /**
319 * Set the click time for input pins. If a button is clicked again
320 * within this millisecond value, it will be counted, else the count
321 * resets. Allows tracking of double-clicks within the specified time.
322 *
323 * @param clickTime The number of milliseconds between clicks.
324 */
325 inline static void setClickTime(uint16_t clickTime) {
326 clickTime_ = clickTime / 2; // Halve clickTime as we count presses and releases.
327 }
328
329 protected:
330 //
331 // Creators...
332 //
333
334 /**
335 * Protected constructor used by sub-classes. Use a Button sub-class of
336 * this class instead of this class directly.
337 *
338 * @param pin The pin to read from.
339 * @param initState The initial (un-pushed) state of the button.
340 */
341 DoubleClickerPin(uint8_t pin, uint8_t initState)
342 :ClickerPin(pin, initState) {}
343
344 private:
345 //
346 // Copying and assignment (not supported)...
347 //
348 DoubleClickerPin(const DoubleClickerPin &cpy) = delete; ///< Copying pins is not supported.
349 DoubleClickerPin &operator=(const DoubleClickerPin &) = delete; ///< Assigning pins is not supported.
350
351 public:
352 //
353 // Accessors...
354 //
355
356 /**
357 * Return the double-click time.
358 *
359 * @returns The number of milliseconds of debounce time.
360 */
361 static inline uint16_t clickTime() {
362 return clickTime_ * 2; // Double the clickTime_ to match halving in setClickTime.
363 }
364
365 /**
366 * Return the number of clicks.
367 *
368 * @param pressed The pressed state of a button.
369 * @param released The released state of a button.
370 *
371 * @returns no click (0), single click (1) or double-click (2).
372 */
373 inline int clicks(uint8_t pressed, uint8_t released) const {
374 if(this->stateCount_ >= 4) {
375 return 2;
376 } else {
377 return this->stateCount_ == 2 && ((millis() - this->millisStart_) >= this->clickTime_);
378 }
379 }
380
381 protected:
382 //
383 // Modifiers...
384 //
385
386 /**
387 * Debounce the pin readings to get a stable state of the pin. When the
388 * state changes, remember the previous state so clicks (press then
389 * release can be identified). Calls DebouncedPin::readPin() and monitors
390 * for a change in debounced state, remembering the previous state.
391 */
392 inline void readPin() {
393 uint8_t currState = currState_; // Remember current state.
394
395 // NB: Calls DebouncedPin version to avoid remembering current state
396 // twice.
398
399 // Save previous state & millis if it changed.
400 if(currState != currState_) {
401 prevState_ = currState;
403 ++stateCount_;
404 } else {
405 stateCount_ = 1;
406 }
408 }
409 }
410
411 protected:
412 //
413 // Data...
414 //
415 static uint16_t clickTime_; ///< Time required for button to be double-clicked.
416
417 uint8_t stateCount_; ///< Count changes in state within double-click time.
418 unsigned long prevMillis_; ///< Previous millisecond count from last state change.
419 };
420}
Debounced pin class that remembers the previous debounced state.
Definition: Pins.h:239
void readPin()
Debounce the pin readings to get a stable state of the pin.
Definition: Pins.h:273
int clicks(uint8_t pressed, uint8_t released)
Return the number of clicks.
Definition: Pins.h:297
uint8_t prevState_
Previous debounced reading of the pin.
Definition: Pins.h:305
ClickerPin(uint8_t pin, uint8_t initState)
Protected constructor used by sub-classes.
Definition: Pins.h:252
Debouned Pin class.
Definition: Pins.h:102
uint8_t prevReading_
The previous pin reading, to monitor state transitions.
Definition: Pins.h:230
void readPin()
Debounce the pin readings to get a stable state of the pin.
Definition: Pins.h:176
unsigned long millisStart_
Debounce start timer to handle button transition.
Definition: Pins.h:231
static void setDebounceTime(uint8_t debounceTime)
Set the debounce time for input pins.
Definition: Pins.h:119
static uint32_t idleTime_
Time required for button to be idle.
Definition: Pins.h:228
static uint8_t debounceTime()
Return the pin debounce time.
Definition: Pins.h:200
static uint16_t heldTime()
Return the pin held time.
Definition: Pins.h:209
static uint8_t debounceTime_
Time required to debounce all input pins.
Definition: Pins.h:226
DebouncedPin(uint8_t pin, uint8_t initState)
Protected constructor used by sub-classes.
Definition: Pins.h:155
static void setHeldTime(uint16_t heldTime)
Set the held time for input pins.
Definition: Pins.h:129
static void setIdleTime(uint32_t idleTime)
Set the idle time for input pins.
Definition: Pins.h:139
static uint32_t idleTime()
Return the pin idle time.
Definition: Pins.h:218
static uint16_t heldTime_
Time required for button to be held.
Definition: Pins.h:227
Pin class that counts state changes within a time-period.
Definition: Pins.h:312
static uint16_t clickTime_
Time required for button to be double-clicked.
Definition: Pins.h:415
DoubleClickerPin(uint8_t pin, uint8_t initState)
Protected constructor used by sub-classes.
Definition: Pins.h:341
unsigned long prevMillis_
Previous millisecond count from last state change.
Definition: Pins.h:418
void readPin()
Debounce the pin readings to get a stable state of the pin.
Definition: Pins.h:392
int clicks(uint8_t pressed, uint8_t released) const
Return the number of clicks.
Definition: Pins.h:373
uint8_t stateCount_
Count changes in state within double-click time.
Definition: Pins.h:417
static uint16_t clickTime()
Return the double-click time.
Definition: Pins.h:361
static void setClickTime(uint16_t clickTime)
Set the click time for input pins.
Definition: Pins.h:325
Pin base class reading direct from the pin (without debouncing).
Definition: Pins.h:17
uint8_t pin_
The Arduino pin connected to the button.
Definition: Pins.h:93
static uint8_t autoId_
Auto-assigned button identifier.
Definition: Pins.h:91
Pin(uint8_t pin, uint8_t initState)
Protected constructor used by sub-classes.
Definition: Pins.h:45
void readPin()
Read the pin directly.
Definition: Pins.h:66
uint8_t currState_
The reading of the pin.
Definition: Pins.h:94
static uint8_t nextId()
Return the next auto-assigned button identifier.
Definition: Pins.h:29
int clicks(uint8_t pressed, uint8_t released)
Return the number of clicks.
Definition: Pins.h:83