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.

Dependents:   ECH_V004

Fork of OneButton by Zibin Zheng

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?

UserRevisionLine numberNew 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