From 29954007e87e090e85f1e7568cab5ccf153ad41d Mon Sep 17 00:00:00 2001 From: "P.M. Kuipers" Date: Sun, 16 May 2021 22:16:07 +0200 Subject: [PATCH] Improved button debouncing --- Makefile | 8 +-- config.hpp | 4 +- configure.ac | 2 +- src/buttontimer/buttontimer.cpp | 86 +++++++++++++++++++++++++++------ src/buttontimer/buttontimer.hpp | 2 + src/mc-hid-server.cpp | 4 +- version.py | 2 +- 7 files changed, 84 insertions(+), 24 deletions(-) diff --git a/Makefile b/Makefile index 7d531df..c41a903 100644 --- a/Makefile +++ b/Makefile @@ -275,7 +275,7 @@ DEFS = -DHAVE_CONFIG_H DEPDIR = .deps DEPS_CFLAGS = -DDBUS_API_SUBJECT_TO_CHANGE -I/usr/include/dbus-c++-1 -I/usr/include/dbus-1.0 -I/usr/lib/arm-linux-gnueabihf/dbus-1.0/include DEPS_LIBS = -ldbus-c++-1 -ldbus-1 -DHMAKE = notfound +DHMAKE = /usr/bin/dh_make ECHO_C = ECHO_N = -n ECHO_T = @@ -295,10 +295,10 @@ OBJEXT = o PACKAGE = mediacore-hid PACKAGE_BUGREPORT = bugs@miqra.nl PACKAGE_NAME = MediaCore HID Server -PACKAGE_STRING = MediaCore HID Server 4.0.0 +PACKAGE_STRING = MediaCore HID Server 4.0.1 PACKAGE_TARNAME = mediacore-hid PACKAGE_URL = http://www.miqra.nl/ -PACKAGE_VERSION = 4.0.0 +PACKAGE_VERSION = 4.0.1 PATH_SEPARATOR = : PKG_CONFIG = /usr/bin/pkg-config PKG_CONFIG_LIBDIR = @@ -306,7 +306,7 @@ PKG_CONFIG_PATH = SET_MAKE = SHELL = /bin/bash STRIP = -VERSION = 4.0.0 +VERSION = 4.0.1 abs_builddir = /home/pi/mediacore-hid abs_srcdir = /home/pi/mediacore-hid abs_top_builddir = /home/pi/mediacore-hid diff --git a/config.hpp b/config.hpp index 15c455b..8aa9b98 100644 --- a/config.hpp +++ b/config.hpp @@ -11,7 +11,7 @@ #define PACKAGE_NAME "MediaCore HID Server" /* Define to the full name and version of this package. */ -#define PACKAGE_STRING "MediaCore HID Server 4.0.0" +#define PACKAGE_STRING "MediaCore HID Server 4.0.1" /* Define to the one symbol short name of this package. */ #define PACKAGE_TARNAME "mediacore-hid" @@ -20,4 +20,4 @@ #define PACKAGE_URL "http://www.miqra.nl/" /* Define to the version of this package. */ -#define PACKAGE_VERSION "4.0.0" +#define PACKAGE_VERSION "4.0.1" diff --git a/configure.ac b/configure.ac index 8c3afeb..e7005e9 100755 --- a/configure.ac +++ b/configure.ac @@ -1,4 +1,4 @@ -AC_INIT([MediaCore HID Server], [4.0.0], [bugs@miqra.nl], [mediacore-hid], [http://www.miqra.nl/]) +AC_INIT([MediaCore HID Server], [4.0.1], [bugs@miqra.nl], [mediacore-hid], [http://www.miqra.nl/]) AC_PREREQ([2.59]) AM_INIT_AUTOMAKE([1.11 no-define foreign subdir-objects]) AC_CONFIG_HEADERS([config.hpp]) diff --git a/src/buttontimer/buttontimer.cpp b/src/buttontimer/buttontimer.cpp index da26ff8..2ca7c02 100644 --- a/src/buttontimer/buttontimer.cpp +++ b/src/buttontimer/buttontimer.cpp @@ -26,7 +26,14 @@ void ButtonTimer::RegisterPress(const uint8_t keycode) // Prevent trouble when calling this from within one of our event listeners if(eventLock) { MutexUnlock(); return; } - pressRegistry[keycode] = now_ms(); + // register current registered time for first triggering press + if(!pressRegistry.count(keycode)) + { + pressRegistry[keycode] = now_ms(); + } + + // register press state to true for debouncing + pressState[keycode] = true; MutexUnlock(); } @@ -36,18 +43,44 @@ void ButtonTimer::RegisterRelease(const uint8_t keycode) MutexLock(); // Prevent trouble when calling this from within one of our event listeners if(eventLock) { MutexUnlock(); return; } - + + // register current press state to false + pressState[keycode] = false; + if(pressRegistry.count(keycode)) { // if it was a long press, the key code would already have been erased, so we // can safely fire the onShortPress event uint64_t now = now_ms(); uint64_t then = pressRegistry[keycode]; - // remove from registry after release, if it was a long press, the event should have already been fired - pressRegistry.erase(keycode); - if(now - then > shortpressMinTime) + if(pressHold.count(keycode)) { + // debounce locks for release + // pressHold[keycode] == true means wait for release + // pressHold[keycode] == false means we're in the release debounce time + if(pressHold[keycode] == true){ + // first release after longpress + // Register time and switch to next mode + pressHold[keycode] = false; + pressRegistry[keycode] = now; + } + else + { + // still in debounce + // release the debounce lock if this release occurs after the shortpresstime + if(now - then > shortpressMinTime){ + pressHold.erase(keycode); + pressRegistry.erase(keycode); + } + } + } + else if(now - then > shortpressMinTime) + { + // only trigger this if the release is later than the shortpresstime + // remove from registry after release, if it was a long press, the event should have already been fired + pressRegistry.erase(keycode); + eventLock = true; // lock out trouble onShortPress(keycode); eventLock = false; // risk of trouble gone @@ -74,32 +107,57 @@ void ButtonTimer::CancelPress(const uint8_t keycode) void ButtonTimer::ThreadLoop() { uint64_t now = now_ms(); - std::list btnList; + std::list shortPressList; + std::list longPressList; boost::optional valid; MutexLock(); // list through all the items - for( std::map::iterator ii=pressRegistry.begin(); ii!=pressRegistry.end(); ++ii) + for( auto const& itm : pressRegistry) { - if(now - (ii->second) >= longpressTime) // if it is in overtime + if(now - (itm.second) >= shortpressMinTime && pressState[itm.first] == false) // if the shortpresstime wa exceeded and the value is false + { + if(!pressHold.count(itm.first)) + { + shortPressList.push_back(itm.first); + } + else if(pressHold[itm.first] == false) + { + // release debounce lock from longpress + pressRegistry.erase(itm.first); + pressHold.erase(itm.first); + } + } + if(now - (itm.second) >= longpressTime && !pressHold.count(itm.first)) // if it is in overtime and not waiting for release debounce { // Schedule to process the thing - btnList.push_back(ii->first); + longPressList.push_back(itm.first); } - } + + } + + for (auto const& gpio : shortPressList) + { + pressRegistry.erase(gpio); + // If any validators are connected, they can retun false to indicate that this connection is not + // allowed + eventLock = true; // lock out trouble + onShortPress(gpio); + eventLock = false; // risk of trouble gone + } // Process listed items - for (std::list::iterator it=btnList.begin(); it != btnList.end(); ++it) + for (auto const& gpio : longPressList) { - pressRegistry.erase(*it); + pressHold[gpio] = true; // debounce wait state // If any validators are connected, they can retun false to indicate that this connection is not // allowed eventLock = true; // lock out trouble - valid = onValidatePress(*it); + valid = onValidatePress(gpio); if(valid.get_value_or(true)) { - onLongPress(*it); + onLongPress(gpio); } eventLock = false; // risk of trouble gone } diff --git a/src/buttontimer/buttontimer.hpp b/src/buttontimer/buttontimer.hpp index 379d846..2380540 100644 --- a/src/buttontimer/buttontimer.hpp +++ b/src/buttontimer/buttontimer.hpp @@ -27,6 +27,8 @@ class ButtonTimer : protected Thread uint32_t longpressTime; uint32_t shortpressMinTime; std::map pressRegistry; + std::map pressState; + std::map pressHold; bool eventLock; static int64_t now_ms(void); diff --git a/src/mc-hid-server.cpp b/src/mc-hid-server.cpp index 6cb8ff7..410e226 100644 --- a/src/mc-hid-server.cpp +++ b/src/mc-hid-server.cpp @@ -82,10 +82,10 @@ HidServer::HidServer(DBus::Connection &connection) { // Initialize button timer - btnTimer = new ButtonTimer(10,5000); // Short press should take at leas 10 ms, and a Long press takes 5 seconds + btnTimer = new ButtonTimer(70,5000); // 70 ms debounce time, and a Long press takes 5 seconds onShortPressConnection = this->btnTimer->onShortPress.connect( boost::bind( &HidServer::onShortPress, this, _1) ); onLongPressConnection = this->btnTimer->onLongPress.connect( boost::bind( &HidServer::onLongPress, this, _1) ); - onValidatePressConnection = this->btnTimer->onValidatePress.connect( boost::bind( &HidServer::onValidatePress, this, _1) ); + //onValidatePressConnection = this->btnTimer->onValidatePress.connect( boost::bind( &HidServer::onValidatePress, this, _1) ); // **** Initialize the GPIO Interrupt pin diff --git a/version.py b/version.py index 403db28..3650087 100644 --- a/version.py +++ b/version.py @@ -1,2 +1,2 @@ PACKAGE="mediacore-hid" -VERSION="4.0.0" +VERSION="4.0.1"