Dim LED ring, add blink mode, and signal OTA outcome on the ring.
Default brightness is ~5%; UART blink mode and green/red pulses mark OTA success or failure. Failed UART uploads skip ESP-NOW distribution. Co-authored-by: Cursor <cursoragent@cursor.com>
This commit is contained in:
+100
-8
@@ -3,6 +3,8 @@
|
||||
#include "driver/i2c_types.h"
|
||||
#include "esp_err.h"
|
||||
#include "esp_log.h"
|
||||
#include "freertos/FreeRTOS.h"
|
||||
#include "freertos/task.h"
|
||||
#include "led_strip.h"
|
||||
#include <stdint.h>
|
||||
|
||||
@@ -16,6 +18,8 @@ static led_strip_handle_t led_ring;
|
||||
|
||||
#define RING_LEDS 95
|
||||
#define LED_RING_PIN 7
|
||||
#define LED_RING_BLINK_ON_MS 350
|
||||
#define LED_RING_BLINK_OFF_MS 150
|
||||
|
||||
static QueueHandle_t led_queue;
|
||||
|
||||
@@ -43,20 +47,33 @@ const uint8_t d9[] = {19, 20, 21, 22, 23, 24, 25, 26, 27, 46, 47, 58,
|
||||
const uint8_t d10[] = {46, 50, 57, 61, 65, 72, 76, 78, 80,
|
||||
82, 84, 86, 88, 90, 92, 93, 94, 95};
|
||||
|
||||
// Lookup Array for the Digits
|
||||
const digit_definition_t digit_lookup[] = {
|
||||
{d0, sizeof(d0)}, {d1, sizeof(d1)}, {d2, sizeof(d2)}, {d3, sizeof(d3)},
|
||||
{d4, sizeof(d4)}, {d5, sizeof(d5)}, {d6, sizeof(d6)}, {d7, sizeof(d7)},
|
||||
{d8, sizeof(d8)}, {d9, sizeof(d9)}, {d10, sizeof(d10)}};
|
||||
|
||||
void led_ring_scale_rgb(uint8_t *r, uint8_t *g, uint8_t *b, uint8_t intensity) {
|
||||
if (intensity == 0) {
|
||||
intensity = LED_RING_DEFAULT_INTENSITY;
|
||||
}
|
||||
*r = (uint16_t)(*r) * intensity / 255;
|
||||
*g = (uint16_t)(*g) * intensity / 255;
|
||||
*b = (uint16_t)(*b) * intensity / 255;
|
||||
}
|
||||
|
||||
static void ring_fill_color(uint8_t r, uint8_t g, uint8_t b) {
|
||||
for (uint32_t i = 0; i < RING_LEDS; i++) {
|
||||
led_strip_set_pixel(led_ring, i, r, g, b);
|
||||
}
|
||||
}
|
||||
|
||||
void vTaskLedRing(void *pvParameters) {
|
||||
/* LED Ring config */
|
||||
led_strip_config_t ring_config = {
|
||||
.strip_gpio_num = LED_RING_PIN,
|
||||
.max_leds = RING_LEDS,
|
||||
};
|
||||
led_strip_rmt_config_t rmt_ring_config = {
|
||||
.resolution_hz = 10 * 1000 * 1000, // 10 MHz
|
||||
.resolution_hz = 10 * 1000 * 1000,
|
||||
};
|
||||
esp_err_t err =
|
||||
led_strip_new_rmt_device(&ring_config, &rmt_ring_config, &led_ring);
|
||||
@@ -67,17 +84,19 @@ void vTaskLedRing(void *pvParameters) {
|
||||
led_command_t cmd;
|
||||
while (1) {
|
||||
if (xQueueReceive(led_queue, &cmd, portMAX_DELAY)) {
|
||||
uint8_t r = cmd.r;
|
||||
uint8_t g = cmd.g;
|
||||
uint8_t b = cmd.b;
|
||||
led_ring_scale_rgb(&r, &g, &b, cmd.intensity);
|
||||
|
||||
led_strip_clear(led_ring);
|
||||
|
||||
if (cmd.mode == LED_CMD_CLEAR) {
|
||||
/* ring already cleared */
|
||||
} else if (cmd.mode == LED_CMD_SET_DIGIT && cmd.value <= 10) {
|
||||
digit_definition_t digit = digit_lookup[cmd.value];
|
||||
|
||||
for (int i = 0; i < digit.count; i++) {
|
||||
// Invert LED Counting for Now
|
||||
led_strip_set_pixel(led_ring, RING_LEDS - digit.leds[i], cmd.r, cmd.g,
|
||||
cmd.b);
|
||||
led_strip_set_pixel(led_ring, RING_LEDS - digit.leds[i], r, g, b);
|
||||
}
|
||||
} else if (cmd.mode == LED_CMD_PROGRESS) {
|
||||
uint32_t lit = ((uint32_t)cmd.progress * RING_LEDS + 50) / 100;
|
||||
@@ -85,8 +104,23 @@ void vTaskLedRing(void *pvParameters) {
|
||||
lit = RING_LEDS;
|
||||
}
|
||||
for (uint32_t i = 0; i < lit; i++) {
|
||||
led_strip_set_pixel(led_ring, i, cmd.r, cmd.g, cmd.b);
|
||||
led_strip_set_pixel(led_ring, i, r, g, b);
|
||||
}
|
||||
} else if (cmd.mode == LED_CMD_BLINK) {
|
||||
uint16_t on_ms = cmd.blink_ms > 0 ? cmd.blink_ms : LED_RING_BLINK_ON_MS;
|
||||
uint8_t count = cmd.blink_count > 0 ? cmd.blink_count : 1;
|
||||
|
||||
for (uint8_t n = 0; n < count; n++) {
|
||||
ring_fill_color(r, g, b);
|
||||
led_strip_refresh(led_ring);
|
||||
vTaskDelay(pdMS_TO_TICKS(on_ms));
|
||||
led_strip_clear(led_ring);
|
||||
led_strip_refresh(led_ring);
|
||||
if (n + 1 < count) {
|
||||
vTaskDelay(pdMS_TO_TICKS(LED_RING_BLINK_OFF_MS));
|
||||
}
|
||||
}
|
||||
continue;
|
||||
}
|
||||
led_strip_refresh(led_ring);
|
||||
}
|
||||
@@ -103,3 +137,61 @@ void led_ring_send_command(led_command_t *cmd) {
|
||||
xQueueSend(led_queue, cmd, portMAX_DELAY);
|
||||
}
|
||||
}
|
||||
|
||||
void led_ring_show_ota_clear(void) {
|
||||
led_command_t cmd = {.mode = LED_CMD_CLEAR};
|
||||
led_ring_send_command(&cmd);
|
||||
}
|
||||
|
||||
void led_ring_show_ota_progress(uint32_t bytes_done, uint32_t total_bytes,
|
||||
uint8_t r, uint8_t g, uint8_t b) {
|
||||
static struct {
|
||||
uint8_t pct;
|
||||
uint8_t r, g, b;
|
||||
} last = {255, 0, 0, 0};
|
||||
|
||||
if (total_bytes == 0) {
|
||||
return;
|
||||
}
|
||||
|
||||
uint32_t pct32 = (bytes_done * 100u + total_bytes / 2) / total_bytes;
|
||||
if (pct32 > 100) {
|
||||
pct32 = 100;
|
||||
}
|
||||
uint8_t pct = (uint8_t)pct32;
|
||||
|
||||
if (pct == last.pct && r == last.r && g == last.g && b == last.b) {
|
||||
return;
|
||||
}
|
||||
last.pct = pct;
|
||||
last.r = r;
|
||||
last.g = g;
|
||||
last.b = b;
|
||||
|
||||
led_command_t cmd = {
|
||||
.mode = LED_CMD_PROGRESS,
|
||||
.progress = pct,
|
||||
.r = r,
|
||||
.g = g,
|
||||
.b = b,
|
||||
.intensity = LED_RING_DEFAULT_INTENSITY,
|
||||
};
|
||||
led_ring_send_command(&cmd);
|
||||
}
|
||||
|
||||
void led_ring_blink_once(uint8_t r, uint8_t g, uint8_t b) {
|
||||
led_command_t cmd = {
|
||||
.mode = LED_CMD_BLINK,
|
||||
.r = r,
|
||||
.g = g,
|
||||
.b = b,
|
||||
.intensity = LED_RING_DEFAULT_INTENSITY,
|
||||
.blink_ms = LED_RING_BLINK_ON_MS,
|
||||
.blink_count = 1,
|
||||
};
|
||||
led_ring_send_command(&cmd);
|
||||
}
|
||||
|
||||
void led_ring_ota_success(void) { led_ring_blink_once(0, 255, 0); }
|
||||
|
||||
void led_ring_ota_failed(void) { led_ring_blink_once(255, 0, 0); }
|
||||
|
||||
Reference in New Issue
Block a user