#include <FastLED.h>
// По мотивам эффекта Stepko - SmokeWaves
// в прошивке vvip эффект сверху вниз
#define pWIDTH 16
#define pHEIGHT 24
#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) {
return getPixelNumber(x, y);
}
void shiftWave() {
for (uint8_t x = 0; x < pWIDTH; x++) {
for (uint8_t y = 0; y < pHEIGHT - 1; y++) {
drawPixelXY(x, y, getPixColorXY(x, y + 1));
int16_t idx = getPixelNumber(x, y + 1);
if (idx >= 0 && idx < NUM_LEDS) leds[idx].nscale8_video(200); //map8(getEffectScaleParamValue2(thisMode),0,235)
}
}
}
typedef struct {
uint16_t wavePos;
float waveSpeed;
uint8_t maxMin;
uint8_t waveColors;
uint16_t waveReg;
} fallingWaves;
#define WAVES_AMOUNT ((pWIDTH)/2)
fallingWaves *fWaves = NULL;
void setup() {
FastLED.addLeds<WS2812B, 3, GRB>(leds, NUM_LEDS);
}
void loop() {
if (loadingFlag) {
loadingFlag = false;
randomSeed(millis());
if (fWaves == NULL) { fWaves = new fallingWaves[WAVES_AMOUNT]; }
for (uint8_t i = 0; i < WAVES_AMOUNT; i++) {
fWaves[i].waveReg = random(0, pWIDTH * 10);
fWaves[i].waveSpeed = float(random(48, 16 * pWIDTH) / random(1, 10));
fWaves[i].maxMin = random((pWIDTH / 4) * 10, (pWIDTH / 2) * 20);
fWaves[i].waveColors = random(0, 9) * 28;
fWaves[i].wavePos = fWaves[i].waveReg;
}
}
uint8_t effectBrightness = 255; // slider
uint8_t scale = 16; // 1 ... 16 // slider
float speedFactor = .2; // .02 ... .2
shiftWave();
blur2d(leds, pWIDTH, pHEIGHT, map(scale,1,16,2,8));
for (uint8_t i = 0; i < map(scale, 1, 16, 2, WAVES_AMOUNT); i++) {
fWaves[i].waveColors++;
fWaves[i].wavePos = (float)beatsin16((uint8_t)(fWaves[i].waveSpeed * (speedFactor * .5)), fWaves[i].waveReg, fWaves[i].maxMin + fWaves[i].waveReg, fWaves[i].waveColors * 256, fWaves[i].waveColors * 8);
if (fWaves[i].wavePos < 0) fWaves[i].wavePos = (pWIDTH * 10) - 1 - (fWaves[i].wavePos - (pWIDTH * 10));
if (fWaves[i].wavePos > pWIDTH * 10) fWaves[i].wavePos = (fWaves[i].wavePos - pWIDTH * 10);
int16_t idx = getPixelNumber(fWaves[i].wavePos / 10, pHEIGHT-1);
if (idx >= 0 && idx < NUM_LEDS) leds[idx] += ColorFromPalette(gCurrentGradientPalette, fWaves[i].waveColors, effectBrightness);
}
EVERY_N_SECONDS(15) {chooseNextPalette();}
EVERY_N_MILLISECONDS(10) nblendPaletteTowardPalette( gCurrentGradientPalette, gTargetGradientPalette, 16);
FastLED.delay(40);
}