Important changes to repositories hosted on mbed.com
Mbed hosted mercurial repositories are deprecated and are due to be permanently deleted in July 2026.
To keep a copy of this software download the repository Zip archive or clone locally using Mercurial.
It is also possible to export all your personal repositories from the account settings page.
debounce.h
00001 ///\file 00002 00003 /****************************************************************************** 00004 The MIT License(MIT) 00005 00006 Embedded Template Library. 00007 https://github.com/ETLCPP/etl 00008 http://www.etlcpp.com 00009 00010 Copyright(c) 2016 jwellbelove 00011 00012 Permission is hereby granted, free of charge, to any person obtaining a copy 00013 of this software and associated documentation files(the "Software"), to deal 00014 in the Software without restriction, including without limitation the rights 00015 to use, copy, modify, merge, publish, distribute, sublicense, and / or sell 00016 copies of the Software, and to permit persons to whom the Software is 00017 furnished to do so, subject to the following conditions : 00018 00019 The above copyright notice and this permission notice shall be included in all 00020 copies or substantial portions of the Software. 00021 00022 THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 00023 IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 00024 FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.IN NO EVENT SHALL THE 00025 AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 00026 LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 00027 OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 00028 SOFTWARE. 00029 ******************************************************************************/ 00030 00031 #ifndef __ETL_DEBOUNCE__ 00032 #define __ETL_DEBOUNCE__ 00033 00034 #include <stdint.h> 00035 00036 #include "platform.h " 00037 #include "static_assert.h" 00038 00039 namespace etl 00040 { 00041 namespace __private_debounce__ 00042 { 00043 class debounce_base 00044 { 00045 public: 00046 00047 void add(bool sample) 00048 { 00049 state &= ~CHANGED; 00050 00051 // Changed from last time? 00052 if (sample != bool((state & LAST) != 0)) 00053 { 00054 count = START_COUNT; 00055 } 00056 } 00057 00058 //************************************************************************* 00059 /// Gets the current debouncer change state. 00060 ///\return 'true' if the debouncer has changed state. 00061 //************************************************************************* 00062 bool has_changed() const 00063 { 00064 return (state & CHANGED) != 0; 00065 } 00066 00067 //************************************************************************* 00068 /// Gets the current debouncer state. 00069 ///\return 'true' if the debouncer is in the true state. 00070 //************************************************************************* 00071 bool is_set() const 00072 { 00073 return (state & CURRENT) != 0; 00074 } 00075 00076 //************************************************************************* 00077 /// Gets the debouncer hold state. 00078 ///\return 'true' if the debouncer is in the hold state. 00079 //************************************************************************* 00080 bool is_held() const 00081 { 00082 return (state & HELD) != 0; 00083 } 00084 00085 //************************************************************************* 00086 /// Gets the debouncer repeat state. 00087 ///\return 'true' if the debouncer is repeating. 00088 //************************************************************************* 00089 bool is_repeating() const 00090 { 00091 return (state & REPEATING) != 0; 00092 } 00093 00094 protected: 00095 00096 //************************************************************************* 00097 /// Constructor. 00098 ///\param initial_state The initial state. Default = false. 00099 //************************************************************************* 00100 debounce_base(bool initial_state = false) 00101 : state(initial_state ? (CURRENT | LAST) : 0), 00102 count(START_COUNT) 00103 { 00104 } 00105 00106 enum 00107 { 00108 START_COUNT = 0 00109 }; 00110 00111 enum 00112 { 00113 CURRENT = 1, 00114 LAST = 2, 00115 HELD = 4, 00116 CHANGED = 8, 00117 REPEATING = 16 00118 }; 00119 00120 uint_least8_t state; 00121 00122 /// The state count. 00123 uint16_t count; 00124 }; 00125 } 00126 00127 //*************************************************************************** 00128 /// A class to debounce signals. 00129 /// The state is decided over N samples, defined by the VALID_COUNT value. 00130 /// If the samples are consistent for VALID_COUNT times then the debouncer state is defined. 00131 /// If the samples change then the debouncer will change state after VALID_COUNT samples. 00132 /// If the samples are true for a count of HOLD_COUNT then the debouncer input is 'held'. 00133 /// The debouncer may be constructed in either state. 00134 //*************************************************************************** 00135 template <const uint16_t VALID_COUNT = 0, const uint16_t HOLD_COUNT = 0, const uint16_t REPEAT_COUNT = 0> 00136 class debounce : public __private_debounce__::debounce_base 00137 { 00138 private: 00139 00140 enum 00141 { 00142 VALID_THRESHOLD = VALID_COUNT, 00143 HOLD_THRESHOLD = VALID_THRESHOLD + HOLD_COUNT, 00144 REPEAT_THRESHOLD = HOLD_THRESHOLD + REPEAT_COUNT 00145 }; 00146 00147 using debounce_base::add; 00148 00149 public: 00150 00151 //************************************************************************* 00152 /// Constructor. 00153 ///\param initial_state The initial state. Default = false. 00154 //************************************************************************* 00155 debounce(bool initial_state = false) 00156 : debounce_base(initial_state) 00157 { 00158 } 00159 00160 //************************************************************************* 00161 /// Adds a new sample. 00162 /// Returns 'true' if the debouncer changes state from... 00163 /// 1. Clear to Set. 00164 /// 2. Set to Clear. 00165 /// 3. Not Held to Held. 00166 /// 4. Key repeats. 00167 ///\param sample The new sample. 00168 ///\return 'true' if the debouncer changed state. 00169 //************************************************************************* 00170 bool add(bool sample) 00171 { 00172 debounce_base::add(sample); 00173 00174 if (count < REPEAT_THRESHOLD) 00175 { 00176 ++count; 00177 00178 if (sample) 00179 { 00180 if (count == VALID_THRESHOLD) 00181 { 00182 // Set. 00183 state |= CHANGED; 00184 state |= CURRENT; 00185 } 00186 else if (count == HOLD_THRESHOLD) 00187 { 00188 // Held. 00189 state |= CHANGED; 00190 state |= HELD; 00191 } 00192 else if (count == REPEAT_THRESHOLD) 00193 { 00194 // Repeat. 00195 state |= CHANGED; 00196 state |= REPEATING; 00197 count = HOLD_THRESHOLD; 00198 } 00199 00200 state |= LAST; 00201 } 00202 else 00203 { 00204 if (count == VALID_THRESHOLD) 00205 { 00206 // Clear. 00207 state |= CHANGED; 00208 state &= ~CURRENT; 00209 state &= ~HELD; 00210 state &= ~REPEATING; 00211 } 00212 00213 state &= ~LAST; 00214 } 00215 } 00216 00217 return (state & CHANGED) != 0; 00218 } 00219 }; 00220 00221 template <const uint16_t VALID_COUNT, const uint16_t HOLD_COUNT> 00222 class debounce<VALID_COUNT, HOLD_COUNT, 0> : public __private_debounce__::debounce_base 00223 { 00224 private: 00225 00226 enum 00227 { 00228 VALID_THRESHOLD = VALID_COUNT, 00229 HOLD_THRESHOLD = VALID_THRESHOLD + HOLD_COUNT 00230 }; 00231 00232 using debounce_base::add; 00233 00234 public: 00235 00236 //************************************************************************* 00237 /// Constructor. 00238 ///\param initial_state The initial state. Default = false. 00239 //************************************************************************* 00240 debounce(bool initial_state = false) 00241 : debounce_base(initial_state) 00242 { 00243 } 00244 00245 //************************************************************************* 00246 /// Adds a new sample. 00247 /// Returns 'true' if the debouncer changes state from... 00248 /// 1. Clear to Set. 00249 /// 2. Set to Clear. 00250 /// 3. Not Held to Held. 00251 ///\param sample The new sample. 00252 ///\return 'true' if the debouncer changed state. 00253 //************************************************************************* 00254 bool add(bool sample) 00255 { 00256 debounce_base::add(sample); 00257 00258 if (count < HOLD_THRESHOLD) 00259 { 00260 ++count; 00261 00262 if (sample) 00263 { 00264 if (count == VALID_THRESHOLD) 00265 { 00266 // Set. 00267 state |= CHANGED; 00268 state |= CURRENT; 00269 } 00270 else if (count == HOLD_THRESHOLD) 00271 { 00272 // Held. 00273 state |= CHANGED; 00274 state |= HELD; 00275 } 00276 00277 state |= LAST; 00278 } 00279 else 00280 { 00281 if (count == VALID_THRESHOLD) 00282 { 00283 // Clear. 00284 state |= CHANGED; 00285 state &= ~CURRENT; 00286 state &= ~HELD; 00287 state &= ~REPEATING; 00288 } 00289 00290 state &= ~LAST; 00291 } 00292 } 00293 00294 return (state & CHANGED) != 0; 00295 } 00296 }; 00297 00298 template <const uint16_t VALID_COUNT> 00299 class debounce<VALID_COUNT, 0, 0> : public __private_debounce__::debounce_base 00300 { 00301 private: 00302 00303 enum 00304 { 00305 VALID_THRESHOLD = VALID_COUNT 00306 }; 00307 00308 using debounce_base::add; 00309 00310 public: 00311 00312 //************************************************************************* 00313 /// Constructor. 00314 ///\param initial_state The initial state. Default = false. 00315 //************************************************************************* 00316 debounce(bool initial_state = false) 00317 : debounce_base(initial_state) 00318 { 00319 } 00320 00321 //************************************************************************* 00322 /// Adds a new sample. 00323 /// Returns 'true' if the debouncer changes state from... 00324 /// 1. Clear to Set. 00325 /// 2. Set to Clear. 00326 ///\param sample The new sample. 00327 ///\return 'true' if the debouncer changed state. 00328 //************************************************************************* 00329 bool add(bool sample) 00330 { 00331 debounce_base::add(sample); 00332 00333 if (count < VALID_THRESHOLD) 00334 { 00335 ++count; 00336 00337 if (sample) 00338 { 00339 if (count == VALID_THRESHOLD) 00340 { 00341 // Set. 00342 state |= CHANGED; 00343 state |= CURRENT; 00344 } 00345 00346 state |= LAST; 00347 } 00348 else 00349 { 00350 if (count == VALID_THRESHOLD) 00351 { 00352 // Clear. 00353 state |= CHANGED; 00354 state &= ~CURRENT; 00355 state &= ~HELD; 00356 state &= ~REPEATING; 00357 } 00358 00359 state &= ~LAST; 00360 } 00361 } 00362 00363 return (state & CHANGED) != 0; 00364 } 00365 }; 00366 00367 template <> 00368 class debounce<0, 0, 0> : public __private_debounce__::debounce_base 00369 { 00370 public: 00371 00372 using debounce_base::add; 00373 00374 //************************************************************************* 00375 /// Constructor. 00376 ///\param initial_state The initial state. Default = false. 00377 //************************************************************************* 00378 debounce() 00379 : debounce_base(false), 00380 valid_threshold(1), 00381 hold_threshold(0), 00382 repeat_threshold(0) 00383 { 00384 } 00385 00386 //************************************************************************* 00387 /// Constructor. 00388 ///\param initial_state The initial state. 00389 ///\param valid_count The count for a valid state. Default = 1. 00390 ///\param hold_count The count after valid_count for a hold state. Default = 0. 00391 ///\param repeat_count The count after hold_count for a key repeat. Default = 0. 00392 //************************************************************************* 00393 debounce(bool initial_state, uint16_t valid_count = 1, uint16_t hold_count = 0, uint16_t repeat_count = 0) 00394 : debounce_base(initial_state) 00395 { 00396 set(valid_count, hold_count, repeat_count); 00397 } 00398 00399 //************************************************************************* 00400 /// Constructor. 00401 ///\param initial_state The initial state. Default = false. 00402 //************************************************************************* 00403 void set(uint16_t valid_count, uint16_t hold_count = 0, uint16_t repeat_count = 0) 00404 { 00405 valid_threshold = valid_count; 00406 hold_threshold = valid_threshold + hold_count; 00407 repeat_threshold = hold_threshold + repeat_count; 00408 } 00409 00410 //************************************************************************* 00411 /// Adds a new sample. 00412 /// Returns 'true' if the debouncer changes state from... 00413 /// 1. Clear to Set. 00414 /// 2. Set to Clear. 00415 /// 3. Not Held to Held. 00416 /// 4. Key repeats. 00417 ///\param sample The new sample. 00418 ///\return 'true' if the debouncer changed state. 00419 //************************************************************************* 00420 bool add(bool sample) 00421 { 00422 debounce_base::add(sample); 00423 00424 if (count < repeat_threshold) 00425 { 00426 ++count; 00427 00428 if (sample) 00429 { 00430 if (count == valid_threshold) 00431 { 00432 if (sample) 00433 { 00434 // Set. 00435 state |= CHANGED; 00436 state |= CURRENT; 00437 } 00438 } 00439 00440 if (hold_threshold != valid_threshold) 00441 { 00442 if ((count == hold_threshold) && sample) 00443 { 00444 // Held. 00445 state |= CHANGED; 00446 state |= HELD; 00447 } 00448 } 00449 00450 if (repeat_threshold != hold_threshold) 00451 { 00452 if ((count == repeat_threshold) && sample) 00453 { 00454 // Repeat. 00455 state |= CHANGED; 00456 state |= REPEATING; 00457 count = hold_threshold; 00458 } 00459 } 00460 00461 state |= LAST; 00462 } 00463 else 00464 { 00465 if (count == valid_threshold) 00466 { 00467 // Clear. 00468 state |= CHANGED; 00469 state &= ~CURRENT; 00470 state &= ~HELD; 00471 state &= ~REPEATING; 00472 } 00473 00474 state &= ~LAST; 00475 } 00476 } 00477 00478 return (state & CHANGED) != 0; 00479 } 00480 00481 private: 00482 00483 uint16_t valid_threshold; 00484 uint16_t hold_threshold; 00485 uint16_t repeat_threshold; 00486 }; 00487 } 00488 00489 #endif 00490
Generated on Tue Jul 12 2022 14:05:40 by
