156 lines
3.6 KiB
C
156 lines
3.6 KiB
C
#include "buttons.h"
|
|
|
|
#include <stdbool.h>
|
|
|
|
#include "driver/gpio.h"
|
|
#include "freertos/FreeRTOS.h"
|
|
#include "freertos/task.h"
|
|
|
|
#define BTN_D0_GPIO 0 /* D0/BOOT, active LOW */
|
|
#define BTN_D1_GPIO 1 /* D1, active HIGH */
|
|
#define BTN_D2_GPIO 2 /* D2, active HIGH */
|
|
|
|
#define BTN_DEBOUNCE_MS 30
|
|
#define BTN_LONG_MS 1000
|
|
#define BTN_POLL_MS 10
|
|
|
|
static bool s_buttons_inited = false;
|
|
|
|
static bool button_pressed(btn_id_t id)
|
|
{
|
|
if (id == BTN_D0) {
|
|
return gpio_get_level(BTN_D0_GPIO) == 0;
|
|
}
|
|
if (id == BTN_D1) {
|
|
return gpio_get_level(BTN_D1_GPIO) == 1;
|
|
}
|
|
if (id == BTN_D2) {
|
|
return gpio_get_level(BTN_D2_GPIO) == 1;
|
|
}
|
|
return false;
|
|
}
|
|
|
|
static bool any_pressed(void)
|
|
{
|
|
return button_pressed(BTN_D0) || button_pressed(BTN_D1) || button_pressed(BTN_D2);
|
|
}
|
|
|
|
void buttons_init(void)
|
|
{
|
|
if (s_buttons_inited) {
|
|
return;
|
|
}
|
|
|
|
gpio_config_t d0_cfg = {
|
|
.pin_bit_mask = 1ULL << BTN_D0_GPIO,
|
|
.mode = GPIO_MODE_INPUT,
|
|
.pull_up_en = GPIO_PULLUP_ENABLE,
|
|
.pull_down_en = GPIO_PULLDOWN_DISABLE,
|
|
.intr_type = GPIO_INTR_DISABLE,
|
|
};
|
|
gpio_config(&d0_cfg);
|
|
|
|
gpio_config_t d1d2_cfg = {
|
|
.pin_bit_mask = (1ULL << BTN_D1_GPIO) | (1ULL << BTN_D2_GPIO),
|
|
.mode = GPIO_MODE_INPUT,
|
|
.pull_up_en = GPIO_PULLUP_DISABLE,
|
|
.pull_down_en = GPIO_PULLDOWN_ENABLE,
|
|
.intr_type = GPIO_INTR_DISABLE,
|
|
};
|
|
gpio_config(&d1d2_cfg);
|
|
|
|
s_buttons_inited = true;
|
|
}
|
|
|
|
btn_event_t buttons_poll(void)
|
|
{
|
|
btn_event_t evt = {.id = BTN_NONE, .kind = BTN_EVT_NONE};
|
|
|
|
if (!s_buttons_inited) {
|
|
buttons_init();
|
|
}
|
|
|
|
if (button_pressed(BTN_D0)) {
|
|
evt.id = BTN_D0;
|
|
evt.kind = BTN_EVT_PRESS;
|
|
return evt;
|
|
}
|
|
if (button_pressed(BTN_D1)) {
|
|
evt.id = BTN_D1;
|
|
evt.kind = BTN_EVT_PRESS;
|
|
return evt;
|
|
}
|
|
if (button_pressed(BTN_D2)) {
|
|
evt.id = BTN_D2;
|
|
evt.kind = BTN_EVT_PRESS;
|
|
return evt;
|
|
}
|
|
|
|
return evt;
|
|
}
|
|
|
|
btn_event_t buttons_wait(uint32_t timeout_ms)
|
|
{
|
|
btn_event_t evt = {.id = BTN_NONE, .kind = BTN_EVT_NONE};
|
|
uint32_t elapsed = 0;
|
|
const bool wait_forever = (timeout_ms == 0xFFFFFFFFu);
|
|
|
|
if (!s_buttons_inited) {
|
|
buttons_init();
|
|
}
|
|
|
|
while (any_pressed()) {
|
|
vTaskDelay(pdMS_TO_TICKS(BTN_POLL_MS));
|
|
if (!wait_forever) {
|
|
elapsed += BTN_POLL_MS;
|
|
if (elapsed >= timeout_ms) {
|
|
return evt;
|
|
}
|
|
}
|
|
}
|
|
|
|
while (wait_forever || elapsed < timeout_ms) {
|
|
btn_id_t id = BTN_NONE;
|
|
|
|
if (button_pressed(BTN_D0)) {
|
|
id = BTN_D0;
|
|
} else if (button_pressed(BTN_D1)) {
|
|
id = BTN_D1;
|
|
} else if (button_pressed(BTN_D2)) {
|
|
id = BTN_D2;
|
|
}
|
|
|
|
if (id != BTN_NONE) {
|
|
uint32_t held_ms = 0;
|
|
|
|
vTaskDelay(pdMS_TO_TICKS(BTN_DEBOUNCE_MS));
|
|
if (!button_pressed(id)) {
|
|
continue;
|
|
}
|
|
|
|
while (button_pressed(id)) {
|
|
vTaskDelay(pdMS_TO_TICKS(BTN_POLL_MS));
|
|
held_ms += BTN_POLL_MS;
|
|
if (!wait_forever) {
|
|
elapsed += BTN_POLL_MS;
|
|
if (elapsed >= timeout_ms) {
|
|
return evt;
|
|
}
|
|
}
|
|
}
|
|
|
|
vTaskDelay(pdMS_TO_TICKS(BTN_DEBOUNCE_MS));
|
|
evt.id = id;
|
|
evt.kind = (held_ms >= BTN_LONG_MS) ? BTN_EVT_LONG_PRESS : BTN_EVT_PRESS;
|
|
return evt;
|
|
}
|
|
|
|
vTaskDelay(pdMS_TO_TICKS(BTN_POLL_MS));
|
|
if (!wait_forever) {
|
|
elapsed += BTN_POLL_MS;
|
|
}
|
|
}
|
|
|
|
return evt;
|
|
}
|