diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..649855c --- /dev/null +++ b/.gitignore @@ -0,0 +1,3 @@ +**/datasheets +**/jlcpcb/ +**/*-backups diff --git a/firmware/components/light/beacon.c b/firmware/components/light/beacon.c index e01d02d..b510d8e 100644 --- a/firmware/components/light/beacon.c +++ b/firmware/components/light/beacon.c @@ -81,12 +81,8 @@ esp_err_t beacon_start(void) { ESP_LOGE(TAG, "Failed to start gptimer: %s", esp_err_to_name(ret)); } - else - { - ESP_LOGI(TAG, "GPTimer started."); - } - ESP_LOGD(TAG, "Beacon started."); + ESP_LOGI(TAG, "GPTimer started."); return ret; } @@ -103,10 +99,7 @@ esp_err_t beacon_stop(void) { ESP_LOGE(TAG, "Failed to stop gptimer: %s", esp_err_to_name(ret)); } - else - { - ESP_LOGI(TAG, "GPTimer stopped."); - } + ESP_LOGI(TAG, "GPTimer stopped."); ret = gptimer_disable(gptimer); if (ret != ESP_OK) diff --git a/firmware/components/touch/CMakeLists.txt b/firmware/components/touch/CMakeLists.txt new file mode 100644 index 0000000..5ca9e95 --- /dev/null +++ b/firmware/components/touch/CMakeLists.txt @@ -0,0 +1,6 @@ +idf_component_register(SRCS + "src/touch.c" + INCLUDE_DIRS "include" + PRIV_REQUIRES + button + ) diff --git a/firmware/components/touch/idf_component.yml b/firmware/components/touch/idf_component.yml new file mode 100644 index 0000000..0aaf53c --- /dev/null +++ b/firmware/components/touch/idf_component.yml @@ -0,0 +1,5 @@ +dependencies: + idf: + version: '>=5.4.0' + espressif/button: ^4.1.3 + diff --git a/firmware/components/touch/include/touch.h b/firmware/components/touch/include/touch.h new file mode 100644 index 0000000..b1f5b49 --- /dev/null +++ b/firmware/components/touch/include/touch.h @@ -0,0 +1,3 @@ +#pragma once + +void init_touch(void); diff --git a/firmware/components/touch/src/touch.c b/firmware/components/touch/src/touch.c new file mode 100644 index 0000000..867513c --- /dev/null +++ b/firmware/components/touch/src/touch.c @@ -0,0 +1,90 @@ +#include "driver/gpio.h" +#include "esp_log.h" +#include "freertos/FreeRTOS.h" +#include "freertos/queue.h" +#include "freertos/task.h" +#include "freertos/timers.h" + +static const char *TAG = "TOUCH"; + +#define TOUCH_GPIO_PIN GPIO_NUM_2 +#define DEBOUNCE_TIME_MS 250 // Debounce time in milliseconds +#define ESP_INTR_FLAG_DEFAULT 0 + +static QueueHandle_t gpio_evt_queue = NULL; +static TimerHandle_t debounce_timer = NULL; +static int last_stable_state = 1; // Last stable state (1 = not pressed) +static int pending_state = 1; // Pending state after debouncing + +// Timer callback for debouncing +static void debounce_timer_callback(TimerHandle_t xTimer) +{ + int current_level = gpio_get_level(TOUCH_GPIO_PIN); + + // Check if state has remained stable + if (current_level == pending_state && current_level != last_stable_state) + { + last_stable_state = current_level; + + if (current_level == 0) + { + ESP_LOGI(TAG, "Touch detected (debounced)!"); + } + else + { + ESP_LOGI(TAG, "Touch released (debounced)!"); + } + } +} + +// Interrupt Service Routine +static void IRAM_ATTR gpio_isr_handler(void *arg) +{ + uint32_t gpio_num = (uint32_t)arg; + xQueueSendFromISR(gpio_evt_queue, &gpio_num, NULL); +} + +// Task for processing GPIO events +static void gpio_task(void *arg) +{ + uint32_t io_num; + + for (;;) + { + if (xQueueReceive(gpio_evt_queue, &io_num, portMAX_DELAY)) + { + pending_state = gpio_get_level(TOUCH_GPIO_PIN); + + // Restart timer for debouncing + xTimerReset(debounce_timer, 0); + } + } +} + +void init_touch(void) +{ + gpio_config_t io_conf = {.intr_type = GPIO_INTR_ANYEDGE, + .mode = GPIO_MODE_INPUT, + .pin_bit_mask = (1ULL << TOUCH_GPIO_PIN), + .pull_down_en = GPIO_PULLDOWN_DISABLE, + .pull_up_en = GPIO_PULLUP_ENABLE}; + + gpio_config(&io_conf); + + // Create debounce timer + debounce_timer = xTimerCreate("debounce_timer", pdMS_TO_TICKS(DEBOUNCE_TIME_MS), + pdFALSE, // One-shot timer + NULL, debounce_timer_callback); + + // Create event queue + gpio_evt_queue = xQueueCreate(10, sizeof(uint32_t)); + + // Start task + xTaskCreate(gpio_task, "gpio_task", 2048, NULL, 10, NULL); + + // Install interrupt service + gpio_install_isr_service(ESP_INTR_FLAG_DEFAULT); + gpio_isr_handler_add(TOUCH_GPIO_PIN, gpio_isr_handler, (void *)TOUCH_GPIO_PIN); + + ESP_LOGI(TAG, "Touch GPIO on pin %d initialized with debounce", TOUCH_GPIO_PIN); +} \ No newline at end of file diff --git a/firmware/main/CMakeLists.txt b/firmware/main/CMakeLists.txt index 5fe6709..8abaa8c 100644 --- a/firmware/main/CMakeLists.txt +++ b/firmware/main/CMakeLists.txt @@ -1,4 +1,4 @@ idf_component_register(SRCS "main.c" - INCLUDE_DIRS "." + INCLUDE_DIRS "." ) diff --git a/firmware/main/idf_component.yml b/firmware/main/idf_component.yml index 343c26f..271f395 100644 --- a/firmware/main/idf_component.yml +++ b/firmware/main/idf_component.yml @@ -1,16 +1,3 @@ -## IDF Component Manager Manifest File dependencies: - ## Required IDF version idf: version: '>=5.4.0' - # # Put list of dependencies here - # # For components maintained by Espressif: - # component: "~1.0.0" - # # For 3rd party components: - # username/component: ">=1.0.0,<2.0.0" - # username2/component2: - # version: "~1.0.0" - # # For transient dependencies `public` flag can be set. - # # `public` flag doesn't have an effect dependencies of the `main` component. - # # All dependencies of `main` are public by default. - # public: true diff --git a/firmware/main/main.c b/firmware/main/main.c index 7584422..9f6c307 100644 --- a/firmware/main/main.c +++ b/firmware/main/main.c @@ -1,12 +1,17 @@ #include "light.h" #include "persistence.h" #include "remote_control.h" +#include "touch.h" + +void init_touch_gpio(void); void app_main(void) { /// init persistence persistence_init("lighthouse"); + init_touch(); + /// init WLED if (wled_init() != ESP_OK) { @@ -20,7 +25,10 @@ void app_main(void) printf("Failed to initialize beacon"); return; } - if (beacon_start() != ESP_OK) + /// start beacon service + uint8_t beacon_enabled = 1; + persistence_load(VALUE_TYPE_INT32, "BEACON_ENABLED", &beacon_enabled); + if (beacon_enabled && beacon_start() != ESP_OK) { printf("Failed to start beacon"); return;