Embedded Template Library 1.0
Loading...
Searching...
No Matches
debounce.h
Go to the documentation of this file.
1
2
3/******************************************************************************
4The MIT License(MIT)
5
6Embedded Template Library.
7https://github.com/ETLCPP/etl
8https://www.etlcpp.com
9
10Copyright(c) 2016 John Wellbelove
11
12Permission is hereby granted, free of charge, to any person obtaining a copy
13of this software and associated documentation files(the "Software"), to deal
14in the Software without restriction, including without limitation the rights
15to use, copy, modify, merge, publish, distribute, sublicense, and / or sell
16copies of the Software, and to permit persons to whom the Software is
17furnished to do so, subject to the following conditions :
18
19The above copyright notice and this permission notice shall be included in all
20copies or substantial portions of the Software.
21
22THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
23IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
24FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.IN NO EVENT SHALL THE
25AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
26LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
27OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
28SOFTWARE.
29******************************************************************************/
30
31#ifndef ETL_DEBOUNCE_INCLUDED
32#define ETL_DEBOUNCE_INCLUDED
33
34#include "platform.h"
35#include "static_assert.h"
36
37#include <stdint.h>
38
39namespace etl
40{
41 namespace private_debounce
42 {
44 {
45 public:
46
47 typedef uint_least8_t flags_t;
48 typedef uint16_t count_t;
49
50 //*************************************************************************
54 //*************************************************************************
55 void add_sample(bool sample)
56 {
57 // Changed from last time?
58 if (sample != ((flags & Sample) != 0))
59 {
60 count = 0;
61 flags = (flags & ~Sample) | (sample ? Sample : 0);
62 }
63
64 flags &= ~Change;
65 }
66
67 //*************************************************************************
70 //*************************************************************************
71 bool has_changed() const
72 {
73 return (flags & Change) != 0;
74 }
75
76 //*************************************************************************
79 //*************************************************************************
80 bool is_set() const
81 {
82 return ((flags & State) > Off);
83 }
84
85 //*************************************************************************
88 //*************************************************************************
89 bool is_held() const
90 {
91 return (flags & State) > On;
92 }
93
94 //*************************************************************************
97 //*************************************************************************
98 bool is_repeating() const
99 {
100 return ((flags & State) == Repeating);
101 }
102
103 protected:
104
105 enum states
106 {
107 Off = 0,
108 On = 1,
109 Held = 2,
110 Repeating = 3,
111 State = 0x03U,
112 Sample = 4,
113 Change = 8
114 };
115
116 //*************************************************************************
118 //*************************************************************************
120 : flags(initial_state ? On : Off),
121 count(0)
122 {
123 }
124
125 //*************************************************************************
127 //*************************************************************************
129 {
130 }
131
132 //*************************************************************************
134 //*************************************************************************
136 {
137 int index1 = ((flags & State) * 2) + (sample ? 1 : 0);
138 int index2 = (sample ? (condition_set ? 0 : 1) : (condition_clear ? 0 : 1));
139
140 flags_t next = flags;
141
142 next &= ~State;
143 next |= state_table[index1][index2];
144
145 if (next != flags)
146 {
147 next |= Change;
148 }
149 else
150 {
151 next &= ~Change;
152 }
153
154 flags = next;
155 }
156
157 flags_t flags;
158 count_t count;
159 };
160
161 //***************************************************************************
163 //***************************************************************************
165 {
166 protected:
167
170 {
171 }
172
173 //*************************************************************************
175 //*************************************************************************
177 {
178 }
179
180 //*************************************************************************
182 //*************************************************************************
183 void set_state(bool sample, bool condition_set, bool condition_clear)
184 {
185 static ETL_CONSTANT uint_least8_t state_table[4][2] =
186 {
187 /* Off 0 */{ debounce_base::Off, debounce_base::Off },
188 /* Off 1 */{ debounce_base::On, debounce_base::Off },
189 /* On 0 */{ debounce_base::Off, debounce_base::On },
190 /* On 1 */{ debounce_base::On, debounce_base::On },
191 };
192
193 get_next(sample, condition_set, condition_clear, state_table);
194 }
195
196 //*************************************************************************
198 //*************************************************************************
199 bool process(bool sample, count_t valid_count)
200 {
201 add_sample(sample);
202
203 if (count < UINT16_MAX)
204 {
205 ++count;
206
207 bool valid = (count == valid_count);
208
209 switch (flags & State)
210 {
211 case Off:
212 {
213 set_state(sample, valid, valid);
214 break;
215 }
216
217 case On:
218 {
219 set_state(sample, valid, valid);
220 break;
221 }
222
223 default:
224 {
225 break;
226 }
227 }
228 }
229
230 if (flags & Change)
231 {
232 count = 0;
233 }
234
235 return (flags & Change);
236 }
237 };
238
239 //***************************************************************************
241 //***************************************************************************
243 {
244 protected:
245
248 {
249 }
250
251 //*************************************************************************
253 //*************************************************************************
255 {
256 }
257
258 //*************************************************************************
260 //*************************************************************************
261 void set_state(bool sample, bool condition_set, bool condition_clear)
262 {
263 static ETL_CONSTANT uint_least8_t state_table[6][2] =
264 {
265 /* Off 0 */{ debounce_base::Off, debounce_base::Off },
266 /* Off 1 */{ debounce_base::On, debounce_base::Off },
267 /* On 0 */{ debounce_base::Off, debounce_base::On },
268 /* On 1 */{ debounce_base::Held, debounce_base::On },
269 /* Held 0 */{ debounce_base::Off, debounce_base::Held },
270 /* Held 1 */{ debounce_base::Held, debounce_base::Held }
271 };
272
273 get_next(sample, condition_set, condition_clear, state_table);
274 }
275
276 //*************************************************************************
278 //*************************************************************************
279 bool process(bool sample, count_t valid_count, count_t hold_count)
280 {
281 add_sample(sample);
282
283 if (count < UINT16_MAX)
284 {
285 ++count;
286
287 bool valid = (count == valid_count);
288 bool hold = (count == hold_count);
289
290 switch (flags & State)
291 {
292 case Off:
293 {
294 set_state(sample, valid, valid);
295 break;
296 }
297
298 case On:
299 {
300 set_state(sample, hold, valid);
301 break;
302 }
303
304 case Held:
305 {
306 set_state(sample, hold, valid);
307 break;
308 }
309
310 default:
311 {
312 break;
313 }
314 }
315 }
316
317 if (flags & Change)
318 {
319 count = 0;
320 }
321
322 return (flags & Change);
323 }
324 };
325
326 //***************************************************************************
328 //***************************************************************************
330 {
331 protected:
332
335 {
336 }
337
338 //*************************************************************************
340 //*************************************************************************
342 {
343 }
344
345 //*************************************************************************
347 //*************************************************************************
348 void set_state(bool sample, bool condition_set, bool condition_clear)
349 {
350 static ETL_CONSTANT uint_least8_t state_table[8][2] =
351 {
352 /* Off 0 */{ debounce_base::Off, debounce_base::Off },
353 /* Off 1 */{ debounce_base::On, debounce_base::Off },
354 /* On 0 */{ debounce_base::Off, debounce_base::On },
355 /* On 1 */{ debounce_base::Held, debounce_base::On },
356 /* Held 0 */{ debounce_base::Off, debounce_base::Held },
357 /* Held 1 */{ debounce_base::Repeating, debounce_base::Held },
358 /* Repeating 0 */{ debounce_base::Off, debounce_base::Repeating },
359 /* Repeating 1 */{ debounce_base::Repeating, debounce_base::Repeating }
360 };
361
362 get_next(sample, condition_set, condition_clear, state_table);
363 }
364
365 //*************************************************************************
367 //*************************************************************************
368 bool process(bool sample, count_t valid_count, count_t hold_count, count_t repeat_count)
369 {
370 add_sample(sample);
371
372 if (count < UINT16_MAX)
373 {
374 ++count;
375
376 bool valid = (count == valid_count);
377 bool hold = (count == hold_count);
378 bool repeat = (count == repeat_count);
379
380 switch (flags & State)
381 {
382 case Off:
383 {
384 set_state(sample, valid, valid);
385 break;
386 }
387
388 case On:
389 {
390 set_state(sample, hold, valid);
391 break;
392 }
393
394 case Held:
395 {
396 set_state(sample, repeat, valid);
397 break;
398 }
399
400 case Repeating:
401 {
402 set_state(sample, repeat, valid);
403
404 if (sample && repeat)
405 {
406 count = 0;
407 flags |= Change;
408 }
409 break;
410 }
411
412 default:
413 {
414 break;
415 }
416 }
417 }
418
419 if (flags & Change)
420 {
421 count = 0;
422 }
423
424 return (flags & Change);
425 }
426 };
427 }
428
429 //***************************************************************************
432 //***************************************************************************
433 template <const uint16_t VALID_COUNT = 0, const uint16_t HOLD_COUNT = 0, const uint16_t REPEAT_COUNT = 0>
435 {
436 public:
437
438 //*************************************************************************
440 //*************************************************************************
442 : debounce4(initial_state)
443 {
444 }
445
446 //*************************************************************************
451 //*************************************************************************
452 bool add(bool sample)
453 {
454 return process(sample, VALID_COUNT, HOLD_COUNT, REPEAT_COUNT);
455 }
456 };
457
458 //***************************************************************************
461 //***************************************************************************
462 template <const uint16_t VALID_COUNT, const uint16_t HOLD_COUNT>
464 {
465 public:
466
467 //*************************************************************************
469 //*************************************************************************
471 : debounce3(initial_state)
472 {
473 }
474
475 //*************************************************************************
483 //*************************************************************************
484 bool add(bool sample)
485 {
486 return process(sample, VALID_COUNT, HOLD_COUNT);
487 }
488 };
489
490 //***************************************************************************
493 //***************************************************************************
494 template <const uint16_t VALID_COUNT>
496 {
497 public:
498
499 //*************************************************************************
501 //*************************************************************************
503 : debounce2(initial_state)
504 {
505 }
506
507 //*************************************************************************
514 //*************************************************************************
515 bool add(bool sample)
516 {
517 return process(sample, VALID_COUNT);
518 }
519 };
520
521 //***************************************************************************
524 //***************************************************************************
525 template <>
526 class debounce<0, 0, 0> : public private_debounce::debounce4
527 {
528 public:
529
530 //*************************************************************************
533 //*************************************************************************
535 : debounce4(initial_state),
536 valid_count(1),
537 hold_count(0),
538 repeat_count(0)
539 {
540 }
541
542 //*************************************************************************
547 //*************************************************************************
549 : debounce4(false)
550 {
551 set(valid, hold, repeat);
552 }
553
554 //*************************************************************************
556 //*************************************************************************
557 void set(count_t valid, count_t hold = 0, count_t repeat = 0)
558 {
559 valid_count = valid;
560 hold_count = hold;
561 repeat_count = repeat;
562 }
563
564 //*************************************************************************
573 //*************************************************************************
574 bool add(bool sample)
575 {
576 return process(sample, valid_count, hold_count, repeat_count);
577 }
578
579 private:
580
581 count_t valid_count;
582 count_t hold_count;
583 count_t repeat_count;
584 };
585}
586
587#endif
bool add(bool sample)
Definition debounce.h:574
void set(count_t valid, count_t hold=0, count_t repeat=0)
Constructor.
Definition debounce.h:557
debounce(count_t valid, count_t hold=0, count_t repeat=0)
Definition debounce.h:548
debounce(bool initial_state=false)
Definition debounce.h:534
bool add(bool sample)
Definition debounce.h:515
debounce(bool initial_state=false)
Constructor.
Definition debounce.h:502
bool add(bool sample)
Definition debounce.h:484
debounce(bool initial_state=false)
Constructor.
Definition debounce.h:470
Definition debounce.h:435
bool add(bool sample)
Definition debounce.h:452
debounce(bool initial_state=false)
Constructor.
Definition debounce.h:441
Definition flags.h:53
State change logic for 2 state debounce.
Definition debounce.h:165
~debounce2()
Destructor.
Definition debounce.h:176
State change logic for 3 state debounce.
Definition debounce.h:243
~debounce3()
Destructor.
Definition debounce.h:254
State change logic for 4 state debounce.
Definition debounce.h:330
~debounce4()
Destructor.
Definition debounce.h:341
Definition debounce.h:44
bool has_changed() const
Definition debounce.h:71
void add_sample(bool sample)
Definition debounce.h:55
bool is_repeating() const
Definition debounce.h:98
debounce_base(bool initial_state)
Constructor.
Definition debounce.h:119
bool is_set() const
Definition debounce.h:80
bool is_held() const
Definition debounce.h:89
void get_next(bool sample, bool condition_set, bool condition_clear, const uint_least8_t state_table[][2])
Gets the next state based on the inputs.
Definition debounce.h:135
~debounce_base()
Destructor.
Definition debounce.h:128
A templated set implementation that uses a fixed size buffer.
Definition set.h:2548
bitset_ext
Definition absolute.h:38
pair holds two objects of arbitrary type
Definition utility.h:164