#include "driver/gpio.h" #include "esp_log.h" #include "esp_sleep.h" #include "freertos/FreeRTOS.h" #include "freertos/task.h" #include "wifi_provisioning.h" #include "reset_button.h" static const char *TAG = "reset_button"; #if CONFIG_FRAME_RESET_BUTTON_GPIO >= 0 #define RESET_BUTTON_GPIO ((gpio_num_t)CONFIG_FRAME_RESET_BUTTON_GPIO) #define RESET_BUTTON_POLL_MS 100 void reset_button_init(void) { /* See manage_button.c's manage_button_init() for why this has to run * before gpio_config() -- a deep sleep with this pin armed as a * wakeup source leaves it "held," and nothing un-holds it on wake * except explicitly asking. */ gpio_hold_dis(RESET_BUTTON_GPIO); gpio_config_t io_conf = { .pin_bit_mask = 1ULL << RESET_BUTTON_GPIO, .mode = GPIO_MODE_INPUT, .pull_up_en = GPIO_PULLUP_ENABLE, }; gpio_config(&io_conf); /* Not esp_sleep_enable_ext1_wakeup_io(): its internal pull resistors * don't hold once the RTC_PERIPH domain powers down for deep sleep, so * the pin floats and reads spuriously low, waking the device instantly * on every sleep entry (confirmed on hardware -- boot-looped every * ~27s, the length of one fetch/display cycle, instead of sleeping for * the configured interval). This GPIO-wakeup variant manages the pull * resistor itself across the sleep transition. */ esp_sleep_enable_gpio_wakeup_on_hp_periph_powerdown(1ULL << RESET_BUTTON_GPIO, ESP_GPIO_WAKEUP_GPIO_LOW); } void reset_button_check(void) { if (gpio_get_level(RESET_BUTTON_GPIO) != 0) { return; /* not pressed */ } ESP_LOGI(TAG, "Reset button held -- hold for %dms to clear config and reprovision", CONFIG_FRAME_RESET_BUTTON_HOLD_MS); int elapsed_ms = 0; while (elapsed_ms < CONFIG_FRAME_RESET_BUTTON_HOLD_MS) { vTaskDelay(pdMS_TO_TICKS(RESET_BUTTON_POLL_MS)); elapsed_ms += RESET_BUTTON_POLL_MS; if (gpio_get_level(RESET_BUTTON_GPIO) != 0) { ESP_LOGI(TAG, "Reset button released early, continuing normal boot"); return; } } ESP_LOGW(TAG, "Reset button held for %dms, clearing config and restarting into provisioning", CONFIG_FRAME_RESET_BUTTON_HOLD_MS); frame_config_clear(); esp_restart(); } #else void reset_button_init(void) {} void reset_button_check(void) {} #endif