AbleButtons V0.2.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 * Read the pin directly. In order to save memory, virtual functions are
58 * *not* used (which can consume almost 1K of memory to deal with).
59 * Runtime polymorphism is not required, so avoiding virtual functions
60 * saves memory.
61 */
62 inline void readPin() {
63 currState_ = digitalRead(pin_);
64 }
65
66 protected:
67 //
68 // Data...
69 //
70 static uint8_t autoId_; ///< Auto-assigned button identifier.
71
72 uint8_t pin_; ///< The Arduino pin connected to the button.
73 uint8_t currState_; ///< The reading of the pin.
74 };
75
76 /**
77 * Debouned Pin class. Manages making reliable readings from an input pin.
78 * The readPin() method manages debouncing the pin readings. You cannot use
79 * this class directly. Use one of the Button sub-classes instead.
80 */
81 class DebouncedPin: public Pin {
82 public:
83 //
84 // Static Members...
85 //
86
87 /**
88 * Set the debounce time for input pins. Pins may read noise as buttons
89 * are pressed and released. This noise can be registered as multiple
90 * button presses in a short time period, confusing your program. The
91 * debounce time is the number of milliseconds to wait when a reading
92 * changes before using that reading. See https://docs.arduino.cc/built-in-examples/digital/Debounce
93 * for details on debounce.
94 *
95 * @param debounceTime The number of milliseconds before a button state
96 * change is returned (default 50ms, max 255ms).
97 */
98 inline static void setDebounceTime(uint8_t debounceTime) {
100 };
101
102 /**
103 * Set the held time for input pins. If a button is pressed for longer
104 * than this time, it will be held.
105 *
106 * @param heldTime The number of milliseconds for a held state (default 1s).
107 */
108 inline static void setHeldTime(uint16_t heldTime) {
110 }
111
112 /**
113 * Set the idle time for input pins. If a button is unpressed for longer
114 * than this time, it will be idle.
115 *
116 * @param idleTime The number of milliseconds for an idle state (default 60s).
117 */
118 inline static void setIdleTime(uint32_t idleTime) {
120 }
121
122 protected:
123 //
124 // Creators...
125 //
126
127 /**
128 * Protected constructor used by sub-classes. Use a sub-class of this
129 * class instead of this class directly.
130 *
131 * @param pin The pin to read from.
132 * @param initState The initial (un-pushed) state of the button.
133 */
134 DebouncedPin(uint8_t pin, uint8_t initState)
135 :Pin(pin, initState), prevReading_(initState) {}
136
137 private:
138 //
139 // Copying and assignment (not supported)...
140 //
141 DebouncedPin(const DebouncedPin &) = delete; ///< Copying pins is not supported.
142 DebouncedPin &operator=(const DebouncedPin &) = delete; ///< Assigning pins not supported.
143
144 protected:
145 //
146 // Modifiers...
147 //
148
149 /**
150 * Debounce the pin readings to get a stable state of the pin. In order to
151 * save memory, virtual functions are *not* used (which can consume almost
152 * 1K of memory to deal with). Runtime polymorphism is not required, so
153 * avoiding virtual functions saves memory.
154 */
155 inline void readPin() {
156 byte currReading = digitalRead(pin_);
157
158 // New reading, so start the debounce timer.
159 if (currReading != prevReading_) {
160 millisStart_ = millis();
161 } else if ((millis() - millisStart_) >= debounceTime_) {
162 // Use reading if we have the same reading for >= DELAY ms.
163 currState_ = currReading;
164 }
165
166 prevReading_ = currReading;
167 }
168
169 public:
170 //
171 // Accessors...
172 //
173
174 /**
175 * Return the pin debounce time.
176 *
177 * @returns The number of milliseconds of debounce time.
178 */
179 static inline uint8_t debounceTime() {
180 return debounceTime_;
181 }
182
183 /**
184 * Return the pin held time.
185 *
186 * @returns The number of milliseconds after which a pin is held.
187 */
188 static inline uint16_t heldTime() {
189 return heldTime_;
190 }
191
192 /**
193 * Return the pin idle time.
194 *
195 * @returns The number of milliseconds after which a pin is idle.
196 */
197 static inline uint32_t idleTime() {
198 return idleTime_;
199 }
200
201 protected:
202 //
203 // Data...
204 //
205 static uint8_t debounceTime_; ///< Time required to debounce all input pins.
206 static uint16_t heldTime_; ///< Time required for button to be held.
207 static uint32_t idleTime_; ///< Time required for button to be idle.
208
209 uint8_t prevReading_; ///< The previous pin reading, to monitor state transitions.
210 unsigned long millisStart_; ///< Debounce start timer to handle button transition.
211 };
212
213 /**
214 * Debounced pin class that remembers the previous debounced state. This
215 * allows clicks (a combination of press then release) to be identified.
216 * This class extends the basic DebouncedPin class to add the previous state.
217 */
218 class ClickerPin: public DebouncedPin {
219 protected:
220 //
221 // Creators...
222 //
223
224 /**
225 * Protected constructor used by sub-classes. Use a Button sub-class of
226 * this class instead of this class directly.
227 *
228 * @param pin The pin to read from.
229 * @param initState The initial (un-pushed) state of the button.
230 */
231 ClickerPin(uint8_t pin, uint8_t initState)
232 :DebouncedPin(pin, initState), prevState_(initState) {}
233
234 private:
235 //
236 // Copying and assignment (not supported)...
237 //
238 ClickerPin(const ClickerPin &cpy) = delete; ///< Copying pins is not supported.
239 ClickerPin &operator=(const ClickerPin &) = delete; ///< Assigning pins is not supported.
240
241 protected:
242 //
243 // Modifiers...
244 //
245
246 /**
247 * Debounce the pin readings to get a stable state of the pin. When the
248 * state changes, remember the previous state so clicks (press then
249 * release can be identified). Calls DebouncedPin::readPin() and monitors
250 * for a change in debounced state, remembering the previous state.
251 */
252 inline void readPin() {
253 uint8_t currState = currState_; // Remember current state.
254
256
257 // Save previous state if it changed.
258 if(currState != currState_) {
259 prevState_ = currState;
260 }
261 }
262
263 protected:
264 //
265 // Data...
266 //
267 uint8_t prevState_; ///< Previous debounced reading of the pin.
268 };
269
270 /**
271 * Pin class that counts state changes within a time-period. This enables it
272 * to identify double-clicks.
273 */
275 public:
276 //
277 // Static Members...
278 //
279
280 /**
281 * Set the click time for input pins. If a button is clicked again
282 * within this millisecond value, it will be counted, else the count
283 * resets. Allows tracking of double-clicks within the specified time.
284 *
285 * @param clickTime The number of milliseconds between clicks.
286 */
287 inline static void setClickTime(uint16_t clickTime) {
288 clickTime_ = clickTime / 2; // Halve clickTime as we count presses and releases.
289 }
290
291 protected:
292 //
293 // Creators...
294 //
295
296 /**
297 * Protected constructor used by sub-classes. Use a Button sub-class of
298 * this class instead of this class directly.
299 *
300 * @param pin The pin to read from.
301 * @param initState The initial (un-pushed) state of the button.
302 */
303 DoubleClickerPin(uint8_t pin, uint8_t initState)
304 :ClickerPin(pin, initState) {}
305
306 private:
307 //
308 // Copying and assignment (not supported)...
309 //
310 DoubleClickerPin(const DoubleClickerPin &cpy) = delete; ///< Copying pins is not supported.
311 DoubleClickerPin &operator=(const DoubleClickerPin &) = delete; ///< Assigning pins is not supported.
312
313 public:
314 //
315 // Accessors...
316 //
317
318 /**
319 * Return the double-click time.
320 *
321 * @returns The number of milliseconds of debounce time.
322 */
323 static inline uint16_t clickTime() {
324 return clickTime_ * 2; // Double the clickTime_ to match halving in setClickTime.
325 }
326
327 protected:
328 //
329 // Modifiers...
330 //
331
332 /**
333 * Debounce the pin readings to get a stable state of the pin. When the
334 * state changes, remember the previous state so clicks (press then
335 * release can be identified). Calls DebouncedPin::readPin() and monitors
336 * for a change in debounced state, remembering the previous state.
337 */
338 inline void readPin() {
339 uint8_t currState = currState_; // Remember current state.
340
341 // NB: Calls DebouncedPin version to avoid remembering current state
342 // twice.
344
345 // Save previous state & millis if it changed.
346 if(currState != currState_) {
347 prevState_ = currState;
349 ++stateCount_;
350 } else {
351 stateCount_ = 1;
352 }
354 }
355 }
356
357 protected:
358 //
359 // Data...
360 //
361 static uint16_t clickTime_; ///< Time required for button to be double-clicked.
362
363 uint8_t stateCount_; ///< Count changes in state within double-click time.
364 unsigned long prevMillis_; ///< Previous millisecond count from last state change.
365 };
366}
Debounced pin class that remembers the previous debounced state.
Definition: Pins.h:218
void readPin()
Debounce the pin readings to get a stable state of the pin.
Definition: Pins.h:252
uint8_t prevState_
Previous debounced reading of the pin.
Definition: Pins.h:267
ClickerPin(uint8_t pin, uint8_t initState)
Protected constructor used by sub-classes.
Definition: Pins.h:231
Debouned Pin class.
Definition: Pins.h:81
uint8_t prevReading_
The previous pin reading, to monitor state transitions.
Definition: Pins.h:209
void readPin()
Debounce the pin readings to get a stable state of the pin.
Definition: Pins.h:155
unsigned long millisStart_
Debounce start timer to handle button transition.
Definition: Pins.h:210
static void setDebounceTime(uint8_t debounceTime)
Set the debounce time for input pins.
Definition: Pins.h:98
static uint32_t idleTime_
Time required for button to be idle.
Definition: Pins.h:207
static uint8_t debounceTime()
Return the pin debounce time.
Definition: Pins.h:179
static uint16_t heldTime()
Return the pin held time.
Definition: Pins.h:188
static uint8_t debounceTime_
Time required to debounce all input pins.
Definition: Pins.h:205
DebouncedPin(uint8_t pin, uint8_t initState)
Protected constructor used by sub-classes.
Definition: Pins.h:134
static void setHeldTime(uint16_t heldTime)
Set the held time for input pins.
Definition: Pins.h:108
static void setIdleTime(uint32_t idleTime)
Set the idle time for input pins.
Definition: Pins.h:118
static uint32_t idleTime()
Return the pin idle time.
Definition: Pins.h:197
static uint16_t heldTime_
Time required for button to be held.
Definition: Pins.h:206
Pin class that counts state changes within a time-period.
Definition: Pins.h:274
static uint16_t clickTime_
Time required for button to be double-clicked.
Definition: Pins.h:361
DoubleClickerPin(uint8_t pin, uint8_t initState)
Protected constructor used by sub-classes.
Definition: Pins.h:303
unsigned long prevMillis_
Previous millisecond count from last state change.
Definition: Pins.h:364
void readPin()
Debounce the pin readings to get a stable state of the pin.
Definition: Pins.h:338
uint8_t stateCount_
Count changes in state within double-click time.
Definition: Pins.h:363
static uint16_t clickTime()
Return the double-click time.
Definition: Pins.h:323
static void setClickTime(uint16_t clickTime)
Set the click time for input pins.
Definition: Pins.h:287
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:72
static uint8_t autoId_
Auto-assigned button identifier.
Definition: Pins.h:70
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:62
uint8_t currState_
The reading of the pin.
Definition: Pins.h:73
static uint8_t nextId()
Return the next auto-assigned button identifier.
Definition: Pins.h:29