Improved button debouncing
This commit is contained in:
parent
44b729f0e6
commit
29954007e8
8
Makefile
8
Makefile
|
@ -275,7 +275,7 @@ DEFS = -DHAVE_CONFIG_H
|
||||||
DEPDIR = .deps
|
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_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
|
DEPS_LIBS = -ldbus-c++-1 -ldbus-1
|
||||||
DHMAKE = notfound
|
DHMAKE = /usr/bin/dh_make
|
||||||
ECHO_C =
|
ECHO_C =
|
||||||
ECHO_N = -n
|
ECHO_N = -n
|
||||||
ECHO_T =
|
ECHO_T =
|
||||||
|
@ -295,10 +295,10 @@ OBJEXT = o
|
||||||
PACKAGE = mediacore-hid
|
PACKAGE = mediacore-hid
|
||||||
PACKAGE_BUGREPORT = bugs@miqra.nl
|
PACKAGE_BUGREPORT = bugs@miqra.nl
|
||||||
PACKAGE_NAME = MediaCore HID Server
|
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_TARNAME = mediacore-hid
|
||||||
PACKAGE_URL = http://www.miqra.nl/
|
PACKAGE_URL = http://www.miqra.nl/
|
||||||
PACKAGE_VERSION = 4.0.0
|
PACKAGE_VERSION = 4.0.1
|
||||||
PATH_SEPARATOR = :
|
PATH_SEPARATOR = :
|
||||||
PKG_CONFIG = /usr/bin/pkg-config
|
PKG_CONFIG = /usr/bin/pkg-config
|
||||||
PKG_CONFIG_LIBDIR =
|
PKG_CONFIG_LIBDIR =
|
||||||
|
@ -306,7 +306,7 @@ PKG_CONFIG_PATH =
|
||||||
SET_MAKE =
|
SET_MAKE =
|
||||||
SHELL = /bin/bash
|
SHELL = /bin/bash
|
||||||
STRIP =
|
STRIP =
|
||||||
VERSION = 4.0.0
|
VERSION = 4.0.1
|
||||||
abs_builddir = /home/pi/mediacore-hid
|
abs_builddir = /home/pi/mediacore-hid
|
||||||
abs_srcdir = /home/pi/mediacore-hid
|
abs_srcdir = /home/pi/mediacore-hid
|
||||||
abs_top_builddir = /home/pi/mediacore-hid
|
abs_top_builddir = /home/pi/mediacore-hid
|
||||||
|
|
|
@ -11,7 +11,7 @@
|
||||||
#define PACKAGE_NAME "MediaCore HID Server"
|
#define PACKAGE_NAME "MediaCore HID Server"
|
||||||
|
|
||||||
/* Define to the full name and version of this package. */
|
/* 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 to the one symbol short name of this package. */
|
||||||
#define PACKAGE_TARNAME "mediacore-hid"
|
#define PACKAGE_TARNAME "mediacore-hid"
|
||||||
|
@ -20,4 +20,4 @@
|
||||||
#define PACKAGE_URL "http://www.miqra.nl/"
|
#define PACKAGE_URL "http://www.miqra.nl/"
|
||||||
|
|
||||||
/* Define to the version of this package. */
|
/* Define to the version of this package. */
|
||||||
#define PACKAGE_VERSION "4.0.0"
|
#define PACKAGE_VERSION "4.0.1"
|
||||||
|
|
|
@ -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])
|
AC_PREREQ([2.59])
|
||||||
AM_INIT_AUTOMAKE([1.11 no-define foreign subdir-objects])
|
AM_INIT_AUTOMAKE([1.11 no-define foreign subdir-objects])
|
||||||
AC_CONFIG_HEADERS([config.hpp])
|
AC_CONFIG_HEADERS([config.hpp])
|
||||||
|
|
|
@ -26,7 +26,14 @@ void ButtonTimer::RegisterPress(const uint8_t keycode)
|
||||||
// Prevent trouble when calling this from within one of our event listeners
|
// Prevent trouble when calling this from within one of our event listeners
|
||||||
if(eventLock) { MutexUnlock(); return; }
|
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();
|
MutexUnlock();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -37,17 +44,43 @@ void ButtonTimer::RegisterRelease(const uint8_t keycode)
|
||||||
// Prevent trouble when calling this from within one of our event listeners
|
// Prevent trouble when calling this from within one of our event listeners
|
||||||
if(eventLock) { MutexUnlock(); return; }
|
if(eventLock) { MutexUnlock(); return; }
|
||||||
|
|
||||||
|
// register current press state to false
|
||||||
|
pressState[keycode] = false;
|
||||||
|
|
||||||
if(pressRegistry.count(keycode))
|
if(pressRegistry.count(keycode))
|
||||||
{
|
{
|
||||||
// if it was a long press, the key code would already have been erased, so we
|
// if it was a long press, the key code would already have been erased, so we
|
||||||
// can safely fire the onShortPress event
|
// can safely fire the onShortPress event
|
||||||
uint64_t now = now_ms();
|
uint64_t now = now_ms();
|
||||||
uint64_t then = pressRegistry[keycode];
|
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
|
eventLock = true; // lock out trouble
|
||||||
onShortPress(keycode);
|
onShortPress(keycode);
|
||||||
eventLock = false; // risk of trouble gone
|
eventLock = false; // risk of trouble gone
|
||||||
|
@ -74,32 +107,57 @@ void ButtonTimer::CancelPress(const uint8_t keycode)
|
||||||
void ButtonTimer::ThreadLoop()
|
void ButtonTimer::ThreadLoop()
|
||||||
{
|
{
|
||||||
uint64_t now = now_ms();
|
uint64_t now = now_ms();
|
||||||
std::list<uint8_t> btnList;
|
std::list<uint8_t> shortPressList;
|
||||||
|
std::list<uint8_t> longPressList;
|
||||||
boost::optional<bool> valid;
|
boost::optional<bool> valid;
|
||||||
MutexLock();
|
MutexLock();
|
||||||
// list through all the items
|
// list through all the items
|
||||||
|
|
||||||
for( std::map<uint8_t,uint64_t>::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
|
// 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
|
// Process listed items
|
||||||
for (std::list<uint8_t>::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
|
// If any validators are connected, they can retun false to indicate that this connection is not
|
||||||
// allowed
|
// allowed
|
||||||
eventLock = true; // lock out trouble
|
eventLock = true; // lock out trouble
|
||||||
|
|
||||||
valid = onValidatePress(*it);
|
valid = onValidatePress(gpio);
|
||||||
if(valid.get_value_or(true))
|
if(valid.get_value_or(true))
|
||||||
{
|
{
|
||||||
onLongPress(*it);
|
onLongPress(gpio);
|
||||||
}
|
}
|
||||||
eventLock = false; // risk of trouble gone
|
eventLock = false; // risk of trouble gone
|
||||||
}
|
}
|
||||||
|
|
|
@ -27,6 +27,8 @@ class ButtonTimer : protected Thread
|
||||||
uint32_t longpressTime;
|
uint32_t longpressTime;
|
||||||
uint32_t shortpressMinTime;
|
uint32_t shortpressMinTime;
|
||||||
std::map<const uint8_t, uint64_t> pressRegistry;
|
std::map<const uint8_t, uint64_t> pressRegistry;
|
||||||
|
std::map<const uint8_t, bool> pressState;
|
||||||
|
std::map<const uint8_t, bool> pressHold;
|
||||||
|
|
||||||
bool eventLock;
|
bool eventLock;
|
||||||
static int64_t now_ms(void);
|
static int64_t now_ms(void);
|
||||||
|
|
|
@ -82,10 +82,10 @@ HidServer::HidServer(DBus::Connection &connection)
|
||||||
{
|
{
|
||||||
|
|
||||||
// Initialize button timer
|
// 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) );
|
onShortPressConnection = this->btnTimer->onShortPress.connect( boost::bind( &HidServer::onShortPress, this, _1) );
|
||||||
onLongPressConnection = this->btnTimer->onLongPress.connect( boost::bind( &HidServer::onLongPress, 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
|
// **** Initialize the GPIO Interrupt pin
|
||||||
|
|
||||||
|
|
|
@ -1,2 +1,2 @@
|
||||||
PACKAGE="mediacore-hid"
|
PACKAGE="mediacore-hid"
|
||||||
VERSION="4.0.0"
|
VERSION="4.0.1"
|
||||||
|
|
Loading…
Reference in New Issue
Block a user