33#define COLOR_ORDER GRB
37#define PIR_LATCH_MS 60000
38#define PIR_RISING_TIME 1000
39#define PIR_FALLING_TIME 1000
57 coord.
angle = (led_index * 2.0f *
M_PI / num_leds) + time_offset;
59 coord.
x = cos(coord.
angle);
60 coord.
y = sin(coord.
angle);
111 {0.5f, 0.5f, 1.0f, 1.0f, 0.8f},
112 {0.0f, 0.0f, 1.5f, 0.8f, 1.2f},
113 {1.0f, 1.0f, 0.8f, 1.2f, 0.6f},
114 {0.5f, 0.0f, 1.2f, 0.9f, 1.0f}
119 float time_scaled = time_ms * params.
time_scale * 0.001f;
122 float wave_sum = 0.0f;
123 for (
int i = 0; i < 4; i++) {
126 float distance = sqrt(dx*dx + dy*dy);
128 float wave_phase = distance *
sources[i].frequency + time_scaled *
sources[i].phase_speed;
129 wave_sum += sin(wave_phase) *
sources[i].amplitude;
134 float noise_x = coord.
x * 0xffff * noise_scale;
135 float noise_y = coord.
y * 0xffff * noise_scale;
138 float noise_mod = (
inoise16(noise_x, noise_y, noise_time) - 32768) / 65536.0f;
148 float normalized = (wave_value + 4.0f) / 8.0f;
149 normalized = constrain(normalized, 0.0f, 1.0f);
152 uint8_t
hue = (uint8_t)(normalized * 255.0f + params.
hue_offset) % 256;
155 float intensity = abs(wave_value);
156 uint8_t sat = (uint8_t)(192 + intensity * 63);
159 uint8_t val = (uint8_t)(normalized * 255.0f * params.
brightness);
173 void update(uint32_t now,
bool auto_cycle_enabled, uint8_t manual_palette) {
174 if (auto_cycle_enabled) {
184 CRGB mapColor(
float hue_norm,
float intensity,
float special_param = 0.0f) {
187 case 1:
return mapOceanBreeze(hue_norm, intensity, special_param);
188 case 2:
return mapNeonNights(hue_norm, intensity, special_param);
198 uint8_t
hue = (uint8_t)(hue_norm * 45);
199 uint8_t sat = 200 + (uint8_t)(intensity * 55);
200 uint8_t val = 150 + (uint8_t)(intensity * 105);
206 uint8_t
hue = 120 + (uint8_t)(hue_norm * 90);
207 uint8_t sat = 180 + (uint8_t)(intensity * 75);
208 uint8_t val = 120 + (uint8_t)(intensity * 135);
214 uint8_t base_hues[] = {0, 85, 128, 192};
215 uint8_t selected_hue = base_hues[(int)(hue_norm * 4) % 4];
217 uint8_t val = 100 + (uint8_t)(intensity * 155);
218 return CHSV(selected_hue, sat, val);
223 uint8_t
hue = 60 + (uint8_t)(hue_norm * 90);
224 uint8_t sat = 150 + (uint8_t)(intensity * 105);
225 uint8_t val = 100 + (uint8_t)(intensity * 155);
231 if (special_param > 0.8f) {
233 uint8_t
brightness = 200 + (uint8_t)(intensity * 55);
236 uint8_t
hue = 200 + (uint8_t)(hue_norm * 100);
237 uint8_t sat = 180 + (uint8_t)(intensity * 75);
238 uint8_t val = 80 + (uint8_t)(intensity * 175);
246 float time_factor = time_ms * 0.0008f;
249 float noise1 =
inoise16(coord.
x * 2000, coord.
y * 2000, time_factor * 1000) / 65536.0f;
250 float noise2 =
inoise16(coord.
x * 1000, coord.
y * 1000, time_factor * 2000) / 65536.0f * 0.5f;
251 float noise3 =
inoise16(coord.
x * 4000, coord.
y * 4000, time_factor * 500) / 65536.0f * 0.25f;
253 float combined_noise = noise1 +
noise2 + noise3;
254 float hue_norm = (combined_noise + coord.
angle / (2*
M_PI) + 1.0f) * 0.5f;
255 float intensity = (combined_noise + 1.0f) * 0.5f;
257 return palette.mapColor(hue_norm, intensity);
261 uint32_t fast_time = time_ms << 3;
263 float x_noise = coord.
x * 8000;
264 float y_noise = coord.
y * 8000;
266 uint16_t noise1 =
inoise16(x_noise, y_noise, fast_time);
267 uint16_t
noise2 =
inoise16(x_noise + 10000, y_noise + 10000, fast_time + 5000);
269 uint8_t threshold = 200;
270 bool lightning = (noise1 >> 8) > threshold || (
noise2 >> 8) > threshold;
273 float lightning_intensity = max((noise1 >> 8) - threshold, (
noise2 >> 8) - threshold) / 55.0f;
274 return palette.mapColor(0.7f, lightning_intensity, 1.0f);
276 float storm_intensity = (noise1 >> 8) / 1020.0f;
277 return palette.mapColor(0.6f, storm_intensity);
282 float slow_time = time_ms * 0.0002f;
284 float blob_scale = 800;
285 uint16_t primary_noise =
inoise16(coord.
x * blob_scale, coord.
y * blob_scale, slow_time * 1000);
286 uint16_t secondary_noise =
inoise16(coord.
x * blob_scale * 0.5f, coord.
y * blob_scale * 0.5f, slow_time * 1500);
288 float blob_value = (primary_noise + secondary_noise * 0.3f) / 65536.0f;
290 if (blob_value > 0.6f) {
292 float intensity = (blob_value - 0.6f) / 0.4f;
293 return palette.mapColor(0.1f, intensity);
294 }
else if (blob_value > 0.3f) {
296 float edge_factor = (blob_value - 0.3f) / 0.3f;
297 return palette.mapColor(0.2f, edge_factor);
300 return palette.mapColor(0.8f, 0.2f);
305 float vertical_pos = sin(coord.
angle) * 0.5f + 0.5f;
306 float cascade_speed = 0.002f;
307 float time_offset = time_ms * cascade_speed;
309 int stream_id = (int)(coord.
angle * 10) % 8;
310 float stream_phase = fmod(vertical_pos + time_offset + stream_id * 0.125f, 1.0f);
312 uint16_t
noise =
inoise16(stream_id * 1000, stream_phase * 10000, time_ms / 4);
313 uint8_t digital_value = (
noise >> 8) > 128 ? 255 : 0;
315 if (digital_value > 0) {
316 float intensity = 1.0f - stream_phase * 0.8f;
317 return palette.mapColor(0.4f, intensity);
324 uint32_t glitch_time = (time_ms / 100) * 100;
326 uint16_t noise1 =
inoise16(coord.
x * 3000, coord.
y * 3000, glitch_time);
327 uint16_t
noise2 =
inoise16(coord.
x * 5000, coord.
y * 5000, glitch_time + 1000);
329 uint16_t glitch_value = noise1 ^
noise2;
331 if ((glitch_value & 0xF000) == 0xF000) {
332 return CRGB(255, 255, 255);
335 float intensity = (glitch_value & 0xFF) / 255.0f;
336 float hue_chaos = ((glitch_value >> 8) & 0xFF) / 255.0f;
338 return palette.mapColor(hue_chaos, intensity, 0.5f);
342 float ocean_time = time_ms * 0.0005f;
344 float current1 =
inoise16(coord.
x * 1200, coord.
y * 1200, ocean_time * 800) / 65536.0f;
345 float current2 =
inoise16(coord.
x * 2400, coord.
y * 2400, ocean_time * 600) / 65536.0f * 0.5f;
346 float current3 =
inoise16(coord.
x * 600, coord.
y * 600, ocean_time * 1000) / 65536.0f * 0.3f;
348 float depth_factor = (current1 + current2 + current3 + 1.5f) / 3.0f;
349 float hue_variation = (current2 + 0.5f);
351 return palette.mapColor(hue_variation, depth_factor);
355 float vertical_component = sin(coord.
angle) * 0.5f + 0.5f;
357 float flame_x = coord.
x * 1500;
358 float flame_y = coord.
y * 1500 + time_ms * 0.003f;
360 uint16_t turbulence =
inoise16(flame_x, flame_y, time_ms);
361 float flame_intensity = (turbulence / 65536.0f) * (1.0f - vertical_component * 0.3f);
363 float fire_hue = flame_intensity * 0.15f;
364 return palette.mapColor(fire_hue, flame_intensity);
368 float nebula_time = time_ms * 0.0003f;
370 float cloud1 =
inoise16(coord.
x * 800, coord.
y * 800, nebula_time * 1000) / 65536.0f;
371 float cloud2 =
inoise16(coord.
x * 1600, coord.
y * 1600, nebula_time * 700) / 65536.0f * 0.5f;
372 float cloud3 =
inoise16(coord.
x * 400, coord.
y * 400, nebula_time * 1200) / 65536.0f * 0.25f;
374 float nebula_density = cloud1 + cloud2 + cloud3;
376 uint16_t star_noise =
inoise16(coord.
x * 4000, coord.
y * 4000, nebula_time * 200);
377 bool is_star = (star_noise > 60000);
380 float star_intensity = (star_noise - 60000) / 5536.0f;
381 return palette.mapColor(0.0f, star_intensity, 1.0f);
383 float hue_drift = (nebula_density + 1.0f) * 0.5f;
384 float intensity = (nebula_density + 1.0f) * 0.4f;
385 return palette.mapColor(hue_drift, intensity);
390 float pulse_period = 2000.0f;
391 float pulse_phase = fmod(time_ms, pulse_period) / pulse_period;
393 float distance_from_center = sqrt(coord.
x * coord.
x + coord.
y * coord.
y);
395 float ring_frequency = 5.0f;
396 float pulse_offset = pulse_phase * 2.0f;
397 float ring_value = sin((distance_from_center * ring_frequency - pulse_offset) * 2 *
M_PI);
399 uint16_t
noise =
inoise16(coord.
x * 2000, coord.
y * 2000, time_ms / 8);
400 float digital_mod = ((
noise >> 8) > 128) ? 1.0f : -0.5f;
402 float final_value = ring_value * digital_mod;
404 if (final_value > 0.3f) {
405 return palette.mapColor(0.8f, final_value, 0.8f);
406 }
else if (final_value > -0.2f) {
407 float transition_intensity = (final_value + 0.2f) * 2.0f;
408 return palette.mapColor(0.3f, transition_intensity);
410 return palette.mapColor(0.7f, 0.1f);
431 void update(uint32_t now,
bool auto_cycle_enabled, uint8_t manual_variant,
const PlasmaParams& params) {
435 if (auto_cycle_enabled) {
469 const char* names[] = {
470 "Cosmic Swirl",
"Electric Storm",
"Lava Lamp",
"Digital Rain",
"Plasma Waves",
471 "Glitch City",
"Ocean Depths",
"Fire Dance",
"Nebula Drift",
"Binary Pulse"
484 switch(variant % 10) {
505 float intensity = (plasma_color.r + plasma_color.g + plasma_color.b) / 765.0f;
508 float time_scaled = time_ms *
plasma_params.time_scale * 0.001f;
509 float wave_sum = 0.0f;
512 float dx = coord.
x - 0.5f;
513 float dy = coord.
y - 0.5f;
514 float distance = sqrt(dx*dx + dy*dy);
515 float wave_phase = distance * 2.0f + time_scaled * 1.5f;
516 wave_sum = sin(wave_phase);
518 float hue_norm = (wave_sum + 1.0f) * 0.5f;
521 return palette.mapColor(hue_norm, intensity, intensity > 0.8f ? 1.0f : 0.0f);
527 float smooth_t =
t *
t * (3.0f - 2.0f *
t);
530 float brightness_a = (a.r + a.g + a.b) / 765.0f;
531 float brightness_b = (b.r + b.g + b.b) / 765.0f;
532 float target_brightness = brightness_a + (brightness_b - brightness_a) * smooth_t;
535 a.r + (
int)((b.r - a.r) * smooth_t),
536 a.g + (
int)((b.g - a.g) * smooth_t),
537 a.b + (
int)((b.b - a.b) * smooth_t)
544 compensation = min(compensation, 2.0f);
556 "Cosmic Swirl",
"Electric Storm",
"Lava Lamp",
"Digital Rain",
"Plasma Waves",
557 "Glitch City",
"Ocean Depths",
"Fire Dance",
"Nebula Drift",
"Binary Pulse"
562 "Sunset Boulevard",
"Ocean Breeze",
"Neon Nights",
"Forest Whisper",
"Galaxy Express"
567 for (
int i = 0; i < 10; i++) {
576 for (
int i = 0; i < 5; i++) {
612 Serial.begin(115200);
620 .setScreenMap(
xyMap);
622 pir.activate(millis());
645 for (
int i = 0; i <
NUM_LEDS; i++) {
650 float global_brightness =
brightness.as<
float>();
651 pixel_color.r = (uint8_t)(pixel_color.r * global_brightness);
652 pixel_color.g = (uint8_t)(pixel_color.g * global_brightness);
653 pixel_color.b = (uint8_t)(pixel_color.b * global_brightness);
655 leds[i] = pixel_color;
661 int sparkle_count =
NUM_LEDS / 100 + 1;
662 for (
int s = 0; s < sparkle_count; s++) {
674 uint32_t now = millis();
675 uint8_t bri =
pir.transition(now);
FL_DISABLE_WARNING_PUSH FL_DISABLE_WARNING_GLOBAL_CONSTRUCTORS CFastLED FastLED
Global LED strip management instance.
central include file for FastLED, defines the CFastLED class/object
uint8_t noise[NUM_LAYERS][WIDTH][HEIGHT]
uint8_t noise2[NUM_LAYERS][WIDTH][HEIGHT]
UINumberField palette("Palette", 0, 0, 2)
uint8_t getPaletteIndex(uint32_t millis32, int width, int max_width, int height, int max_height, uint32_t y_speed)
ColorPaletteManager palette_manager
RingCoord calculateRingCoord(int led_index, int num_leds, float time_offset=0.0f)
UICheckbox autoPalette("Auto Cycle Palettes", true)
uint8_t getPaletteIndex(const fl::string &name)
UICheckbox autoCycle("Auto Cycle Effects", true)
CRGB drawCosmicSwirl(const RingCoord &coord, uint32_t time_ms, ColorPaletteManager &palette)
CRGB drawDigitalRain(const RingCoord &coord, uint32_t time_ms, ColorPaletteManager &palette)
CRGB drawOceanDepths(const RingCoord &coord, uint32_t time_ms, ColorPaletteManager &palette)
NoiseVariantManager variant_manager(palette_manager)
CRGB drawLavaLamp(const RingCoord &coord, uint32_t time_ms, ColorPaletteManager &palette)
CLEDController * controller
uint8_t getVariantIndex(const fl::string &name)
CRGB drawFireDance(const RingCoord &coord, uint32_t time_ms, ColorPaletteManager &palette)
UISlider timescale("Time Scale", 1,.1, 10,.1)
Pir pir(PIN_PIR, PIR_LATCH_MS, PIR_RISING_TIME, PIR_FALLING_TIME)
fl::string variant_names[10]
UISlider timeBitshift("Time Bitshift", 5, 0, 16, 1)
fl::string palette_names[5]
CRGB drawElectricStorm(const RingCoord &coord, uint32_t time_ms, ColorPaletteManager &palette)
CRGB drawGlitchCity(const RingCoord &coord, uint32_t time_ms, ColorPaletteManager &palette)
CRGB drawNebulaDrift(const RingCoord &coord, uint32_t time_ms, ColorPaletteManager &palette)
UIDropdown variants("Noise Variants", variant_names)
UISlider brightness("Brightness", 1, 0, 1)
UICheckbox useDither("Use Binary Dither", true)
UIDropdown palettes("Color Palettes", palette_names)
CRGB drawBinaryPulse(const RingCoord &coord, uint32_t time_ms, ColorPaletteManager &palette)
UISlider brightness("Brightness", 128, 0, 255, 1)
Base definition for an LED controller.
CRGB mapSunsetBoulevard(float hue_norm, float intensity, float special_param)
CRGB mapForestWhisper(float hue_norm, float intensity, float special_param)
static const uint32_t PALETTE_CHANGE_INTERVAL
void update(uint32_t now, bool auto_cycle_enabled, uint8_t manual_palette)
uint32_t last_palette_change
CRGB mapGalaxyExpress(float hue_norm, float intensity, float special_param)
CRGB mapNeonNights(float hue_norm, float intensity, float special_param)
CRGB mapColor(float hue_norm, float intensity, float special_param=0.0f)
CRGB mapOceanBreeze(float hue_norm, float intensity, float special_param)
NoiseVariantManager(ColorPaletteManager &palette_mgr)
float transition_progress
const char * getCurrentVariantName() const
CRGB renderPixel(const RingCoord &coord, uint32_t time_ms)
PlasmaParams plasma_params
CRGB smoothLerpCRGB(const CRGB &a, const CRGB &b, float t)
void startTransition(uint8_t new_variant, uint32_t now)
static const uint32_t TRANSITION_DURATION
uint32_t transition_start
void update(uint32_t now, bool auto_cycle_enabled, uint8_t manual_variant, const PlasmaParams ¶ms)
uint8_t getCurrentVariant() const
CRGB renderVariant(uint8_t variant, const RingCoord &coord, uint32_t time_ms)
PlasmaWaveGenerator plasma_gen
ColorPaletteManager & palette_manager
CRGB drawPlasmaWithPalette(const RingCoord &coord, uint32_t time_ms, ColorPaletteManager &palette)
CRGB calculatePlasmaPixel(const RingCoord &coord, uint32_t time_ms, const PlasmaParams ¶ms)
CRGB mapWaveToColor(float wave_value, const PlasmaParams ¶ms)
float cos_table[NUM_LEDS]
RingCoord fastRingCoord(int led_index, float time_offset=0.0f)
float sin_table[NUM_LEDS]
A simple timer utility class for tracking timed events.
static ScreenMap Circle(int numLeds, float cm_between_leds=1.5f, float cm_led_diameter=0.5f, float completion=1.0f)
Result type for promise operations.
#define BINARY_DITHER
Enable dithering using binary dithering (only option)
#define DISABLE_DITHER
Disable dithering.
FastLED's Elegant JSON Library: fl::Json
@ TypicalLEDStrip
Typical values for SMD5050 LEDs.
uint16_t inoise16(uint32_t x, uint32_t y, uint32_t z, uint32_t t)
16-bit, fixed point implementation of Perlin's noise.
LIB8STATIC uint16_t random16()
Generate a 16-bit random number.
LIB8STATIC uint8_t random8()
Generate an 8-bit random number.
#define EVERY_N_MILLISECONDS(N)
Alias for EVERY_N_MILLIS.
CRGB blend(const CRGB &p1, const CRGB &p2, fract8 amountOfP2)
Noise generation classes.
@ White
<div style='background:#FFFFFF;width:4em;height:4em;'></div>
@ Black
<div style='background:#000000;width:4em;height:4em;'></div>
Representation of an RGB pixel (Red, Green, Blue)
Representation of an HSV pixel (hue, saturation, value (aka brightness)).