-
Notifications
You must be signed in to change notification settings - Fork 6
/
Copy pathbutton.c
109 lines (84 loc) · 2.74 KB
/
button.c
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
#include <string.h>
#include <esplibs/libmain.h>
#include "button.h"
typedef struct _button {
uint8_t gpio_num;
button_callback_fn callback;
uint16_t debounce_time;
uint16_t long_press_time;
bool pressed_value;
uint32_t last_press_time;
uint32_t last_event_time;
struct _button *next;
} button_t;
button_t *buttons = NULL;
static button_t *button_find_by_gpio(const uint8_t gpio_num) {
button_t *button = buttons;
while (button && button->gpio_num != gpio_num)
button = button->next;
return button;
}
void button_intr_callback(uint8_t gpio) {
button_t *button = button_find_by_gpio(gpio);
if (!button)
return;
uint32_t now = xTaskGetTickCountFromISR();
if ((now - button->last_event_time)*portTICK_PERIOD_MS < button->debounce_time) {
// debounce time, ignore events
return;
}
button->last_event_time = now;
if (gpio_read(button->gpio_num) == button->pressed_value) {
// Record when the button is pressed down.
button->last_press_time = now;
} else {
// The button is released. Handle the use cases.
if ((now - button->last_press_time) * portTICK_PERIOD_MS > button->long_press_time) {
button->callback(button->gpio_num, button_event_long_press);
} else {
button->callback(button->gpio_num, button_event_single_press);
}
}
}
int button_create(const uint8_t gpio_num, bool pressed_value, uint16_t long_press_time, button_callback_fn callback) {
button_t *button = button_find_by_gpio(gpio_num);
if (button)
return -1;
button = malloc(sizeof(button_t));
memset(button, 0, sizeof(*button));
button->gpio_num = gpio_num;
button->callback = callback;
button->pressed_value = pressed_value;
// times in milliseconds
button->debounce_time = 50;
button->long_press_time = long_press_time;
uint32_t now = xTaskGetTickCountFromISR();
button->last_event_time = now;
button->last_press_time = now;
button->next = buttons;
buttons = button;
gpio_set_pullup(button->gpio_num, true, true);
gpio_set_interrupt(button->gpio_num, GPIO_INTTYPE_EDGE_ANY, button_intr_callback);
return 0;
}
void button_delete(const uint8_t gpio_num) {
if (!buttons)
return;
button_t *button = NULL;
if (buttons->gpio_num == gpio_num) {
button = buttons;
buttons = buttons->next;
} else {
button_t *b = buttons;
while (b->next) {
if (b->next->gpio_num == gpio_num) {
button = b->next;
b->next = b->next->next;
break;
}
}
}
if (button) {
gpio_set_interrupt(gpio_num, GPIO_INTTYPE_EDGE_ANY, NULL);
}
}