Library for detecting button clicks, doubleclicks and long press pattern on a single button. Updated to use Callback class when mbed lib >= 122 is used. Then also member functions can be used as callbacks.
Fork of OneButton by
OneButton.cpp@3:48a593e2d4cf, 2016-09-22 (annotated)
- Committer:
- JojoS
- Date:
- Thu Sep 22 21:46:37 2016 +0000
- Revision:
- 3:48a593e2d4cf
- Parent:
- 2:26960fb1d783
reverted to original state machine behaviour by mh. This works better for detecting click / double click events.
Who changed what in which revision?
User | Revision | Line number | New contents of line |
---|---|---|---|
jaup | 1:fdf67f893a5c | 1 | // Modifyed to support mbed environment, rewrite the state machine. |
jaup | 1:fdf67f893a5c | 2 | // by Zibin Zheng <znbin@qq.com> |
jaup | 1:fdf67f893a5c | 3 | |
jaup | 0:62d614796022 | 4 | // ----- |
jaup | 0:62d614796022 | 5 | // OneButton.cpp - Library for detecting button clicks, doubleclicks and long press pattern on a single button. |
jaup | 0:62d614796022 | 6 | // This class is implemented for use with the Arduino environment. |
jaup | 0:62d614796022 | 7 | // Copyright (c) by Matthias Hertel, http://www.mathertel.de |
jaup | 0:62d614796022 | 8 | // This work is licensed under a BSD style license. See http://www.mathertel.de/License.aspx |
jaup | 0:62d614796022 | 9 | // More information on: http://www.mathertel.de/Arduino |
jaup | 0:62d614796022 | 10 | // ----- |
jaup | 1:fdf67f893a5c | 11 | |
jaup | 0:62d614796022 | 12 | |
jaup | 0:62d614796022 | 13 | #include "OneButton.h" |
jaup | 0:62d614796022 | 14 | |
jaup | 1:fdf67f893a5c | 15 | |
jaup | 0:62d614796022 | 16 | // ----- Initialization and Default Values ----- |
jaup | 0:62d614796022 | 17 | |
jaup | 1:fdf67f893a5c | 18 | OneButton::OneButton(PinName pin, bool active_level) |
jaup | 0:62d614796022 | 19 | { |
JojoS | 2:26960fb1d783 | 20 | btn_pin = new DigitalIn((PinName)pin); // sets the MenuPin as input |
jaup | 1:fdf67f893a5c | 21 | |
JojoS | 2:26960fb1d783 | 22 | timer = new Timer; |
JojoS | 2:26960fb1d783 | 23 | timer->start(); |
jaup | 0:62d614796022 | 24 | |
JojoS | 2:26960fb1d783 | 25 | _clickTicks = 400; // number of millisec that have to pass by before a click is detected. |
JojoS | 2:26960fb1d783 | 26 | _pressTicks = 800; // number of millisec that have to pass by before a long button press is detected. |
JojoS | 2:26960fb1d783 | 27 | _debounceTicks = 10; |
jaup | 0:62d614796022 | 28 | |
JojoS | 2:26960fb1d783 | 29 | _state = 0; // starting with state 0: waiting for button to be pressed |
JojoS | 2:26960fb1d783 | 30 | _isLongPressed = false; // Keep track of long press state |
jaup | 0:62d614796022 | 31 | |
JojoS | 2:26960fb1d783 | 32 | button_level = (bool)(btn_pin->read()); |
JojoS | 2:26960fb1d783 | 33 | active = active_level; |
jaup | 1:fdf67f893a5c | 34 | |
JojoS | 2:26960fb1d783 | 35 | if (active_level) { |
JojoS | 2:26960fb1d783 | 36 | // button connects VCC to the pin when pressed. |
JojoS | 2:26960fb1d783 | 37 | btn_pin->mode(PullDown); |
JojoS | 2:26960fb1d783 | 38 | |
JojoS | 2:26960fb1d783 | 39 | } else { |
JojoS | 2:26960fb1d783 | 40 | // turn on pullUp resistor |
JojoS | 2:26960fb1d783 | 41 | btn_pin->mode(PullUp); |
JojoS | 2:26960fb1d783 | 42 | } |
jaup | 0:62d614796022 | 43 | |
JojoS | 2:26960fb1d783 | 44 | #if (MBED_LIBRARY_VERSION < 122) |
JojoS | 2:26960fb1d783 | 45 | clickFn = NULL; |
JojoS | 2:26960fb1d783 | 46 | pressFn = NULL; |
JojoS | 2:26960fb1d783 | 47 | doubleClickFn = NULL; |
JojoS | 2:26960fb1d783 | 48 | longPressStartFn = NULL; |
JojoS | 2:26960fb1d783 | 49 | longPressStopFn = NULL; |
JojoS | 2:26960fb1d783 | 50 | duringLongPressFn = NULL; |
JojoS | 2:26960fb1d783 | 51 | #endif |
jaup | 0:62d614796022 | 52 | } // OneButton |
jaup | 0:62d614796022 | 53 | |
jaup | 0:62d614796022 | 54 | |
jaup | 0:62d614796022 | 55 | // explicitly set the number of millisec that have to pass by before a click is detected. |
jaup | 0:62d614796022 | 56 | void OneButton::setClickTicks(int ticks) |
jaup | 0:62d614796022 | 57 | { |
JojoS | 2:26960fb1d783 | 58 | _clickTicks = ticks; |
jaup | 0:62d614796022 | 59 | } // setClickTicks |
jaup | 0:62d614796022 | 60 | |
jaup | 0:62d614796022 | 61 | |
jaup | 0:62d614796022 | 62 | // explicitly set the number of millisec that have to pass by before a long button press is detected. |
jaup | 0:62d614796022 | 63 | void OneButton::setPressTicks(int ticks) |
jaup | 0:62d614796022 | 64 | { |
JojoS | 2:26960fb1d783 | 65 | _pressTicks = ticks; |
jaup | 0:62d614796022 | 66 | } // setPressTicks |
jaup | 0:62d614796022 | 67 | |
jaup | 0:62d614796022 | 68 | |
JojoS | 2:26960fb1d783 | 69 | #if (MBED_LIBRARY_VERSION < 122) |
jaup | 0:62d614796022 | 70 | // save function for click event |
jaup | 0:62d614796022 | 71 | void OneButton::attachClick(callbackFunction newFunction) |
jaup | 0:62d614796022 | 72 | { |
JojoS | 2:26960fb1d783 | 73 | clickFn = newFunction; |
jaup | 0:62d614796022 | 74 | } // attachClick |
jaup | 0:62d614796022 | 75 | |
jaup | 0:62d614796022 | 76 | |
jaup | 0:62d614796022 | 77 | // save function for doubleClick event |
jaup | 0:62d614796022 | 78 | void OneButton::attachDoubleClick(callbackFunction newFunction) |
jaup | 0:62d614796022 | 79 | { |
JojoS | 2:26960fb1d783 | 80 | doubleClickFn = newFunction; |
jaup | 0:62d614796022 | 81 | } // attachDoubleClick |
jaup | 0:62d614796022 | 82 | |
jaup | 0:62d614796022 | 83 | |
jaup | 0:62d614796022 | 84 | // save function for press event |
jaup | 0:62d614796022 | 85 | // DEPRECATED, is replaced by attachLongPressStart, attachLongPressStop, attachDuringLongPress, |
jaup | 0:62d614796022 | 86 | void OneButton::attachPress(callbackFunction newFunction) |
jaup | 0:62d614796022 | 87 | { |
JojoS | 2:26960fb1d783 | 88 | pressFn = newFunction; |
jaup | 0:62d614796022 | 89 | } // attachPress |
jaup | 0:62d614796022 | 90 | |
jaup | 0:62d614796022 | 91 | // save function for longPressStart event |
jaup | 0:62d614796022 | 92 | void OneButton::attachLongPressStart(callbackFunction newFunction) |
jaup | 0:62d614796022 | 93 | { |
JojoS | 2:26960fb1d783 | 94 | longPressStartFn = newFunction; |
jaup | 0:62d614796022 | 95 | } // attachLongPressStart |
jaup | 0:62d614796022 | 96 | |
jaup | 0:62d614796022 | 97 | // save function for longPressStop event |
jaup | 0:62d614796022 | 98 | void OneButton::attachLongPressStop(callbackFunction newFunction) |
jaup | 0:62d614796022 | 99 | { |
JojoS | 2:26960fb1d783 | 100 | longPressStopFn = newFunction; |
jaup | 0:62d614796022 | 101 | } // attachLongPressStop |
jaup | 0:62d614796022 | 102 | |
jaup | 0:62d614796022 | 103 | // save function for during longPress event |
jaup | 0:62d614796022 | 104 | void OneButton::attachDuringLongPress(callbackFunction newFunction) |
jaup | 0:62d614796022 | 105 | { |
JojoS | 2:26960fb1d783 | 106 | duringLongPressFn = newFunction; |
jaup | 0:62d614796022 | 107 | } // attachDuringLongPress |
JojoS | 2:26960fb1d783 | 108 | #endif |
jaup | 0:62d614796022 | 109 | |
jaup | 0:62d614796022 | 110 | // function to get the current long pressed state |
jaup | 0:62d614796022 | 111 | bool OneButton::isLongPressed() |
jaup | 0:62d614796022 | 112 | { |
JojoS | 2:26960fb1d783 | 113 | return _isLongPressed; |
jaup | 0:62d614796022 | 114 | } |
jaup | 0:62d614796022 | 115 | |
jaup | 1:fdf67f893a5c | 116 | /** |
jaup | 1:fdf67f893a5c | 117 | * @brief Button driver core function, driver state machine. |
jaup | 1:fdf67f893a5c | 118 | * @param handle: the button handle strcut. |
jaup | 1:fdf67f893a5c | 119 | * @retval None |
jaup | 1:fdf67f893a5c | 120 | */ |
jaup | 0:62d614796022 | 121 | void OneButton::tick(void) |
jaup | 0:62d614796022 | 122 | { |
JojoS | 2:26960fb1d783 | 123 | int read_gpio_level = btn_pin->read(); // current button signal. |
jaup | 0:62d614796022 | 124 | |
JojoS | 2:26960fb1d783 | 125 | /*------------button debounce handle---------------*/ |
JojoS | 2:26960fb1d783 | 126 | if(ticks != timer->read_ms()) { //1ms scan again. |
JojoS | 2:26960fb1d783 | 127 | if(read_gpio_level != button_level) { |
JojoS | 2:26960fb1d783 | 128 | //continue read 'debounce_cnt' times same new level change |
JojoS | 2:26960fb1d783 | 129 | if(++_debounce_cnt >= _debounceTicks) { |
JojoS | 2:26960fb1d783 | 130 | button_level = read_gpio_level; |
JojoS | 2:26960fb1d783 | 131 | _debounce_cnt = 0; |
JojoS | 2:26960fb1d783 | 132 | } |
jaup | 0:62d614796022 | 133 | |
JojoS | 2:26960fb1d783 | 134 | } else { //leved not change ,counter reset. |
JojoS | 2:26960fb1d783 | 135 | _debounce_cnt = 0; |
JojoS | 2:26960fb1d783 | 136 | } |
JojoS | 2:26960fb1d783 | 137 | } |
jaup | 0:62d614796022 | 138 | |
JojoS | 2:26960fb1d783 | 139 | //current (relative) time in msecs. |
JojoS | 2:26960fb1d783 | 140 | ticks = timer->read_ms(); |
jaup | 0:62d614796022 | 141 | |
JojoS | 2:26960fb1d783 | 142 | /*-----------------State machine-------------------*/ |
JojoS | 2:26960fb1d783 | 143 | switch (_state) { |
JojoS | 2:26960fb1d783 | 144 | case 0: |
JojoS | 2:26960fb1d783 | 145 | if(button_level == active) { //start press |
JojoS | 2:26960fb1d783 | 146 | timer->reset(); |
JojoS | 2:26960fb1d783 | 147 | _state = 1; |
JojoS | 2:26960fb1d783 | 148 | } |
JojoS | 2:26960fb1d783 | 149 | break; |
jaup | 0:62d614796022 | 150 | |
JojoS | 2:26960fb1d783 | 151 | case 1: |
JojoS | 2:26960fb1d783 | 152 | if(button_level != active) { //released |
JojoS | 2:26960fb1d783 | 153 | _state = 2; |
jaup | 0:62d614796022 | 154 | |
JojoS | 2:26960fb1d783 | 155 | } else if(ticks > _pressTicks) { |
JojoS | 3:48a593e2d4cf | 156 | if(pressFn) pressFn(); //press event |
JojoS | 2:26960fb1d783 | 157 | if(longPressStartFn) longPressStartFn(); |
JojoS | 2:26960fb1d783 | 158 | _isLongPressed = 1; |
JojoS | 2:26960fb1d783 | 159 | _state = 5; |
JojoS | 2:26960fb1d783 | 160 | } |
JojoS | 2:26960fb1d783 | 161 | break; |
jaup | 0:62d614796022 | 162 | |
JojoS | 2:26960fb1d783 | 163 | case 2: |
JojoS | 2:26960fb1d783 | 164 | if(ticks > _clickTicks) { //released |
JojoS | 3:48a593e2d4cf | 165 | if (clickFn) clickFn(); |
JojoS | 2:26960fb1d783 | 166 | _state = 0; //reset |
jaup | 0:62d614796022 | 167 | |
JojoS | 2:26960fb1d783 | 168 | } else if(button_level == active) { //press again |
JojoS | 2:26960fb1d783 | 169 | _state = 3; |
JojoS | 2:26960fb1d783 | 170 | } |
JojoS | 2:26960fb1d783 | 171 | break; |
jaup | 0:62d614796022 | 172 | |
JojoS | 2:26960fb1d783 | 173 | case 3: //repeat press pressing |
JojoS | 2:26960fb1d783 | 174 | if(button_level != active) { //double releasd |
JojoS | 2:26960fb1d783 | 175 | //double click event |
JojoS | 2:26960fb1d783 | 176 | if(doubleClickFn) doubleClickFn(); |
JojoS | 2:26960fb1d783 | 177 | _state = 0; |
JojoS | 2:26960fb1d783 | 178 | } |
JojoS | 2:26960fb1d783 | 179 | break; |
jaup | 0:62d614796022 | 180 | |
JojoS | 2:26960fb1d783 | 181 | case 5: |
JojoS | 2:26960fb1d783 | 182 | if(button_level == active) { |
JojoS | 2:26960fb1d783 | 183 | //continue hold trigger |
JojoS | 2:26960fb1d783 | 184 | if(duringLongPressFn) duringLongPressFn(); |
jaup | 1:fdf67f893a5c | 185 | |
JojoS | 2:26960fb1d783 | 186 | } else { //releasd |
JojoS | 2:26960fb1d783 | 187 | if(longPressStopFn) longPressStopFn(); |
JojoS | 2:26960fb1d783 | 188 | _isLongPressed = 0; |
JojoS | 2:26960fb1d783 | 189 | _state = 0; //reset |
JojoS | 2:26960fb1d783 | 190 | } |
JojoS | 2:26960fb1d783 | 191 | break; |
JojoS | 2:26960fb1d783 | 192 | } |
jaup | 1:fdf67f893a5c | 193 | } |
jaup | 0:62d614796022 | 194 | |
jaup | 0:62d614796022 | 195 | // end. |
jaup | 0:62d614796022 | 196 |