@@ -429,3 +429,136 @@ void VisualStateManager::SetScanningStarted()
429429 _updateVisualState ();
430430 }
431431}
432+
433+ void VisualStateManager::RunLedTest ()
434+ {
435+ // Save current state
436+ uint64_t savedFlags = s_stateFlags.load (std::memory_order_relaxed);
437+
438+ OS_LOGI (TAG, " === LED Test Started ===" );
439+
440+ // --- Phase 1: Mono LED brightness sweep (tests LEDC PWM) ---
441+ if (s_monoLedDriver != nullptr ) {
442+ OS_LOGI (TAG, " [Mono] Brightness sweep up" );
443+ s_monoLedDriver->ClearPattern ();
444+
445+ static const MonoLedDriver::State solidOn[] = {
446+ {true , 100'000 }
447+ };
448+ for (uint16_t b = 0 ; b <= 255 ; b += 5 ) {
449+ s_monoLedDriver->SetBrightness (static_cast <uint8_t >(b));
450+ s_monoLedDriver->SetPattern (solidOn);
451+ vTaskDelay (pdMS_TO_TICKS (20 ));
452+ }
453+
454+ OS_LOGI (TAG, " [Mono] Brightness sweep down" );
455+ for (int16_t b = 255 ; b >= 0 ; b -= 5 ) {
456+ s_monoLedDriver->SetBrightness (static_cast <uint8_t >(b));
457+ s_monoLedDriver->SetPattern (solidOn);
458+ vTaskDelay (pdMS_TO_TICKS (20 ));
459+ }
460+
461+ // Restore default brightness
462+ s_monoLedDriver->SetBrightness (255 );
463+ s_monoLedDriver->ClearPattern ();
464+ vTaskDelay (pdMS_TO_TICKS (500 ));
465+ }
466+
467+ // --- Phase 2: RGB LED color test ---
468+ if (s_rgbLedDriver != nullptr ) {
469+ uint8_t savedBrightness = 20 ; // default from Init()
470+
471+ s_rgbLedDriver->SetBrightness (255 );
472+
473+ OS_LOGI (TAG, " [RGB] Red" );
474+ static const RgbLedDriver::RGBState red[] = {
475+ {255 , 0 , 0 , 100'000 }
476+ };
477+ s_rgbLedDriver->SetPattern (red);
478+ vTaskDelay (pdMS_TO_TICKS (1500 ));
479+
480+ OS_LOGI (TAG, " [RGB] Green" );
481+ static const RgbLedDriver::RGBState green[] = {
482+ {0 , 255 , 0 , 100'000 }
483+ };
484+ s_rgbLedDriver->SetPattern (green);
485+ vTaskDelay (pdMS_TO_TICKS (1500 ));
486+
487+ OS_LOGI (TAG, " [RGB] Blue" );
488+ static const RgbLedDriver::RGBState blue[] = {
489+ {0 , 0 , 255 , 100'000 }
490+ };
491+ s_rgbLedDriver->SetPattern (blue);
492+ vTaskDelay (pdMS_TO_TICKS (1500 ));
493+
494+ OS_LOGI (TAG, " [RGB] White" );
495+ static const RgbLedDriver::RGBState white[] = {
496+ {255 , 255 , 255 , 100'000 }
497+ };
498+ s_rgbLedDriver->SetPattern (white);
499+ vTaskDelay (pdMS_TO_TICKS (1500 ));
500+
501+ OS_LOGI (TAG, " [RGB] Color cycle" );
502+ static const RgbLedDriver::RGBState cycle[] = {
503+ {255 , 0 , 0 , 500 },
504+ {255 , 165 , 0 , 500 },
505+ {255 , 255 , 0 , 500 },
506+ { 0 , 255 , 0 , 500 },
507+ { 0 , 255 , 255 , 500 },
508+ { 0 , 0 , 255 , 500 },
509+ {128 , 0 , 255 , 500 },
510+ {255 , 0 , 255 , 500 },
511+ };
512+ s_rgbLedDriver->SetPattern (cycle);
513+ vTaskDelay (pdMS_TO_TICKS (4000 ));
514+
515+ OS_LOGI (TAG, " [RGB] Brightness sweep" );
516+ static const RgbLedDriver::RGBState solidWhite[] = {
517+ {255 , 255 , 255 , 100'000 }
518+ };
519+ for (uint16_t b = 0 ; b <= 255 ; b += 5 ) {
520+ s_rgbLedDriver->SetBrightness (static_cast <uint8_t >(b));
521+ s_rgbLedDriver->SetPattern (solidWhite);
522+ vTaskDelay (pdMS_TO_TICKS (20 ));
523+ }
524+ for (int16_t b = 255 ; b >= 0 ; b -= 5 ) {
525+ s_rgbLedDriver->SetBrightness (static_cast <uint8_t >(b));
526+ s_rgbLedDriver->SetPattern (solidWhite);
527+ vTaskDelay (pdMS_TO_TICKS (20 ));
528+ }
529+
530+ s_rgbLedDriver->SetBrightness (savedBrightness);
531+ s_rgbLedDriver->ClearPattern ();
532+ vTaskDelay (pdMS_TO_TICKS (500 ));
533+ }
534+
535+ // --- Phase 3: State pattern test (both LEDs together) ---
536+ struct TestStep {
537+ const char * name;
538+ uint64_t flags;
539+ uint32_t durationMs;
540+ };
541+
542+ static const TestStep steps[] = {
543+ { " WiFi Disconnected" , 0 , 2000 },
544+ { " WiFi Connected (no WS)" , kHasIpAddressFlag , 2000 },
545+ { " WebSocket Connected" , kWebSocketConnectedFlag | kHasIpAddressFlag | kWiFiConnectedFlag , 2000 },
546+ { " E-Stop Active" , kEmergencyStoppedFlag , 2000 },
547+ { " E-Stop Active Clearing" , kEmergencyStoppedFlag | kEmergencyStopActiveClearingFlag , 2000 },
548+ {" E-Stop Awaiting Release" , kEmergencyStoppedFlag | kEmergencyStopAwaitingReleaseFlag , 2000 },
549+ { " Critical Error" , kCriticalErrorFlag , 2000 },
550+ };
551+
552+ OS_LOGI (TAG, " State patterns:" );
553+ for (const auto & step : steps) {
554+ OS_LOGI (TAG, " %s" , step.name );
555+ s_stateFlags.store (step.flags , std::memory_order_relaxed);
556+ _updateVisualState ();
557+ vTaskDelay (pdMS_TO_TICKS (step.durationMs ));
558+ }
559+
560+ // Restore original state
561+ OS_LOGI (TAG, " === LED Test Complete, restoring state ===" );
562+ s_stateFlags.store (savedFlags, std::memory_order_relaxed);
563+ _updateVisualState ();
564+ }
0 commit comments