58#define CORKSCREW_TURNS 2
61#define CORKSCREW_TURNS 19.25
69 "# Festival Stick Demo\n\n"
70 "This example demonstrates **proper corkscrew LED mapping** for a festival stick using FastLED's advanced mapping capabilities.\n\n"
72 "- **19+ turns** with 288 LEDs total\n"
73 "- Uses `Corkscrew.toScreenMap()` for accurate web interface visualization\n"
74 "- Multiple render modes: **Noise**, **Position**, **Fire**, **Wave**, and **Animartrix** effects\n"
75 "- Real-time cylindrical surface mapping\n"
76 "- **Wave mode**: Cylindrical 2D wave simulation with ripple effects and configurable blur\n"
77 "- **Animartrix mode**: Advanced 2D animation effects with polar coordinate patterns\n\n"
79 "1. Draws patterns into a rectangular grid (`frameBuffer`)\n"
80 "2. Maps the grid to corkscrew LED positions using `readFrom()`\n"
81 "3. Web interface shows the actual spiral shape via ScreenMap\n\n"
82 "*Select different render modes and adjust parameters to see various effects!*");
143 if (value ==
"EASE_NONE") {
145 }
else if (value ==
"EASE_IN_QUAD") {
147 }
else if (value ==
"EASE_OUT_QUAD") {
149 }
else if (value ==
"EASE_IN_OUT_QUAD") {
151 }
else if (value ==
"EASE_IN_CUBIC") {
153 }
else if (value ==
"EASE_OUT_CUBIC") {
155 }
else if (value ==
"EASE_IN_OUT_CUBIC") {
157 }
else if (value ==
"EASE_IN_SINE") {
159 }
else if (value ==
"EASE_OUT_SINE") {
161 }
else if (value ==
"EASE_IN_OUT_SINE") {
339 XYMap xyRect(width, height,
false);
344 waveArgs.
speed = 0.16f;
364 FL_WARN(
" This group contains noise pattern controls:");
365 FL_WARN(
" - Use Noise Pattern toggle");
366 FL_WARN(
" - Noise Scale and Speed sliders");
367 FL_WARN(
" - Color Palette selection for noise");
368 FL_WARN(
" UIGroup automatically applied group membership via variadic constructor");
376 string selectedPalette = dropdown.
value();
377 FL_WARN(
"Noise palette changed to: " << selectedPalette);
378 if (selectedPalette ==
"Party") {
380 }
else if (selectedPalette ==
"Heat") {
382 }
else if (selectedPalette ==
"Ocean") {
384 }
else if (selectedPalette ==
"Forest") {
386 }
else if (selectedPalette ==
"Rainbow") {
392 string mode = dropdown.
value();
396 FL_WARN(
"Render mode changed to: " << mode);
405 case 0: order =
RGB;
break;
406 case 1: order =
RBG;
break;
407 case 2: order =
GRB;
break;
408 case 3: order =
GBR;
break;
409 case 4: order =
BRG;
break;
410 case 5: order =
BGR;
break;
430 float increment = elapsedSeconds *
speed.value() *
439 if (combinedPosition > 1.0f)
440 combinedPosition = 1.0f;
441 return combinedPosition;
452 uint32_t now = millis();
453 uint16_t noise_z = now * noise_speed / 10;
454 uint16_t noise_x = now * noise_speed / 80;
455 uint16_t noise_y = now * noise_speed / 160;
461 uint8_t dataSmoothing = 0;
462 if(noise_speed < 50) {
463 dataSmoothing = 200 - (noise_speed * 4);
467 for(
int x = 0;
x < width;
x++) {
468 for(
int y = 0;
y < height;
y++) {
471 float angle = (float(
x) / float(width)) * 2.0f *
PI;
475 float cylinder_radius = noise_scale;
478 float noise_x_cyl = cos(angle) * cylinder_radius;
479 float noise_y_cyl = sin(angle) * cylinder_radius;
480 float noise_z_height = float(
y) * noise_scale;
483 int xoffset = int(noise_x_cyl) + noise_x;
484 int yoffset = int(noise_y_cyl) + noise_y;
485 int zoffset = int(noise_z_height) + noise_z;
488 uint8_t data =
inoise8(xoffset, yoffset, zoffset);
491 data =
qsub8(data, 16);
497 uint8_t olddata = (oldColor.r + oldColor.g + oldColor.b) / 3;
498 uint8_t newdata =
scale8(olddata, dataSmoothing) +
scale8(data, 256 - dataSmoothing);
503 uint8_t index = data;
509 ihue = (now / 100) % 256;
548 for (
int dx = 0; dx < 2; ++dx) {
549 for (
int dy = 0; dy < 2; ++dy) {
552 uint8_t alpha = data.
second;
580 switch (paletteIndex) {
584 return electricGreenFirePal;
586 return electricBlueFirePal;
596 float xf = (float)width / (
float)max_width;
597 uint8_t
x = (uint8_t)(xf * 255);
599 uint32_t cosx =
cos8(
x);
600 uint32_t sinx =
sin8(
x);
610 uint16_t noise16 =
inoise16(cosx << 8, sinx << 8,
y << 8,
z << 8);
612 uint8_t noise_val = noise16 >> 8;
614 int8_t subtraction_factor =
abs8(height - (max_height - 1)) * 255 /
617 return qsub8(noise_val, subtraction_factor);
630 for (
int w = 0; w < width; w++) {
631 for (
int h = 0; h < height; h++) {
633 uint8_t palette_index =
658 switch (paletteIndex) {
664 return waveRainbowpal;
676 int min_x = perc * width;
677 int max_x = (1 - perc) * width;
678 int min_y = perc * height;
679 int max_y = (1 - perc) * height;
685 float ripple_strength = 1.5f;
686 waveFx->setf(
x,
y, ripple_strength);
687 waveFx->setf(
x + 1,
y, ripple_strength);
688 waveFx->setf(
x,
y + 1, ripple_strength);
689 waveFx->setf(
x + 1,
y + 1, ripple_strength);
691 FL_WARN(
"Wave ripple triggered at (" <<
x <<
", " <<
y <<
") with 2x2 pattern");
702 uint32_t min_interval = (uint32_t)(500 *
speed);
703 uint32_t max_interval = (uint32_t)(3000 *
speed);
706 uint32_t min =
MIN(min_interval, max_interval);
707 uint32_t max =
MAX(min_interval, max_interval);
708 if (min >= max) max = min + 1;
722 waveFx->setXCylindrical(
true);
753 static int lastAnimartrixIndex = -1;
767 uint32_t now = millis();
UIDropdown luminanceFunction("Luminance Function", easeOptions)
UIDropdown saturationFunction("Saturation Function", easeOptions)
CRGBPalette16 currentPalette
FL_DISABLE_WARNING_PUSH FL_DISABLE_WARNING_GLOBAL_CONSTRUCTORS CFastLED FastLED
Global LED strip management instance.
@ APA102HD
APA102 LED chipset with 5-bit gamma correction.
central include file for FastLED, defines the CFastLED class/object
CLEDController * controller
UISlider brightness("Brightness", 128, 0, 255, 1)
Base definition for an LED controller.
Manages and renders multiple visual effects (Fx) for LED strips.
fl::pair< vec2< u16 >, u8 > Entry
fl::size getOptionCount() const
fl::string getOption(fl::size index) const
static XYMap constructRectangularGrid(u16 width, u16 height, u16 offset=0)
#define DEFINE_GRADIENT_PALETTE(X)
Defines a static RGB palette very compactly using a series of connected color gradients.
#define FL_OPTIMIZATION_LEVEL_O0_END
#define FL_OPTIMIZATION_LEVEL_O0_BEGIN
UISlider brightness("Brightness", 255, 0, 255, 1)
UISlider fireScaleXY("Fire Scale", 8, 1, 100, 1)
FL_OPTIMIZATION_LEVEL_O0_BEGIN float get_position(uint32_t now)
UISlider waveBlurAmount("Wave Blur Amount", 50, 0, 172, 1)
FL_OPTIMIZATION_LEVEL_O0_END void fillFrameBufferNoise()
UIDropdown paletteDropdown("Color Palette", paletteOptions)
fl::unique_ptr< Animartrix > animartrix
UIGroup pointGraphicsGroup("Point Graphics Mode", speed, positionCoarse, positionFine, positionExtraFine, autoAdvance)
UITitle festivalStickTitle("Festival Stick - Advanced Version")
Corkscrew corkscrew(CORKSCREW_TURNS, NUM_LEDS)
UIGroup noiseGroup("Noise Controls", noiseScale, noiseSpeed, paletteDropdown)
UIDropdown luminanceFunction("Luminance Function", easeInfo)
void drawWave(uint32_t now)
UIGroup fireGroup("Fire Controls", fireScaleXY, fireSpeedY, fireScaleX, fireInvSpeedZ, firePalette)
UICheckbox splatRendering("Splat Rendering", true)
UISlider positionCoarse("Position Coarse (10x)", 0.0f, 0.0f, 1.0f, 0.01f)
UISlider fireInvSpeedZ("Fire Inverse SpeedZ", 20, 1, 100, 1)
UICheckbox allWhite("All White", false)
UIGroup waveGroup("Wave Controls", waveSpeed, waveDampening, waveHalfDuplex, waveAutoTrigger, waveTriggerSpeed, waveTriggerButton, wavePalette, waveBlurAmount, waveBlurPasses)
UIDropdown renderModeDropdown("Render Mode", renderModeOptions)
static float currentPosition
UISlider waveDampening("Wave Dampening", 9.1f, 0.0f, 20.0f, 0.1f)
constexpr uint16_t CORKSCREW_HEIGHT
UINumberField animartrixColorOrder("Animartrix Color Order", 0, 0, 5)
CRGBPalette16 getFirePalette()
void processWaveAutoTrigger(uint32_t now)
static uint32_t nextWaveTrigger
void drawNoise(uint32_t now)
UISlider animartrixTimeSpeed("Animartrix Time Speed", 1, -10, 10,.1)
UISlider noiseScale("Noise Scale", 100, 10, 200, 5)
UISlider waveSpeed("Wave Speed", 0.03f, 0.0f, 1.0f, 0.01f)
UINumberField animartrixIndex("Animartrix Animation", 5, 0, NUM_ANIMATIONS - 1)
UICheckbox waveHalfDuplex("Wave Half Duplex", true)
string renderModeOptions[]
UIGroup renderGroup("Render Options", renderModeDropdown, splatRendering, allWhite, brightness)
UICheckbox waveAutoTrigger("Wave Auto Trigger", true)
uint8_t getFirePaletteIndex(uint32_t millis32, int width, int max_width, int height, int max_height, uint32_t y_speed)
static uint32_t lastUpdateTime
CRGBPalette16 getWavePalette()
UIGroup animartrixGroup("Animartrix Controls", animartrixIndex, animartrixTimeSpeed, animartrixColorOrder)
fl::unique_ptr< FxEngine > fxEngine
void drawAnimartrix(uint32_t now)
UISlider fireSpeedY("Fire SpeedY", 1.3, 1, 6,.1)
constexpr uint16_t CORKSCREW_WIDTH
UINumberField wavePalette("Wave Palette", 0, 0, 2)
fl::shared_ptr< Grid< CRGB > > frameBufferPtr
void drawFire(uint32_t now)
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 `Corkscrew.toScreenMap()` for accurate web interface visualization\n" "- Multiple render modes: **Noise**, **Position**, **Fire**, **Wave**, and **Animartrix** effects\n" "- Real-time cylindrical surface mapping\n" "- **Wave mode**: Cylindrical 2D wave simulation with ripple effects and configurable blur\n" "- **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 ScreenMap\n\n" "*Select different render modes and adjust parameters to see various effects!*")
UISlider positionFine("Position Fine (1x)", 0.0f, 0.0f, 0.1f, 0.001f)
UICheckbox autoAdvance("Auto Advance", true)
UIButton waveTriggerButton("Trigger Wave")
WaveCrgbGradientMapPtr crgMap
UIGroup colorBoostGroup("Color Boost", saturationFunction, luminanceFunction)
UISlider fireScaleX("Fire ScaleX",.3, 0.1, 3,.01)
UINumberField firePalette("Fire Palette", 0, 0, 2)
fl::vector< fl::string > easeInfo
UISlider positionExtraFine("Position Extra Fine (0.1x)", 0.0f, 0.0f, 0.01f, 0.0001f)
UISlider noiseSpeed("Noise Speed", 4, 1, 100, 1)
UIDropdown saturationFunction("Saturation Function", easeInfo)
void fillFrameBufferFire(uint32_t now)
CRGBPalette16 noisePalette
EaseType getEaseType(fl::string value)
UISlider waveBlurPasses("Wave Blur Passes", 1, 1, 10, 1)
UISlider waveTriggerSpeed("Wave Trigger Speed", 0.5f, 0.0f, 1.0f, 0.01f)
Corkscrew corkscrew(CORKSCREW_TURNS, NUM_LEDS)
UICheckbox splatRendering("Splat Rendering", true)
UICheckbox allWhite("All White", false)
LIB8STATIC_ALWAYS_INLINE uint8_t qadd8(uint8_t i, uint8_t j)
Add one byte to another, saturating at 0xFF.
LIB8STATIC_ALWAYS_INLINE int8_t abs8(int8_t i)
Take the absolute value of a signed 8-bit uint8_t.
LIB8STATIC_ALWAYS_INLINE uint8_t qsub8(uint8_t i, uint8_t j)
Subtract one byte from another, saturating at 0x00.
uint16_t inoise16(uint32_t x, uint32_t y, uint32_t z, uint32_t t)
16-bit, fixed point implementation of Perlin's noise.
uint8_t inoise8(uint16_t x, uint16_t y, uint16_t z)
8-Bit, fixed point implementation of Perlin's noise.
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 uint16_t random16()
Generate a 16-bit random number.
LIB8STATIC uint8_t random8()
Generate an 8-bit random number.
LIB8STATIC_ALWAYS_INLINE uint8_t scale8(uint8_t i, fract8 scale)
Scale one byte by a second one, which is treated as the numerator of a fraction whose denominator is ...
LIB8STATIC uint8_t cos8(uint8_t theta)
Fast 8-bit approximation of cos(x).
#define sin8
Platform-independent alias of the fast sin implementation.
CRGB ColorFromPalette(const CRGBPalette16 &pal, fl::u8 index, fl::u8 brightness, TBlendType blendType)
constexpr fl::u16 calculateCorkscrewHeight(float totalTurns, fl::u16 numLeds)
shared_ptr< T > make_shared(Args &&... args)
EOrder
RGB color channel orderings, used when instantiating controllers to determine what order the controll...
@ RBG
Red, Blue, Green (0021)
@ BGR
Blue, Green, Red (0210)
@ GBR
Green, Blue, Red (0120)
@ GRB
Green, Red, Blue (0102)
@ BRG
Blue, Red, Green (0201)
@ RGB
Red, Green, Blue (0012)
constexpr fl::u16 calculateCorkscrewWidth(float totalTurns, fl::u16 numLeds)
HeapVector< T, Allocator > vector
Functions to generate and fill arrays with noise.
Corkscrew LED strip projection and rendering.
CRGB & nscale8(fl::u8 scaledown)
Scale down a RGB to N/256ths of its current brightness, using "plain math" dimming rules.
CRGB colorBoost(fl::EaseType saturation_function=fl::EASE_NONE, fl::EaseType luminance_function=fl::EASE_NONE) const
@ Blue
<div style='background:#0000FF;width:4em;height:4em;'></div>
Representation of an RGB pixel (Red, Green, Blue)