57#define CORKSCREW_TURNS 2
60#define CORKSCREW_TURNS 19.25
68 "# Festival Stick Demo\n\n"
69 "This example demonstrates **proper corkscrew LED mapping** for a festival stick using FastLED's advanced mapping capabilities.\n\n"
71 "- **19+ turns** with 288 LEDs total\n"
72 "- Uses `fl::Corkscrew.toScreenMap()` for accurate web interface visualization\n"
73 "- Multiple render modes: **Noise**, **Position**, **Fire**, **Wave**, and **fl::Animartrix** effects\n"
74 "- Real-time cylindrical surface mapping\n"
75 "- **Wave mode**: Cylindrical 2D wave simulation with ripple effects and configurable blur\n"
76 "- **fl::Animartrix mode**: Advanced 2D animation effects with polar coordinate patterns\n\n"
78 "1. Draws patterns into a rectangular grid (`frameBuffer`)\n"
79 "2. Maps the grid to corkscrew LED positions using `readFrom()`\n"
80 "3. Web interface shows the actual spiral shape via fl::ScreenMap\n\n"
81 "*Select different render modes and adjust parameters to see various effects!*");
130 if (value ==
"fl::EaseType::EASE_NONE") {
132 }
else if (value ==
"EASE_IN_QUAD") {
134 }
else if (value ==
"EASE_OUT_QUAD") {
136 }
else if (value ==
"EASE_IN_OUT_QUAD") {
138 }
else if (value ==
"EASE_IN_CUBIC") {
140 }
else if (value ==
"EASE_OUT_CUBIC") {
142 }
else if (value ==
"EASE_IN_OUT_CUBIC") {
144 }
else if (value ==
"EASE_IN_SINE") {
146 }
else if (value ==
"EASE_OUT_SINE") {
148 }
else if (value ==
"EASE_IN_OUT_SINE") {
230fl::UIGroup waveGroup(
"Wave Controls",
waveSpeed,
waveDampening,
waveHalfDuplex,
waveIsotropicStencil,
waveAutoTrigger,
waveTriggerSpeed,
waveTriggerButton,
wavePalette,
waveBlurAmount,
waveBlurPasses);
332 waveArgs.
speed = 0.16f;
352 FL_WARN(
" This group contains noise pattern controls:");
353 FL_WARN(
" - Use Noise Pattern toggle");
354 FL_WARN(
" - Noise Scale and Speed sliders");
355 FL_WARN(
" - Color Palette selection for noise");
356 FL_WARN(
" fl::UIGroup automatically applied group membership via variadic constructor");
365 FL_WARN(
"Noise palette changed to: " << selectedPalette);
366 if (selectedPalette ==
"Party") {
368 }
else if (selectedPalette ==
"Heat") {
370 }
else if (selectedPalette ==
"Ocean") {
372 }
else if (selectedPalette ==
"Forest") {
374 }
else if (selectedPalette ==
"Rainbow") {
384 FL_WARN(
"Render mode changed to: " << mode);
393 case 0: order =
RGB;
break;
394 case 1: order =
RBG;
break;
395 case 2: order =
GRB;
break;
396 case 3: order =
GBR;
break;
397 case 4: order =
BRG;
break;
398 case 5: order =
BGR;
break;
418 float increment = elapsedSeconds *
speed.value() *
427 if (combinedPosition > 1.0f)
428 combinedPosition = 1.0f;
429 return combinedPosition;
441 uint16_t noise_z = now * noise_speed / 10;
442 uint16_t noise_x = now * noise_speed / 80;
443 uint16_t noise_y = now * noise_speed / 160;
449 uint8_t dataSmoothing = 0;
450 if(noise_speed < 50) {
451 dataSmoothing = 200 - (noise_speed * 4);
455 for(
int x = 0;
x < width;
x++) {
456 for(
int y = 0;
y < height;
y++) {
459 float angle = (float(
x) / float(width)) * 2.0f *
FL_PI;
463 float cylinder_radius = noise_scale;
466 float noise_x_cyl =
fl::cos(angle) * cylinder_radius;
467 float noise_y_cyl =
fl::sin(angle) * cylinder_radius;
468 float noise_z_height = float(
y) * noise_scale;
471 int xoffset = int(noise_x_cyl) + noise_x;
472 int yoffset = int(noise_y_cyl) + noise_y;
473 int zoffset = int(noise_z_height) + noise_z;
476 uint8_t data =
inoise8(xoffset, yoffset, zoffset);
479 data = qsub8(data, 16);
480 data = qadd8(data, scale8(data, 39));
485 uint8_t olddata = (oldColor.r + oldColor.g + oldColor.b) / 3;
486 uint8_t newdata = scale8(olddata, dataSmoothing) + scale8(data, 256 - dataSmoothing);
491 uint8_t index = data;
497 ihue = (now / 100) % 256;
536 for (
int dx = 0; dx < 2; ++dx) {
537 for (
int dy = 0; dy < 2; ++dy) {
540 uint8_t alpha = data.
second;
568 switch (paletteIndex) {
572 return electricGreenFirePal;
574 return electricBlueFirePal;
584 float xf = (float)width / (
float)max_width;
585 uint8_t
x = (uint8_t)(xf * 255);
587 uint32_t cosx = cos8(
x);
588 uint32_t sinx = sin8(
x);
598 uint16_t noise16 =
inoise16(cosx << 8, sinx << 8,
y << 8,
z << 8);
600 uint8_t noise_val = noise16 >> 8;
602 int8_t subtraction_factor = abs8(height - (max_height - 1)) * 255 /
605 return qsub8(noise_val, subtraction_factor);
618 for (
int w = 0; w < width; w++) {
619 for (
int h = 0; h < height; h++) {
621 uint8_t palette_index =
646 switch (paletteIndex) {
652 return waveRainbowpal;
664 int min_x = perc * width;
665 int max_x = (1 - perc) * width;
666 int min_y = perc * height;
667 int max_y = (1 - perc) * height;
673 float ripple_strength = 1.5f;
674 waveFx->setf(
x,
y, ripple_strength);
675 waveFx->setf(
x + 1,
y, ripple_strength);
676 waveFx->setf(
x,
y + 1, ripple_strength);
677 waveFx->setf(
x + 1,
y + 1, ripple_strength);
679 FL_WARN(
"Wave ripple triggered at (" <<
x <<
", " <<
y <<
") with 2x2 pattern");
690 uint32_t min_interval = (uint32_t)(500 *
speed);
691 uint32_t max_interval = (uint32_t)(3000 *
speed);
694 uint32_t
min =
fl::min(min_interval, max_interval);
695 uint32_t
max =
fl::max(min_interval, max_interval);
710 waveFx->setXCylindrical(
true);
744 static int lastAnimartrixIndex = -1;
fl::FxEngine fxEngine(NUM_LEDS)
fl::Animartrix animartrix(xyMap, FIRST_ANIMATION)
fl::UISlider brightness("Brightness", BRIGHTNESS, 0, 255)
fl::UICheckbox allWhite("All White", false)
fl::UIDropdown saturationFunction("Saturation Function", easeOptions)
fl::UIDropdown luminanceFunction("Luminance Function", easeOptions)
CRGBPalette16 currentPalette
FL_DISABLE_WARNING_PUSH FL_DISABLE_WARNING_GLOBAL_CONSTRUCTORS CFastLED FastLED
Global LED strip management instance.
FL_DISABLE_WARNING_PUSH U constexpr common_type_t< T, U > min(T a, U b) FL_NOEXCEPT
Memory functions are available in fl:: namespace via fl/stl/cstring.h Using declarations cannot work ...
constexpr common_type_t< T, U > max(T a, U b) FL_NOEXCEPT
@ APA102HD
APA102 LED chipset with 5-bit gamma correction.
CLEDController * controller
fl::UISlider scale("Scale", 4,.1, 4,.1)
::fl::DrawContext DrawContext
Manages and renders multiple visual effects (Fx) for LED strips.
fl::pair< vec2< u16 >, u8 > Entry
fl::string getOption(fl::size index) const FL_NOEXCEPT
fl::string value() const FL_NOEXCEPT
fl::size getOptionCount() const FL_NOEXCEPT
static XYMap constructRectangularGrid(u16 width, u16 height, u16 offset=0) FL_NOEXCEPT
fl::CLEDController CLEDController
#define DEFINE_GRADIENT_PALETTE(X)
CRGB ColorFromPalette(const CRGBPalette16 &pal, fl::u8 index, fl::u8 brightness, TBlendType blendType)
fl::UISlider noiseSpeed("Noise Speed", 4, 1, 100, 1)
fl::UISlider waveTriggerSpeed("Wave Trigger Speed", 0.5f, 0.0f, 1.0f, 0.01f)
fl::UICheckbox splatRendering("Splat Rendering", true)
fl::UIDropdown renderModeDropdown("Render Mode", renderModeOptions)
fl::UICheckbox waveIsotropicStencil("Wave Isotropic stencil (rounder ripples)", false)
fl::UIGroup colorBoostGroup("Color Boost", saturationFunction, luminanceFunction)
fl::EaseType getEaseType(fl::string value)
fl::WaveCrgbGradientMapPtr crgMap
fl::UIGroup animartrixGroup("fl::Animartrix Controls", animartrixIndex, animartrixTimeSpeed, animartrixColorOrder)
fl::UICheckbox waveHalfDuplex("Wave Half Duplex", true)
FL_OPTIMIZATION_LEVEL_O0_BEGIN float get_position(uint32_t now)
FL_OPTIMIZATION_LEVEL_O0_END void fillFrameBufferNoise()
fl::UICheckbox autoAdvance("Auto Advance", true)
fl::UIGroup pointGraphicsGroup("Point Graphics Mode", speed, positionCoarse, positionFine, positionExtraFine, autoAdvance)
fl::string paletteOptions[]
fl::UITitle festivalStickTitle("Festival Stick - Advanced Version")
void drawWave(uint32_t now)
fl::UISlider waveSpeed("Wave Speed", 0.03f, 0.0f, 1.0f, 0.01f)
fl::UISlider fireSpeedY("Fire SpeedY", 1.3, 1, 6,.1)
UINumberField animartrixIndex("fl::Animartrix Animation", 5, 0, static_cast< int >(fl::AnimartrixAnim::NUM_ANIMATIONS) - 1)
fl::Corkscrew corkscrew(CORKSCREW_TURNS, NUM_LEDS)
fl::CRGBPalette16 noisePalette
fl::UIDropdown saturationFunction("Saturation Function", easeInfo)
fl::UISlider animartrixTimeSpeed("fl::Animartrix Time Speed", 1, -10, 10,.1)
fl::UISlider noiseScale("Noise Scale", 100, 10, 200, 5)
fl::CRGBPalette16 getFirePalette()
static float currentPosition
fl::UIGroup waveGroup("Wave Controls", waveSpeed, waveDampening, waveHalfDuplex, waveIsotropicStencil, waveAutoTrigger, waveTriggerSpeed, waveTriggerButton, wavePalette, waveBlurAmount, waveBlurPasses)
constexpr uint16_t CORKSCREW_HEIGHT
fl::shared_ptr< fl::Grid< fl::CRGB > > frameBufferPtr
void processWaveAutoTrigger(uint32_t now)
static uint32_t nextWaveTrigger
void drawNoise(uint32_t now)
fl::UIButton waveTriggerButton("Trigger Wave")
fl::UIDropdown paletteDropdown("Color Palette", paletteOptions)
fl::UISlider positionFine("Position Fine (1x)", 0.0f, 0.0f, 0.1f, 0.001f)
uint8_t getFirePaletteIndex(uint32_t millis32, int width, int max_width, int height, int max_height, uint32_t y_speed)
static uint32_t lastUpdateTime
fl::UIGroup renderGroup("Render Options", renderModeDropdown, splatRendering, allWhite, brightness)
fl::UISlider fireScaleX("Fire ScaleX",.3, 0.1, 3,.01)
fl::UISlider waveDampening("Wave Dampening", 9.1f, 0.0f, 20.0f, 0.1f)
void drawAnimartrix(uint32_t now)
fl::UIGroup fireGroup("Fire Controls", fireScaleXY, fireSpeedY, fireScaleX, fireInvSpeedZ, firePalette)
fl::string renderModeOptions[]
fl::UISlider fireScaleXY("Fire Scale", 8, 1, 100, 1)
constexpr uint16_t CORKSCREW_WIDTH
UINumberField wavePalette("Wave Palette", 0, 0, 2)
void drawFire(uint32_t now)
fl::UIDescription festivalStickDescription("# Festival Stick Demo\n\n" "This example demonstrates **proper corkscrew LED mapping** for a festival stick using FastLED's advanced mapping capabilities.\n\n" "## Key Features\n" "- **19+ turns** with 288 LEDs total\n" "- Uses `fl::Corkscrew.toScreenMap()` for accurate web interface visualization\n" "- Multiple render modes: **Noise**, **Position**, **Fire**, **Wave**, and **fl::Animartrix** effects\n" "- Real-time cylindrical surface mapping\n" "- **Wave mode**: Cylindrical 2D wave simulation with ripple effects and configurable blur\n" "- **fl::Animartrix mode**: Advanced 2D animation effects with polar coordinate patterns\n\n" "## How It Works\n" "1. Draws patterns into a rectangular grid (`frameBuffer`)\n" "2. Maps the grid to corkscrew LED positions using `readFrom()`\n" "3. Web interface shows the actual spiral shape via fl::ScreenMap\n\n" "*Select different render modes and adjust parameters to see various effects!*")
fl::UICheckbox waveAutoTrigger("Wave Auto Trigger", true)
fl::CRGBPalette16 getWavePalette()
UINumberField animartrixColorOrder("fl::Animartrix Color Order", 0, 0, 5)
fl::UISlider positionExtraFine("Position Extra Fine (0.1x)", 0.0f, 0.0f, 0.01f, 0.0001f)
fl::UIDropdown luminanceFunction("Luminance Function", easeInfo)
UINumberField firePalette("Fire Palette", 0, 0, 2)
fl::vector< fl::string > easeInfo
fl::UISlider waveBlurPasses("Wave Blur Passes", 1, 1, 10, 1)
fl::UISlider waveBlurAmount("Wave Blur Amount", 50, 0, 172, 1)
fl::UISlider fireInvSpeedZ("Fire Inverse SpeedZ", 20, 1, 100, 1)
void fillFrameBufferFire(uint32_t now)
fl::UIGroup noiseGroup("Noise Controls", noiseScale, noiseSpeed, paletteDropdown)
fl::UISlider positionCoarse("Position Coarse (10x)", 0.0f, 0.0f, 1.0f, 0.01f)
fl::UICheckbox splatRendering("Splat Rendering", true)
fl::Corkscrew corkscrew(CORKSCREW_TURNS, NUM_LEDS)
fl::u16 inoise16(fl::u32 x, fl::u32 y, fl::u32 z, fl::u32 t)
fl::u8 inoise8(fl::u16 x, fl::u16 y, fl::u16 z)
const TProgmemRGBPalette16 OceanColors_p
Ocean colors, blues and whites.
const TProgmemRGBPalette16 HeatColors_p
Approximate "black body radiation" palette, akin to the FastLED HeatColor() function.
const TProgmemRGBPalette16 ForestColors_p
Forest colors, greens.
const TProgmemRGBPalette16 PartyColors_p
HSV color ramp: blue, purple, pink, red, orange, yellow (and back).
const TProgmemRGBPalette16 RainbowColors_p
HSV Rainbow.
LIB8STATIC fl::u16 random16() FL_NOEXCEPT
Generate a 16-bit random number.
LIB8STATIC fl::u8 random8() FL_NOEXCEPT
Generate an 8-bit random number.
Centralized logging categories for FastLED hardware interfaces and subsystems.
FL_DISABLE_WARNING_PUSH U constexpr common_type_t< T, U > min(T a, U b) FL_NOEXCEPT
constexpr common_type_t< T, U > max(T a, U b) FL_NOEXCEPT
fl::u32 millis()
Universal millisecond timer - returns milliseconds since system startup.
constexpr fl::u16 calculateCorkscrewHeight(float totalTurns, fl::u16 numLeds)
float fmodf(float x, float y) FL_NOEXCEPT
shared_ptr< T > make_shared(Args &&... args) FL_NOEXCEPT
enable_if< is_fixed_point< T >::value, T >::type cos(T angle) FL_NOEXCEPT
constexpr fl::u16 calculateCorkscrewWidth(float totalTurns, fl::u16 numLeds)
enable_if< is_fixed_point< T >::value, T >::type sin(T angle) FL_NOEXCEPT
#define FL_OPTIMIZATION_LEVEL_O0_END
#define FL_OPTIMIZATION_LEVEL_O0_BEGIN
2D wave simulation effect for LED matrices
Corkscrew LED strip projection and rendering.
CRGB colorBoost(EaseType saturation_function=EaseType::EASE_NONE, EaseType luminance_function=EaseType::EASE_NONE) const FL_NOEXCEPT
CRGB & nscale8(u8 scaledown) FL_NOEXCEPT
Scale down a RGB to N/256ths of its current brightness, using "plain math" dimming rules.
@ Blue
<div style='background:#0000FF;width:4em;height:4em;'></div>
Representation of an 8-bit RGB pixel (Red, Green, Blue)
float speed
Wave propagation speed (0.0-1.0, typical: 0.1-0.3)
bool x_cyclical
If true, waves wrap around the x-axis (cylindrical topology)
WaveCrgbMapPtr crgbMap
Custom color mapper (nullptr uses default grayscale)
bool auto_updates
If true, simulation advances automatically in draw()
SuperSample factor
Supersampling quality (SUPER_SAMPLE_2X recommended for balance)
float dampening
Energy dampening factor (higher = faster decay, typical: 3-10)
bool half_duplex
If true, constrains waves to positive values only.