@@ -67,6 +67,9 @@ static StaticTask_t BackgroundHwTaskBuffer;
6767static uint8_t BackgroundHwStackBuffer [HW_TASK_STACK_SIZE ];
6868
6969bool bRequestGyroMeasurement = false;
70+ bool bAwaitingConnection = false;
71+ LedEffect_t ledEffect = {0 };
72+ LedMode_t ledMode = LED_MODE_STATUS ;
7073
7174static void ApplicationInitSW (void );
7275static void ApplicationTask (SApplicationHandles * pAppHandles );
@@ -529,6 +532,11 @@ ApplicationTask(SApplicationHandles* pAppHandles)
529532
530533static void SerialAPICommandHandler (void )
531534{
535+ if (bAwaitingConnection ) {
536+ bAwaitingConnection = false;
537+ zaf_event_distributor_enqueue_proprietary_app_event (EVENT_APP_CONNECTED , NULL );
538+ }
539+
532540 const bool handler_invoked = invoke_cmd_handler (serial_frame );
533541 if (!handler_invoked )
534542 {
@@ -794,20 +802,78 @@ zaf_event_distributor_app_proprietary(event_nc_t *event)
794802 EVENT_APP event_nc = (EVENT_APP ) event -> event ;
795803 switch (event_nc ) {
796804 case EVENT_APP_USERTASK_READY :
797- // Indicate that the firmware is ready by enabling the LED at low power
798- rgb_t color = {4 , 0 , 0 };
799- set_color_buffer (color );
805+ if (ledMode != LED_MODE_MANUAL ) {
806+ // Fade slowly to white
807+ LedEffectFade_t fade = {
808+ .color = white ,
809+ .brightness = 0xff ,
810+ .increasing = false,
811+ .ticksPerStep = 2 ,
812+ .tickCounter = 0
813+ };
814+ ledEffect = (LedEffect_t ) {
815+ .type = LED_EFFECT_FADE ,
816+ .effect .fade = fade
817+ };
818+ bAwaitingConnection = true;
819+ }
820+ break ;
821+
822+ case EVENT_APP_CONNECTED :
823+ if (ledMode != LED_MODE_MANUAL ) {
824+ // Indicate that the Serial API is connected by turning the LED white solid
825+ if (ledEffect .type == LED_EFFECT_FADE ) {
826+ ledEffect .effect .fade .stopAtMax = true;
827+ } else {
828+ LedEffectSolid_t solid = {
829+ .color = white ,
830+ .modified = true
831+ };
832+ ledEffect = (LedEffect_t ) {
833+ .type = LED_EFFECT_SOLID ,
834+ .effect .solid = solid
835+ };
836+ }
837+ }
800838 break ;
801839
802840 case EVENT_APP_USERTASK_GYRO_MEASUREMENT :
841+ // A gyro measurement was requested
842+ gyro_reading_t gyro_reading = event -> payload -> gyro_reading ;
843+
844+ if (ledMode == LED_MODE_CALIBRATION ) {
845+ // Indicate bad orientation (more than 20° from vertical) in calibration mode
846+ if (gyro_reading .z < -960 || gyro_reading .z > 960 ) {
847+ LedEffectSolid_t solid = {
848+ .color = white ,
849+ .modified = true
850+ };
851+ ledEffect = (LedEffect_t ) {
852+ .type = LED_EFFECT_SOLID ,
853+ .effect .solid = solid
854+ };
855+ } else {
856+ if (ledEffect .type != LED_EFFECT_FADE || ledEffect .effect .fade .color .R != 0xff ) {
857+ LedEffectFade_t fade = {
858+ .color = red ,
859+ .brightness = 0xff ,
860+ .increasing = false,
861+ .ticksPerStep = 1 ,
862+ .tickCounter = 0
863+ };
864+ ledEffect = (LedEffect_t ) {
865+ .type = LED_EFFECT_FADE ,
866+ .effect .fade = fade
867+ };
868+ }
869+ }
870+ }
871+
803872 if (!bRequestGyroMeasurement ) {
804873 return ;
805874 }
806875 bRequestGyroMeasurement = false;
807876
808- // A gyro measurement was requested
809- gyro_reading_t gyro_reading = event -> payload -> gyro_reading ;
810-
811877 uint8_t cmd [8 ];
812878 uint8_t i = 0 ;
813879 cmd [i ++ ] = NABU_CASA_GYRO_MEASURE ;
@@ -824,6 +890,69 @@ zaf_event_distributor_app_proprietary(event_nc_t *event)
824890 );
825891 break ;
826892
893+ case EVENT_APP_USERTASK_TICK_LED : {
894+ switch (ledEffect .type ) {
895+ case LED_EFFECT_SOLID : {
896+ // For solid LED effect, set the color once
897+ if (ledEffect .effect .solid .modified ) {
898+ ledEffect .effect .solid .modified = false;
899+ set_color_buffer (ledEffect .effect .solid .color );
900+ }
901+ break ;
902+ }
903+
904+ case LED_EFFECT_FADE : {
905+ // For fading, change the brightness every N ticks,
906+ // and update the color
907+ LedEffectFade_t fade = ledEffect .effect .fade ;
908+
909+ if (fade .brightness > 0xe0 && fade .stopAtMax ) {
910+ // Switch to solid mode
911+ LedEffectSolid_t solid = {
912+ .color = fade .color ,
913+ .modified = true
914+ };
915+ ledEffect = (LedEffect_t ) {
916+ .type = LED_EFFECT_SOLID ,
917+ .effect .solid = solid
918+ };
919+ break ;
920+ }
921+
922+ if (fade .tickCounter == 0 ) {
923+ if (fade .increasing ) {
924+ fade .brightness ++ ;
925+ if (fade .brightness == 0xff ) {
926+ fade .increasing = false;
927+ }
928+ } else {
929+ fade .brightness -- ;
930+ if (fade .brightness == 0 ) {
931+ fade .increasing = true;
932+ }
933+ }
934+
935+ uint16_t r = ((uint16_t ) fade .color .R ) * ((uint16_t ) fade .brightness ) / 0xff ;
936+ uint16_t g = ((uint16_t ) fade .color .G ) * ((uint16_t ) fade .brightness ) / 0xff ;
937+ uint16_t b = ((uint16_t ) fade .color .B ) * ((uint16_t ) fade .brightness ) / 0xff ;
938+
939+ rgb_t color = {
940+ (uint8_t ) g ,
941+ (uint8_t ) r ,
942+ (uint8_t ) b
943+ };
944+
945+ set_color_buffer (color );
946+ }
947+
948+ fade .tickCounter = (fade .tickCounter + 1 ) % fade .ticksPerStep ;
949+ ledEffect .effect .fade = fade ;
950+ break ;
951+ }
952+ }
953+ break ;
954+ }
955+
827956 default :
828957 // Nothing to do
829958 break ;
@@ -957,6 +1086,23 @@ ApplicationInit(
9571086 initWs2812 ();
9581087 initqma6100p ();
9591088
1089+ // Try to restore the user-defined color from NVM
1090+ NabuCasaLedStorage_t ledStorage = {0 };
1091+ if (
1092+ SerialApiNvmReadAppData (NC_APPDATA_OFFSET_LED , (uint8_t * )& ledStorage , sizeof (ledStorage ))
1093+ && ledStorage .valid
1094+ ) {
1095+ rgb_t color = {
1096+ .G = ledStorage .g ,
1097+ .R = ledStorage .r ,
1098+ .B = ledStorage .b
1099+ };
1100+ ledMode = LED_MODE_MANUAL ;
1101+ set_color_buffer (color );
1102+ } else {
1103+ set_color_buffer (white );
1104+ }
1105+
9601106 /*************************************************************************************
9611107 * CREATE USER TASKS - ZW_ApplicationRegisterTask() and ZW_UserTask_CreateTask()
9621108 *************************************************************************************
0 commit comments