Add LED ring boot chase and connect flash animations.
Give pods quick visual feedback on power-up and when a slave joins the master. Co-authored-by: Cursor <cursoragent@cursor.com>
This commit is contained in:
@@ -718,6 +718,7 @@ static void handle_discover(const uint8_t *sender_mac,
|
|||||||
(unsigned)discover->network, mac_str,
|
(unsigned)discover->network, mac_str,
|
||||||
(unsigned long)preferred_id_for_master());
|
(unsigned long)preferred_id_for_master());
|
||||||
|
|
||||||
|
led_ring_connected_anim();
|
||||||
queue_tx(SLAVE_TX_SLAVE_INFO);
|
queue_tx(SLAVE_TX_SLAVE_INFO);
|
||||||
/* Battery after ASSIGN_ID so reports carry the definitive client_id. */
|
/* Battery after ASSIGN_ID so reports carry the definitive client_id. */
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -27,6 +27,16 @@ static led_strip_handle_t led_ring;
|
|||||||
#define LED_RING_BATTERY_LOW_R 255
|
#define LED_RING_BATTERY_LOW_R 255
|
||||||
#define LED_RING_BATTERY_LOW_G 0
|
#define LED_RING_BATTERY_LOW_G 0
|
||||||
#define LED_RING_BATTERY_LOW_B 0
|
#define LED_RING_BATTERY_LOW_B 0
|
||||||
|
/** Boot chase: all RING_LEDS within ~1 s. */
|
||||||
|
#define LED_RING_BOOT_STEP_MS 10
|
||||||
|
#define LED_RING_BOOT_R 255
|
||||||
|
#define LED_RING_BOOT_G 255
|
||||||
|
#define LED_RING_BOOT_B 255
|
||||||
|
/** Connected: every other LED briefly blue. */
|
||||||
|
#define LED_RING_CONNECTED_HOLD_MS 120
|
||||||
|
#define LED_RING_CONNECTED_R 0
|
||||||
|
#define LED_RING_CONNECTED_G 0
|
||||||
|
#define LED_RING_CONNECTED_B 255
|
||||||
|
|
||||||
static QueueHandle_t led_queue;
|
static QueueHandle_t led_queue;
|
||||||
static SemaphoreHandle_t s_battery_low_done;
|
static SemaphoreHandle_t s_battery_low_done;
|
||||||
@@ -166,6 +176,33 @@ void vTaskLedRing(void *pvParameters) {
|
|||||||
xSemaphoreGive(s_battery_low_done);
|
xSemaphoreGive(s_battery_low_done);
|
||||||
}
|
}
|
||||||
continue;
|
continue;
|
||||||
|
} else if (cmd.mode == LED_CMD_BOOT) {
|
||||||
|
uint8_t br = LED_RING_BOOT_R;
|
||||||
|
uint8_t bg = LED_RING_BOOT_G;
|
||||||
|
uint8_t bb = LED_RING_BOOT_B;
|
||||||
|
led_ring_scale_rgb(&br, &bg, &bb, LED_RING_DEFAULT_INTENSITY);
|
||||||
|
for (uint32_t i = 0; i < RING_LEDS; i++) {
|
||||||
|
led_strip_clear(led_ring);
|
||||||
|
led_strip_set_pixel(led_ring, i, br, bg, bb);
|
||||||
|
led_strip_refresh(led_ring);
|
||||||
|
vTaskDelay(pdMS_TO_TICKS(LED_RING_BOOT_STEP_MS));
|
||||||
|
}
|
||||||
|
led_strip_clear(led_ring);
|
||||||
|
led_strip_refresh(led_ring);
|
||||||
|
continue;
|
||||||
|
} else if (cmd.mode == LED_CMD_CONNECTED) {
|
||||||
|
uint8_t cr = LED_RING_CONNECTED_R;
|
||||||
|
uint8_t cg = LED_RING_CONNECTED_G;
|
||||||
|
uint8_t cb = LED_RING_CONNECTED_B;
|
||||||
|
led_ring_scale_rgb(&cr, &cg, &cb, LED_RING_DEFAULT_INTENSITY);
|
||||||
|
for (uint32_t i = 0; i < RING_LEDS; i += 2) {
|
||||||
|
led_strip_set_pixel(led_ring, i, cr, cg, cb);
|
||||||
|
}
|
||||||
|
led_strip_refresh(led_ring);
|
||||||
|
vTaskDelay(pdMS_TO_TICKS(LED_RING_CONNECTED_HOLD_MS));
|
||||||
|
led_strip_clear(led_ring);
|
||||||
|
led_strip_refresh(led_ring);
|
||||||
|
continue;
|
||||||
}
|
}
|
||||||
led_strip_refresh(led_ring);
|
led_strip_refresh(led_ring);
|
||||||
}
|
}
|
||||||
@@ -256,3 +293,13 @@ void led_ring_show_battery_low(void) {
|
|||||||
led_ring_send_command(&cmd);
|
led_ring_send_command(&cmd);
|
||||||
(void)xSemaphoreTake(s_battery_low_done, portMAX_DELAY);
|
(void)xSemaphoreTake(s_battery_low_done, portMAX_DELAY);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void led_ring_boot_anim(void) {
|
||||||
|
led_command_t cmd = {.mode = LED_CMD_BOOT};
|
||||||
|
led_ring_send_command(&cmd);
|
||||||
|
}
|
||||||
|
|
||||||
|
void led_ring_connected_anim(void) {
|
||||||
|
led_command_t cmd = {.mode = LED_CMD_CONNECTED};
|
||||||
|
led_ring_send_command(&cmd);
|
||||||
|
}
|
||||||
|
|||||||
+9
-1
@@ -19,7 +19,9 @@ typedef enum {
|
|||||||
LED_CMD_PROGRESS,
|
LED_CMD_PROGRESS,
|
||||||
LED_CMD_BLINK,
|
LED_CMD_BLINK,
|
||||||
LED_CMD_FIND_ME,
|
LED_CMD_FIND_ME,
|
||||||
LED_CMD_BATTERY_LOW
|
LED_CMD_BATTERY_LOW,
|
||||||
|
LED_CMD_BOOT,
|
||||||
|
LED_CMD_CONNECTED
|
||||||
} led_mode_t;
|
} led_mode_t;
|
||||||
|
|
||||||
typedef struct {
|
typedef struct {
|
||||||
@@ -53,4 +55,10 @@ void led_ring_find_me(void);
|
|||||||
/** First 4 LEDs red at ~10 % for 5 s, then off (blocking in LED task). */
|
/** First 4 LEDs red at ~10 % for 5 s, then off (blocking in LED task). */
|
||||||
void led_ring_show_battery_low(void);
|
void led_ring_show_battery_low(void);
|
||||||
|
|
||||||
|
/** Chase: each ring LED lights once in sequence (~1 s total). */
|
||||||
|
void led_ring_boot_anim(void);
|
||||||
|
|
||||||
|
/** Every second LED briefly blue (join / reconnect). */
|
||||||
|
void led_ring_connected_anim(void);
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|||||||
+2
-1
@@ -207,6 +207,7 @@ void app_main(void) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
led_ring_init();
|
led_ring_init();
|
||||||
|
led_ring_boot_anim();
|
||||||
|
|
||||||
if (app_config.master) {
|
if (app_config.master) {
|
||||||
cmd_queue = xQueueCreate(64, sizeof(generic_msg_t));
|
cmd_queue = xQueueCreate(64, sizeof(generic_msg_t));
|
||||||
@@ -240,7 +241,7 @@ void app_main(void) {
|
|||||||
cmd_set_log_level_register();
|
cmd_set_log_level_register();
|
||||||
}
|
}
|
||||||
|
|
||||||
ESP_LOGI(TAG, "LED ring: UART LED_RING commands only (no local demo loop)");
|
ESP_LOGI(TAG, "LED ring: boot anim + UART LED_RING commands");
|
||||||
|
|
||||||
/* After OTA: PENDING_VERIFY until confirm; crash before this → rollback. */
|
/* After OTA: PENDING_VERIFY until confirm; crash before this → rollback. */
|
||||||
ota_confirm_schedule();
|
ota_confirm_schedule();
|
||||||
|
|||||||
Reference in New Issue
Block a user