From 5df3122a758f6c383289788cb9bb42332ce335a0 Mon Sep 17 00:00:00 2001 From: puckipedia Date: Sun, 1 Feb 2026 13:07:57 +0100 Subject: [PATCH] Handle button events outside interrupt context (#125) A lot of the button tasks configure TMOS tasks, which causes a lot of graphical glitches, when the bluetooth icon is drawn but the other tasks for rendering the effects still run. This also fixes the "WFI inside the interrupt handler" issue causing poweroff to hang. --- src/button.c | 59 ++++++++++++++++++++++++++++++++++++++++++++++++++-- src/button.h | 2 ++ src/main.c | 2 ++ 3 files changed, 61 insertions(+), 2 deletions(-) diff --git a/src/button.c b/src/button.c index 6adb495..70f310e 100644 --- a/src/button.c +++ b/src/button.c @@ -1,4 +1,6 @@ +#include "CH58xBLE_LIB.h" #include "button.h" +#include #define DEBOUNCE_HIGH_THRES (200) // 0-255 #define DEBOUNCE_LOW_THRES (55) // 0-255 @@ -8,6 +10,13 @@ static volatile void (*onePressHandler[KEY_INDEX])(void) = { NULL }; static volatile void (*longPressHandler[KEY_INDEX])(void) = { NULL }; +static volatile bool onePressPending[KEY_INDEX] = { false }; +static volatile bool longPressPending[KEY_INDEX] = { false }; + +static tmosTaskID button_task_id = INVALID_TASK_ID; +#define BTN_PRESS (1 << 0) +static uint16_t btn_task(tmosTaskID, uint16_t); + void btn_init() { GPIOA_ModeCfg(KEY1_PIN, GPIO_ModeIN_PD); @@ -18,6 +27,11 @@ void btn_init() PFIC_EnableIRQ(TMR3_IRQn); } +void btn_init_task(void) +{ + button_task_id = TMOS_ProcessEventRegister(btn_task); +} + void btn_onOnePress(int key, void (*handler)(void)) { if (key >= KEY_INDEX) return; @@ -30,6 +44,41 @@ void btn_onLongPress(int key, void (*handler)(void)) longPressHandler[key] = handler; } +void btn_tick(void) +{ + for (int i = 0; i < KEY_INDEX; i++) { + if (onePressPending[i]) { + onePressPending[i] = false; + if (onePressHandler[i]) onePressHandler[i](); + } + if (longPressPending[i]) { + longPressPending[i] = false; + if (longPressHandler[i]) longPressHandler[i](); + } + } +} + +static uint16_t btn_task(tmosTaskID id, uint16_t events) +{ + + if(events & SYS_EVENT_MSG) { + uint8 *pMsg = tmos_msg_receive(button_task_id); + if(pMsg != NULL) + { + tmos_msg_deallocate(pMsg); + } + return (events ^ SYS_EVENT_MSG); + } + + if (events & BTN_PRESS) { + btn_tick(); + return (events ^ BTN_PRESS); + } + + return events; +} + + __HIGH_CODE static int debounce(int key, int is_press) { @@ -59,11 +108,17 @@ static void check(int k) hold[k]++; if (hold[k] >= LONGPRESS_THRES && is_longpress[k] == 0) { is_longpress[k] = 1; - if (longPressHandler[k]) longPressHandler[k](); + longPressPending[k] = true; + if (button_task_id != INVALID_TASK_ID) { + tmos_set_event(button_task_id, BTN_PRESS); + } } } else { if (hold[k] > 0 && hold[k] < LONGPRESS_THRES) { - if (onePressHandler[k]) onePressHandler[k](); + onePressPending[k] = true; + if (button_task_id != INVALID_TASK_ID) { + tmos_set_event(button_task_id, BTN_PRESS); + } } is_longpress[k] = 0; hold[k] = 0; diff --git a/src/button.h b/src/button.h index 234e45b..87d1b2c 100644 --- a/src/button.h +++ b/src/button.h @@ -19,5 +19,7 @@ enum keys { void btn_onOnePress(int key, void (*handler)(void)); void btn_onLongPress(int key, void (*handler)(void)); void btn_init(); +void btn_init_task(void); +void btn_tick(void); #endif /* __BUTTON_H__ */ diff --git a/src/main.c b/src/main.c index a1127cb..10a62e0 100644 --- a/src/main.c +++ b/src/main.c @@ -344,6 +344,7 @@ static void disp_charging() { int blink = 0; while (mode == BOOT) { + btn_tick(); int percent = batt_raw2percent(batt_raw()); if (charging_status()) { @@ -446,6 +447,7 @@ int main() ble_setup(); spawn_tasks(); + btn_init_task(); mode = NORMAL; while (1) {