From da5e4d92d17c52333e6f5a9fac5a08066db236f9 Mon Sep 17 00:00:00 2001 From: wdllmh Date: Thu, 16 Apr 2026 10:37:45 +0800 Subject: [PATCH 1/3] Enhance long press functionality: add LONG_CALLBACK_TICKS for callback interval control and fix state machine diagrams in documentation --- README.md | 14 +++++++------- README_CN.md | 14 +++++++------- multi_button.c | 10 ++++++++++ multi_button.h | 2 ++ 4 files changed, 26 insertions(+), 14 deletions(-) diff --git a/README.md b/README.md index b6cf825..58cb3bf 100644 --- a/README.md +++ b/README.md @@ -64,13 +64,13 @@ void timer_5ms_isr(void) ## State Machine ``` - +-- long hold --> [LONG_HOLD] - | | -[IDLE] -- press --> [PRESS] release - ^ | | - | release | - | v | - | [RELEASE] <---------------------+ + +------------- release --------- [LONG_HOLD] + v ^ +[IDLE] -- press --> [PRESS] --long hold--+ + ^ | + | release + | v + | [RELEASE] | | ^ | timeout| | quick press | | | diff --git a/README_CN.md b/README_CN.md index 4cd0979..57711d1 100644 --- a/README_CN.md +++ b/README_CN.md @@ -265,13 +265,13 @@ void on_long_hold(Button* btn, void* user_data) ## 状态机说明 ``` - +-- 长按 --> [LONG_HOLD] - | | -[IDLE] -- 按下 --> [PRESS] 抬起 - ^ | | - | 抬起 | - | v | - | [RELEASE] <-----------------+ + +------------- 抬起 --------- [LONG_HOLD] + v ^ +[IDLE] -- 按下 --> [PRESS] ----- 长按 ----+ + ^ | + | 抬起 + | v + | [RELEASE] | | ^ | 超时| | 快速按下 | | | diff --git a/multi_button.c b/multi_button.c index e79c2b7..b17d44d 100644 --- a/multi_button.c +++ b/multi_button.c @@ -177,6 +177,9 @@ static void button_handler(Button* handle) handle->event = (uint8_t)BTN_LONG_PRESS_START; EVENT_CB(BTN_LONG_PRESS_START); handle->state = BTN_STATE_LONG_HOLD; + #if LONG_CALLBACK_TICKS > 1 // if LONG_CALLBACK_TICKS is 1, we will call BTN_LONG_PRESS_HOLD immediately in the next tick, no need to reset ticks here + handle->ticks = 0; // reset for long-press hold timing + #endif } break; @@ -228,6 +231,13 @@ static void button_handler(Button* handle) if (handle->button_level == handle->active_level) { // Continue holding handle->event = (uint8_t)BTN_LONG_PRESS_HOLD; + #if LONG_CALLBACK_TICKS > 1 + if (handle->ticks >= LONG_CALLBACK_TICKS) { + handle->ticks = 0; // reset for next long-press hold callback + } else { + break; // not yet time for next callback + } + #endif EVENT_CB(BTN_LONG_PRESS_HOLD); } else { // Released from long press diff --git a/multi_button.h b/multi_button.h index 3372a7a..8523ad3 100644 --- a/multi_button.h +++ b/multi_button.h @@ -19,6 +19,7 @@ #define DEBOUNCE_TICKS 3 // MAX 7 (0 ~ 7) - debounce filter depth #define SHORT_TICKS (300 / TICKS_INTERVAL) // short press threshold #define LONG_TICKS (1000 / TICKS_INTERVAL) // long press threshold +#define LONG_CALLBACK_TICKS 5 // minimum TICKS interval between two BTN_LONG_PRESS_HOLD event callback. LONG_CALLBACK_TICKS * TICKS_INTERVAL = minimum interval in ms. #define PRESS_REPEAT_MAX_NUM 15 // maximum repeat counter value // Compile-time check: debounce_cnt is a 3-bit field, max value is 7 @@ -26,6 +27,7 @@ #error "DEBOUNCE_TICKS exceeds 3-bit field maximum (7)" #endif + // Forward declaration typedef struct _Button Button; From 8730b84f7de48bbf37be4243f1cd4c9a458c45b0 Mon Sep 17 00:00:00 2001 From: wdllmh Date: Thu, 16 Apr 2026 12:09:34 +0800 Subject: [PATCH 2/3] Refactor long press callback interval logic and update test for tick saturation --- multi_button.c | 6 +----- tests/test_button.c | 2 +- 2 files changed, 2 insertions(+), 6 deletions(-) diff --git a/multi_button.c b/multi_button.c index b17d44d..b4d03ec 100644 --- a/multi_button.c +++ b/multi_button.c @@ -232,11 +232,7 @@ static void button_handler(Button* handle) // Continue holding handle->event = (uint8_t)BTN_LONG_PRESS_HOLD; #if LONG_CALLBACK_TICKS > 1 - if (handle->ticks >= LONG_CALLBACK_TICKS) { - handle->ticks = 0; // reset for next long-press hold callback - } else { - break; // not yet time for next callback - } + if(handle->ticks % LONG_CALLBACK_TICKS != 0) break; // only call callback at defined intervals #endif EVENT_CB(BTN_LONG_PRESS_HOLD); } else { diff --git a/tests/test_button.c b/tests/test_button.c index 043c85c..98f1100 100644 --- a/tests/test_button.c +++ b/tests/test_button.c @@ -366,7 +366,7 @@ static int test_ticks_saturation(void) /* Press and hold the button */ mock_gpio_value = 1; - tick_n(DEBOUNCE_TICKS + 5); + tick_n(DEBOUNCE_TICKS + 5 + LONG_TICKS); /* Manually set ticks near UINT16_MAX to test saturation */ test_btn.ticks = UINT16_MAX - 2; From 182d1dfaf097c344e404ceddb7d0cf27ce0a2651 Mon Sep 17 00:00:00 2001 From: wdllmh Date: Thu, 16 Apr 2026 12:17:06 +0800 Subject: [PATCH 3/3] Add compile-time check for LONG_CALLBACK_TICKS to ensure minimum value --- multi_button.h | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/multi_button.h b/multi_button.h index 8523ad3..96c9ef8 100644 --- a/multi_button.h +++ b/multi_button.h @@ -26,6 +26,10 @@ #if DEBOUNCE_TICKS > 7 #error "DEBOUNCE_TICKS exceeds 3-bit field maximum (7)" #endif +// Compile-time check: avoid div-0 problem +#if LONG_CALLBACK_TICKS < 1 + #error "LONG_CALLBACK_TICKS must be at least 1" +#endif // Forward declaration