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 = static_cast<flags_t>((flags & static_cast<flags_t>(~Sample)) | (sample ? Sample : 0));
62 }
63
64 flags &= static_cast<flags_t>(~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 //*************************************************************************
119 debounce_base(bool initial_state)
120 : flags(initial_state ? On : Off)
121 , count(0)
122 {
123 }
124
125 //*************************************************************************
127 //*************************************************************************
129
130 //*************************************************************************
132 //*************************************************************************
133 void get_next(bool sample, bool condition_set, bool condition_clear, const uint_least8_t state_table[][2])
134 {
135 int index1 = ((flags & State) * 2) + (sample ? 1 : 0);
136 int index2 = (sample ? (condition_set ? 0 : 1) : (condition_clear ? 0 : 1));
137
138 flags_t next = flags;
139
140 next &= static_cast<flags_t>(~State);
141 next |= state_table[index1][index2];
142
143 if (next != flags)
144 {
145 next |= Change;
146 }
147 else
148 {
149 next &= static_cast<flags_t>(~Change);
150 }
151
152 flags = next;
153 }
154
155 flags_t flags;
156 count_t count;
157 };
158
159 //***************************************************************************
161 //***************************************************************************
162 class debounce2 : public debounce_base
163 {
164 protected:
165
166 debounce2(bool initial_state)
167 : debounce_base(initial_state)
168 {
169 }
170
171 //*************************************************************************
173 //*************************************************************************
175
176 //*************************************************************************
178 //*************************************************************************
179 void set_state(bool sample, bool condition_set, bool condition_clear)
180 {
181 static ETL_CONSTANT uint_least8_t state_table[4][2] = {
182 /* Off 0 */ {debounce_base::Off, debounce_base::Off},
183 /* Off 1 */ {debounce_base::On, debounce_base::Off},
184 /* On 0 */ {debounce_base::Off, debounce_base::On},
185 /* On 1 */ {debounce_base::On, debounce_base::On},
186 };
187
188 get_next(sample, condition_set, condition_clear, state_table);
189 }
190
191 //*************************************************************************
193 //*************************************************************************
194 bool process(bool sample, count_t valid_count)
195 {
196 add_sample(sample);
197
198 if (count < UINT16_MAX)
199 {
200 ++count;
201
202 bool valid = (count == valid_count);
203
204 switch (flags & State)
205 {
206 case Off:
207 {
208 set_state(sample, valid, valid);
209 break;
210 }
211
212 case On:
213 {
214 set_state(sample, valid, valid);
215 break;
216 }
217
218 default:
219 {
220 break;
221 }
222 }
223 }
224
225 if (flags & Change)
226 {
227 count = 0;
228 }
229
230 return (flags & Change);
231 }
232 };
233
234 //***************************************************************************
236 //***************************************************************************
237 class debounce3 : public debounce_base
238 {
239 protected:
240
241 debounce3(bool initial_state)
242 : debounce_base(initial_state)
243 {
244 }
245
246 //*************************************************************************
248 //*************************************************************************
250
251 //*************************************************************************
253 //*************************************************************************
254 void set_state(bool sample, bool condition_set, bool condition_clear)
255 {
256 static ETL_CONSTANT uint_least8_t state_table[6][2] = {/* Off 0 */ {debounce_base::Off, debounce_base::Off},
257 /* Off 1 */ {debounce_base::On, debounce_base::Off},
258 /* On 0 */ {debounce_base::Off, debounce_base::On},
259 /* On 1 */ {debounce_base::Held, debounce_base::On},
260 /* Held 0 */ {debounce_base::Off, debounce_base::Held},
261 /* Held 1 */ {debounce_base::Held, debounce_base::Held}};
262
263 get_next(sample, condition_set, condition_clear, state_table);
264 }
265
266 //*************************************************************************
268 //*************************************************************************
269 bool process(bool sample, count_t valid_count, count_t hold_count)
270 {
271 add_sample(sample);
272
273 if (count < UINT16_MAX)
274 {
275 ++count;
276
277 bool valid = (count == valid_count);
278 bool hold = (count == hold_count);
279
280 switch (flags & State)
281 {
282 case Off:
283 {
284 set_state(sample, valid, valid);
285 break;
286 }
287
288 case On:
289 {
290 set_state(sample, hold, valid);
291 break;
292 }
293
294 case Held:
295 {
296 set_state(sample, hold, valid);
297 break;
298 }
299
300 default:
301 {
302 break;
303 }
304 }
305 }
306
307 if (flags & Change)
308 {
309 count = 0;
310 }
311
312 return (flags & Change);
313 }
314 };
315
316 //***************************************************************************
318 //***************************************************************************
319 class debounce4 : public debounce_base
320 {
321 protected:
322
323 debounce4(bool initial_state)
324 : debounce_base(initial_state)
325 {
326 }
327
328 //*************************************************************************
330 //*************************************************************************
332
333 //*************************************************************************
335 //*************************************************************************
336 void set_state(bool sample, bool condition_set, bool condition_clear)
337 {
338 static ETL_CONSTANT uint_least8_t state_table[8][2] = {/* Off 0 */ {debounce_base::Off, debounce_base::Off},
339 /* Off 1 */ {debounce_base::On, debounce_base::Off},
340 /* On 0 */ {debounce_base::Off, debounce_base::On},
341 /* On 1 */ {debounce_base::Held, debounce_base::On},
342 /* Held 0 */ {debounce_base::Off, debounce_base::Held},
343 /* Held 1 */ {debounce_base::Repeating, debounce_base::Held},
344 /* Repeating 0 */ {debounce_base::Off, debounce_base::Repeating},
345 /* Repeating 1 */
346 {debounce_base::Repeating, debounce_base::Repeating}};
347
348 get_next(sample, condition_set, condition_clear, state_table);
349 }
350
351 //*************************************************************************
353 //*************************************************************************
354 bool process(bool sample, count_t valid_count, count_t hold_count, count_t repeat_count)
355 {
356 add_sample(sample);
357
358 if (count < UINT16_MAX)
359 {
360 ++count;
361
362 bool valid = (count == valid_count);
363 bool hold = (count == hold_count);
364 bool repeat = (count == repeat_count);
365
366 switch (flags & State)
367 {
368 case Off:
369 {
370 set_state(sample, valid, valid);
371 break;
372 }
373
374 case On:
375 {
376 set_state(sample, hold, valid);
377 break;
378 }
379
380 case Held:
381 {
382 set_state(sample, repeat, valid);
383 break;
384 }
385
386 case Repeating:
387 {
388 set_state(sample, repeat, valid);
389
390 if (sample && repeat)
391 {
392 count = 0;
393 flags |= Change;
394 }
395 break;
396 }
397
398 default:
399 {
400 break;
401 }
402 }
403 }
404
405 if (flags & Change)
406 {
407 count = 0;
408 }
409
410 return (flags & Change);
411 }
412 };
413 } // namespace private_debounce
414
415 //***************************************************************************
418 //***************************************************************************
419 template <const uint16_t VALID_COUNT = 0, const uint16_t HOLD_COUNT = 0, const uint16_t REPEAT_COUNT = 0>
421 {
422 public:
423
424 //*************************************************************************
426 //*************************************************************************
427 debounce(bool initial_state = false)
428 : debounce4(initial_state)
429 {
430 }
431
432 //*************************************************************************
437 //*************************************************************************
438 bool add(bool sample)
439 {
440 return process(sample, VALID_COUNT, HOLD_COUNT, REPEAT_COUNT);
441 }
442 };
443
444 //***************************************************************************
447 //***************************************************************************
448 template <const uint16_t VALID_COUNT, const uint16_t HOLD_COUNT>
449 class debounce<VALID_COUNT, HOLD_COUNT, 0> : public private_debounce::debounce3
450 {
451 public:
452
453 //*************************************************************************
455 //*************************************************************************
456 debounce(bool initial_state = false)
457 : debounce3(initial_state)
458 {
459 }
460
461 //*************************************************************************
469 //*************************************************************************
470 bool add(bool sample)
471 {
472 return process(sample, VALID_COUNT, HOLD_COUNT);
473 }
474 };
475
476 //***************************************************************************
479 //***************************************************************************
480 template <const uint16_t VALID_COUNT>
481 class debounce<VALID_COUNT, 0, 0> : public private_debounce::debounce2
482 {
483 public:
484
485 //*************************************************************************
487 //*************************************************************************
488 debounce(bool initial_state = false)
489 : debounce2(initial_state)
490 {
491 }
492
493 //*************************************************************************
500 //*************************************************************************
501 bool add(bool sample)
502 {
503 return process(sample, VALID_COUNT);
504 }
505 };
506
507 //***************************************************************************
510 //***************************************************************************
511 template <>
512 class debounce<0, 0, 0> : public private_debounce::debounce4
513 {
514 public:
515
516 //*************************************************************************
519 //*************************************************************************
520 debounce(bool initial_state = false)
521 : debounce4(initial_state)
522 , valid_count(1)
523 , hold_count(0)
524 , repeat_count(0)
525 {
526 }
527
528 //*************************************************************************
534 //*************************************************************************
535 debounce(count_t valid, count_t hold = 0, count_t repeat = 0)
536 : debounce4(false)
537 {
538 set(valid, hold, repeat);
539 }
540
541 //*************************************************************************
543 //*************************************************************************
544 void set(count_t valid, count_t hold = 0, count_t repeat = 0)
545 {
546 valid_count = valid;
547 hold_count = hold;
548 repeat_count = repeat;
549 }
550
551 //*************************************************************************
560 //*************************************************************************
561 bool add(bool sample)
562 {
563 return process(sample, valid_count, hold_count, repeat_count);
564 }
565
566 private:
567
568 count_t valid_count;
569 count_t hold_count;
570 count_t repeat_count;
571 };
572} // namespace etl
573
574#endif
bool add(bool sample)
Definition debounce.h:561
void set(count_t valid, count_t hold=0, count_t repeat=0)
Constructor.
Definition debounce.h:544
debounce(count_t valid, count_t hold=0, count_t repeat=0)
Definition debounce.h:535
debounce(bool initial_state=false)
Definition debounce.h:520
bool add(bool sample)
Definition debounce.h:501
debounce(bool initial_state=false)
Constructor.
Definition debounce.h:488
bool add(bool sample)
Definition debounce.h:470
debounce(bool initial_state=false)
Constructor.
Definition debounce.h:456
bool add(bool sample)
Definition debounce.h:438
debounce(bool initial_state=false)
Constructor.
Definition debounce.h:427
Definition flags.h:53
State change logic for 2 state debounce.
Definition debounce.h:163
~debounce2()
Destructor.
Definition debounce.h:174
State change logic for 3 state debounce.
Definition debounce.h:238
~debounce3()
Destructor.
Definition debounce.h:249
State change logic for 4 state debounce.
Definition debounce.h:320
~debounce4()
Destructor.
Definition debounce.h:331
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:133
~debounce_base()
Destructor.
Definition debounce.h:128
bitset_ext
Definition absolute.h:40