elemes/velxio-deployer-firmware/main/led_button.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;
}
}
}