#include "FastLED.h"
// --- Configuration ---
#define DATA_PIN 2
// #define BRIGHTNESS_PIN A0 //<-- REMOVED
#define LED_TYPE WS2812
#define COLOR_ORDER RGB
#define NUM_LEDS 75
#define VOLTS 5
#define FRAMES_PER_SECOND 100
#define MASTER_BRIGHTNESS 255
#define MIN_BRIGHTNESS 200 // No longer used, but kept for reference
#define SECONDS_PER_PALETTE 15
// --- Pattern Timing Constants ---
#define PATTERN_SWITCH_SECONDS 25
#define HUE_SHIFT_SECONDS 7
#define PALETTE_BLEND_MILLISECONDS 10
#define SHOW_UPDATE_MILLISECONDS 40
// --- Twinkle Pattern Constants ---
#define TWINKLE_SPEED 6
#define TWINKLE_DENSITY 5
#define COOL_INCANDESCENT 1
// --- Marquee Pattern Constants ---
#define MARQUEE_SPACING 20
#define MARQUEE_WIDTH 5
#define MARQUEE_FADE_RATE 70
#define MARQUEE_HUE2_SHIFT 60
// --- Ripple Pattern Constants ---
#define RIPPLE_MAX_STEPS 16
#define RIPPLE_FADE_RATE 0.8
#define RIPPLE_DELAY 50
// --- Meteor Shower Constants ---
#define METEOR_INITIAL_LENGTH_FRAMES 280
#define METEOR_MEDIUM_LENGTH_FRAMES 500
#define METEOR_RANDOM_PICK_START_FRAMES 600
#define METEOR_RANDOM_PICK_END_FRAMES 790
#define METEOR_RANDOM_LENGTH_START_FRAMES 790
#define METEOR_RANDOM_LENGTH_END_FRAMES 1090
#define METEOR_FULL_CYCLE_FRAMES 1180
#define METEOR_DELAY 30
// --- Fire Pattern Constants ---
#define COOLING 55 // Lower number means more intense cooling.
#define SPARKING 120 // Chance of lighting a new 'spark' (0-255) Higher = more sparks.
// --- Sparkle Pattern Constants ---
#define SPARKLE_DELAY 20
#define SPARKLE_SPEED_DELAY_MIN 100
#define SPARKLE_SPEED_DELAY_MAX 1000
// --- Rainbow Cycle Constants ---
#define RAINBOW_CYCLE_SPEED_DELAY 20
#define THEATER_RAINBOW_SPEED_DELAY 60
// --- Alternate Color Constants ---
#define ALTERNATE_COLOR_WAIT 60
// --- Random Fill Constants ---
#define RANDOM_FILL_WAIT 60
// --- Stars Pattern Constants ---
#define STARS_FADE_RATE 0.95 // Fade factor for stars (0.0 - 1.0, closer to 1.0 fades slower)
#define STARS_DELAY 30
#define STAR_CHANCE 20 // Chance out of STAR_CHANCE for a new star to appear each frame
// --- Random Color Fill Constants ---
#define RANDOM_COLOR_FILL_WAIT 60
// --- Global Variables ---
bool autorunl = true;
unsigned int dimmer = 1;
int MASTER_BRIGHTNESS_INIT = MASTER_BRIGHTNESS; // Store initial master brightness
// int potValA; //<-- REMOVED
// uint8_t brightnessa; //<-- REMOVED
CRGB leds[NUM_LEDS];
int color2;
int center = 0;
int step = -1;
const float fadeRate2 = RIPPLE_FADE_RATE; // Use defined constant
int diff;
uint32_t currentBg = random(256);
uint32_t nextBg = currentBg;
uint16_t holdTime = 60;
uint8_t spacing = MARQUEE_SPACING;
int8_t delta = 1;
uint8_t width = MARQUEE_WIDTH;
uint8_t hue = 60;
boolean fadingTail = 1;
uint8_t fadeRate = MARQUEE_FADE_RATE;
uint8_t hue2_shift = MARQUEE_HUE2_SHIFT;
boolean DEBUG = 0;
int16_t pos;
int8_t advance;
uint8_t color;
byte ledsX[NUM_LEDS][3];
boolean RAINBOWs = false;
boolean RANDOMpick = false;
uint16_t timeframe;
byte idex = 0;
byte colorTIP = 0;
byte meteorLENGTH;
byte loopCount = 1;
CRGBPalette16 gCurrentPalette;
CRGBPalette16 gTargetPalette;
CRGBPalette16 gPal;
// --- Palette Definitions ---
const TProgmemRGBPalette16 RedGreenWhite_p FL_PROGMEM =
{ CRGB::Red, CRGB::Red, CRGB::Red, CRGB::Red,
CRGB::Red, CRGB::Red, CRGB::Red, CRGB::Red,
CRGB::Red, CRGB::Red, CRGB::Gray, CRGB::Gray,
CRGB::Green, CRGB::Green, CRGB::Green, CRGB::Green };
const TProgmemRGBPalette16 Holly_p FL_PROGMEM =
{ 0x00580c, 0x00580c, 0x00580c, 0x00580c,
0x00580c, 0x00580c, 0x00580c, 0x00580c,
0x00580c, 0x00580c, 0x00580c, 0x00580c,
0x00580c, 0x00580c, 0x00580c, 0xB00402
};
const TProgmemRGBPalette16 RedWhite_p FL_PROGMEM =
{ CRGB::Red, CRGB::Red, CRGB::Red, CRGB::Red,
CRGB::Gray, CRGB::Gray, CRGB::Gray, CRGB::Gray,
CRGB::Red, CRGB::Red, CRGB::Red, CRGB::Red,
CRGB::Gray, CRGB::Gray, CRGB::Gray, CRGB::Gray };
const TProgmemRGBPalette16 BlueWhite_p FL_PROGMEM =
{ CRGB::Blue, CRGB::Blue, CRGB::Blue, CRGB::Blue,
CRGB::Blue, CRGB::Blue, CRGB::Blue, CRGB::Blue,
CRGB::Blue, CRGB::Blue, CRGB::Blue, CRGB::Blue,
CRGB::Blue, CRGB::Gray, CRGB::Gray, CRGB::Gray };
const TProgmemRGBPalette16 FairyLight_p FL_PROGMEM =
{ CRGB::FairyLight, CRGB::FairyLight, CRGB::FairyLight, CRGB::FairyLight,
((CRGB::FairyLight & 0xFEFEFE) / 2), ((CRGB::FairyLight & 0xFEFEFE) / 2), CRGB::FairyLight, CRGB::FairyLight,
((CRGB::FairyLight & 0xFCFCFC) / 4), ((CRGB::FairyLight & 0xFCFCFC) / 4), CRGB::FairyLight, CRGB::FairyLight,
CRGB::FairyLight, CRGB::FairyLight, CRGB::FairyLight, CRGB::FairyLight };
const TProgmemRGBPalette16 Snow_p FL_PROGMEM =
{ 0x304048, 0x304048, 0x304048, 0x304048,
0x304048, 0x304048, 0x304048, 0x304048,
0x304048, 0x304048, 0x304048, 0x304048,
0x304048, 0x304048, 0x304048, 0xE0F0FF };
const TProgmemRGBPalette16 RetroC9_p FL_PROGMEM =
{ 0xB80400, 0x902C02, 0xB80400, 0x902C02,
0x902C02, 0xB80400, 0x902C02, 0xB80400,
0x046002, 0x046002, 0x046002, 0x046002,
0x070758, 0x070758, 0x070758,
0x606820
};
const TProgmemRGBPalette16 Ice_p FL_PROGMEM =
{
0x0C1040, 0x0C1040, 0x0C1040, 0x0C1040,
0x0C1040, 0x0C1040, 0x0C1040, 0x0C1040,
0x0C1040, 0x0C1040, 0x0C1040, 0x0C1040,
0x182080, 0x182080, 0x182080, 0x5080C0
};
const TProgmemRGBPalette16* ActivePaletteList[] = {
&RetroC9_p,
&BlueWhite_p,
&RainbowColors_p,
&FairyLight_p,
&RedGreenWhite_p,
&PartyColors_p,
&RedWhite_p,
&Snow_p,
&Holly_p,
&Ice_p
};
// --- Function Declarations - MUST BE BEFORE gPatterns ---
void drawTwinkles();
void juggle();
void sinelon();
void meteorShower();
void SnowSparkle();
void Sparkle();
void rainbowCycle();
void theaterChaseRainbow();
void randomPositionFill();
void alternateColor();
void randomColorFill();
void stars();
void fire();
void ripple2();
void flashes();
void balls();
void fill_solid_color();
void gradient_fill();
void bpm();
void marque_v3();
void rainbow();
void nextPattern();
void fill_black();
int wrap(int step);
void one_color_allHSV(int ahue, int abright);
CRGB computeOneTwinkle( uint32_t ms, uint8_t salt);
uint8_t attackDecayWave8( uint8_t i);
void coolLikeIncandescent( CRGB& c, uint8_t phase);
void chooseNextColorPalette( CRGBPalette16& pal);
byte * Wheel(byte WheelPos);
byte adjacent_ccw(byte i);
void Fire2012WithPalette();
void showStrip();
void setPixel(int Pixel, byte red, byte green, byte blue);
void setAll(byte red, byte green, byte blue);
// --- Function Pointer Array for Patterns ---
typedef void (*SimplePatternList[])();
SimplePatternList gPatterns = {
drawTwinkles, juggle, sinelon, meteorShower, SnowSparkle, Sparkle, rainbowCycle,
theaterChaseRainbow, randomPositionFill, alternateColor, randomColorFill, stars,
fire, ripple2, flashes, balls, fill_solid_color, gradient_fill, bpm, marque_v3,
rainbow // Added rainbow to the list for easier access
};
uint8_t gCurrentPatternNumber = 0;
uint8_t gHue = 0;
// --- Setup Function ---
void setup() {
delay(3000); // Startup delay
Serial.begin(115200); // Use a faster baud rate for ESP8266
FastLED.addLeds<LED_TYPE, DATA_PIN, COLOR_ORDER>(leds, NUM_LEDS).setCorrection(TypicalLEDStrip);
FastLED.setMaxPowerInVoltsAndMilliamps(VOLTS, 2000);
FastLED.setBrightness(MASTER_BRIGHTNESS_INIT); // Brightness is set once here
chooseNextColorPalette(gTargetPalette);
}
// --- Next Pattern Function ---
void nextPattern() {
FastLED.clear();
gCurrentPatternNumber = (gCurrentPatternNumber + 1) % (sizeof(gPatterns) / sizeof(gPatterns[0]));
}
// --- Pattern Functions ---
void fill_solid_color() {
uint8_t hue1 = random8(255);
uint8_t hue2 = random8(255);
static uint32_t lastChangeTime = 0;
uint32_t currentTime = millis();
if (currentTime - lastChangeTime > 2000) {
hue1 = random8(255);
hue2 = random8(255);
lastChangeTime = currentTime;
}
for (int i = 0; i < NUM_LEDS; i++) {
if (i % 2 == 0) {
leds[i] = CHSV(hue1, 255, 255);
} else {
leds[i] = CHSV(hue2, 255, 255);
}
}
}
void fill_black() {
FastLED.clear();
}
void rainbow() {
fill_rainbow(leds, NUM_LEDS, gHue, 7);
}
void sinelon() {
fadeToBlackBy(leds, NUM_LEDS, 20);
int pos = beatsin16(13, 0, NUM_LEDS);
leds[pos] += CHSV(gHue, 255, 192);
}
void bpm() {
uint8_t BeatsPerMinute = 62;
CRGBPalette16 palette = PartyColors_p;
uint8_t beat = beatsin8(BeatsPerMinute, 64, 255);
for (int i = 0; i < NUM_LEDS; i++) {
leds[i] = ColorFromPalette(palette, gHue + (i * 2), beat - gHue + (i * 10));
}
}
void juggle() {
fadeToBlackBy(leds, NUM_LEDS, 20);
byte dothue = 0;
for (int i = 0; i < 8; i++) {
leds[beatsin16(i + 7, 0, NUM_LEDS)] |= CHSV(dothue, 200, 255);
dothue += 32;
}
}
void gradient_fill() {
static uint8_t hue1 = 0;
static uint8_t hue2 = 60;
EVERY_N_SECONDS(5) {
hue1 = random8();
hue2 = random8();
}
// FINAL FIX: Explicitly cast '2' to the required enum type.
fill_gradient(leds, 0, CHSV(hue1, 255, 255), NUM_LEDS - 1, CHSV(hue2, 255, 255), (TGradientDirectionCode)2);
}
DEFINE_GRADIENT_PALETTE( heatmap_gp ) {
0, 0, 0, 0,
90, 255, 0, 0,
128, 255, 255, 0,
255, 255,255,255
};
void fire() {
CRGBPalette16 myPal = heatmap_gp;
gPal = myPal;
hue = 0;
Fire2012WithPalette();
}
void marque_v3() {
for (uint8_t i = 0; i < (NUM_LEDS / spacing); i++) {
for (uint8_t w = 0; w < width; w++) {
pos = (spacing * (i - 1) + spacing + advance + w) % NUM_LEDS;
if (w % 2 == 0) {
color = hue;
} else {
color = hue + hue2_shift;
}
leds[pos] = CHSV(color, 255, 255);
delay(10);
}
if (DEBUG == 1) {
Serial.print(" "); Serial.print(pos);
}
}
if (DEBUG == 1) { Serial.println(" "); }
FastLED.show();
if (fadingTail == 1) {
fadeToBlackBy(leds, NUM_LEDS, fadeRate);
} else {
for (uint8_t i = 0; i < (NUM_LEDS / spacing); i++) {
for (uint8_t w = 0; w < width; w++) {
pos = (spacing * (i - 1) + spacing + advance + w) % NUM_LEDS;
leds[pos] = CRGB::Black;
}
}
}
advance = (advance + delta + NUM_LEDS) % NUM_LEDS;
}
CRGB gBackgroundColor = CRGB::Black;
void drawTwinkles() {
uint16_t PRNG16 = 11337;
uint32_t clock32 = millis();
CRGB bg;
if ((0 == 1) && (gCurrentPalette[0] == gCurrentPalette[1] )) {
bg = gCurrentPalette[0];
uint8_t bglight = bg.getAverageLight();
if (bglight > 64) {
bg.nscale8_video(16);
} else if (bglight > 16) {
bg.nscale8_video(64);
} else {
bg.nscale8_video(86);
}
} else {
bg = gBackgroundColor;
}
uint8_t backgroundBrightness = bg.getAverageLight();
for (CRGB& pixel : leds) {
PRNG16 = (uint16_t)(PRNG16 * 2053) + 1384;
uint16_t myclockoffset16 = PRNG16;
PRNG16 = (uint16_t)(PRNG16 * 2053) + 1384;
uint8_t myspeedmultiplierQ5_3 = (((PRNG16 & 0xFF) >> 4) + (PRNG16 & 0x0F)) & 0x0F + 0x08;
uint32_t myclock30 = (uint32_t)((clock32 * myspeedmultiplierQ5_3) >> 3) + myclockoffset16;
uint8_t myunique8 = PRNG16 >> 8;
CRGB c = computeOneTwinkle(myclock30, myunique8);
uint8_t cbright = c.getAverageLight();
int16_t deltabright = cbright - backgroundBrightness;
if (deltabright >= 32 || (!bg)) {
pixel = c;
} else if (deltabright > 0) {
pixel = blend(bg, c, deltabright * 8);
} else {
pixel = bg;
}
}
}
void ripple2() {
if (currentBg == nextBg) {
nextBg = random(256);
}
else if (nextBg > currentBg) {
currentBg++;
} else {
currentBg--;
}
for (uint16_t l = 0; l < NUM_LEDS; l++) {
leds[l] = CHSV(currentBg, 255, 50);
}
if (step == -1) {
center = random(NUM_LEDS);
color2 = random(256);
step = 0;
}
if (step == 0) {
leds[center] = CHSV(color2, 255, 255);
step++;
}
else {
if (step < RIPPLE_MAX_STEPS) {
leds[wrap(center + step)] = CHSV(color2, 255, pow(fadeRate2, step) * 255);
leds[wrap(center - step)] = CHSV(color2, 255, pow(fadeRate2, step) * 255);
if (step > 3) {
leds[wrap(center + step - 3)] = CHSV(color2, 255, pow(fadeRate2, step - 2) * 255);
leds[wrap(center - step + 3)] = CHSV(color2, 255, pow(fadeRate2, step - 2) * 255);
}
step++;
}
else {
step = -1;
}
}
FastLED.show();
delay(RIPPLE_DELAY);
}
int wrap(int step) {
if (step < 0) return NUM_LEDS + step;
if (step > NUM_LEDS - 1) return step - NUM_LEDS;
return step;
}
void one_color_allHSV(int ahue, int abright) {
for (int i = 0 ; i < NUM_LEDS; i++ ) {
leds[i] = CHSV(ahue, 255, abright);
}
}
CRGB computeOneTwinkle(uint32_t ms, uint8_t salt) {
uint16_t ticks = ms >> (8 - TWINKLE_SPEED);
uint8_t fastcycle8 = ticks;
uint16_t slowcycle16 = (ticks >> 8) + salt;
slowcycle16 += sin8(slowcycle16);
slowcycle16 = (slowcycle16 * 2053) + 1384;
uint8_t slowcycle8 = (slowcycle16 & 0xFF) + (slowcycle16 >> 8);
uint8_t bright = 0;
if (((slowcycle8 & 0x0E) / 2) < TWINKLE_DENSITY) {
bright = attackDecayWave8(fastcycle8);
}
uint8_t hue = slowcycle8 - salt;
CRGB c;
if (bright > 0) {
c = ColorFromPalette(gCurrentPalette, hue, bright, NOBLEND);
if (COOL_INCANDESCENT == 1) {
coolLikeIncandescent(c, fastcycle8);
}
} else {
c = CRGB::Black;
}
return c;
}
uint8_t attackDecayWave8(uint8_t i) {
if (i < 86) {
return i * 3;
} else {
i -= 86;
return 255 - (i + (i / 2));
}
}
void coolLikeIncandescent(CRGB& c, uint8_t phase) {
if (phase < 128) return;
uint8_t cooling = (phase - 128) >> 4;
c.g = qsub8(c.g, cooling);
c.b = qsub8(c.b, cooling * 2);
}
void chooseNextColorPalette(CRGBPalette16& pal) {
const uint8_t numberOfPalettes = sizeof(ActivePaletteList) / sizeof(ActivePaletteList[0]);
static uint8_t whichPalette = -1;
whichPalette = addmod8(whichPalette, 1, numberOfPalettes);
pal = *(ActivePaletteList[whichPalette]);
}
void Sparkle() {
byte red = random(255);
byte green = random(255);
byte blue = random(255);
int Pixel = random(NUM_LEDS);
FastLED.clear();
setPixel(Pixel, red, green, blue);
showStrip();
delay(SPARKLE_DELAY);
setPixel(Pixel, 0, 0, 0);
}
byte * Wheel(byte WheelPos) {
static byte c[3];
if (WheelPos < 85) {
c[0] = WheelPos * 3;
c[1] = 255 - WheelPos * 3;
c[2] = 0;
} else if (WheelPos < 170) {
WheelPos -= 85;
c[0] = 255 - WheelPos * 3;
c[1] = 0;
c[2] = WheelPos * 3;
} else {
WheelPos -= 170;
c[0] = 0;
c[1] = WheelPos * 3;
c[2] = 255 - WheelPos * 3;
}
return c;
}
void rainbowCycle() {
byte *c;
uint16_t i, j;
FastLED.clear();
for (j = 0; j < 256 * 5; j++) {
for (i = 0; i < NUM_LEDS; i++) {
c = Wheel(((i * 256 / NUM_LEDS) + j) & 255);
setPixel(i, *c, *(c + 1), *(c + 2));
}
showStrip();
delay(RAINBOW_CYCLE_SPEED_DELAY);
}
}
void theaterChaseRainbow() {
byte *c;
FastLED.clear();
for (int j = 0; j < 256; j++) {
for (int q = 0; q < 3; q++) {
for (int i = 0; i < NUM_LEDS; i = i + 3) {
c = Wheel((i + j) % 255);
setPixel(i + q, *c, *(c + 1), *(c + 2));
}
showStrip();
delay(THEATER_RAINBOW_SPEED_DELAY);
for (int i = 0; i < NUM_LEDS; i = i + 3) {
setPixel(i + q, 0, 0, 0);
}
}
}
}
void alternateColor() {
FastLED.clear();
byte red = random(255);
byte green = random(255);
byte blue = random(255);
byte red2 = random(255);
byte green2 = random(255);
byte blue2 = random(255);
uint8_t wait = ALTERNATE_COLOR_WAIT;
for (uint16_t i = 0; i < NUM_LEDS; i++) {
if (i % 2 == 0) {
setPixel(i, red, green, blue);
} else {
setPixel(i, red2, green2, blue2);
}
}
FastLED.show();
delay(wait);
delay(wait);
}
void randomPositionFill() {
byte red = random(255);
byte green = random(255);
byte blue = random(255);
uint8_t wait = RANDOM_FILL_WAIT;
FastLED.clear();
int used[NUM_LEDS];
int lights = 0;
for (int i = 0; i < NUM_LEDS; i++) {
used[i] = 0;
}
while (lights < NUM_LEDS) {
int j = random(0, NUM_LEDS);
if (used[j] != 1) {
setPixel(j, red, green, blue);
used[j] = 1;
lights++;
FastLED.show();
delay(wait);
}
}
}
void stars() {
FastLED.clear();
if (random(STAR_CHANCE) == 1) {
uint16_t i = random(NUM_LEDS);
if (ledsX[i][0] < 1 && ledsX[i][1] < 1 && ledsX[i][2] < 1) {
ledsX[i][0] = random(256);
ledsX[i][1] = random(256);
ledsX[i][2] = random(256);
}
}
for (uint16_t l = 0; l < NUM_LEDS; l++) {
if (ledsX[l][0] > 1 || ledsX[l][1] > 1 || ledsX[l][2] > 1) {
setPixel(l, ledsX[l][0], ledsX[l][1], ledsX[l][2]);
if (ledsX[l][0] > 1) {
ledsX[l][0] = ledsX[l][0] * STARS_FADE_RATE;
} else {
ledsX[l][0] = 0;
}
if (ledsX[l][1] > 1) {
ledsX[l][1] = ledsX[l][1] * STARS_FADE_RATE;
} else {
ledsX[l][1] = 0;
}
if (ledsX[l][2] > 1) {
ledsX[l][2] = ledsX[l][2] * STARS_FADE_RATE;
} else {
ledsX[l][2] = 0;
}
} else {
setPixel(l, 0, 0, 0);
}
}
FastLED.show();
delay(STARS_DELAY);
}
void randomColorFill() {
uint8_t wait = RANDOM_COLOR_FILL_WAIT;
FastLED.clear();
for (uint16_t i = 0; i < NUM_LEDS; i++) {
byte r = random(0, 255);
byte g = random(0, 255);
byte b = random(0, 255);
for (uint16_t j = 1; j < NUM_LEDS - i + 1; j++) {
setPixel(j - 1, 0, 0, 0);
setPixel(j, r, g, b);
FastLED.show();
delay(wait);
}
}
}
// --- Main Loop ---
void loop() {
// Potentiometer reading and dynamic brightness setting have been removed.
// Brightness is now fixed at the level set in setup().
gPatterns[gCurrentPatternNumber](); // Execute current pattern
FastLED.delay(1000 / FRAMES_PER_SECOND); // Frame delay
EVERY_N_MILLISECONDS(SHOW_UPDATE_MILLISECONDS) { // Control show updates to LED strip
FastLED.show();
}
EVERY_N_MILLISECONDS(PALETTE_BLEND_MILLISECONDS) { // Smooth palette blending
nblendPaletteTowardPalette(gCurrentPalette, gTargetPalette, 12);
}
EVERY_N_MILLISECONDS(20) { // Hue increment for color cycling effects
gHue++;
}
if (autorunl) {
EVERY_N_SECONDS(PATTERN_SWITCH_SECONDS) { // Switch patterns automatically
nextPattern();
}
}
EVERY_N_SECONDS(HUE_SHIFT_SECONDS) { // Random hue shift
hue = hue + random8(30, 61);
}
EVERY_N_SECONDS(SECONDS_PER_PALETTE) { // Change color palette periodically
chooseNextColorPalette(gTargetPalette);
}
}
// Meteor shower effect
void meteorShower() {
hue++;
for (byte i = 0; i < NUM_LEDS; i++ ) {
ledsX[i][0] = leds[i].r;
ledsX[i][1] = leds[i].g;
ledsX[i][2] = leds[i].b;
}
byte iCCW;
timeframe++;
if ((timeframe >= 1) && (timeframe <= METEOR_INITIAL_LENGTH_FRAMES)) { meteorLENGTH = 29; }
if ((timeframe > METEOR_INITIAL_LENGTH_FRAMES) && (timeframe <= METEOR_MEDIUM_LENGTH_FRAMES)) { meteorLENGTH = 45; }
if ((timeframe > 0) && (timeframe <= METEOR_INITIAL_LENGTH_FRAMES)) { RAINBOWs = true; }
else { RAINBOWs = false; }
if (RAINBOWs == true) { hue = hue - 20; if (hue <= 0) { hue = 1; } }
if ((timeframe > METEOR_RANDOM_PICK_START_FRAMES) && (timeframe <= METEOR_RANDOM_PICK_END_FRAMES)) { RANDOMpick = true; }
else { RANDOMpick = false; }
if (RANDOMpick == true) { idex = random8(46); }
else {
idex++;
if (idex > meteorLENGTH) { idex = 0; }
}
if ((timeframe > METEOR_RANDOM_LENGTH_START_FRAMES) && (timeframe <= METEOR_RANDOM_LENGTH_END_FRAMES)) { meteorLENGTH = random8(7, 38); }
if (timeframe == METEOR_FULL_CYCLE_FRAMES) {
timeframe = 0;
loopCount++;
}
if (loopCount == 1) { colorTIP = 0; }
if (loopCount == 2) { colorTIP = 1; }
if (loopCount == 3) { colorTIP = random8(11); }
if (loopCount == 4) {
colorTIP = 0;
loopCount = 0;
}
switch (idex) {
case 0:
switch (colorTIP) {
case 0: leds[0] = CHSV(hue, 255, 255); break;
case 1: leds[0] = CRGB(100, 100, 100); break;
case 2: leds[0] = CRGB::Yellow; break;
case 3: leds[0] = CRGB::Violet; break;
case 4: leds[0] = CRGB::Green; break;
case 5: leds[0] = CRGB::Purple; break;
case 6: leds[0] = CRGB::Orange; break;
case 7: leds[0] = CRGB::Cyan; break;
case 8: leds[0] = CRGB::GreenYellow; break;
case 9: leds[0] = CRGB::Magenta; break;
case 10: leds[0] = CRGB::SkyBlue; break;
}
break;
case 1: leds[0] = CHSV((hue - 20), 255, 210); break;
case 2: leds[0] = CHSV((hue - 22), 255, 180); break;
case 3: leds[0] = CHSV((hue - 23), 255, 150); break;
case 4: leds[0] = CHSV((hue - 24), 255, 110); break;
case 5: leds[0] = CHSV((hue - 25), 255, 90); break;
case 6: leds[0] = CHSV((hue - 26), 160, 60); break;
case 7: leds[0] = CHSV((hue - 27), 140, 40); break;
case 8: leds[0] = CHSV((hue - 28), 120, 20); break;
case 9: leds[0] = CHSV((hue - 29), 100, 20); break;
case 10: case 11: case 12: case 13: case 14: case 15: case 16: case 17: case 18: case 19:
case 20: case 21: case 22: case 23: case 24: case 25: case 26: case 27: case 28: case 29:
case 30: case 31: case 32: case 33: case 34: case 35: case 36: case 37: case 38: case 39:
case 40: case 41: case 42: case 43: case 44: case 45: leds[0] = CRGB::Black; break;
}
for (byte i = 1; i < NUM_LEDS; i++ ) {
iCCW = adjacent_ccw(i);
leds[i].r = ledsX[iCCW][0];
leds[i].g = ledsX[iCCW][1];
leds[i].b = ledsX[iCCW][2];
}
delay(METEOR_DELAY);
}
byte adjacent_ccw(byte i) {
byte r;
if (i > 0) { r = i - 1; }
else { r = NUM_LEDS - 1; }
return r;
}
#define FIRE_PALETTE_HEATMAP
void Fire2012WithPalette() {
static byte heat[NUM_LEDS];
for (int i = 0; i < NUM_LEDS; i++) {
heat[i] = qsub8(heat[i], random8(0, ((COOLING * 10) / NUM_LEDS) + 2));
}
for (int k = NUM_LEDS - 1; k >= 2; k--) {
heat[k] = (heat[k - 1] + heat[k - 2] + heat[k - 2] ) / 3;
}
if (random8() < SPARKING) {
int y = random8(7);
heat[y] = qadd8(heat[y], random8(160, 255));
}
for (int j = 0; j < NUM_LEDS; j++) {
byte colorindex = scale8(heat[j], 240);
CRGB color;
#ifdef FIRE_PALETTE_HEATMAP
color = ColorFromPalette( (CRGBPalette16&)heatmap_gp, colorindex, 255, NOBLEND);
#else
color = ColorFromPalette(gPal, colorindex);
#endif
int pixelnumber;
if (true) {
pixelnumber = (NUM_LEDS - 1) - j;
} else {
pixelnumber = j;
}
leds[pixelnumber] = color;
}
}
void flashes() {
int positionl = random(NUM_LEDS);
int randomwidth = random(NUM_LEDS);
if (randomwidth > (NUM_LEDS - positionl)) randomwidth = NUM_LEDS - positionl;
uint8_t hue1 = random8(255);
uint8_t hue2 = hue1 + random8(30, 61);
for (int flashCounter = 0; flashCounter < random8(3, 8); flashCounter++) {
if (flashCounter == 0) dimmer = 5;
else dimmer = random8(1, 3);
// FINAL FIX: Explicitly cast '2' to the required enum type.
fill_gradient(leds, positionl, CHSV(hue1, 255, 255), positionl + randomwidth, CHSV(hue2, 255, 255), (TGradientDirectionCode)2);
delay(15);
FastLED.show();
delay(random8(4, 10));
// FINAL FIX: Explicitly cast '2' to the required enum type.
fill_gradient(leds, positionl, CHSV(0, 0, 0), positionl + randomwidth, CHSV(0, 0, 0), (TGradientDirectionCode)2);
delay(15);
FastLED.show();
if (flashCounter == 0) delay (150);
delay(50 + random8(100));
}
delay(random8(50) * 100);
}
void balls() {
leds[0].r = 0;
leds[0].g = 0;
leds[0].b = 0;
int BallCount = 5;
byte colors[5][3] = { {0xff, 0, 0},
{0, 0xff, 0},
{0, 0, 0xff},
{0xff, 0xff, 0xff},
{0xff, 0xff, 0} };
float Gravity = -9.81;
int StartHeight = 1;
float Height[BallCount];
float ImpactVelocityStart = sqrt( -2 * Gravity * StartHeight );
float ImpactVelocity[BallCount];
float TimeSinceLastBounce[BallCount];
int Position[BallCount];
long ClockTimeSinceLastBounce[BallCount];
float Dampening[BallCount];
for (int i = 0 ; i < BallCount ; i++) {
ClockTimeSinceLastBounce[i] = millis();
Height[i] = StartHeight;
Position[i] = 0;
ImpactVelocity[i] = ImpactVelocityStart;
TimeSinceLastBounce[i] = 0;
Dampening[i] = 0.90 - float(i) / pow(BallCount, 2);
}
long ballscounter = 0;
while (ballscounter < 7000) {
for (int i = 0 ; i < BallCount ; i++) {
TimeSinceLastBounce[i] = millis() - ClockTimeSinceLastBounce[i];
Height[i] = 0.5 * Gravity * pow( TimeSinceLastBounce[i] / 1000 , 2.0 ) + ImpactVelocity[i] * TimeSinceLastBounce[i] / 1000;
if ( Height[i] < 0 ) {
Height[i] = 0;
ImpactVelocity[i] = Dampening[i] * ImpactVelocity[i];
ClockTimeSinceLastBounce[i] = millis();
if ( ImpactVelocity[i] < 0.01 ) {
ImpactVelocity[i] = ImpactVelocityStart;
}
}
Position[i] = round( Height[i] * (NUM_LEDS - 1) / StartHeight);
}
for (int i = 0 ; i < BallCount ; i++) {
setPixel(Position[i], colors[i][0], colors[i][1], colors[i][2]);
}
showStrip();
setAll(0, 0, 0);
ballscounter++;
}
}
void showStrip() {
FastLED.show();
}
void setPixel(int Pixel, byte red, byte green, byte blue) {
if(Pixel >= 0 && Pixel < NUM_LEDS){
leds[Pixel].r = red;
leds[Pixel].g = green;
leds[Pixel].b = blue;
}
}
void setAll(byte red, byte green, byte blue) {
for (int i = 0; i < NUM_LEDS; i++ ) {
setPixel(i, red, green, blue);
}
showStrip();
}
void SnowSparkle() {
byte red = 0x00;
byte green = 0x00;
byte blue = 0x10;
int SparkleDelay = SPARKLE_DELAY;
int SpeedDelay = random(SPARKLE_SPEED_DELAY_MIN, SPARKLE_SPEED_DELAY_MAX);
setAll(red, green, blue);
int Pixel = random(NUM_LEDS);
setPixel(Pixel, 0xaa, 0xaa, 0xff);
showStrip();
delay(SparkleDelay);
setPixel(Pixel, red, green, blue);
showStrip();
delay(SpeedDelay);
}