Library for detecting button clicks, doubleclicks and long press pattern on a single button.
Dependents: OneButton_Example ABBlind
OneButton.cpp@1:fdf67f893a5c, 2016-09-01 (annotated)
- Committer:
- jaup
- Date:
- Thu Sep 01 09:21:00 2016 +0000
- Revision:
- 1:fdf67f893a5c
- Parent:
- 0:62d614796022
frist commit
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 | { |
jaup | 0:62d614796022 | 20 | btn_pin = new DigitalIn((PinName)pin); // sets the MenuPin as input |
jaup | 1:fdf67f893a5c | 21 | |
jaup | 1:fdf67f893a5c | 22 | timer = new Timer; |
jaup | 1:fdf67f893a5c | 23 | timer->start(); |
jaup | 0:62d614796022 | 24 | |
jaup | 1:fdf67f893a5c | 25 | _clickTicks = 400; // number of millisec that have to pass by before a click is detected. |
jaup | 0:62d614796022 | 26 | _pressTicks = 800; // number of millisec that have to pass by before a long button press is detected. |
jaup | 1:fdf67f893a5c | 27 | _debounceTicks = 10; |
jaup | 0:62d614796022 | 28 | |
jaup | 0:62d614796022 | 29 | _state = 0; // starting with state 0: waiting for button to be pressed |
jaup | 0:62d614796022 | 30 | _isLongPressed = false; // Keep track of long press state |
jaup | 0:62d614796022 | 31 | |
jaup | 1:fdf67f893a5c | 32 | button_level = (bool)(btn_pin->read()); |
jaup | 1:fdf67f893a5c | 33 | active = active_level; |
jaup | 1:fdf67f893a5c | 34 | |
jaup | 1:fdf67f893a5c | 35 | if (active_level) { |
jaup | 1:fdf67f893a5c | 36 | // button connects VCC to the pin when pressed. |
jaup | 1:fdf67f893a5c | 37 | btn_pin->mode(PullDown); |
jaup | 0:62d614796022 | 38 | |
jaup | 0:62d614796022 | 39 | } else { |
jaup | 1:fdf67f893a5c | 40 | // turn on pullUp resistor |
jaup | 1:fdf67f893a5c | 41 | btn_pin->mode(PullUp); |
jaup | 1:fdf67f893a5c | 42 | } |
jaup | 0:62d614796022 | 43 | |
jaup | 1:fdf67f893a5c | 44 | _clickFunc = NULL; |
jaup | 1:fdf67f893a5c | 45 | _pressFunc = NULL; |
jaup | 0:62d614796022 | 46 | _doubleClickFunc = NULL; |
jaup | 0:62d614796022 | 47 | _longPressStartFunc = NULL; |
jaup | 0:62d614796022 | 48 | _longPressStopFunc = NULL; |
jaup | 0:62d614796022 | 49 | _duringLongPressFunc = NULL; |
jaup | 0:62d614796022 | 50 | } // OneButton |
jaup | 0:62d614796022 | 51 | |
jaup | 0:62d614796022 | 52 | |
jaup | 0:62d614796022 | 53 | // explicitly set the number of millisec that have to pass by before a click is detected. |
jaup | 0:62d614796022 | 54 | void OneButton::setClickTicks(int ticks) |
jaup | 0:62d614796022 | 55 | { |
jaup | 0:62d614796022 | 56 | _clickTicks = ticks; |
jaup | 0:62d614796022 | 57 | } // setClickTicks |
jaup | 0:62d614796022 | 58 | |
jaup | 0:62d614796022 | 59 | |
jaup | 0:62d614796022 | 60 | // explicitly set the number of millisec that have to pass by before a long button press is detected. |
jaup | 0:62d614796022 | 61 | void OneButton::setPressTicks(int ticks) |
jaup | 0:62d614796022 | 62 | { |
jaup | 0:62d614796022 | 63 | _pressTicks = ticks; |
jaup | 0:62d614796022 | 64 | } // setPressTicks |
jaup | 0:62d614796022 | 65 | |
jaup | 0:62d614796022 | 66 | |
jaup | 0:62d614796022 | 67 | // save function for click event |
jaup | 0:62d614796022 | 68 | void OneButton::attachClick(callbackFunction newFunction) |
jaup | 0:62d614796022 | 69 | { |
jaup | 0:62d614796022 | 70 | _clickFunc = newFunction; |
jaup | 0:62d614796022 | 71 | } // attachClick |
jaup | 0:62d614796022 | 72 | |
jaup | 0:62d614796022 | 73 | |
jaup | 0:62d614796022 | 74 | // save function for doubleClick event |
jaup | 0:62d614796022 | 75 | void OneButton::attachDoubleClick(callbackFunction newFunction) |
jaup | 0:62d614796022 | 76 | { |
jaup | 0:62d614796022 | 77 | _doubleClickFunc = newFunction; |
jaup | 0:62d614796022 | 78 | } // attachDoubleClick |
jaup | 0:62d614796022 | 79 | |
jaup | 0:62d614796022 | 80 | |
jaup | 0:62d614796022 | 81 | // save function for press event |
jaup | 0:62d614796022 | 82 | // DEPRECATED, is replaced by attachLongPressStart, attachLongPressStop, attachDuringLongPress, |
jaup | 0:62d614796022 | 83 | void OneButton::attachPress(callbackFunction newFunction) |
jaup | 0:62d614796022 | 84 | { |
jaup | 0:62d614796022 | 85 | _pressFunc = newFunction; |
jaup | 0:62d614796022 | 86 | } // attachPress |
jaup | 0:62d614796022 | 87 | |
jaup | 0:62d614796022 | 88 | // save function for longPressStart event |
jaup | 0:62d614796022 | 89 | void OneButton::attachLongPressStart(callbackFunction newFunction) |
jaup | 0:62d614796022 | 90 | { |
jaup | 0:62d614796022 | 91 | _longPressStartFunc = newFunction; |
jaup | 0:62d614796022 | 92 | } // attachLongPressStart |
jaup | 0:62d614796022 | 93 | |
jaup | 0:62d614796022 | 94 | // save function for longPressStop event |
jaup | 0:62d614796022 | 95 | void OneButton::attachLongPressStop(callbackFunction newFunction) |
jaup | 0:62d614796022 | 96 | { |
jaup | 0:62d614796022 | 97 | _longPressStopFunc = newFunction; |
jaup | 0:62d614796022 | 98 | } // attachLongPressStop |
jaup | 0:62d614796022 | 99 | |
jaup | 0:62d614796022 | 100 | // save function for during longPress event |
jaup | 0:62d614796022 | 101 | void OneButton::attachDuringLongPress(callbackFunction newFunction) |
jaup | 0:62d614796022 | 102 | { |
jaup | 0:62d614796022 | 103 | _duringLongPressFunc = newFunction; |
jaup | 0:62d614796022 | 104 | } // attachDuringLongPress |
jaup | 0:62d614796022 | 105 | |
jaup | 0:62d614796022 | 106 | // function to get the current long pressed state |
jaup | 0:62d614796022 | 107 | bool OneButton::isLongPressed() |
jaup | 0:62d614796022 | 108 | { |
jaup | 0:62d614796022 | 109 | return _isLongPressed; |
jaup | 0:62d614796022 | 110 | } |
jaup | 0:62d614796022 | 111 | |
jaup | 1:fdf67f893a5c | 112 | /** |
jaup | 1:fdf67f893a5c | 113 | * @brief Button driver core function, driver state machine. |
jaup | 1:fdf67f893a5c | 114 | * @param handle: the button handle strcut. |
jaup | 1:fdf67f893a5c | 115 | * @retval None |
jaup | 1:fdf67f893a5c | 116 | */ |
jaup | 0:62d614796022 | 117 | void OneButton::tick(void) |
jaup | 0:62d614796022 | 118 | { |
jaup | 1:fdf67f893a5c | 119 | int read_gpio_level = btn_pin->read(); // current button signal. |
jaup | 0:62d614796022 | 120 | |
jaup | 1:fdf67f893a5c | 121 | /*------------button debounce handle---------------*/ |
jaup | 1:fdf67f893a5c | 122 | if(ticks != timer->read_ms()) { //1ms scan again. |
jaup | 1:fdf67f893a5c | 123 | if(read_gpio_level != button_level) { |
jaup | 1:fdf67f893a5c | 124 | //continue read 'debounce_cnt' times same new level change |
jaup | 1:fdf67f893a5c | 125 | if(++_debounce_cnt >= _debounceTicks) { |
jaup | 1:fdf67f893a5c | 126 | button_level = read_gpio_level; |
jaup | 1:fdf67f893a5c | 127 | _debounce_cnt = 0; |
jaup | 1:fdf67f893a5c | 128 | } |
jaup | 0:62d614796022 | 129 | |
jaup | 1:fdf67f893a5c | 130 | } else { //leved not change ,counter reset. |
jaup | 1:fdf67f893a5c | 131 | _debounce_cnt = 0; |
jaup | 1:fdf67f893a5c | 132 | } |
jaup | 1:fdf67f893a5c | 133 | } |
jaup | 0:62d614796022 | 134 | |
jaup | 1:fdf67f893a5c | 135 | //current (relative) time in msecs. |
jaup | 1:fdf67f893a5c | 136 | ticks = (uint16_t)(timer->read_ms()); |
jaup | 0:62d614796022 | 137 | |
jaup | 1:fdf67f893a5c | 138 | /*-----------------State machine-------------------*/ |
jaup | 1:fdf67f893a5c | 139 | switch (_state) { |
jaup | 1:fdf67f893a5c | 140 | case 0: |
jaup | 1:fdf67f893a5c | 141 | if(button_level == active) { //start press |
jaup | 1:fdf67f893a5c | 142 | if(_clickFunc) _clickFunc(); |
jaup | 1:fdf67f893a5c | 143 | timer->reset(); |
jaup | 1:fdf67f893a5c | 144 | _state = 1; |
jaup | 1:fdf67f893a5c | 145 | } |
jaup | 1:fdf67f893a5c | 146 | break; |
jaup | 0:62d614796022 | 147 | |
jaup | 1:fdf67f893a5c | 148 | case 1: |
jaup | 1:fdf67f893a5c | 149 | if(button_level != active) { //released |
jaup | 1:fdf67f893a5c | 150 | _state = 2; |
jaup | 0:62d614796022 | 151 | |
jaup | 1:fdf67f893a5c | 152 | } else if(ticks > _pressTicks) { |
jaup | 1:fdf67f893a5c | 153 | if(_longPressStartFunc) _longPressStartFunc(); |
jaup | 1:fdf67f893a5c | 154 | _isLongPressed = 1; |
jaup | 1:fdf67f893a5c | 155 | _state = 5; |
jaup | 1:fdf67f893a5c | 156 | } |
jaup | 1:fdf67f893a5c | 157 | break; |
jaup | 0:62d614796022 | 158 | |
jaup | 1:fdf67f893a5c | 159 | case 2: |
jaup | 1:fdf67f893a5c | 160 | if(ticks > _clickTicks) { //released |
jaup | 1:fdf67f893a5c | 161 | //press event |
jaup | 1:fdf67f893a5c | 162 | if(_pressFunc) _pressFunc(); //press event |
jaup | 1:fdf67f893a5c | 163 | _state = 0; //reset |
jaup | 0:62d614796022 | 164 | |
jaup | 1:fdf67f893a5c | 165 | } else if(button_level == active) { //press again |
jaup | 1:fdf67f893a5c | 166 | if(_clickFunc) _clickFunc(); |
jaup | 1:fdf67f893a5c | 167 | _state = 3; |
jaup | 1:fdf67f893a5c | 168 | } |
jaup | 1:fdf67f893a5c | 169 | break; |
jaup | 0:62d614796022 | 170 | |
jaup | 1:fdf67f893a5c | 171 | case 3: //repeat press pressing |
jaup | 1:fdf67f893a5c | 172 | if(button_level != active) { //double releasd |
jaup | 1:fdf67f893a5c | 173 | //double click event |
jaup | 1:fdf67f893a5c | 174 | if(_doubleClickFunc) _doubleClickFunc(); |
jaup | 1:fdf67f893a5c | 175 | _state = 0; |
jaup | 1:fdf67f893a5c | 176 | } |
jaup | 1:fdf67f893a5c | 177 | break; |
jaup | 0:62d614796022 | 178 | |
jaup | 1:fdf67f893a5c | 179 | case 5: |
jaup | 1:fdf67f893a5c | 180 | if(button_level == active) { |
jaup | 1:fdf67f893a5c | 181 | //continue hold trigger |
jaup | 1:fdf67f893a5c | 182 | if(_duringLongPressFunc) _duringLongPressFunc(); |
jaup | 1:fdf67f893a5c | 183 | |
jaup | 1:fdf67f893a5c | 184 | } else { //releasd |
jaup | 0:62d614796022 | 185 | if(_longPressStopFunc) _longPressStopFunc(); |
jaup | 1:fdf67f893a5c | 186 | _isLongPressed = 0; |
jaup | 1:fdf67f893a5c | 187 | _state = 0; //reset |
jaup | 1:fdf67f893a5c | 188 | } |
jaup | 1:fdf67f893a5c | 189 | break; |
jaup | 1:fdf67f893a5c | 190 | } |
jaup | 1:fdf67f893a5c | 191 | } |
jaup | 0:62d614796022 | 192 | |
jaup | 0:62d614796022 | 193 | // end. |
jaup | 0:62d614796022 | 194 |