151 lines
4.1 KiB
C
151 lines
4.1 KiB
C
#include "esp_log.h"
|
|
#include "driver/gpio.h"
|
|
#include "esp_timer.h"
|
|
#include "nvs_flash.h"
|
|
#include "esp_system.h"
|
|
#include "led_button.h"
|
|
|
|
static const char *TAG = "LED_BTN";
|
|
|
|
static led_pattern_t current_pattern = LED_OFF;
|
|
static bool button_previous_state = true;
|
|
static bool button_pressed_flag = false;
|
|
static int64_t last_toggle_time = 0;
|
|
static bool blink_state = false;
|
|
|
|
/* Long-press factory reset tracking */
|
|
static int64_t button_press_start_ms = 0;
|
|
static bool button_is_held = false;
|
|
|
|
static void set_led(bool red, bool green, bool blue)
|
|
{
|
|
gpio_set_level(LED_GPIO_RED, red ? 1 : 0);
|
|
gpio_set_level(LED_GPIO_GREEN, green ? 1 : 0);
|
|
gpio_set_level(LED_GPIO_BLUE, blue ? 1 : 0);
|
|
}
|
|
|
|
void led_button_init(void)
|
|
{
|
|
gpio_set_direction(LED_GPIO_RED, GPIO_MODE_OUTPUT);
|
|
gpio_set_direction(LED_GPIO_GREEN, GPIO_MODE_OUTPUT);
|
|
gpio_set_direction(LED_GPIO_BLUE, GPIO_MODE_OUTPUT);
|
|
|
|
gpio_set_direction(BTN_GPIO_RETRY, GPIO_MODE_INPUT);
|
|
gpio_set_pull_mode(BTN_GPIO_RETRY, GPIO_PULLUP_ONLY);
|
|
|
|
set_led(false, false, false);
|
|
button_previous_state = gpio_get_level(BTN_GPIO_RETRY);
|
|
ESP_LOGI(TAG, "LED + Button initialized");
|
|
}
|
|
|
|
void led_set_pattern(led_pattern_t pattern)
|
|
{
|
|
current_pattern = pattern;
|
|
|
|
switch (pattern) {
|
|
case LED_OFF:
|
|
set_led(false, false, false);
|
|
break;
|
|
case LED_GREEN:
|
|
set_led(false, true, false);
|
|
break;
|
|
case LED_RED:
|
|
set_led(true, false, false);
|
|
break;
|
|
case LED_BLUE:
|
|
set_led(false, false, true);
|
|
break;
|
|
case LED_GREEN_BLINK:
|
|
case LED_RED_BLINK:
|
|
case LED_BLUE_BLINK:
|
|
case LED_BLUE_BLINK_SLOW:
|
|
case LED_BLUE_BLINK_FAST:
|
|
/* Toggle handled by led_button_tick(). Start off. */
|
|
blink_state = false;
|
|
last_toggle_time = esp_timer_get_time() / 1000;
|
|
set_led(false, false, false);
|
|
break;
|
|
}
|
|
}
|
|
|
|
bool button_retry_pressed(void)
|
|
{
|
|
bool current = gpio_get_level(BTN_GPIO_RETRY);
|
|
|
|
if (button_previous_state && !current) {
|
|
button_previous_state = current;
|
|
ESP_LOGI(TAG, "Retry button pressed");
|
|
return true;
|
|
}
|
|
|
|
button_previous_state = current;
|
|
return false;
|
|
}
|
|
|
|
void led_button_tick(void)
|
|
{
|
|
/* Factory reset long-press detection (GPIO0 = BOOT button) */
|
|
bool btn_level = gpio_get_level(BTN_GPIO_RETRY);
|
|
if (btn_level == 0) { /* button pressed (active low with pull-up) */
|
|
if (!button_is_held) {
|
|
button_is_held = true;
|
|
button_press_start_ms = esp_timer_get_time() / 1000;
|
|
} else {
|
|
int64_t held_ms = (esp_timer_get_time() / 1000) - button_press_start_ms;
|
|
if (held_ms > 5000) {
|
|
ESP_LOGW(TAG, "BOOT button held %lldms — factory reset!", held_ms);
|
|
esp_err_t erase_err = nvs_flash_erase();
|
|
if (erase_err != ESP_OK) {
|
|
ESP_LOGE(TAG, "NVS erase failed: %d", erase_err);
|
|
}
|
|
esp_restart();
|
|
}
|
|
}
|
|
} else {
|
|
button_is_held = false;
|
|
}
|
|
|
|
if (current_pattern != LED_GREEN_BLINK &&
|
|
current_pattern != LED_RED_BLINK &&
|
|
current_pattern != LED_BLUE_BLINK &&
|
|
current_pattern != LED_BLUE_BLINK_SLOW &&
|
|
current_pattern != LED_BLUE_BLINK_FAST) {
|
|
return;
|
|
}
|
|
|
|
int64_t now = esp_timer_get_time() / 1000;
|
|
int64_t interval = 200;
|
|
switch (current_pattern) {
|
|
case LED_RED_BLINK:
|
|
case LED_BLUE_BLINK_FAST:
|
|
interval = 100;
|
|
break;
|
|
case LED_BLUE_BLINK_SLOW:
|
|
interval = 1000;
|
|
break;
|
|
default:
|
|
break;
|
|
}
|
|
|
|
if (now - last_toggle_time >= interval) {
|
|
last_toggle_time = now;
|
|
blink_state = !blink_state;
|
|
|
|
switch (current_pattern) {
|
|
case LED_BLUE_BLINK:
|
|
case LED_BLUE_BLINK_SLOW:
|
|
case LED_BLUE_BLINK_FAST:
|
|
set_led(false, false, blink_state);
|
|
break;
|
|
case LED_RED_BLINK:
|
|
set_led(blink_state, false, false);
|
|
break;
|
|
case LED_GREEN_BLINK:
|
|
set_led(false, blink_state, false);
|
|
break;
|
|
default:
|
|
break;
|
|
}
|
|
}
|
|
}
|