@@ -660,92 +660,16 @@ static const char _data_FX_MODE_SAW[] PROGMEM = "Saw@!,Width;!,!;!";
660660/*
661661 * Blink several LEDs in random colors on, reset, repeat.
662662 * Inspired by www.tweaking4all.com/hardware/arduino/adruino-led-strip-effects/
663+ * Cycle mode checkbox is check2
663664 */
664665uint16_t mode_twinkle (void ) {
665- // Cycle mode: randomly switch all LEDs to new color, then back to old color
666- if (SEGMENT.check1 )
667- {
668- // tiny segments: no cycling needed, avoid bitset allocation
669- if (SEGLEN <= 1 )
670- {
671- return mode_static ();
672- }
666+ uint32_t cycleTime = 20 + (255 - SEGMENT.speed ) * 5 ;
667+ uint32_t it = strip.now / cycleTime;
673668
674- unsigned dataSize = (SEGLEN + 7 ) >> 3 ; // 1 bit per LED for tracking
675- if ( ! SEGENV.allocateData (dataSize))
676- {
677- return mode_static (); // allocation failed
678- }
679-
680- uint32_t cycleTime = 20 + (255 - SEGMENT.speed )*5 ;
681- uint32_t it = strip.now / cycleTime;
682-
683- // Initialize on first call
684- if ((SEGENV.call == 0 ) || (SEGENV.aux1 > 1 ))
685- {
686- SEGENV.aux0 = 0 ; // Count of LEDs switched in current cycle
687- SEGENV.aux1 = 0 ; // Direction: 0 = switching to new color, 1 = switching back
688- memset (SEGENV.data , 0 , dataSize); // Clear all bits
689- SEGMENT.fill (SEGCOLOR (1 )); // Start with secondary color
690- }
691-
692- if (it != SEGENV.step )
693- {
694- SEGENV.step = it;
695-
696- // Check if all LEDs have been switched
697- if (SEGENV.aux0 >= SEGLEN)
698- {
699- // Flip direction and reset counter
700- SEGENV.aux1 = ! SEGENV.aux1 ;
701- SEGENV.aux0 = 0 ;
702- memset (SEGENV.data , 0 , dataSize); // Clear all bits for next cycle
703- }
704- else
705- {
706- // Switch one random LED that hasn't been switched yet
707- unsigned attempts = 0 ;
708- unsigned maxAttempts = SEGLEN * 2 ; // Avoid infinite loop
709- while (attempts < maxAttempts)
710- {
711- unsigned j = hw_random16 (SEGLEN);
712- unsigned index = j >> 3 ;
713- unsigned bitNum = j & 0x07 ;
714-
715- if ( ! bitRead (SEGENV.data [index], bitNum))
716- {
717- // This LED hasn't been switched yet
718- bitWrite (SEGENV.data [index], bitNum, true );
719- SEGENV.aux0 ++;
720-
721- if (SEGENV.aux1 == 0 )
722- {
723- // Switching to primary color
724- SEGMENT.setPixelColor (j, SEGMENT.color_from_palette (j, true , PALETTE_SOLID_WRAP, 0 ));
725- }
726- else
727- {
728- // Switching back to secondary color
729- SEGMENT.setPixelColor (j, SEGCOLOR (1 ));
730- }
731- break ;
732- }
733- attempts++;
734- }
735-
736- if (attempts >= maxAttempts) {
737- // Fail-safe: complete the cycle to avoid getting stuck
738- SEGENV.aux0 = SEGLEN;
739- }
740- }
741- }
742- }
743- else // Original twinkle behavior
744- {
669+ // Standard twinkle
670+ if ( ! SEGMENT.check2 ) {
745671 SEGMENT.fade_out (224 );
746672
747- uint32_t cycleTime = 20 + (255 - SEGMENT.speed )*5 ;
748- uint32_t it = strip.now / cycleTime;
749673 if (it != SEGENV.step )
750674 {
751675 unsigned maxOn = map (SEGMENT.intensity , 0 , 255 , 1 , SEGLEN); // make sure at least one LED is on
@@ -758,7 +682,7 @@ uint16_t mode_twinkle(void) {
758682 SEGENV.step = it;
759683 }
760684
761- unsigned PRNG16 = SEGENV.aux1 ;
685+ uint16_t PRNG16 = SEGENV.aux1 ;
762686
763687 for (unsigned i = 0 ; i < SEGENV.aux0 ; i++)
764688 {
@@ -767,11 +691,52 @@ uint16_t mode_twinkle(void) {
767691 unsigned j = p >> 16 ;
768692 SEGMENT.setPixelColor (j, SEGMENT.color_from_palette (j, true , PALETTE_SOLID_WRAP, 0 ));
769693 }
694+
695+ return FRAMETIME;
696+ }
697+
698+ // Cycle mode: randomly switch all LEDs to new color, then back to old color
699+ if (SEGLEN <= 1 ) return mode_static ();
700+
701+ unsigned dataSize = (SEGLEN + 7 ) >> 3 ;
702+ if ( ! SEGENV.allocateData (dataSize)) return mode_static ();
703+
704+ if (SEGENV.call == 0 || SEGENV.aux1 > 1 )
705+ {
706+ SEGENV.aux0 = 0 ;
707+ SEGENV.aux1 = 0 ;
708+ memset (SEGENV.data , 0 , dataSize);
709+ SEGMENT.fill (SEGCOLOR (1 ));
710+ }
711+
712+ if (it != SEGENV.step )
713+ {
714+ SEGENV.step = it;
715+ if (SEGENV.aux0 >= SEGLEN)
716+ {
717+ SEGENV.aux1 = ! SEGENV.aux1 ;
718+ SEGENV.aux0 = 0 ;
719+ memset (SEGENV.data , 0 , dataSize);
720+ }
721+ else
722+ {
723+ for (unsigned attempts = 0 ; attempts < SEGLEN * 2 ; attempts++) {
724+ unsigned j = hw_random16 (SEGLEN);
725+ unsigned byteIndex = j >> 3 , bitNum = j & 0x07 ;
726+ if ( ! bitRead (SEGENV.data [byteIndex], bitNum))
727+ {
728+ bitWrite (SEGENV.data [byteIndex], bitNum, true );
729+ SEGENV.aux0 ++;
730+ SEGMENT.setPixelColor (j, SEGENV.aux1 ? SEGCOLOR (1 ) : SEGMENT.color_from_palette (j, true , PALETTE_SOLID_WRAP, 0 ));
731+ break ;
732+ }
733+ }
734+ }
770735 }
771736
772737 return FRAMETIME;
773738}
774- static const char _data_FX_MODE_TWINKLE[] PROGMEM = " Twinkle@!,!,,,,Cycle mode;!,!;!;;m12=0" ; // pixels
739+ static const char _data_FX_MODE_TWINKLE[] PROGMEM = " Twinkle@!,!,,,,, Cycle mode;!,!;!;;m12=0" ; // pixels
775740
776741
777742/*
0 commit comments