//Yaroslaw Turbin 15.06.2023
//https://vk.com/ldirko
//https://www.reddit.com/user/ldirko/
//https://twitter.com/ldir_ko
//https://www.youtube.com/@ldirldir
//license Creative Commons Attribution 4.0 International (CC-BY-4.0)
#include "FastLED.h"
#define NUM_LEDS 16*7
#define NUM_LEDS_BUFF 600
// LEDs pin
#define DATA_PIN 3
// #define LED_TYPE WS2812B
#define LED_TYPE WS2811
#define COLOR_ORDER GRB
// LED brightness
#define BRIGHTNESS 255
#define MAX_POWER_MILLIAMPS 800
// Define the array of leds
CRGB leds[NUM_LEDS+1];
CRGB leds_buff[NUM_LEDS_BUFF+1];
#include "tables.h"
void setup() {
Serial.begin(115200);
FastLED.addLeds<LED_TYPE, DATA_PIN, COLOR_ORDER>(leds, NUM_LEDS).setCorrection( TypicalLEDStrip );
// FastLED.setMaxPowerInVoltsAndMilliamps(5, MAX_POWER_MILLIAMPS);
FastLED.setBrightness(BRIGHTNESS);
FastLED.clear();
}
byte pixelMapX_norm[NUM_LEDS+1];
byte pixelMapY_norm[NUM_LEDS+1];
int lookup_table_from_buff_to_leds [NUM_LEDS];
void GammaCorrection(){ //gamma correction function
byte r,g,b;
for (uint16_t i=0; i<NUM_LEDS; i++){
r=leds[i].r;
g=leds[i].g;
b=leds[i].b;
leds[i].r = pgm_read_byte(exp_gamma + r);
leds[i].g = pgm_read_byte(exp_gamma + g);
leds[i].b = pgm_read_byte(exp_gamma + b);
}
}
CRGB GammaCorrection_color(CRGB color){ //gamma correction function
byte r,g,b;
r=color.r;
g=color.g;
b=color.b;
color.r = pgm_read_byte(exp_gamma + r);
color.g = pgm_read_byte(exp_gamma + g);
color.b = pgm_read_byte(exp_gamma + b);
return (color);
}
int XY_buff (int x, int y, int _buffX ){
int index = y*_buffX + x;
return( index);
}
int getMinVal (int map[]){
int minVal = map[0];
for (int i = 1; i < NUM_LEDS; i++) {
if (map[i]<minVal) minVal = map[i];
}
return minVal;
}
int getMaxVal (int map[]){
int maxVal = map[0];
for (int i = 1; i < NUM_LEDS; i++) {
if (map[i]>maxVal) maxVal = map[i];
}
return maxVal;
}
void normMapsGenerator_From_Coords (int Xres, int Yres, int *pixelMapX, int *pixelMapY) {
static byte init=1;
byte _buffX, _buffY;
if (!init) return;
double timestamp = millis();
if ((Xres*Yres) > NUM_LEDS_BUFF)
{Serial.println ("too big resolution! _buffX and _buffY set to 24x24"); _buffX = 24; _buffY = 24;}
else {_buffX = Xres; _buffY = Yres;}
int minValueX = getMinVal (pixelMapX);
int maxValueX = getMaxVal (pixelMapX);
int minValueY = getMinVal (pixelMapY);
int maxValueY = getMaxVal (pixelMapY);
int Xrange = maxValueX-minValueX;
int Yrange = maxValueY-minValueY;
for (int i = 0; i < NUM_LEDS; i++) {
int X_norm = (float)(pixelMapX[i]-minValueX)/Xrange*(_buffX-1)+0.5; // normalize pixel coord to buffer resolution
int Y_norm = (float)(pixelMapY[i]-minValueY)/Yrange*(_buffY-1)+0.5; // normalize pixel coord to buffer resolution
pixelMapX_norm [i] = X_norm;
pixelMapY_norm [i] = Y_norm;
int buffIndex = XY_buff(X_norm, Y_norm, _buffX);
lookup_table_from_buff_to_leds[i]=buffIndex;
}
pixelMapX_norm[NUM_LEDS]=_buffX; //save resolution X
pixelMapY_norm[NUM_LEDS]=_buffY; //save resolution Y
Serial.println("normalization map generated");
Serial.print("total leds "); Serial.println(NUM_LEDS);
Serial.print("buffer resolution X: ");
Serial.println(_buffX);
Serial.print("buffer resolution Y: ");
Serial.println(_buffY);
Serial.print("norm mapX: ");
for (int i = 0; i < NUM_LEDS; i++) {
int Xnorm4 = pixelMapX_norm[i];
Serial.print(Xnorm4); Serial.print(",");
}
Serial.println();
Serial.print("norm mapY: ");
for (int i = 0; i < NUM_LEDS; i++) {
int Ynorm4 = pixelMapY_norm[i];
Serial.print(Ynorm4); Serial.print(",");
}
Serial.println();
Serial.println("lookup_table_from_buff_to_leds:");
for (int i = 0; i < NUM_LEDS; i++) {
int index = lookup_table_from_buff_to_leds[i];
Serial.print(index); Serial.print(",");
}
Serial.println();
Serial.print("tables generated in sec: ");
Serial.print((millis()-timestamp)/1000);
init = 0;
}
void Sin_plasma (byte *pixelMapX_norm, byte *pixelMapY_norm) {
double t=millis()/200.;
int t1 = t*6;
int t2 = t*7;
// byte _buffX = pixelMapX_norm[NUM_LEDS];
// byte _buffY = pixelMapY_norm[NUM_LEDS];
// int index =0;
// for (int j = 0; j < _buffY; j++) {
// for (int i = 0; i < _buffX; i++) {
// byte ind = sin8(i*8+sin8(i*2+t1))/2+sin8(j*8+sin8(j*2+t2)/2);
// leds_buff [index++].setHue(ind);
// }
// }
// for (int i = 0; i < NUM_LEDS; i++) {
// leds[i] = leds_buff[lookup_table_from_buff_to_leds[i]];
// }
for (int z = 0; z < NUM_LEDS; z++) { //fastest method
byte i = pixelMapX_norm[z];
byte j = pixelMapY_norm[z];
byte ind = sin8(i*8+sin8(i*2+t1))/2+sin8(j*8+sin8(j*2+t2)/2);
leds[z].setHue(ind);
}
}
void fire2021 (byte *pixelMapX_norm, byte *pixelMapY_norm){
int a = millis();
int a1 = a/3;
byte _buffY = pixelMapY_norm[NUM_LEDS];
for (int z = 0; z < NUM_LEDS; z++) { //fastest method
byte i = pixelMapX_norm[z];
byte j = pixelMapY_norm[z];
CRGB color = HeatColor(qsub8 (inoise8 (i * 60, j * 60+a, a1), abs8(j - (_buffY-1)) * 255 / (_buffY+4)));
leds[z] = color;
}
}
void RGB_hiphotic(byte *pixelMapX_norm, byte *pixelMapY_norm) {
int a = millis()/8.;
CRGB color;
for (int z = 0; z < NUM_LEDS; z++) { //fastest method
byte x = pixelMapX_norm[z];
byte y = pixelMapY_norm[z];
color.b=sin8((x-8)*cos8((y+20)*4)/4+a);
color.g=(sin8(x*16+a/3)+cos8(y*8+a/2))/2;
color.r=sin8(cos8(x*8+a/3)+sin8(y*8+a/4)+a);
color = GammaCorrection_color(color);
nblend (leds[z], color, 64);
}
}
void Distortion_Waves(byte *pixelMapX_norm, byte *pixelMapY_norm) {
byte speed = 5;
uint8_t w = 2;
uint8_t scale = 4;
CRGB color;
byte _buffX = pixelMapX_norm[NUM_LEDS];
byte _buffY = pixelMapY_norm[NUM_LEDS];
int a=millis()/24;
uint16_t a2=a/2;
uint16_t a3=a/3;
uint16_t cx = beatsin8 (10-speed,0,_buffX)*scale;
uint16_t cy = beatsin8 (12-speed,0,_buffY)*scale;
uint16_t cx1 = beatsin8 (13-speed,0,_buffX)*scale;
uint16_t cy1 = beatsin8 (15-speed,0,_buffY)*scale;
uint16_t cx2 = beatsin8 (17-speed,0,_buffX)*scale;
uint16_t cy2 = beatsin8 (14-speed,0,_buffY)*scale;
for (int z = 0; z < NUM_LEDS; z++) {
byte x = pixelMapX_norm[z];
byte y = pixelMapY_norm[z];
int x_scale=x*scale;
int y_scale=y*scale;
byte rdistort = cos_wave [(cos_wave[((x<<3)+a )&255]+cos_wave[((y<<3)-a2)&255]+a3 )&255]>>1;
byte gdistort = cos_wave [(cos_wave[((x<<3)-a2)&255]+cos_wave[((y<<3)+a3)&255]+a+32 )&255]>>1;
byte bdistort = cos_wave [(cos_wave[((x<<3)+a3)&255]+cos_wave[((y<<3)-a) &255]+a2+64)&255]>>1;
byte valueR = rdistort+ w* (a- ( ((x_scale - cx) * (x_scale - cx) + (y_scale - cy) * (y_scale - cy))>>7 ));
byte valueG = gdistort+ w* (a2-( ((x_scale - cx1) * (x_scale - cx1) + (y_scale - cy1) * (y_scale - cy1))>>7 ));
byte valueB = bdistort+ w* (a3-( ((x_scale - cx2) * (x_scale - cx2) + (y_scale - cy2) * (y_scale - cy2))>>7 ));
color.r = cos_wave [valueR];
color.g = cos_wave [valueG];
color.b = cos_wave [valueB];
color = GammaCorrection_color(color);
nblend (leds[z], color, 16);
}
}
void testRadial (byte *pixelMapX_norm, byte *pixelMapY_norm){
double time= millis()/8.0;
int a = time;
int a4= a/4.;
for (int z = 0; z < NUM_LEDS; z++) {
byte i = pixelMapX_norm[z];
byte j = pixelMapY_norm[z];
leds[z].setHue (((i<<3)+(sin8((j<<3)+a))>>1)+a4);
}
}
void loop() {
normMapsGenerator_From_Coords (16,16, pixelMapX, pixelMapY);
// normMapsGenerator_From_Coords (20,8, pixelMapX_Cilindr, pixelMapY_Cilindr);
// testRadial (pixelMapX_norm, pixelMapY_norm);
// Sin_plasma (pixelMapX_norm, pixelMapY_norm);
// fire2021 (pixelMapX_norm, pixelMapY_norm);
Distortion_Waves(pixelMapX_norm, pixelMapY_norm);
// RGB_hiphotic(pixelMapX_norm, pixelMapY_norm);
FastLED.show();
}
FPS: 0
Power: 0.00W
Power: 0.00W