diff --git a/wled00/FX.cpp b/wled00/FX.cpp index f439e4c664..aa0c5b6b07 100644 --- a/wled00/FX.cpp +++ b/wled00/FX.cpp @@ -924,6 +924,70 @@ static uint16_t chase(uint32_t color1, uint32_t color2, uint32_t color3, bool do return FRAMETIME; } +/** + * Chase_Race function to allow 3 colored bands to race along the LEDs with black between the colors. + * Uses segment palette colors SEGCOLOR(0), SEGCOLOR(1), and SEGCOLOR(2). + */ +uint16_t chase_race() +{ + // Handle edge cases + if (SEGLEN == 0) + { + return FRAMETIME; // Skip rendering for zero LEDs + } + if (SEGLEN == 1) + { + // For one LED, cycle through colors based on time + uint16_t counter = strip.now * ((SEGMENT.speed >> 2) + 1); + uint8_t phase = (counter >> 8) % 3; // Cycle every ~256ms + uint32_t color = (phase == 0) ? SEGCOLOR(0) : (phase == 1) ? SEGCOLOR(1) + : SEGCOLOR(2); + SEGMENT.setPixelColor(0, color); + return FRAMETIME; + } + + // Use segment palette colors + uint32_t color1 = SEGCOLOR(0); + uint32_t color2 = SEGCOLOR(1); + uint32_t color3 = SEGCOLOR(2); + + // Original animation logic + uint16_t counter = strip.now * ((SEGMENT.speed >> 2) + 1); + uint16_t a = (counter * SEGLEN) >> 16; + + // Use intensity setting to vary chase up to 1/2 string length + unsigned size = 1 + ((SEGMENT.intensity * SEGLEN) >> 10); + unsigned gap = 1 + size / 4; // Smaller black band size as a fraction of color size + + // Calculate positions for each color band + uint16_t positions[] = { + a, // Start of color1 + (a + size) % SEGLEN, // End of color1 + (a + size + gap) % SEGLEN, // Start of color2 + (a + size * 2 + gap) % SEGLEN, // End of color2 + (a + size * 2 + gap * 2) % SEGLEN, // Start of color3 + (a + size * 3 + gap * 2) % SEGLEN // End of color3 + }; + + // Set background to black + SEGMENT.fill(0); + + // Fill the three color segments directly + for (unsigned count = 0; count < positions[1] - positions[0] + (positions[1] < positions[0] ? SEGLEN : 0); count++) + { + SEGMENT.setPixelColor((positions[0] + count) % SEGLEN, color1); + } + for (unsigned count = 0; count < positions[3] - positions[2] + (positions[3] < positions[2] ? SEGLEN : 0); count++) + { + SEGMENT.setPixelColor((positions[2] + count) % SEGLEN, color2); + } + for (unsigned count = 0; count < positions[5] - positions[4] + (positions[5] < positions[4] ? SEGLEN : 0); count++) + { + SEGMENT.setPixelColor((positions[4] + count) % SEGLEN, color3); + } + + return FRAMETIME; +} /* * Bicolor chase, more primary color. @@ -933,6 +997,10 @@ uint16_t mode_chase_color(void) { } static const char _data_FX_MODE_CHASE_COLOR[] PROGMEM = "Chase@!,Width;!,!,!;!"; +/* + * Chase Race with 3 color strips + */ +static const char _data_FX_MODE_CHASE_RACE[] PROGMEM = "Chase Race@!,Width;!,!,!;!"; /* * Primary running followed by random color. @@ -10476,7 +10544,7 @@ void WS2812FX::setupEffectData() { addEffect(FX_MODE_MULTI_STROBE, &mode_multi_strobe, _data_FX_MODE_MULTI_STROBE); addEffect(FX_MODE_BLINK_RAINBOW, &mode_blink_rainbow, _data_FX_MODE_BLINK_RAINBOW); addEffect(FX_MODE_ANDROID, &mode_android, _data_FX_MODE_ANDROID); - addEffect(FX_MODE_CHASE_COLOR, &mode_chase_color, _data_FX_MODE_CHASE_COLOR); + addEffect(FX_MODE_CHASE_COLOR, &mode_chase_color, _data_FX_MODE_CHASE_COLOR); addEffect(FX_MODE_CHASE_RANDOM, &mode_chase_random, _data_FX_MODE_CHASE_RANDOM); addEffect(FX_MODE_CHASE_RAINBOW, &mode_chase_rainbow, _data_FX_MODE_CHASE_RAINBOW); addEffect(FX_MODE_CHASE_FLASH, &mode_chase_flash, _data_FX_MODE_CHASE_FLASH); @@ -10486,6 +10554,7 @@ void WS2812FX::setupEffectData() { addEffect(FX_MODE_TRAFFIC_LIGHT, &mode_traffic_light, _data_FX_MODE_TRAFFIC_LIGHT); addEffect(FX_MODE_COLOR_SWEEP_RANDOM, &mode_color_sweep_random, _data_FX_MODE_COLOR_SWEEP_RANDOM); addEffect(FX_MODE_RUNNING_COLOR, &mode_running_color, _data_FX_MODE_RUNNING_COLOR); + addEffect(FX_MODE_CHASE_RACE, &chase_race, _data_FX_MODE_CHASE_RACE); addEffect(FX_MODE_AURORA, &mode_aurora, _data_FX_MODE_AURORA); addEffect(FX_MODE_RUNNING_RANDOM, &mode_running_random, _data_FX_MODE_RUNNING_RANDOM); addEffect(FX_MODE_LARSON_SCANNER, &mode_larson_scanner, _data_FX_MODE_LARSON_SCANNER); @@ -10683,4 +10752,4 @@ addEffect(FX_MODE_PS1DSONICBOOM, &mode_particle1DsonicBoom, _data_FX_MODE_PS_SON addEffect(FX_MODE_PS1DSPRINGY, &mode_particleSpringy, _data_FX_MODE_PS_SPRINGY); #endif // WLED_DISABLE_PARTICLESYSTEM1D -} +} \ No newline at end of file diff --git a/wled00/FX.h b/wled00/FX.h index 6481ff7572..558fb04fec 100644 --- a/wled00/FX.h +++ b/wled00/FX.h @@ -353,8 +353,8 @@ extern byte realtimeMode; // used in getMappedPixelIndex() #define FX_MODE_PS1DSONICSTREAM 214 #define FX_MODE_PS1DSONICBOOM 215 #define FX_MODE_PS1DSPRINGY 216 -#define MODE_COUNT 217 - +#define FX_MODE_CHASE_RACE 217 +#define MODE_COUNT 218 #define BLEND_STYLE_FADE 0x00 // universal #define BLEND_STYLE_FAIRY_DUST 0x01 // universal