#include <FastLED.h>
#define LED_PIN 3
#define COLOR_ORDER GRB
#define CHIPSET WS2812B
#define kMatrixWidth 20
#define kMatrixHeight 20
#define kMatrixSerpentine true
#define kMatrixRowMajor true
#define kMatrixFlipMajor true
#define kMatrixFlipMinor false
#define NUM_LEDS ((kMatrixWidth) * (kMatrixHeight))
#define kHalfWidth (kMatrixWidth / 2)
#define kHalfHeight (kMatrixHeight / 2)
CRGB leds_plus_safety_pixel[NUM_LEDS + 1];
CRGB* const leds(leds_plus_safety_pixel + 1);
float XY_angle[kMatrixWidth][kMatrixHeight];
float XY_radius[kMatrixWidth][kMatrixHeight];
void setup() {
FastLED.addLeds<CHIPSET, LED_PIN, COLOR_ORDER>(leds, NUM_LEDS).setCorrection(UncorrectedColor);
for (int8_t x = -kHalfWidth; x < kHalfWidth; x++) {
for (int8_t y = -kHalfHeight; y < kHalfHeight; y++) {
XY_angle[x + kHalfWidth][y + kHalfHeight] = atan2(y, x) * (360. / 2. / PI) * kHalfWidth;
XY_radius[x + kHalfWidth][y + kHalfHeight] = hypotf(x, y);
}
}
}
void loop() {
drawFrame();
FastLED.show();
}
void drawFrame() {
static byte scale = 16;
static byte speed = 48;
static uint32_t t;
t += speed;
for (uint8_t x = 0; x < kMatrixWidth; x++) {
for (uint8_t y = 0; y < kMatrixHeight; y++) {
float angle = XY_angle[x][y];
float radius = XY_radius[x][y];
int16_t Bri = inoise8(angle, radius * scale - t) - radius * kMatrixHeight;
byte Col = Bri;
if (Bri < 0) Bri = 0; if(Bri != 0) Bri = 256 - (Bri * 0.2);
nblend(leds[XY(x, y)], ColorFromPalette(HeatColors_p, Col, Bri), speed);}
}
}
int16_t XY(int8_t x, int8_t y) {
uint8_t major, minor, sz_major, sz_minor;
if (x >= kMatrixWidth || y >= kMatrixHeight || x < 0 || y < 0) return -1;
if (kMatrixRowMajor)
major = x, minor = y, sz_major = kMatrixWidth, sz_minor = kMatrixHeight;
else
major = y, minor = x, sz_major = kMatrixHeight, sz_minor = kMatrixWidth;
if (kMatrixFlipMajor ^ (minor & 1 && kMatrixSerpentine))
major = sz_major - 1 - major;
if (kMatrixFlipMinor)
minor = sz_minor - 1 - minor;
return (uint16_t) minor * sz_major + major;
}