From ce31fd7c572d025ca96fab9e2a87fa705fba570c Mon Sep 17 00:00:00 2001 From: taco Date: Wed, 3 Sep 2025 08:25:59 +1000 Subject: [PATCH] multi click support including buzzer toggle --- examples/companion_radio/ui-new/UITask.cpp | 46 +++++++++++++++++++--- examples/companion_radio/ui-new/UITask.h | 6 +++ src/helpers/ui/MomentaryButton.cpp | 38 +++++++++++++++++- src/helpers/ui/MomentaryButton.h | 6 +++ 4 files changed, 89 insertions(+), 7 deletions(-) diff --git a/examples/companion_radio/ui-new/UITask.cpp b/examples/companion_radio/ui-new/UITask.cpp index c751eaf5..d3fc5bad 100644 --- a/examples/companion_radio/ui-new/UITask.cpp +++ b/examples/companion_radio/ui-new/UITask.cpp @@ -495,6 +495,10 @@ void UITask::loop() { c = checkDisplayOn(KEY_SELECT); } else if (ev == BUTTON_EVENT_LONG_PRESS) { c = handleLongPress(KEY_ENTER); + } else if (ev == BUTTON_EVENT_DOUBLE_CLICK) { + c = handleDoubleClick(KEY_ENTER); + } else if (ev == BUTTON_EVENT_TRIPLE_CLICK) { + c = handleTripleClick(KEY_ENTER); } #endif #if defined(WIO_TRACKER_L1) @@ -604,10 +608,43 @@ char UITask::handleLongPress(char c) { return c; } -/* -void UITask::handleButtonTriplePress() { - MESH_DEBUG_PRINTLN("UITask: triple press triggered"); - // Toggle buzzer quiet mode +char UITask::handleDoubleClick(char c) { + MESH_DEBUG_PRINTLN("UITask: double click triggered"); + c = 0; + return c; +} + +char UITask::handleTripleClick(char c) { + MESH_DEBUG_PRINTLN("UITask: triple click triggered"); + toggleBuzzer(); + c = 0; + return c; +} + +void UITask::toggleGPS() { + if (_sensors != NULL) { + // toggle GPS on/off + int num = _sensors->getNumSettings(); + for (int i = 0; i < num; i++) { + if (strcmp(_sensors->getSettingName(i), "gps") == 0) { + if (strcmp(_sensors->getSettingValue(i), "1") == 0) { + _sensors->setSettingValue("gps", "0"); + soundBuzzer(UIEventType::ack); + showAlert("GPS: Disabled", 600); + } else { + _sensors->setSettingValue("gps", "1"); + soundBuzzer(UIEventType::ack); + showAlert("GPS: Enabled", 600); + } + _next_refresh = 0; + break; + } + } + } +} + +void UITask::toggleBuzzer() { + // Toggle buzzer quiet mode #ifdef PIN_BUZZER if (buzzer.isQuiet()) { buzzer.quiet(false); @@ -620,4 +657,3 @@ void UITask::handleButtonTriplePress() { _next_refresh = 0; // trigger refresh #endif } -*/ diff --git a/examples/companion_radio/ui-new/UITask.h b/examples/companion_radio/ui-new/UITask.h index f9e01550..a96abf89 100644 --- a/examples/companion_radio/ui-new/UITask.h +++ b/examples/companion_radio/ui-new/UITask.h @@ -37,6 +37,8 @@ class UITask : public AbstractUITask { // Button action handlers char checkDisplayOn(char c); char handleLongPress(char c); + char handleDoubleClick(char c); + char handleTripleClick(char c); void setCurrScreen(UIScreen* c); @@ -55,6 +57,10 @@ public: bool hasDisplay() const { return _display != NULL; } bool isButtonPressed() const; + void toggleBuzzer(); + void toggleGPS(); + + // from AbstractUITask void msgRead(int msgcount) override; void newMsg(uint8_t path_len, const char* from_name, const char* text, int msgcount) override; diff --git a/src/helpers/ui/MomentaryButton.cpp b/src/helpers/ui/MomentaryButton.cpp index 36309600..4b87705a 100644 --- a/src/helpers/ui/MomentaryButton.cpp +++ b/src/helpers/ui/MomentaryButton.cpp @@ -9,6 +9,10 @@ MomentaryButton::MomentaryButton(int8_t pin, int long_press_millis, bool reverse cancel = 0; _long_millis = long_press_millis; _threshold = 0; + _click_count = 0; + _last_click_time = 0; + _multi_click_window = 500; + _pending_click = false; } MomentaryButton::MomentaryButton(int8_t pin, int long_press_millis, int analog_threshold) { @@ -20,6 +24,10 @@ MomentaryButton::MomentaryButton(int8_t pin, int long_press_millis, int analog_t cancel = 0; _long_millis = long_press_millis; _threshold = analog_threshold; + _click_count = 0; + _last_click_time = 0; + _multi_click_window = 500; + _pending_click = false; } void MomentaryButton::begin() { @@ -35,6 +43,8 @@ bool MomentaryButton::isPressed() const { void MomentaryButton::cancelClick() { cancel = 1; + _click_count = 0; + _pending_click = false; } bool MomentaryButton::isPressed(int level) const { @@ -60,10 +70,14 @@ int MomentaryButton::check(bool repeat_click) { // button UP if (_long_millis > 0) { if (down_at > 0 && (unsigned long)(millis() - down_at) < _long_millis) { // only a CLICK if still within the long_press millis - event = BUTTON_EVENT_CLICK; + _click_count++; + _last_click_time = millis(); + _pending_click = true; } } else { - event = BUTTON_EVENT_CLICK; // any UP results in CLICK event when NOT using long_press feature + _click_count++; + _last_click_time = millis(); + _pending_click = true; } if (event == BUTTON_EVENT_CLICK && cancel) { event = BUTTON_EVENT_NONE; @@ -87,5 +101,25 @@ int MomentaryButton::check(bool repeat_click) { } } + if (_pending_click && (millis() - _last_click_time) >= _multi_click_window) { + switch (_click_count) { + case 1: + event = BUTTON_EVENT_CLICK; + break; + case 2: + event = BUTTON_EVENT_DOUBLE_CLICK; + break; + case 3: + event = BUTTON_EVENT_TRIPLE_CLICK; + break; + default: + // For 4+ clicks, treat as triple click? + event = BUTTON_EVENT_TRIPLE_CLICK; + break; + } + _click_count = 0; + _pending_click = false; + } + return event; } \ No newline at end of file diff --git a/src/helpers/ui/MomentaryButton.h b/src/helpers/ui/MomentaryButton.h index d002f652..1122e56a 100644 --- a/src/helpers/ui/MomentaryButton.h +++ b/src/helpers/ui/MomentaryButton.h @@ -5,6 +5,8 @@ #define BUTTON_EVENT_NONE 0 #define BUTTON_EVENT_CLICK 1 #define BUTTON_EVENT_LONG_PRESS 2 +#define BUTTON_EVENT_DOUBLE_CLICK 3 +#define BUTTON_EVENT_TRIPLE_CLICK 4 class MomentaryButton { int8_t _pin; @@ -13,6 +15,10 @@ class MomentaryButton { int _long_millis; int _threshold; // analog mode unsigned long down_at; + uint8_t _click_count; + unsigned long _last_click_time; + int _multi_click_window; + bool _pending_click; bool isPressed(int level) const;