#include <FastLED.h>
#define pWIDTH 64
#define pHEIGHT 8
#define NUM_LEDS ((pWIDTH) * (pHEIGHT))
extern CRGBPalette16 gCurrentGradientPalette;
extern CRGBPalette16 gTargetGradientPalette;
CRGB leds[NUM_LEDS];
bool loadingFlag = true;
void drawPixelXY(int8_t x, int8_t y, CRGB color) {
if (leds == nullptr) return;
if (x < 0 || x > pWIDTH - 1 || y < 0 || y > pHEIGHT - 1) return;
int16_t thisPixel = getPixelNumber(x, y);
if (thisPixel >= 0 && thisPixel < NUM_LEDS) leds[thisPixel] = color;
}
uint16_t getPixelNumber(uint8_t x, uint8_t y) {
if (x >= pWIDTH || y >= pHEIGHT)
return NUM_LEDS;
if (y & 1)
x = pWIDTH - 1 - x;
return x + (y * pWIDTH);
}
uint32_t getPixColor(int16_t thisPixel) {
if (leds == nullptr) return 0;
if (thisPixel < 0 || thisPixel > NUM_LEDS - 1) return 0;
return (((uint32_t)leds[thisPixel].r << 16) | ((uint32_t)leds[thisPixel].g << 8 ) | (uint32_t)leds[thisPixel].b);
}
uint32_t getPixColorXY(int8_t x, int8_t y) {
return getPixColor(getPixelNumber(x, y));
}
uint16_t XY(uint8_t x, uint8_t y) {
uint16_t idx = getPixelNumber(x, y);
if (idx >= 0 && idx < NUM_LEDS) return idx;
}
void setup() {
FastLED.addLeds<WS2812B, 3, GRB>(leds, NUM_LEDS);
}
void loop() {
if (loadingFlag) {
loadingFlag = false;
FastLED.clear();
}
EVERY_N_SECONDS(15) {chooseNextPalette();}
EVERY_N_MILLISECONDS(12) nblendPaletteTowardPalette( gCurrentGradientPalette, gTargetGradientPalette, 12);
draw();
FastLED.show();
}
// Sample code taken from: https://editor.soulmatelights.com/gallery/671-tixyland
//https://tixy.land/?code=sin%28sin%28y%29%2Bx%2Bt%29*cos%28t%2By%29
//https://tixy.land/?code=tan%28sqrt%28sin%28x%29*16*sin%28x%29*16%2Bcos%28y%29*16*cos%28y%29*16%29%2Bt%29
//https://tixy.land/?code=sin%28x%2Bsin%28y%2F2%2Bt*5%29%29%2Bcos%28y%29
//https://tixy.land/?code=sin%28sin%28x%2Bt%29%2By%2Bt*10%29-y%2F10
//https://tixy.land/?code=sin%28sin%28y%2Bt%29%2Bx%2Bt*10%29-y%2F10
byte effect = 6;
uint8_t gHue = 0;
float code(double t, double i, double x, double y) {
//put tixy.land formulas after return
//use fmod() against C++ modulo %
//float r = static_cast <float> (rand()) / static_cast <float> (RAND_MAX); // use against random()
switch (effect){
case 0:return .1/(sin(y/4+t)-sin(x*4+t)); break;
case 1:return sin(hypot(x-=(pWIDTH-1)/2.,y-=(pHEIGHT-1)/2.)-t+atan2(y,x)); break;
case 2:return abs(cos(atan2(y-(pHEIGHT-1)/2.,x-(pWIDTH-1)/2.)*64+t)); break;
case 3:return sin(cos(x)+t)*cos(sin(y-2)+t); break;
case 4:return sin(y*sin(t/2)*2+t+i*9); break;
case 5:return sin(atan((y-(pHEIGHT-1)/2.)/(x-(pWIDTH-1)/2.))+t*2); break;
case 6:return 1-fmod(((t/3+x+sin(t+x)/2)+y/16),1.0); break;
case 7:return (y-(pHEIGHT-1)/2.)/2-tan(x/2-i)*sin(t); break;
case 8:return (y-(pHEIGHT-1)/2.)/3-(sin(x/2))*sin(t); break;
case 9:return sin(x)-sin(x/2-2*t)-y/1.2+3; break;
case 10:return sin(x*x*3*i-y/2+t*2); break;
case 11:return min(7-y+sin(x+sin(y+t*8))*8,0); break; //fire https://twitter.com/davemakes/status/1324226447351803905
//case 12:return 4-hypot(x-(pHEIGHT-1)/2.,y-(pHEIGHT-1)/2.)-sin(i/2-t); break;//https://twitter.com/maettig/status/1326162655061696513
case 12:return sin(pWIDTH*atan2(y-(pHEIGHT-1)/2.,x-(pWIDTH-1)/2.)+t); break;
case 13:return sin(6 * atan2(y - (pHEIGHT-1)/2. + sin(t) * pHEIGHT/2, x - (pWIDTH-1)/2. + sin(t/4) * pWIDTH/2) + t*2); break; //i add move for //https://twitter.com/aemkei/status/1326637631409676291
case 14:return sin((t/16)*i+x); break;
//case 15:return sin(x+t)+sin(y+t)+sin(x+y+t)/2; break;
case 15:return 1-fmod((x*x+y-t*(fmod(1-x*x,5.0))*3.0),16.0)/16.0; break;
case 16:return sin(sin(y)+x+t)*cos(t+y); break;
case 17:return (x-(pWIDTH-1)/2.)*(y-(pHEIGHT-1)/2.) - sin(t)*64; break;
case 18:return sin(t-sqrt(pow((x-(pWIDTH-1)/2.),2.)+pow((y-(pHEIGHT-1)/2.),2.))); break;
case 19:return sin(y/2.25+t + sin(t)); break;
case 20:return x>pWIDTH/2-(sin(t*5+y*3)*6)?1:.2; break; // Ldir's DNA ))) https://twitter.com/ldir_ko/status/1326099121170771968 https://tixy.land/?code=x%3E7-%28sin%28t*5%2By*3%29*6%29%3F1%3A.2
}
//_____________________
//float r = static_cast <float> (rand()) / static_cast <float> (RAND_MAX); // my fire )) https://twitter.com/ldir_ko/status/1325720180262113281 https://tixy.land/?code=%7Ei%2F200*%28y%2F40%2Frandom%28%29%29
//return -i/200*(y/40/r); // my fire ))
//____________________________________
}
void processFrame(double t, double x, double y) {
EVERY_N_MILLISECONDS( 30 ) { gHue++; }
double i = (y * 8) + x;
double frame = constrain(code(t, i, x, y), -1, 1) * 255;
if (frame >= 0) { leds[XY(x, (pHEIGHT - 1 - y))]= CHSV(gHue,255,frame); } //change to XY(x, y) for non rotate display
else { leds[XY(x, (pHEIGHT - 1 - y))] = CHSV(gHue+128, 255, -frame); } //change to XY(x, y) for non rotate display
}
void draw() {
//effect = 2;
FastLED.clear();
double t = millis() / 1000.0; // some formulas is hardcoded and fps get down. this speedup it
for (byte x = 0; x < pWIDTH; x++) {
for (byte y = 0; y < pHEIGHT; y++) {
processFrame(t, x, y);
}
}
//EVERY_N_SECONDS(20){
// if(effect++>20) effect = 0;
//}
}