From 02dfa1385e25875659eec20313b8914ccbf60954 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ma=C3=ABl=20Gassmann?= Date: Fri, 11 Oct 2024 02:18:54 +0200 Subject: [+] Button module with long / short press and release detection --- components/button/CMakeLists.txt | 3 ++ components/button/button_handler.c | 76 ++++++++++++++++++++++++++++++++++++++ components/button/button_handler.h | 33 +++++++++++++++++ components/screen/screen.c | 2 +- 4 files changed, 113 insertions(+), 1 deletion(-) create mode 100644 components/button/CMakeLists.txt create mode 100644 components/button/button_handler.c create mode 100644 components/button/button_handler.h (limited to 'components') diff --git a/components/button/CMakeLists.txt b/components/button/CMakeLists.txt new file mode 100644 index 0000000..1497865 --- /dev/null +++ b/components/button/CMakeLists.txt @@ -0,0 +1,3 @@ +idf_component_register(SRCS "button_handler.c" + INCLUDE_DIRS "." + PRIV_REQUIRES esp_timer esp_driver_gpio) diff --git a/components/button/button_handler.c b/components/button/button_handler.c new file mode 100644 index 0000000..eb89212 --- /dev/null +++ b/components/button/button_handler.c @@ -0,0 +1,76 @@ +#include "button_handler.h" + +bool is_pressed(struct Button* b) +{ + return b->time > b->p_time; +} + +bool was_pressed(struct Button* b, int64_t since) +{ + return b->time >= b->p_time && b->time > since; +} + +bool was_pressed_and_released(struct Button* b, int64_t since) +{ + return b->time == b->p_time && b->time > since; +} + +bool was_short_pressed(struct Button* b, int64_t since) +{ + return (is_pressed(b) && (esp_timer_get_time() - b->time)/1000 < LONG_PRESS) || (was_pressed_and_released(b, since) && b->dt < LONG_PRESS); +} + +bool was_long_pressed(struct Button* b, int64_t since) +{ + return (is_pressed(b) && (esp_timer_get_time() - b->time)/1000 >= LONG_PRESS) || (was_pressed_and_released(b, since) && b->dt >= LONG_PRESS); +} + +bool was_short_pressed_and_released(struct Button* b, int64_t since) +{ + return was_pressed_and_released(b, since) && b->dt < LONG_PRESS; +} + +bool was_long_pressed_and_released(struct Button* b, int64_t since) +{ + return was_pressed_and_released(b, since) && b->dt >= LONG_PRESS; +} + +static void IRAM_ATTR button_handler(void* arg) { + struct Button* b = (struct Button*)arg; + xQueueSendFromISR(uinput_evt_queue, &b, NULL); +} + +void button_task(void* arg) { + struct Button* b; + while (1) { + if (xQueueReceive(uinput_evt_queue, &b, portMAX_DELAY)) { + uint8_t lvl = gpio_get_level(b->pin); + if (lvl == 0 && (b->time == b->p_time || b->time == 0)) { // Button pressed + b->time = esp_timer_get_time(); + printf("Button pressed\n"); + } else if (lvl == 1 && b->time != b->p_time) { // Button released + b->dt = (esp_timer_get_time() - b->time) / 1000; + printf("Button released after %d ms\n", b->dt); + b->p_time = b->time; + } + } + } +} + + +void setup_button(struct Button* b) { + b->pin = CONFIG_BUTTON_PIN; // Assume CONFIG_BUTTON_PIN is defined + + gpio_config_t io_conf = { + .intr_type = GPIO_INTR_ANYEDGE, + .pin_bit_mask = (1ULL << b->pin), + .mode = GPIO_MODE_INPUT, + .pull_up_en = GPIO_PULLUP_ENABLE, + }; + gpio_config(&io_conf); + + uinput_evt_queue = xQueueCreate(10, sizeof(struct Button*)); + xTaskCreate(button_task, "button_task", 2048, NULL, 10, NULL); + gpio_install_isr_service(ESP_INTR_FLAG_DEFAULT); + gpio_isr_handler_add(b->pin, button_handler, (void*)b); +} \ No newline at end of file diff --git a/components/button/button_handler.h b/components/button/button_handler.h new file mode 100644 index 0000000..a980d5b --- /dev/null +++ b/components/button/button_handler.h @@ -0,0 +1,33 @@ +#ifndef BUTTON_HANDLER_H +#define BUTTON_HANDLER_H + +#include +#include +#include "freertos/FreeRTOS.h" +#include "freertos/task.h" +#include "driver/gpio.h" +#include "esp_timer.h" + +#define LONG_PRESS 500 +#define BUTTON_PIN CONFIG_BUTTON_PIN +#define ESP_INTR_FLAG_DEFAULT 0 + +struct Button { + uint8_t pin; + int64_t time; + int64_t p_time; + uint16_t dt; +}; +static QueueHandle_t uinput_evt_queue = NULL; + +void setup_button(struct Button* b); +void button_task(void* arg); +bool is_pressed(struct Button* b); +bool was_pressed(struct Button* b, int64_t since); +bool was_pressed_and_released(struct Button* b, int64_t since); +bool was_short_pressed(struct Button* b, int64_t since); +bool was_long_pressed(struct Button* b, int64_t since); +bool was_short_pressed_and_released(struct Button* b, int64_t since); +bool was_long_pressed_and_released(struct Button* b, int64_t since); + +#endif // BUTTON_HANDLER_H \ No newline at end of file diff --git a/components/screen/screen.c b/components/screen/screen.c index 92f55de..bb4fbcc 100644 --- a/components/screen/screen.c +++ b/components/screen/screen.c @@ -180,7 +180,7 @@ void display(struct Screen* screen, char digits[4]) { for (uint8_t i = 0; i < 4; ++i) { uint8_t digit = digits[i] - '0'; - printf("%i", digit); + //printf("%i", digit); if (screen->nixies[i].digit != digit){ screen->nixies[i].digit = digit; set_digit(screen->mcp, &(screen->nixies[i])); // Call set_digit function -- cgit v1.2.3