summaryrefslogtreecommitdiff
path: root/components/button
diff options
context:
space:
mode:
authorMaël Gassmann <mael.gassmann@students.bfh.ch>2024-10-11 02:18:54 +0200
committerMaël Gassmann <mael.gassmann@students.bfh.ch>2024-10-11 02:19:31 +0200
commit02dfa1385e25875659eec20313b8914ccbf60954 (patch)
treeb8df240517543f2e4a55a9188ea5856abec932cf /components/button
parent62f508b029c4cc6d0819eb5b3e06353c902be2be (diff)
[+] Button module with long / short press and release detectionmaster
Diffstat (limited to 'components/button')
-rw-r--r--components/button/CMakeLists.txt3
-rw-r--r--components/button/button_handler.c76
-rw-r--r--components/button/button_handler.h33
3 files changed, 112 insertions, 0 deletions
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 <stdio.h>
+#include <stdint.h>
+#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