Debounce a mechanical switch by periodic sampling.
Dependents: RedButton WS_7_Seg_mit_LM1635 WS_7_Seg_mit_LM1635 Lichtschalter_M0 ... more
Debouncer.cpp@1:e59480cf6c72, 2015-05-18 (annotated)
- Committer:
- huliyang
- Date:
- Mon May 18 13:08:33 2015 +0000
- Revision:
- 1:e59480cf6c72
- Parent:
- 0:2359961af424
- Child:
- 2:7f2f00805d41
Debouncer: example
Who changed what in which revision?
User | Revision | Line number | New 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 | 0:2359961af424 | 71 | : in(pin, mode), now(mode == PullUp), previous(mode == PullUp ? -1 : 0) |
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 | 0:2359961af424 | 78 | Debouncer &Debouncer::samples(int 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 | } |