/** * @file localbtn.c * @brief Local GPIO0 BTN reading implementation using edge capture */ #include "localbtn.h" #include "driver/gpio.h" #include "esp_timer.h" #include "esp_log.h" #include "freertos/FreeRTOS.h" #include "freertos/task.h" #include "soc/gpio_num.h" #include static const char *TAG = "LOCALBTN"; uint8_t current_mode; bool initialized; TaskHandle_t localbtnTaskhandle; localbtn_mode_change_callback_t callback; #define BOOT_BTN GPIO_NUM_0 // TODO: move to config bool boot_button_pressed(void) { return gpio_get_level(BOOT_BTN) == 0; // active LOW } static void localbtn_task(void *arg) { bool lastState = false; while (1) { vTaskDelay(pdMS_TO_TICKS(10)); bool currentState = boot_button_pressed(); if ((currentState) && (lastState != currentState)) { printf("BOOT button pressed\n"); if (callback) { callback(current_mode); } } lastState = currentState; } } esp_err_t localbtn_init() { gpio_config_t io_conf = { .pin_bit_mask = 1ULL << BOOT_BTN, .mode = GPIO_MODE_INPUT, .pull_up_en = GPIO_PULLUP_ENABLE, // safe even if external pull-up exists .pull_down_en = GPIO_PULLDOWN_DISABLE, .intr_type = GPIO_INTR_DISABLE}; ESP_ERROR_CHECK(gpio_config(&io_conf)); // Create monitor task BaseType_t ret = xTaskCreate(localbtn_task, "localbtn_monitor", 2048, NULL, 5, &localbtnTaskhandle); if (ret != pdPASS) { return ESP_FAIL; } initialized = true; ESP_LOGI(TAG, "local btn initialized on GPIO%d", BOOT_BTN); return ESP_OK; } void localbtn_deinit(void) { if (!initialized) { return; } if (localbtnTaskhandle) { vTaskDelete(localbtnTaskhandle); localbtnTaskhandle = NULL; } initialized = false; } void localbtn_register_callback(localbtn_mode_change_callback_t cb) { callback = cb; }