//source: https://editor.soulmatelights.com/gallery/user/348-tara
#include "FastLED.h"
#define DATA_PIN 2
#define BRIGHTNESS 255
#define NUM_LEDS 256
#define LED_COLS 16
#define LED_ROWS 16
#define LED_TYPE WS2812B
#define COLOR_ORDER GRB
CRGB leds[NUM_LEDS];
//#define FRAMES_PER_SECOND 60
const uint8_t kMatrixWidth = 16;
const uint8_t kMatrixHeight = 16;
const bool kMatrixSerpentineLayout = false;
#define COUNT 4 // default: 4
float posX[COUNT];
float posY[COUNT];
uint8_t aimX[COUNT];
uint8_t aimY[COUNT];
float Sradius[COUNT];
byte Shue[COUNT];;
CRGB color[COUNT];
CRGB color1[COUNT];
CRGB color2[COUNT];
CRGB color3[COUNT];
CRGB color4[COUNT];
CRGB color5[COUNT];
CRGB color6[COUNT];
CRGB color7[COUNT];
CRGB color8[COUNT];
byte starPoints[COUNT];
bool run[COUNT];
bool load = true;
const byte Smax = max(LED_COLS, LED_ROWS);
const float speedFactor = NUM_LEDS/255;
extern const TProgmemRGBPalette16 ZAlcoholFireColors_p FL_PROGMEM = {CRGB::Black, 0x000033, 0x000066, 0x000099, 0x0000cc, CRGB::Blue, 0x0026ff, 0x004cff, 0x0073ff, 0x0099ff, CRGB::DeepSkyBlue, 0x1bc2fe, 0x36c5fd, 0x51c8fc, 0x6ccbfb, CRGB::LightSkyBlue}; //* Blue
extern const TProgmemRGBPalette16 ZRubidiumFireColors_p FL_PROGMEM = {CRGB::Red, 0x0f001a, 0x1e0034, 0x2d004e, 0x3c0068, CRGB::Red, CRGB::Indigo, CRGB::Indigo, CRGB::Indigo, CRGB::Indigo, CRGB::Indigo, 0x3c0084, 0x2d0086, 0x1e0087, 0x0f0089, CRGB::Red}; //* Indigo
// const float SSspeed = (float) NUM_LEDS / 255; // 255 Speed normalization for different matrix sizes
const float addRadius = (float) NUM_LEDS / 400; // 400 Normalization of increase in radius
void SdrawPixelXYF(float x, float y, CRGB color) {
if (x < 0 || y < 0 || x > ((float) LED_COLS - 1) || y > ((float) LED_ROWS - 1)) return;
uint8_t xx = (x - (int) x) * 255, yy = (y - (int) y) * 255, ix = 255 - xx, iy = 255 - yy;
// calculate the intensities for each affected pixel
#define WU_WEIGHT(a, b)((uint8_t)(((a) * (b) + (a) + (b)) >> 8))
uint8_t wu[4] = {
WU_WEIGHT(ix, iy),
WU_WEIGHT(xx, iy),
WU_WEIGHT(ix, yy),
WU_WEIGHT(xx, yy)
};
// multiply the intensities by the colour, and saturating-add them to the pixels
for (uint8_t i = 0; i < 4; i++) {
int16_t xn = x + (i & 1), yn = y + ((i >> 1) & 1);
CRGB clr = leds[XY(xn, yn)];
clr.r = qadd8(clr.r, (color.r * wu[i]) >> 8);
clr.g = qadd8(clr.g, (color.g * wu[i]) >> 8);
clr.b = qadd8(clr.b, (color.b * wu[i]) >> 8);
leds[XY(xn, yn)] = clr;
}
}
void SdrawCircleF(float x0, float y0, float radius,
const CRGB & color, float step = 0.25) {
float a = radius, b = 0.;
float radiusError = step - a;
if (radius <= step * 2) {
SdrawPixelXYF(x0, y0, color);
return;
}
while (a >= b) {
SdrawPixelXYF(a + x0, b + y0, color);
SdrawPixelXYF(b + x0, a + y0, color);
SdrawPixelXYF(-a + x0, b + y0, color);
SdrawPixelXYF(-b + x0, a + y0, color);
SdrawPixelXYF(-a + x0, -b + y0, color);
SdrawPixelXYF(-b + x0, -a + y0, color);
SdrawPixelXYF(a + x0, -b + y0, color);
SdrawPixelXYF(b + x0, -a + y0, color);
//+++++++++++++++++++++
b += step;
if (radiusError < 0.)
radiusError += 2. * b + step;
else {
a -= step;
radiusError += 2 * (b - a + step);
}
}
}
void drawLineF(float x1, float y1, float x2, float y2,
const CRGB & color) {
float deltaX = fabs(x2 - x1);
float deltaY = fabs(y2 - y1);
float error = deltaX - deltaY;
float signX = x1 < x2 ? 0.5 : -0.5;
float signY = y1 < y2 ? 0.5 : -0.5;
while (x1 != x2 || y1 != y2) {
if ((signX > 0. && x1 > x2 + signX) || (signX < 0. && x1 < x2 + signX))
break;
if ((signY > 0. && y1 > y2 + signY) || (signY < 0. && y1 < y2 + signY))
break;
SdrawPixelXYF(x1, y1, color);
float error2 = error;
if (error2 > -deltaY) {
error -= deltaY;
x1 += signX;
}
if (error2 < deltaX) {
error += deltaX;
y1 += signY;
}
}
}
void drawStarF(float x, float y, float biggy, float little, int16_t points, float dangle, CRGB color) {
float radius2 = 255.0 / points;
for (int i = 0; i < points; i++) {
// drawLineF(x + ((little * (sin8(i * radius2 + radius2 / 8 - dangle) - 128.0)) / 128), y + ((little * (cos8(i * radius2 + radius2 / 8 - dangle) - 128.0)) / 128), x + ((biggy * (sin8(i * radius2 - dangle) - 128.0)) / 128), y + ((biggy * (cos8(i * radius2 - dangle) - 128.0)) / 128), color);
//drawLineF(x + ((little * (sin8(i * radius2 - radius2 / 8 - dangle) - 128.0)) / 128), y + ((little * (cos8(i * radius2 - radius2 / 8 - dangle) - 128.0)) / 128), x + ((biggy * (sin8(i * radius2 - dangle) - 128.0)) / 128), y + ((biggy * (cos8(i * radius2 - dangle) - 128.0)) / 128), color);
drawLineF(x + ((little * (sin8(i * radius2 + radius2 / 8 ) - 128.0)) / 128), y + ((little * (cos8(i * radius2 + radius2 / 8 ) - 128.0)) / 128), x + ((biggy * (sin8(i * radius2 ) - 128.0)) / 128), y + ((biggy * (cos8(i * radius2 ) - 128.0)) / 128), color);
drawLineF(x + ((little * (sin8(i * radius2 - radius2 / 8 ) - 128.0)) / 128), y + ((little * (cos8(i * radius2 - radius2 / 8 ) - 128.0)) / 128), x + ((biggy * (sin8(i * radius2 ) - 128.0)) / 128), y + ((biggy * (cos8(i * radius2 ) - 128.0)) / 128), color);
}
}
void aimChange(byte idx) {
randomSeed(millis());
aimX[idx] = random(LED_COLS / 2 , LED_COLS / 2 );
aimY[idx] = random(LED_ROWS / 2 , LED_ROWS / 2 );
Sradius[idx] = 1;
Shue[idx] = random8();
color[idx] = ColorFromPalette(RainbowStripeColors_p, Shue[idx],255); //CHSV(hue, 255, 255);
color1[idx] = ColorFromPalette(PartyColors_p, Shue[idx], 255); //CHSV(hue, 255, 255);
color2[idx] = ColorFromPalette(LavaColors_p, Shue[idx], 255); //CHSV(hue, 255, 255);
color3[idx] = ColorFromPalette(ZRubidiumFireColors_p, Shue[idx], 255); //CHSV(hue, 255, 255);
color4[idx] = ColorFromPalette(CloudColors_p, Shue[idx],255); //CHSV(hue, 255, 255);
color5[idx] = ColorFromPalette(ForestColors_p, Shue[idx], 255); //CHSV(hue, 255, 255);
color6[idx] = ColorFromPalette(RainbowColors_p, Shue[idx], 255); //CHSV(hue, 255, 255);
color7[idx] = ColorFromPalette(ZAlcoholFireColors_p, Shue[idx],255); //CHSV(hue, 255, 255);
color8[idx] = ColorFromPalette(OceanColors_p, Shue[idx],255); //CHSV(hue, 255, 255);
starPoints[idx] = random(4, 7);
run[idx] = false;
}
void setup() {
FastLED.addLeds<LED_TYPE,DATA_PIN,COLOR_ORDER>(leds, NUM_LEDS); //setCorrection(TypicalLEDStrip);
//FastLED.addLeds<LED_TYPE,DATA_PIN,CLK_PIN,COLOR_ORDER>(leds, NUM_LEDS).setCorrection(TypicalLEDStrip);
FastLED.setBrightness(BRIGHTNESS);
//Serial.begin(115200);
}
void loop()
{
fadeToBlackBy(leds, NUM_LEDS, 50);
if (load) {
for (byte i = 0; i < COUNT; i++) {
aimChange(i);
}
run[0] = true;
load = false;
}
for (byte i = 0; i < COUNT; i++) {
if (Sradius[i] > Smax / COUNT) {
run[i + 1 < COUNT ? i + 1 : 0] = true;
}
static float angle[COUNT];
if (run[i]) {
Sradius[i] += addRadius * speedFactor;
angle[i] += Sradius[i];
switch (Shue[i] % 10) {
case 0:
SdrawCircleF(aimX[i], aimY[i], Sradius[i], color[i]); // рисуем круг
break;
case 1:
drawStarF(aimX[i], aimY[i], 1.3 * Sradius[i], Sradius[i], 4, angle[i], color[i]); // рисуем квадрат
break;
case 2:
drawStarF(aimX[i], aimY[i], 2 * Sradius[i], Sradius[i], starPoints[i], angle[i], color[i]); // рисуем звезду
break;
case 3:
SdrawCircleF(aimX[i], aimY[i], Sradius[i], color1[i]); // рисуем круг
break;
case 4:
drawStarF(aimX[i], aimY[i], 1.3 * Sradius[i], Sradius[i], 4, angle[i], color2[i]); // рисуем квадрат
break;
case 5:
drawStarF(aimX[i], aimY[i], 2 * Sradius[i], Sradius[i], starPoints[i], angle[i], color3[i]); // рисуем звезду
break;
case 6:
SdrawCircleF(aimX[i], aimY[i], Sradius[i], color4[i]); // рисуем круг
break;
case 7:
drawStarF(aimX[i], aimY[i], 1.3 * Sradius[i], Sradius[i], 4, angle[i], color5[i]); // рисуем квадрат
break;
case 8:
drawStarF(aimX[i], aimY[i], 2 * Sradius[i], Sradius[i], starPoints[i], angle[i], color6[i]); // рисуем звезду
break;
case 9:
// draw7();
break;
}
}
if (Sradius[i] > Smax) aimChange(i);
}
delay(16); //fps ~= 60
FastLED.show();
}
uint16_t XY( uint8_t x, uint8_t y)
{
uint16_t i;
if( kMatrixSerpentineLayout == false) {
i = (y * kMatrixWidth) + x;
}
if( kMatrixSerpentineLayout == true) {
if( y & 0x01) {
// Odd rows run backwards
uint8_t reverseX = (kMatrixWidth - 1) - x;
i = (y * kMatrixWidth) + reverseX;
} else {
// Even rows run forwards
i = (y * kMatrixWidth) + x;
}
}
return i;
}