Skip to content

Commit

Permalink
Improve touch handling
Browse files Browse the repository at this point in the history
  • Loading branch information
TokenRat committed Sep 6, 2024
1 parent 7dd4dee commit 66a5e51
Show file tree
Hide file tree
Showing 3 changed files with 62 additions and 5 deletions.
52 changes: 49 additions & 3 deletions lib/EFTouch/EFTouch.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -28,10 +28,12 @@

#include "EFTouch.h"

constexpr unsigned int DEFAULT_DETECTION_STEP = 10000;

EFTouchClass::EFTouchClass()
: pin_fingerprint(EFTOUCH_PIN_TOUCH_FINGERPRINT)
, pin_nose(EFTOUCH_PIN_TOUCH_NOSE)
, detection_step(10000)
, detection_step(DEFAULT_DETECTION_STEP)
, noise_fingerprint(0)
, noise_nose(0)
, last_touch_millis_fingerprint(0)
Expand All @@ -53,7 +55,7 @@ EFTouchClass::~EFTouchClass() {
}

void EFTouchClass::init() {
this->init(10000, EFTOUCH_PIN_TOUCH_FINGERPRINT, EFTOUCH_PIN_TOUCH_NOSE);
this->init(DEFAULT_DETECTION_STEP, EFTOUCH_PIN_TOUCH_FINGERPRINT, EFTOUCH_PIN_TOUCH_NOSE);
}

void EFTouchClass::init(touch_value_t detection_step, uint8_t pin_fingerprint, uint8_t pin_nose) {
Expand All @@ -76,6 +78,7 @@ void EFTouchClass::init(touch_value_t detection_step, uint8_t pin_fingerprint, u
LOGF_DEBUG("(EFTouch) Registered: pin_fingerprint=%d pin_nose=%d\r\n", pin_fingerprint, pin_nose);

this->calibrate();
this->longpressAlreadyRegisteredByCheckNose = false;
this->enableInterrupts(EFTouchZone::Fingerprint);
this->enableInterrupts(EFTouchZone::Nose);
}
Expand Down Expand Up @@ -140,6 +143,37 @@ uint8_t EFTouchClass::readNose() {
}
}

void EFTouchClass::checkForLongpressEvents() {

// const bool currentStateNose = this->isNoseTouched();
// const bool raising_flank = this->lastStateNose == false && currentStateNose == true;
// if (raising_flank) {
// this->lastStateNose = currentStateNose;
// // Just started pressing
// // The ISR *should* have run already and updated last_touch_millis_nose, but some reason this does not always happen
// // So we have to manually do it here.
// auto ms = this->last_touch_millis_nose;
// LOGF_INFO("XXX Detected touch, updating time: %d\r\n", ms);
// this->last_touch_millis_nose = millis();
// return;
// }

if (this->onNoseLongpressIsr == nullptr || this->longpressAlreadyRegisteredByCheckNose == true || this->isNoseTouched() == false) {
// No interrupt method configured or
// we have already triggered and waiting for a reset or
// there is no touch -> do nothing
return;
}

auto ms = this->last_touch_millis_nose;
if (this->last_touch_millis_nose + EFTOUCH_LONGPRESS_DURATION_MS < millis()) {
longpressAlreadyRegisteredByCheckNose = true;
LOGF_INFO("XXX ISR Event by checkForLongpressEvent. last touch: %d\r\n", ms);
LOGF_INFO("XXX isr Event by checkForLongpressEvent. current millis: %d\r\n", millis());
this->onNoseLongpressIsr();
}
}

void ARDUINO_ISR_ATTR _eftouch_isr_fingerprint() {
EFTouch._handleInterrupt(
EFTouchZone::Fingerprint,
Expand Down Expand Up @@ -206,6 +240,7 @@ void ARDUINO_ISR_ATTR EFTouchClass::_handleInterrupt(EFTouchZone zone, bool rais
this->onFingerprintTouchIsr();
}
} else {
// Release
// Fire onFingerprintShortpressIsr() if applicable
if (this->onFingerprintShortpressIsr != nullptr) {
if (this->last_touch_millis_fingerprint + EFTOUCH_SHORTPRESS_DURATION_MS < millis()) {
Expand All @@ -226,6 +261,8 @@ void ARDUINO_ISR_ATTR EFTouchClass::_handleInterrupt(EFTouchZone zone, bool rais
break;
case EFTouchZone::Nose:
if (raising_flank) {
// longpressAlreadyRegisteredByCheckNose = false;

// Register first touch timestamp
this->last_touch_millis_nose = millis();

Expand All @@ -234,13 +271,22 @@ void ARDUINO_ISR_ATTR EFTouchClass::_handleInterrupt(EFTouchZone zone, bool rais
this->onNoseTouchIsr();
}
} else {
// Release
// If it was already handled, we will ignore this interrupt
bool ignoreEvent = longpressAlreadyRegisteredByCheckNose;
// reset, so we can register new longpress events by the check mehtod
longpressAlreadyRegisteredByCheckNose = false;
if (ignoreEvent) {
break;
}

// Fire onNoseShortpressIsr() if applicable
if (this->onNoseShortpressIsr != nullptr) {
if (this->last_touch_millis_nose + EFTOUCH_SHORTPRESS_DURATION_MS < millis()) {
this->onNoseShortpressIsr();
}
}
// Fire onFingerperintLongpressIsr() if applicable
// Fire onNonseLongpressIsr() if applicable
if (this->onNoseLongpressIsr != nullptr) {
if (this->last_touch_millis_nose + EFTOUCH_LONGPRESS_DURATION_MS < millis()) {
this->onNoseLongpressIsr();
Expand Down
12 changes: 10 additions & 2 deletions lib/EFTouch/EFTouch.h
Original file line number Diff line number Diff line change
Expand Up @@ -53,8 +53,10 @@ class EFTouchClass {
touch_value_t noise_fingerprint; //!< Calibrated noise floor for fingerprint touch pad
touch_value_t noise_nose; //!< Calibrated noise floor for nose touch pad

unsigned long last_touch_millis_fingerprint; //!< Timestamp when the fingerprint was last touched
unsigned long last_touch_millis_nose; //!< Timestamp when the nose was last touched
volatile unsigned long last_touch_millis_fingerprint; //!< Timestamp when the fingerprint was last touched
volatile unsigned long last_touch_millis_nose; //!< Timestamp when the nose was last touched
bool lastStateNose;
volatile bool longpressAlreadyRegisteredByCheckNose;

void (*onFingerprintTouchIsr)(void); //!< ISR to execute if the fingerprint is first touched
void (*onFingerprintReleaseIsr)(void); //!< ISR to execute if the fingerprint is fully released
Expand Down Expand Up @@ -142,6 +144,12 @@ class EFTouchClass {
*/
uint8_t readNose();

/**
* @brief This method should be called in a loop or some timer to makre sure, the lib checks for long-press
* even if the buttons are still being held.
*/
void checkForLongpressEvents();

/**
* @brief Enable interrupt handling for the given touch zone
*
Expand Down
3 changes: 3 additions & 0 deletions src/main.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -238,6 +238,9 @@ void setup() {
* @brief Main program loop
*/
void loop() {
// The user might be holding the buttons. Calling EFTouch periodically allows it to check this and send events before release
EFTouch.checkForLongpressEvents();

// Handler: ISR Events
if (isrEvents.fingerprintTouch) {
fsm.queueEvent(FSMEvent::FingerprintTouch);
Expand Down

0 comments on commit 66a5e51

Please sign in to comment.