Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
14 changes: 7 additions & 7 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -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
| | |
Expand Down
14 changes: 7 additions & 7 deletions README_CN.md
Original file line number Diff line number Diff line change
Expand Up @@ -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]
| | ^
| 超时| | 快速按下
| | |
Expand Down
6 changes: 6 additions & 0 deletions multi_button.c
Original file line number Diff line number Diff line change
Expand Up @@ -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;

Expand Down Expand Up @@ -228,6 +231,9 @@ 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 != 0) break; // only call callback at defined intervals
#endif
EVENT_CB(BTN_LONG_PRESS_HOLD);
} else {
// Released from long press
Expand Down
6 changes: 6 additions & 0 deletions multi_button.h
Original file line number Diff line number Diff line change
Expand Up @@ -19,12 +19,18 @@
#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
#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
typedef struct _Button Button;
Expand Down
2 changes: 1 addition & 1 deletion tests/test_button.c
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand Down