#include "buttons.h" #include #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; }