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 20:36:52 2016 +0000
Revision:
2:26960fb1d783
Parent:
1:fdf67f893a5c
Child:
3:48a593e2d4cf
with mbed lib >=122, the Callback class is used. For older libs it is compatible with older functions. With Callback class also member functions can be used.

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 if(clickFn) clickFn();
JojoS 2:26960fb1d783 147 timer->reset();
JojoS 2:26960fb1d783 148 _state = 1;
JojoS 2:26960fb1d783 149 }
JojoS 2:26960fb1d783 150 break;
jaup 0:62d614796022 151
JojoS 2:26960fb1d783 152 case 1:
JojoS 2:26960fb1d783 153 if(button_level != active) { //released
JojoS 2:26960fb1d783 154 _state = 2;
jaup 0:62d614796022 155
JojoS 2:26960fb1d783 156 } else if(ticks > _pressTicks) {
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 2:26960fb1d783 165 //press event
JojoS 2:26960fb1d783 166 if(pressFn) pressFn(); //press event
JojoS 2:26960fb1d783 167 _state = 0; //reset
jaup 0:62d614796022 168
JojoS 2:26960fb1d783 169 } else if(button_level == active) { //press again
JojoS 2:26960fb1d783 170 if(clickFn) clickFn();
JojoS 2:26960fb1d783 171 _state = 3;
JojoS 2:26960fb1d783 172 }
JojoS 2:26960fb1d783 173 break;
jaup 0:62d614796022 174
JojoS 2:26960fb1d783 175 case 3: //repeat press pressing
JojoS 2:26960fb1d783 176 if(button_level != active) { //double releasd
JojoS 2:26960fb1d783 177 //double click event
JojoS 2:26960fb1d783 178 if(doubleClickFn) doubleClickFn();
JojoS 2:26960fb1d783 179 _state = 0;
JojoS 2:26960fb1d783 180 }
JojoS 2:26960fb1d783 181 break;
jaup 0:62d614796022 182
JojoS 2:26960fb1d783 183 case 5:
JojoS 2:26960fb1d783 184 if(button_level == active) {
JojoS 2:26960fb1d783 185 //continue hold trigger
JojoS 2:26960fb1d783 186 if(duringLongPressFn) duringLongPressFn();
jaup 1:fdf67f893a5c 187
JojoS 2:26960fb1d783 188 } else { //releasd
JojoS 2:26960fb1d783 189 if(longPressStopFn) longPressStopFn();
JojoS 2:26960fb1d783 190 _isLongPressed = 0;
JojoS 2:26960fb1d783 191 _state = 0; //reset
JojoS 2:26960fb1d783 192 }
JojoS 2:26960fb1d783 193 break;
JojoS 2:26960fb1d783 194 }
jaup 1:fdf67f893a5c 195 }
jaup 0:62d614796022 196
jaup 0:62d614796022 197 // end.
jaup 0:62d614796022 198