//
// Sparkle Slider Labs v1.0 - Goal: Sparkles on black background going off randomly everywhere accept the slider LEDs
// Static 6 pixel wide slider solid color with white (SLD_SAT 0) on either side and tapering SLD_SAT towards center
//
#include <Adafruit_NeoPixel.h>
#define LED_PIN 6
#define LED_COUNT 16
#define FRAME_DELAY 40
#define SLIDER_SIZE 6 //Must be even
#define SLD_PARAM 3
#define SLD_LOC 0
#define SLD_SAT 1
#define SLD_BRIGHT 2
#define BRIGHT_LVLS 32
#define MAX_SPARKLES 5
#define BASE_SPARKLE_DELAY 100
#define SPRK_RAND_DELAY 1000
#define SPRK_ACTIVE 0
#define SPRK_LOC 1
#define SPRK_PINDX 2
#define SPRK_RAND 3
#define SPRK_PARAM 4 //SPRK_ACTIVE status, SPRK_LOCation LED, pulse index, random scaler
byte slider[SLIDER_SIZE][SLD_PARAM]; //Slider values for easier addressing
byte initSliderSLD_LOC = LED_COUNT/2;
int slideColorIndex = 0;
byte bright[BRIGHT_LVLS];
byte sparkles[MAX_SPARKLES][SPRK_PARAM];
int sparkleDelay[MAX_SPARKLES];
bool openSpot;
byte randomSpot;
unsigned long currentMillis;
unsigned long frameStartMillis;
unsigned long sparkleStartMillis[MAX_SPARKLES];
Adafruit_NeoPixel led(LED_COUNT, LED_PIN, NEO_GRB + NEO_KHZ800);
void setup(){
Serial.begin(115200);
led.begin();
// Create slider SLD_SAT and SLD_BRIGHT values
for (byte sl = 0; sl < SLIDER_SIZE; sl++){
// Set Location Values for each slider pixel
slider[sl][SLD_LOC] = initSliderSLD_LOC - SLIDER_SIZE/2 + sl;
// Set White Pixels
if ( sl == 0 || sl == SLIDER_SIZE-1){
slider[sl][SLD_SAT] = 0;
slider[sl][SLD_BRIGHT] = 255;
}
// Set Saturation & Brightness Values for each other slider pixel
else if ( sl < SLIDER_SIZE/2 ){
slider[sl][SLD_SAT] = 128 + (128/(SLIDER_SIZE/2))*(sl+1);
slider[sl][SLD_BRIGHT] = 63 + (192/(SLIDER_SIZE/2))*(sl+1);
} else {
slider[sl][SLD_SAT] = 255 - (128/(SLIDER_SIZE/2))*(sl-SLIDER_SIZE/2);
slider[sl][SLD_BRIGHT] = 255 - (192/(SLIDER_SIZE/2))*(sl-SLIDER_SIZE/2);
}
}
for(byte sp = 0; sp < MAX_SPARKLES; sp++){
sparkles[sp][SPRK_ACTIVE] = false;
sparkles[sp][SPRK_LOC] = sp*(LED_COUNT/MAX_SPARKLES)+1;
sparkles[sp][SPRK_PINDX] = 0;
sparkles[sp][SPRK_RAND] = random(SPRK_RAND_DELAY);
sparkleDelay[sp] = BASE_SPARKLE_DELAY + sparkles[sp][SPRK_RAND];
}
for(byte i = 0; i < BRIGHT_LVLS; i++){
bright[i] = led.sine8((256/BRIGHT_LVLS)*i+196);
}
}
void loop(){
currentMillis = millis();
if (currentMillis - frameStartMillis >= FRAME_DELAY){
led.clear();
// Build slider
for(byte sl = 0; sl < SLIDER_SIZE; sl++){
led.setPixelColor(slider[sl][SLD_LOC], led.ColorHSV(slideColorIndex, slider[sl][SLD_SAT], slider[sl][SLD_BRIGHT]));
}
slideColorIndex += 256;
frameStartMillis = currentMillis;
for(byte sp = 0; sp < MAX_SPARKLES; sp++){
if (sparkles[sp][SPRK_ACTIVE] == true){
led.setPixelColor(sparkles[sp][SPRK_LOC], led.ColorHSV(0, 0, bright[sparkles[sp][SPRK_PINDX]]));
sparkles[sp][SPRK_PINDX]++;
}
}
led.show();
frameStartMillis = currentMillis;
}
for(byte sp = 0; sp < MAX_SPARKLES; sp++){
if (sparkles[sp][SPRK_PINDX] == BRIGHT_LVLS-1){
sparkles[sp][SPRK_ACTIVE] = false;
sparkles[sp][SPRK_PINDX] = 0;
sparkleStartMillis[sp] = currentMillis;
}
}
for(byte sp = 0; sp < MAX_SPARKLES; sp++){
if (currentMillis - sparkleStartMillis[sp] >= sparkleDelay[sp] && sparkles[sp][SPRK_ACTIVE] == false){
sparkles[sp][SPRK_ACTIVE] = true;
do { // Find open spot
openSpot = true;
randomSpot = random(LED_COUNT);
for(byte sp = 0; sp < MAX_SPARKLES; sp++){
if (sparkles[sp][SPRK_LOC] == randomSpot){openSpot = false;}
}
for(byte i = 0; i < SLIDER_SIZE; i++){
if (slider[i][SLD_LOC] == randomSpot){openSpot = false;}
}
} while(!openSpot);
sparkles[sp][SPRK_LOC] = randomSpot;
sparkles[sp][SPRK_RAND] = random(SPRK_RAND_DELAY);
sparkleDelay[sp] = BASE_SPARKLE_DELAY + sparkles[sp][SPRK_RAND];
}
}
// printInfo();
}
void printInfo(){
Serial.print("PARAM: ");
for(byte sp = 0; sp < MAX_SPARKLES; sp++){
Serial.print(sparkles[sp][SPRK_ACTIVE]);
Serial.print(" ");
Serial.print(sparkles[sp][SPRK_LOC]);
Serial.print(" ");
Serial.print(sparkles[sp][SPRK_PINDX]);
Serial.print(" ");
Serial.print(sparkles[sp][SPRK_RAND]);
Serial.print(" | ");
}
Serial.println();
}