Debounce a mechanical switch by periodic sampling.

Dependents:   RedButton WS_7_Seg_mit_LM1635 WS_7_Seg_mit_LM1635 Lichtschalter_M0 ... more

Committer:
huliyang
Date:
Mon May 18 12:57:27 2015 +0000
Revision:
0:2359961af424
Child:
1:e59480cf6c72
init

Who changed what in which revision?

UserRevisionLine numberNew contents of line
huliyang 0:2359961af424 1 /* Copyright (c) 2015 Liyang HU, MIT License
huliyang 0:2359961af424 2 *
huliyang 0:2359961af424 3 * Permission is hereby granted, free of charge, to any person obtaining
huliyang 0:2359961af424 4 * a copy of this software and associated documentation files (the
huliyang 0:2359961af424 5 * "Software"), to deal in the Software without restriction, including
huliyang 0:2359961af424 6 * without limitation the rights to use, copy, modify, merge, publish,
huliyang 0:2359961af424 7 * distribute, sublicense, and/or sell copies of the Software, and to
huliyang 0:2359961af424 8 * permit persons to whom the Software is furnished to do so, subject to
huliyang 0:2359961af424 9 * the following conditions:
huliyang 0:2359961af424 10 *
huliyang 0:2359961af424 11 * The above copyright notice and this permission notice shall be
huliyang 0:2359961af424 12 * included in all copies or substantial portions of the Software.
huliyang 0:2359961af424 13 *
huliyang 0:2359961af424 14 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
huliyang 0:2359961af424 15 * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
huliyang 0:2359961af424 16 * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
huliyang 0:2359961af424 17 * IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
huliyang 0:2359961af424 18 * CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
huliyang 0:2359961af424 19 * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
huliyang 0:2359961af424 20 * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
huliyang 0:2359961af424 21 */
huliyang 0:2359961af424 22
huliyang 0:2359961af424 23 #include <mbed.h>
huliyang 0:2359961af424 24 #include <Debouncer.h>
huliyang 0:2359961af424 25
huliyang 0:2359961af424 26 /*! \class Debouncer
huliyang 0:2359961af424 27 * \brief Debounce a mechanical switch by periodic sampling.
huliyang 0:2359961af424 28 * \code
huliyang 0:2359961af424 29 FIXME: EXAMPLE HERE
huliyang 0:2359961af424 30 * \endcode
huliyang 0:2359961af424 31 * \note This implements \a DebounceSwitch2() as described by
huliyang 0:2359961af424 32 * http://www.ganssle.com/debouncing-pt2.htm
huliyang 0:2359961af424 33 * \note In particular, directly hooking up a mechanical switch as an
huliyang 0:2359961af424 34 * interrupt will not suffice: in general, the signal will not always
huliyang 0:2359961af424 35 * satisfy any arbitrary processor's interrupt pin's min clock width,
huliyang 0:2359961af424 36 * data setup nor hold times & c., and will not trigger reliably.
huliyang 0:2359961af424 37 */
huliyang 0:2359961af424 38
huliyang 0:2359961af424 39 void Debouncer::tick(void)
huliyang 0:2359961af424 40 {
huliyang 0:2359961af424 41 previous = (previous << 1) | in;
huliyang 0:2359961af424 42 uint32_t rise = (1 << _samples) - 1;
huliyang 0:2359961af424 43 uint32_t window = rise + rise + 1;
huliyang 0:2359961af424 44 uint32_t recent = previous & window;
huliyang 0:2359961af424 45 if(recent == rise)
huliyang 0:2359961af424 46 {
huliyang 0:2359961af424 47 if(!now) fun_rise.call();
huliyang 0:2359961af424 48 now = true;
huliyang 0:2359961af424 49 }
huliyang 0:2359961af424 50 else if(recent == (window & ~rise))
huliyang 0:2359961af424 51 {
huliyang 0:2359961af424 52 if(now) fun_fall.call();
huliyang 0:2359961af424 53 now = false;
huliyang 0:2359961af424 54 }
huliyang 0:2359961af424 55 }
huliyang 0:2359961af424 56
huliyang 0:2359961af424 57 //! Create a \a Debouncer attached to the specified \a pin.
huliyang 0:2359961af424 58 //! \param pin Pin to poll.
huliyang 0:2359961af424 59 //! \param mode Pin mode, e.g. \a PullUp or \a PullDown.
huliyang 0:2359961af424 60 Debouncer::Debouncer(PinName pin, PinMode mode)
huliyang 0:2359961af424 61 : in(pin, mode), now(mode == PullUp), previous(mode == PullUp ? -1 : 0)
huliyang 0:2359961af424 62 {
huliyang 0:2359961af424 63 samples(); period();
huliyang 0:2359961af424 64 }
huliyang 0:2359961af424 65
huliyang 0:2359961af424 66 //! Set the number of identical samples needed to regard the input as stable.
huliyang 0:2359961af424 67 //! \note Limited to at most 32 samples.
huliyang 0:2359961af424 68 Debouncer &Debouncer::samples(int n)
huliyang 0:2359961af424 69 {
huliyang 0:2359961af424 70 _samples = n;
huliyang 0:2359961af424 71 return *this;
huliyang 0:2359961af424 72 }
huliyang 0:2359961af424 73
huliyang 0:2359961af424 74 //! Set the time period between samples.
huliyang 0:2359961af424 75 Debouncer &Debouncer::period(float seconds)
huliyang 0:2359961af424 76 {
huliyang 0:2359961af424 77 detach();
huliyang 0:2359961af424 78 attach(this, &Debouncer::tick, seconds);
huliyang 0:2359961af424 79 return *this;
huliyang 0:2359961af424 80 }
huliyang 0:2359961af424 81
huliyang 0:2359961af424 82 //! Get the current stable state of the input.
huliyang 0:2359961af424 83 Debouncer::operator bool(void) { return now; }
huliyang 0:2359961af424 84
huliyang 0:2359961af424 85 //! Attach a function to call when the stable state falls.
huliyang 0:2359961af424 86 Debouncer &Debouncer::attach_fall(void (*fun)(void))
huliyang 0:2359961af424 87 {
huliyang 0:2359961af424 88 fun_fall.attach(fun);
huliyang 0:2359961af424 89 return *this;
huliyang 0:2359961af424 90 }
huliyang 0:2359961af424 91
huliyang 0:2359961af424 92 //! Attach a function to call when the stable state rises.
huliyang 0:2359961af424 93 Debouncer &Debouncer::attach_rise(void (*fun)(void))
huliyang 0:2359961af424 94 {
huliyang 0:2359961af424 95 fun_rise.attach(fun);
huliyang 0:2359961af424 96 return *this;
huliyang 0:2359961af424 97 }
huliyang 0:2359961af424 98
huliyang 0:2359961af424 99 //! Attach a member function to call when the stable state falls.
huliyang 0:2359961af424 100 template <typename T>
huliyang 0:2359961af424 101 Debouncer &Debouncer::attach_fall(T *obj, void (T::*fun)(void))
huliyang 0:2359961af424 102 {
huliyang 0:2359961af424 103 fun_fall.attach(obj, fun);
huliyang 0:2359961af424 104 return *this;
huliyang 0:2359961af424 105 }
huliyang 0:2359961af424 106
huliyang 0:2359961af424 107 //! Attach a member function to call when the stable state rises.
huliyang 0:2359961af424 108 template <typename T>
huliyang 0:2359961af424 109 Debouncer &Debouncer::attach_rise(T *obj, void (T::*fun)(void))
huliyang 0:2359961af424 110 {
huliyang 0:2359961af424 111 fun_rise.attach(obj, fun);
huliyang 0:2359961af424 112 return *this;
huliyang 0:2359961af424 113 }