Files
n_signer/firmware/feather_s3_tft/main/buttons.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;
}