fix(display): make the USER button click immediate, 3 s hold to power off

Power-off now needs a 3 second hold; any shorter press toggles the display.
MomentaryButton reports a CLICK for any release short of its threshold, so
that single value defines both.

The button also felt unreliable - "a brief press doesn't wake it, more often
than not". MomentaryButton's multi-click detection withholds a CLICK for
MULTI_CLICK_WINDOW_MS (280 ms) after release, and folds a second press
arriving inside that window into a DOUBLE_CLICK. Since the handler only acts
on CLICK, an impatient second press produced nothing at all: press, see
nothing, press again, still nothing. Multi-click is now off for these targets,
so CLICK fires on release.

Both settings are build flags defaulted in variants/heltec_v4_r8/target.cpp
and overridden only on the two TFT observer bases, because the companion
builds share this user_btn and do use double/triple click.

DISPLAY_TOUCH_DEBUG additionally logs which input caused a toggle
("Display: button -> on"), so any remaining flake can be attributed to the
button or to a spurious touch read rather than guessed at.
This commit is contained in:
agessaman committed 2026-08-28 15:37:09 -07:00
1 parent 018d68063f
commit 3e7e0322e5
6 files changed
+39 -9

No files matched your search

+8 -3
View File
@@ -326,12 +326,17 @@ void UITask::updateActivityRows() {
#endif
#ifdef DISPLAY_TOUCH_TOGGLE
void UITask::toggleDisplay() {
void UITask::toggleDisplay(const char* source) {
if (_display->isOn()) {
_display->turnOff();
} else {
_display->turnOn();
}
#ifdef DISPLAY_TOUCH_DEBUG
Serial.printf("Display: %s -> %s\n", source, _display->isOn() ? "on" : "off");
#else
(void)source;
#endif
#ifdef DISPLAY_REDRAW_ON_CHANGE
_frame_valid = false; // wake draws one complete current frame
#endif
@@ -348,7 +353,7 @@ void UITask::loop() {
int ev = user_btn.check();
if (ev == BUTTON_EVENT_CLICK) {
#ifdef DISPLAY_TOUCH_TOGGLE
toggleDisplay(); // same action as tapping the panel
toggleDisplay("button"); // same action as tapping the panel
#else
if (_display->isOn()) {
// TODO: any action ?
@@ -392,7 +397,7 @@ void UITask::loop() {
unsigned long now = millis();
if (millisReached(now, _next_touch)) {
_next_touch = now + TOUCH_POLL_MILLIS;
if (_touch.checkTap(now)) toggleDisplay();
if (_touch.checkTap(now)) toggleDisplay("touch");
}
}
#endif
+1 -1
View File
@@ -48,7 +48,7 @@ class UITask {
CHSC6XTouch _touch;
unsigned long _next_touch = 0;
void toggleDisplay();
void toggleDisplay(const char* source);
#endif
#ifdef WITH_MQTT_BRIDGE
+8 -3
View File
@@ -303,12 +303,17 @@ void UITask::updateActivityRows() {
#endif
#ifdef DISPLAY_TOUCH_TOGGLE
void UITask::toggleDisplay() {
void UITask::toggleDisplay(const char* source) {
if (_display->isOn()) {
_display->turnOff();
} else {
_display->turnOn();
}
#ifdef DISPLAY_TOUCH_DEBUG
Serial.printf("Display: %s -> %s\n", source, _display->isOn() ? "on" : "off");
#else
(void)source;
#endif
#ifdef DISPLAY_REDRAW_ON_CHANGE
_frame_valid = false; // wake draws one complete current frame
#endif
@@ -327,7 +332,7 @@ void UITask::loop() {
if (btnState != _prevBtnState) {
if (btnState == USER_BTN_PRESSED) { // pressed?
#ifdef DISPLAY_TOUCH_TOGGLE
toggleDisplay(); // same action as tapping the panel
toggleDisplay("button"); // same action as tapping the panel
#else
if (_display->isOn()) {
// TODO: any action ?
@@ -371,7 +376,7 @@ void UITask::loop() {
unsigned long now = millis();
if (millisReached(now, _next_touch)) {
_next_touch = now + TOUCH_POLL_MILLIS;
if (_touch.checkTap(now)) toggleDisplay();
if (_touch.checkTap(now)) toggleDisplay("touch");
}
}
#endif
+1 -1
View File
@@ -45,7 +45,7 @@ class UITask {
CHSC6XTouch _touch;
unsigned long _next_touch = 0;
void toggleDisplay();
void toggleDisplay(const char* source);
#endif
#ifdef WITH_MQTT_BRIDGE
+8
View File
@@ -339,6 +339,10 @@ build_flags =
; Blanking is a runtime setting now: `set display.timeout <secs>`, 0 = stay on,
; 60 s default. Tap the Expansion Kit panel or press USER to toggle by hand.
-D DISPLAY_TOUCH_TOGGLE=1
; Hold 3 s to power off; any shorter press toggles the display, acted on the
; moment the button is released rather than 280 ms later.
-D USER_BTN_LONG_PRESS_MILLIS=3000
-D USER_BTN_MULTICLICK=0
; Diagnostic: logs the raw CHSC6X frame (and TP_INT) when it changes. Drop this
; and PIN_TOUCH_INT once touch is confirmed working.
-D DISPLAY_TOUCH_DEBUG=1
@@ -414,6 +418,10 @@ build_flags =
; Blanking is a runtime setting now: `set display.timeout <secs>`, 0 = stay on,
; 60 s default. Tap the Expansion Kit panel or press USER to toggle by hand.
-D DISPLAY_TOUCH_TOGGLE=1
; Hold 3 s to power off; any shorter press toggles the display, acted on the
; moment the button is released rather than 280 ms later.
-D USER_BTN_LONG_PRESS_MILLIS=3000
-D USER_BTN_MULTICLICK=0
; Diagnostic: logs the raw CHSC6X frame (and TP_INT) when it changes. Drop this
; and PIN_TOUCH_INT once touch is confirmed working.
-D DISPLAY_TOUCH_DEBUG=1
+13 -1
View File
@@ -25,7 +25,19 @@ AutoDiscoverRTCClock rtc_clock(fallback_clock);
#ifdef DISPLAY_CLASS
DISPLAY_CLASS display(&board.periph_power);
MomentaryButton user_btn(PIN_USER_BTN, 1000, true);
#ifndef USER_BTN_LONG_PRESS_MILLIS
#define USER_BTN_LONG_PRESS_MILLIS 1000
#endif
// Multi-click detection holds a CLICK back for MULTI_CLICK_WINDOW_MS (280 ms)
// after release, and folds a second press inside that window into a
// DOUBLE_CLICK. Targets that only want a plain click set this to 0 so the
// event fires on release instead of being delayed - or swallowed when an
// impatient second press arrives.
#ifndef USER_BTN_MULTICLICK
#define USER_BTN_MULTICLICK 1
#endif
MomentaryButton user_btn(PIN_USER_BTN, USER_BTN_LONG_PRESS_MILLIS, true, false,
USER_BTN_MULTICLICK);
#endif
bool radio_init() {