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 13:25:07 2015 +0000
Revision:
2:7f2f00805d41
Parent:
1:e59480cf6c72
Debouncer: re-order fields for better alignment & packing

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 1:e59480cf6c72 29 #include <mbed.h>
huliyang 1:e59480cf6c72 30 #include <Pulsator.h>
huliyang 1:e59480cf6c72 31
huliyang 1:e59480cf6c72 32 Debouncer butt(PI_BUTTON);
huliyang 1:e59480cf6c72 33 void fall(void) { puts("Pushed!"); }
huliyang 1:e59480cf6c72 34 void rise(void) { puts("Released!"); }
huliyang 1:e59480cf6c72 35
huliyang 1:e59480cf6c72 36 int main(void) {
huliyang 1:e59480cf6c72 37 butt.attach_fall(&fall).attach_rise(&rise);
huliyang 1:e59480cf6c72 38 while(true) wait(1.0f);
huliyang 1:e59480cf6c72 39 }
huliyang 0:2359961af424 40 * \endcode
huliyang 0:2359961af424 41 * \note This implements \a DebounceSwitch2() as described by
huliyang 0:2359961af424 42 * http://www.ganssle.com/debouncing-pt2.htm
huliyang 0:2359961af424 43 * \note In particular, directly hooking up a mechanical switch as an
huliyang 0:2359961af424 44 * interrupt will not suffice: in general, the signal will not always
huliyang 0:2359961af424 45 * satisfy any arbitrary processor's interrupt pin's min clock width,
huliyang 1:e59480cf6c72 46 * data setup nor hold times & c., and so will not trigger reliably.
huliyang 0:2359961af424 47 */
huliyang 0:2359961af424 48
huliyang 0:2359961af424 49 void Debouncer::tick(void)
huliyang 0:2359961af424 50 {
huliyang 0:2359961af424 51 previous = (previous << 1) | in;
huliyang 0:2359961af424 52 uint32_t rise = (1 << _samples) - 1;
huliyang 0:2359961af424 53 uint32_t window = rise + rise + 1;
huliyang 0:2359961af424 54 uint32_t recent = previous & window;
huliyang 0:2359961af424 55 if(recent == rise)
huliyang 0:2359961af424 56 {
huliyang 0:2359961af424 57 if(!now) fun_rise.call();
huliyang 0:2359961af424 58 now = true;
huliyang 0:2359961af424 59 }
huliyang 0:2359961af424 60 else if(recent == (window & ~rise))
huliyang 0:2359961af424 61 {
huliyang 0:2359961af424 62 if(now) fun_fall.call();
huliyang 0:2359961af424 63 now = false;
huliyang 0:2359961af424 64 }
huliyang 0:2359961af424 65 }
huliyang 0:2359961af424 66
huliyang 0:2359961af424 67 //! Create a \a Debouncer attached to the specified \a pin.
huliyang 0:2359961af424 68 //! \param pin Pin to poll.
huliyang 0:2359961af424 69 //! \param mode Pin mode, e.g. \a PullUp or \a PullDown.
huliyang 0:2359961af424 70 Debouncer::Debouncer(PinName pin, PinMode mode)
huliyang 2:7f2f00805d41 71 : in(pin, mode), previous(mode == PullUp ? -1 : 0), now(mode == PullUp)
huliyang 0:2359961af424 72 {
huliyang 0:2359961af424 73 samples(); period();
huliyang 0:2359961af424 74 }
huliyang 0:2359961af424 75
huliyang 0:2359961af424 76 //! Set the number of identical samples needed to regard the input as stable.
huliyang 0:2359961af424 77 //! \note Limited to at most 32 samples.
huliyang 2:7f2f00805d41 78 Debouncer &Debouncer::samples(uint8_t n)
huliyang 0:2359961af424 79 {
huliyang 0:2359961af424 80 _samples = n;
huliyang 0:2359961af424 81 return *this;
huliyang 0:2359961af424 82 }
huliyang 0:2359961af424 83
huliyang 0:2359961af424 84 //! Set the time period between samples.
huliyang 0:2359961af424 85 Debouncer &Debouncer::period(float seconds)
huliyang 0:2359961af424 86 {
huliyang 0:2359961af424 87 detach();
huliyang 0:2359961af424 88 attach(this, &Debouncer::tick, seconds);
huliyang 0:2359961af424 89 return *this;
huliyang 0:2359961af424 90 }
huliyang 0:2359961af424 91
huliyang 0:2359961af424 92 //! Get the current stable state of the input.
huliyang 0:2359961af424 93 Debouncer::operator bool(void) { return now; }
huliyang 0:2359961af424 94
huliyang 0:2359961af424 95 //! Attach a function to call when the stable state falls.
huliyang 0:2359961af424 96 Debouncer &Debouncer::attach_fall(void (*fun)(void))
huliyang 0:2359961af424 97 {
huliyang 0:2359961af424 98 fun_fall.attach(fun);
huliyang 0:2359961af424 99 return *this;
huliyang 0:2359961af424 100 }
huliyang 0:2359961af424 101
huliyang 0:2359961af424 102 //! Attach a function to call when the stable state rises.
huliyang 0:2359961af424 103 Debouncer &Debouncer::attach_rise(void (*fun)(void))
huliyang 0:2359961af424 104 {
huliyang 0:2359961af424 105 fun_rise.attach(fun);
huliyang 0:2359961af424 106 return *this;
huliyang 0:2359961af424 107 }
huliyang 0:2359961af424 108
huliyang 0:2359961af424 109 //! Attach a member function to call when the stable state falls.
huliyang 0:2359961af424 110 template <typename T>
huliyang 0:2359961af424 111 Debouncer &Debouncer::attach_fall(T *obj, void (T::*fun)(void))
huliyang 0:2359961af424 112 {
huliyang 0:2359961af424 113 fun_fall.attach(obj, fun);
huliyang 0:2359961af424 114 return *this;
huliyang 0:2359961af424 115 }
huliyang 0:2359961af424 116
huliyang 0:2359961af424 117 //! Attach a member function to call when the stable state rises.
huliyang 0:2359961af424 118 template <typename T>
huliyang 0:2359961af424 119 Debouncer &Debouncer::attach_rise(T *obj, void (T::*fun)(void))
huliyang 0:2359961af424 120 {
huliyang 0:2359961af424 121 fun_rise.attach(obj, fun);
huliyang 0:2359961af424 122 return *this;
huliyang 0:2359961af424 123 }