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
- Committer:
- JojoS
- Date:
- 2016-09-22
- Revision:
- 3:48a593e2d4cf
- Parent:
- 2:26960fb1d783
File content as of revision 3:48a593e2d4cf:
// Modifyed to support mbed environment, rewrite the state machine. // by Zibin Zheng <znbin@qq.com> // ----- // OneButton.cpp - Library for detecting button clicks, doubleclicks and long press pattern on a single button. // This class is implemented for use with the Arduino environment. // Copyright (c) by Matthias Hertel, http://www.mathertel.de // This work is licensed under a BSD style license. See http://www.mathertel.de/License.aspx // More information on: http://www.mathertel.de/Arduino // ----- #include "OneButton.h" // ----- Initialization and Default Values ----- OneButton::OneButton(PinName pin, bool active_level) { btn_pin = new DigitalIn((PinName)pin); // sets the MenuPin as input timer = new Timer; timer->start(); _clickTicks = 400; // number of millisec that have to pass by before a click is detected. _pressTicks = 800; // number of millisec that have to pass by before a long button press is detected. _debounceTicks = 10; _state = 0; // starting with state 0: waiting for button to be pressed _isLongPressed = false; // Keep track of long press state button_level = (bool)(btn_pin->read()); active = active_level; if (active_level) { // button connects VCC to the pin when pressed. btn_pin->mode(PullDown); } else { // turn on pullUp resistor btn_pin->mode(PullUp); } #if (MBED_LIBRARY_VERSION < 122) clickFn = NULL; pressFn = NULL; doubleClickFn = NULL; longPressStartFn = NULL; longPressStopFn = NULL; duringLongPressFn = NULL; #endif } // OneButton // explicitly set the number of millisec that have to pass by before a click is detected. void OneButton::setClickTicks(int ticks) { _clickTicks = ticks; } // setClickTicks // explicitly set the number of millisec that have to pass by before a long button press is detected. void OneButton::setPressTicks(int ticks) { _pressTicks = ticks; } // setPressTicks #if (MBED_LIBRARY_VERSION < 122) // save function for click event void OneButton::attachClick(callbackFunction newFunction) { clickFn = newFunction; } // attachClick // save function for doubleClick event void OneButton::attachDoubleClick(callbackFunction newFunction) { doubleClickFn = newFunction; } // attachDoubleClick // save function for press event // DEPRECATED, is replaced by attachLongPressStart, attachLongPressStop, attachDuringLongPress, void OneButton::attachPress(callbackFunction newFunction) { pressFn = newFunction; } // attachPress // save function for longPressStart event void OneButton::attachLongPressStart(callbackFunction newFunction) { longPressStartFn = newFunction; } // attachLongPressStart // save function for longPressStop event void OneButton::attachLongPressStop(callbackFunction newFunction) { longPressStopFn = newFunction; } // attachLongPressStop // save function for during longPress event void OneButton::attachDuringLongPress(callbackFunction newFunction) { duringLongPressFn = newFunction; } // attachDuringLongPress #endif // function to get the current long pressed state bool OneButton::isLongPressed() { return _isLongPressed; } /** * @brief Button driver core function, driver state machine. * @param handle: the button handle strcut. * @retval None */ void OneButton::tick(void) { int read_gpio_level = btn_pin->read(); // current button signal. /*------------button debounce handle---------------*/ if(ticks != timer->read_ms()) { //1ms scan again. if(read_gpio_level != button_level) { //continue read 'debounce_cnt' times same new level change if(++_debounce_cnt >= _debounceTicks) { button_level = read_gpio_level; _debounce_cnt = 0; } } else { //leved not change ,counter reset. _debounce_cnt = 0; } } //current (relative) time in msecs. ticks = timer->read_ms(); /*-----------------State machine-------------------*/ switch (_state) { case 0: if(button_level == active) { //start press timer->reset(); _state = 1; } break; case 1: if(button_level != active) { //released _state = 2; } else if(ticks > _pressTicks) { if(pressFn) pressFn(); //press event if(longPressStartFn) longPressStartFn(); _isLongPressed = 1; _state = 5; } break; case 2: if(ticks > _clickTicks) { //released if (clickFn) clickFn(); _state = 0; //reset } else if(button_level == active) { //press again _state = 3; } break; case 3: //repeat press pressing if(button_level != active) { //double releasd //double click event if(doubleClickFn) doubleClickFn(); _state = 0; } break; case 5: if(button_level == active) { //continue hold trigger if(duringLongPressFn) duringLongPressFn(); } else { //releasd if(longPressStopFn) longPressStopFn(); _isLongPressed = 0; _state = 0; //reset } break; } } // end.