Skip to content

Commit 5782c2e

Browse files
authored
Merge pull request #720 from oltaco/newui-multiclick-toggles
new-ui: add double/triple clicks, buzzer and gps toggle functions
2 parents 3e7459a + 96a71bb commit 5782c2e

File tree

5 files changed

+134
-23
lines changed

5 files changed

+134
-23
lines changed

examples/companion_radio/ui-new/UITask.cpp

Lines changed: 53 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -225,11 +225,11 @@ class HomeScreen : public UIScreen {
225225
}
226226

227227
bool handleInput(char c) override {
228-
if (c == KEY_LEFT) {
228+
if (c == KEY_LEFT || c == KEY_PREV) {
229229
_page = (_page + HomePage::Count - 1) % HomePage::Count;
230230
return true;
231231
}
232-
if (c == KEY_RIGHT || c == KEY_SELECT) {
232+
if (c == KEY_NEXT || c == KEY_RIGHT) {
233233
_page = (_page + 1) % HomePage::Count;
234234
if (_page == HomePage::RECENT) {
235235
_task->showAlert("Recent adverts", 800);
@@ -331,7 +331,7 @@ class MsgPreviewScreen : public UIScreen {
331331
}
332332

333333
bool handleInput(char c) override {
334-
if (c == KEY_SELECT || c == KEY_RIGHT) {
334+
if (c == KEY_NEXT || c == KEY_RIGHT) {
335335
num_unread--;
336336
if (num_unread == 0) {
337337
_task->gotoHomeScreen();
@@ -494,9 +494,13 @@ void UITask::loop() {
494494
#if defined(PIN_USER_BTN)
495495
int ev = user_btn.check();
496496
if (ev == BUTTON_EVENT_CLICK) {
497-
c = checkDisplayOn(KEY_SELECT);
497+
c = checkDisplayOn(KEY_NEXT);
498498
} else if (ev == BUTTON_EVENT_LONG_PRESS) {
499499
c = handleLongPress(KEY_ENTER);
500+
} else if (ev == BUTTON_EVENT_DOUBLE_CLICK) {
501+
c = handleDoubleClick(KEY_PREV);
502+
} else if (ev == BUTTON_EVENT_TRIPLE_CLICK) {
503+
c = handleTripleClick(KEY_SELECT);
500504
}
501505
#endif
502506
#if defined(WIO_TRACKER_L1)
@@ -516,9 +520,13 @@ void UITask::loop() {
516520
#if defined(PIN_USER_BTN_ANA)
517521
ev = analog_btn.check();
518522
if (ev == BUTTON_EVENT_CLICK) {
519-
c = checkDisplayOn(KEY_SELECT);
523+
c = checkDisplayOn(KEY_NEXT);
520524
} else if (ev == BUTTON_EVENT_LONG_PRESS) {
521525
c = handleLongPress(KEY_ENTER);
526+
} else if (ev == BUTTON_EVENT_DOUBLE_CLICK) {
527+
c = handleDoubleClick(KEY_PREV);
528+
} else if (ev == BUTTON_EVENT_TRIPLE_CLICK) {
529+
c = handleTripleClick(KEY_SELECT);
522530
}
523531
#endif
524532
#if defined(DISP_BACKLIGHT) && defined(BACKLIGHT_BTN)
@@ -615,20 +623,53 @@ char UITask::handleLongPress(char c) {
615623
return c;
616624
}
617625

618-
/*
619-
void UITask::handleButtonTriplePress() {
620-
MESH_DEBUG_PRINTLN("UITask: triple press triggered");
621-
// Toggle buzzer quiet mode
626+
char UITask::handleDoubleClick(char c) {
627+
MESH_DEBUG_PRINTLN("UITask: double click triggered");
628+
checkDisplayOn(c);
629+
return c;
630+
}
631+
632+
char UITask::handleTripleClick(char c) {
633+
MESH_DEBUG_PRINTLN("UITask: triple click triggered");
634+
checkDisplayOn(c);
635+
toggleBuzzer();
636+
c = 0;
637+
return c;
638+
}
639+
640+
void UITask::toggleGPS() {
641+
if (_sensors != NULL) {
642+
// toggle GPS on/off
643+
int num = _sensors->getNumSettings();
644+
for (int i = 0; i < num; i++) {
645+
if (strcmp(_sensors->getSettingName(i), "gps") == 0) {
646+
if (strcmp(_sensors->getSettingValue(i), "1") == 0) {
647+
_sensors->setSettingValue("gps", "0");
648+
soundBuzzer(UIEventType::ack);
649+
showAlert("GPS: Disabled", 800);
650+
} else {
651+
_sensors->setSettingValue("gps", "1");
652+
soundBuzzer(UIEventType::ack);
653+
showAlert("GPS: Enabled", 800);
654+
}
655+
_next_refresh = 0;
656+
break;
657+
}
658+
}
659+
}
660+
}
661+
662+
void UITask::toggleBuzzer() {
663+
// Toggle buzzer quiet mode
622664
#ifdef PIN_BUZZER
623665
if (buzzer.isQuiet()) {
624666
buzzer.quiet(false);
625667
soundBuzzer(UIEventType::ack);
626-
showAlert("Buzzer: ON", 600);
668+
showAlert("Buzzer: ON", 800);
627669
} else {
628670
buzzer.quiet(true);
629-
showAlert("Buzzer: OFF", 600);
671+
showAlert("Buzzer: OFF", 800);
630672
}
631673
_next_refresh = 0; // trigger refresh
632674
#endif
633675
}
634-
*/

examples/companion_radio/ui-new/UITask.h

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -43,6 +43,8 @@ class UITask : public AbstractUITask {
4343
// Button action handlers
4444
char checkDisplayOn(char c);
4545
char handleLongPress(char c);
46+
char handleDoubleClick(char c);
47+
char handleTripleClick(char c);
4648

4749
void setCurrScreen(UIScreen* c);
4850

@@ -61,6 +63,10 @@ class UITask : public AbstractUITask {
6163
bool hasDisplay() const { return _display != NULL; }
6264
bool isButtonPressed() const;
6365

66+
void toggleBuzzer();
67+
void toggleGPS();
68+
69+
6470
// from AbstractUITask
6571
void msgRead(int msgcount) override;
6672
void newMsg(uint8_t path_len, const char* from_name, const char* text, int msgcount) override;

src/helpers/ui/MomentaryButton.cpp

Lines changed: 58 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,7 @@
11
#include "MomentaryButton.h"
22

3+
#define MULTI_CLICK_WINDOW_MS 280
4+
35
MomentaryButton::MomentaryButton(int8_t pin, int long_press_millis, bool reverse, bool pulldownup) {
46
_pin = pin;
57
_reverse = reverse;
@@ -9,6 +11,10 @@ MomentaryButton::MomentaryButton(int8_t pin, int long_press_millis, bool reverse
911
cancel = 0;
1012
_long_millis = long_press_millis;
1113
_threshold = 0;
14+
_click_count = 0;
15+
_last_click_time = 0;
16+
_multi_click_window = MULTI_CLICK_WINDOW_MS;
17+
_pending_click = false;
1218
}
1319

1420
MomentaryButton::MomentaryButton(int8_t pin, int long_press_millis, int analog_threshold) {
@@ -20,6 +26,10 @@ MomentaryButton::MomentaryButton(int8_t pin, int long_press_millis, int analog_t
2026
cancel = 0;
2127
_long_millis = long_press_millis;
2228
_threshold = analog_threshold;
29+
_click_count = 0;
30+
_last_click_time = 0;
31+
_multi_click_window = MULTI_CLICK_WINDOW_MS;
32+
_pending_click = false;
2333
}
2434

2535
void MomentaryButton::begin() {
@@ -35,6 +45,10 @@ bool MomentaryButton::isPressed() const {
3545

3646
void MomentaryButton::cancelClick() {
3747
cancel = 1;
48+
down_at = 0;
49+
_click_count = 0;
50+
_last_click_time = 0;
51+
_pending_click = false;
3852
}
3953

4054
bool MomentaryButton::isPressed(int level) const {
@@ -60,13 +74,20 @@ int MomentaryButton::check(bool repeat_click) {
6074
// button UP
6175
if (_long_millis > 0) {
6276
if (down_at > 0 && (unsigned long)(millis() - down_at) < _long_millis) { // only a CLICK if still within the long_press millis
63-
event = BUTTON_EVENT_CLICK;
77+
_click_count++;
78+
_last_click_time = millis();
79+
_pending_click = true;
6480
}
6581
} else {
66-
event = BUTTON_EVENT_CLICK; // any UP results in CLICK event when NOT using long_press feature
82+
_click_count++;
83+
_last_click_time = millis();
84+
_pending_click = true;
6785
}
6886
if (event == BUTTON_EVENT_CLICK && cancel) {
6987
event = BUTTON_EVENT_NONE;
88+
_click_count = 0;
89+
_last_click_time = 0;
90+
_pending_click = false;
7091
}
7192
down_at = 0;
7293
}
@@ -77,8 +98,16 @@ int MomentaryButton::check(bool repeat_click) {
7798
}
7899

79100
if (_long_millis > 0 && down_at > 0 && (unsigned long)(millis() - down_at) >= _long_millis) {
80-
event = BUTTON_EVENT_LONG_PRESS;
81-
down_at = 0;
101+
if (_pending_click) {
102+
// long press during multi-click detection - cancel pending clicks
103+
cancelClick();
104+
} else {
105+
event = BUTTON_EVENT_LONG_PRESS;
106+
down_at = 0;
107+
_click_count = 0;
108+
_last_click_time = 0;
109+
_pending_click = false;
110+
}
82111
}
83112
if (down_at > 0 && repeat_click) {
84113
unsigned long diff = (unsigned long)(millis() - down_at);
@@ -87,5 +116,30 @@ int MomentaryButton::check(bool repeat_click) {
87116
}
88117
}
89118

119+
if (_pending_click && (millis() - _last_click_time) >= _multi_click_window) {
120+
if (down_at > 0) {
121+
// still pressed - wait for button release before processing clicks
122+
return event;
123+
}
124+
switch (_click_count) {
125+
case 1:
126+
event = BUTTON_EVENT_CLICK;
127+
break;
128+
case 2:
129+
event = BUTTON_EVENT_DOUBLE_CLICK;
130+
break;
131+
case 3:
132+
event = BUTTON_EVENT_TRIPLE_CLICK;
133+
break;
134+
default:
135+
// For 4+ clicks, treat as triple click?
136+
event = BUTTON_EVENT_TRIPLE_CLICK;
137+
break;
138+
}
139+
_click_count = 0;
140+
_last_click_time = 0;
141+
_pending_click = false;
142+
}
143+
90144
return event;
91145
}

src/helpers/ui/MomentaryButton.h

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,8 @@
55
#define BUTTON_EVENT_NONE 0
66
#define BUTTON_EVENT_CLICK 1
77
#define BUTTON_EVENT_LONG_PRESS 2
8+
#define BUTTON_EVENT_DOUBLE_CLICK 3
9+
#define BUTTON_EVENT_TRIPLE_CLICK 4
810

911
class MomentaryButton {
1012
int8_t _pin;
@@ -13,6 +15,10 @@ class MomentaryButton {
1315
int _long_millis;
1416
int _threshold; // analog mode
1517
unsigned long down_at;
18+
uint8_t _click_count;
19+
unsigned long _last_click_time;
20+
int _multi_click_window;
21+
bool _pending_click;
1622

1723
bool isPressed(int level) const;
1824

src/helpers/ui/UIScreen.h

Lines changed: 11 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -2,13 +2,17 @@
22

33
#include "DisplayDriver.h"
44

5-
#define KEY_LEFT 0xB4
6-
#define KEY_UP 0xB5
7-
#define KEY_DOWN 0xB6
8-
#define KEY_RIGHT 0xB7
9-
#define KEY_SELECT 10
10-
#define KEY_ENTER 13
11-
#define KEY_BACK 27 // Esc
5+
#define KEY_LEFT 0xB4
6+
#define KEY_UP 0xB5
7+
#define KEY_DOWN 0xB6
8+
#define KEY_RIGHT 0xB7
9+
#define KEY_SELECT 10
10+
#define KEY_ENTER 13
11+
#define KEY_CANCEL 27 // Esc
12+
#define KEY_HOME 0xF0
13+
#define KEY_NEXT 0xF1
14+
#define KEY_PREV 0xF2
15+
#define KEY_CONTEXT_MENU 0xF3
1216

1317
class UIScreen {
1418
protected:

0 commit comments

Comments
 (0)