-
Notifications
You must be signed in to change notification settings - Fork 725
Expand file tree
/
Copy pathmulti_button.h
More file actions
116 lines (100 loc) · 4.09 KB
/
multi_button.h
File metadata and controls
116 lines (100 loc) · 4.09 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
/*
* Copyright (c) 2016 Zibin Zheng <znbin@qq.com>
* All rights reserved
*/
#ifndef MULTI_BUTTON_H
#define MULTI_BUTTON_H
#include <stdint.h>
#include <string.h>
// Version information
#define MULTIBUTTON_VERSION_MAJOR 1
#define MULTIBUTTON_VERSION_MINOR 1
#define MULTIBUTTON_VERSION_PATCH 1
// Configuration constants - can be modified according to your needs
#define TICKS_INTERVAL 5 // ms - timer interrupt interval
#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 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
// Forward declaration
typedef struct _Button Button;
// Button callback function type
typedef void (*BtnCallback)(Button* handle, void* user_data);
// Button event types
typedef enum {
BTN_PRESS_DOWN = 0, // button pressed down
BTN_PRESS_UP, // button released
BTN_PRESS_REPEAT, // repeated press detected
BTN_SINGLE_CLICK, // single click completed
BTN_DOUBLE_CLICK, // double click completed
BTN_LONG_PRESS_START, // long press started
BTN_LONG_PRESS_HOLD, // long press holding
BTN_EVENT_COUNT, // total number of events
BTN_NONE_PRESS // no event
} ButtonEvent;
// Button state machine states
typedef enum {
BTN_STATE_IDLE = 0, // idle state
BTN_STATE_PRESS, // pressed state
BTN_STATE_RELEASE, // released state waiting for timeout
BTN_STATE_REPEAT, // repeat press state
BTN_STATE_LONG_HOLD // long press hold state
} ButtonState;
// Button structure
struct _Button {
uint16_t ticks; // tick counter
uint8_t repeat : 4; // repeat counter (0-15)
uint8_t event : 4; // current event (0-15)
uint8_t state : 3; // state machine state (0-7)
uint8_t debounce_cnt : 3; // debounce counter (0-7)
uint8_t active_level : 1; // active GPIO level (0 or 1)
uint8_t button_level : 1; // current button level
uint8_t button_id; // button identifier
uint8_t (*hal_button_level)(uint8_t button_id); // HAL function to read GPIO
BtnCallback cb[BTN_EVENT_COUNT]; // callback function array
void* user_data; // user context pointer passed to callbacks
Button* next; // next button in linked list
};
// Optional thread-safety support for RTOS environments.
// Define MULTIBUTTON_THREAD_SAFE and provide MULTIBUTTON_LOCK()/MULTIBUTTON_UNLOCK()
// macros before including this header to enable thread-safe list operations.
//
// NOTE: Callbacks are executed OUTSIDE the lock, so a regular (non-recursive) mutex
// is safe. Callbacks may freely call button_stop()/button_start() without deadlock.
//
// Example:
// #define MULTIBUTTON_THREAD_SAFE
// #define MULTIBUTTON_LOCK() osMutexAcquire(btn_mutex, osWaitForever)
// #define MULTIBUTTON_UNLOCK() osMutexRelease(btn_mutex)
// #include "multi_button.h"
#ifdef MULTIBUTTON_THREAD_SAFE
#if !defined(MULTIBUTTON_LOCK) || !defined(MULTIBUTTON_UNLOCK)
#error "Define MULTIBUTTON_LOCK() and MULTIBUTTON_UNLOCK() when using MULTIBUTTON_THREAD_SAFE"
#endif
#else
#define MULTIBUTTON_LOCK()
#define MULTIBUTTON_UNLOCK()
#endif
#ifdef __cplusplus
extern "C" {
#endif
// Public API functions
void button_init(Button* handle, uint8_t(*pin_level)(uint8_t), uint8_t active_level, uint8_t button_id);
void button_attach(Button* handle, ButtonEvent event, BtnCallback cb, void* user_data);
void button_detach(Button* handle, ButtonEvent event);
ButtonEvent button_get_event(Button* handle);
int button_start(Button* handle);
void button_stop(Button* handle);
void button_ticks(void);
// Utility functions
uint8_t button_get_repeat_count(Button* handle);
void button_reset(Button* handle);
int button_is_pressed(Button* handle);
#ifdef __cplusplus
}
#endif
#endif