//61 led rings cilindrical and planar maps demo
//Yaroslaw Turbin 05-04-2021
//https://vk.com/ldirko
//https://www.reddit.com/user/ldirko/
//https://twitter.com/ldir_ko
#include <FastLED.h>
#define DATA_PIN 3
#define NUM_LEDS 128
#define NUM_COLS_CILINDR 45 // resolution for cilindrical lookup table
#define NUM_ROWS_CILINDR 5
#define NUM_COLS_PLANAR 19 // resolution for planar lookup table
#define NUM_ROWS_PLANAR 23
#define LED_TYPE WS2812B //leds type
#define COLOR_ORDER GRB //color order of leds
#define MAX_POWER_MILLIAMPS 800 //write here your power in milliamps. default i set 800 mA for safety
#define BRIGHTNESS 255
CRGB leds[NUM_LEDS+1]; //one safe pixel in bottom. its index 61
uint8_t gCurrentPatternNumber =0; // Index number of which pattern is current
const uint8_t exp_gamma[256] PROGMEM = {
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1,
1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
1, 2, 2, 2, 2, 2, 2, 2, 2, 2, 3, 3, 3, 3, 3,
4, 4, 4, 4, 4, 5, 5, 5, 5, 5, 6, 6, 6, 7, 7,
7, 7, 8, 8, 8, 9, 9, 9, 10, 10, 10, 11, 11, 12, 12,
12, 13, 13, 14, 14, 14, 15, 15, 16, 16, 17, 17, 18, 18, 19,
19, 20, 20, 21, 21, 22, 23, 23, 24, 24, 25, 26, 26, 27, 28,
28, 29, 30, 30, 31, 32, 32, 33, 34, 35, 35, 36, 37, 38, 39,
39, 40, 41, 42, 43, 44, 44, 45, 46, 47, 48, 49, 50, 51, 52,
53, 54, 55, 56, 57, 58, 59, 60, 61, 62, 63, 64, 65, 66, 67,
68, 70, 71, 72, 73, 74, 75, 77, 78, 79, 80, 82, 83, 84, 85,
87, 89, 91, 92, 93, 95, 96, 98, 99, 100, 101, 102, 105, 106, 108,
109, 111, 112, 114, 115, 117, 118, 120, 121, 123, 125, 126, 128, 130, 131,
133, 135, 136, 138, 140, 142, 143, 145, 147, 149, 151, 152, 154, 156, 158,
160, 162, 164, 165, 167, 169, 171, 173, 175, 177, 179, 181, 183, 185, 187,
190, 192, 194, 196, 198, 200, 202, 204, 207, 209, 211, 213, 216, 218, 220,
222, 225, 227, 229, 232, 234, 236, 239, 241, 244, 246, 249, 251, 253, 254, 255};
void setup() {
FastLED.addLeds<LED_TYPE, DATA_PIN, COLOR_ORDER>(leds, NUM_LEDS)
.setCorrection( TypicalLEDStrip );
// FastLED.setMaxPowerInVoltsAndMilliamps( 5, MAX_POWER_MILLIAMPS);
FastLED.setBrightness(BRIGHTNESS);
FastLED.clear();
}
#define ARRAY_SIZE(A) (sizeof(A) / sizeof((A)[0]))
// List of patterns to cycle through. Each is defined as a separate function below.
typedef void (*SimplePatternList[])();
SimplePatternList gPatterns = {seven,six,five,first, second, trird,four};
void loop() {
EVERY_N_SECONDS( 10 ) // speed of change patterns periodically
{gCurrentPatternNumber = (gCurrentPatternNumber + 1) % ARRAY_SIZE(gPatterns);}
gPatterns[gCurrentPatternNumber]();
FastLED.show();
} // main cycle
void first (){
uint16_t a = millis()/8;
for (int j = 0; j < NUM_ROWS_CILINDR; j++) {
for (int i = 0; i < NUM_COLS_CILINDR; i++) {
byte index = XY_cilindrical(i,j);
if (index!=128) leds[index].setHue (i*16+(sin8((j<<3)+a))>>1);
}} //end cycles
}
void second (){
uint16_t a = millis()/4;
for (int j = 0; j < NUM_ROWS_CILINDR; j++) {
for (int i = 0; i < NUM_COLS_CILINDR; i++) {
byte index = XY_cilindrical(i,j);
if (index!=128) {
leds[index].b=sin8((i/2-16)*cos8((j+20)*4)/4+a);
leds[index].g=(sin8(i*16+a/3)+cos8(j*8+a/2))/2;
leds[index].r=sin8(cos8(i*8+a/3)+sin8(j*8+a/4)+a);}
}} //end cycles
GammaCorrection();
}
void trird (){
uint16_t a = millis()/4;
for (int j = 0; j < NUM_ROWS_CILINDR; j++) {
for (int i = 0; i < NUM_COLS_CILINDR; i++) {
byte index = XY_cilindrical(i,j);
if (index!=128) leds[index].setHue (i*255/(NUM_COLS_CILINDR-1)*3+j*32+a/2); //full moving rainbow
}} //end cycles
}
void four (){
uint16_t a = millis()/4;
for (int j = 0; j < NUM_ROWS_CILINDR; j++) {
for (int i = 0; i < NUM_COLS_CILINDR; i++) {
byte index = XY_cilindrical(i,j);
if (index!=128) leds[index]= HeatColor(inoise8(i*70+a,j*60+a*2)); //red tonnel
}} //end cycles
}
void five (){
uint16_t a = millis()/4;
for (int j = 0; j < NUM_ROWS_CILINDR; j++) {
for (int i = 0; i < NUM_COLS_CILINDR; i++) {
byte index = XY_cilindrical(i,j);
if (index!=128) leds[index]=HeatColor(qsub8 (inoise8 (i * 80+a , j * 5+ a , a /3), abs8(j - (NUM_ROWS_CILINDR-1)) * 255 / (NUM_ROWS_CILINDR+3)));
}} //end cycles
}
void six (){
uint16_t a = millis()/8;
for (int j = 0; j < NUM_ROWS_CILINDR; j++) {
for (int i = 0; i < NUM_COLS_CILINDR; i++) {
byte index = XY_cilindrical(i,j);
if (index!=128) leds[index].setHue ((sin8((i<<5)+a*2)>>1)+(sin8((j<<5)+a))>>1);
}} //end cycles
}
void seven (){
uint16_t a = millis()/8;
for (int j = 0; j < NUM_ROWS_CILINDR; j++) {
for (int i = 0; i < NUM_COLS_CILINDR; i++) {
byte index = XY_cilindrical(i,j);
if (index!=128)
leds[index].setRGB( (sin8(i*32+a)+cos8(j*16+a/2))/2, sin8(j*16+a/2+sin8(leds[index].r+a)/16), cos8(i*32+j*16-a/2+leds[index].g));
}} //end cycles
GammaCorrection();
}
void firePlanar() {
int a = millis();
for (int j = 0; j < NUM_ROWS_PLANAR; j++) {
for (int i = 0; i < NUM_COLS_PLANAR; i++) {
byte index = XY_planar(i,j);
if (index!=128)
leds[index] = HeatColor(qsub8 (inoise8 (i * 127 , j * 127+ a , a /3), abs8(j - (NUM_ROWS_PLANAR-1)) * 255 / (NUM_ROWS_PLANAR+2)));
}}
}
void patternPlanar() {
int a = millis();
for (int j = 0; j < NUM_ROWS_PLANAR; j++) {
for (int i = 0; i < NUM_COLS_PLANAR; i++) {
byte index = XY_planar(i,j);
if (index!=128)
leds[index].setHue (sin8((i<<4)+a/6)/2+sin8((j<<4)+a/6)/2);
}}
}
byte XY_cilindrical (byte x, byte y) {
static const byte CilindricalLookTable [] = //1/6 of full table for reduce memory size. little bit tricky to calculate index ))
{0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10,
45, 46, 128, 47, 48, 128, 49, 50, 128, 51, 52,
80, 128, 81, 82, 83, 128, 84, 85, 86, 128, 87,
104, 128, 105, 128, 106, 128, 107, 128, 108, 128, 109,
120, 128, 128, 121, 128, 128, 128, 122, 128, 128, 123};
static const byte offs [] = { 5, 4, 3, 2, 1};
byte index = CilindricalLookTable [y*5+x%5];
if (index!=128) {index+= (x/5)*offs[y];}
return (index);
}
byte XY_planar (byte x, byte y) {
static const byte PlanarLookTable [] ={
28, 128, 128, 128, 128, 41, 42, 43, 44, 1, 2, 3, 4, 5, 128, 128, 128, 128, 128,
128, 128, 128, 128, 40, 128, 128, 128, 128, 128, 128, 128, 128, 128, 6, 128, 128, 128, 128,
128, 128, 128, 39, 128, 128, 128, 128, 79, 45, 46, 47, 128, 128, 128, 7, 128, 128, 128,
128, 128, 38, 128, 128, 128, 78, 128, 128, 128, 128, 128, 48, 128, 128, 128, 8, 128, 128,
128, 128, 128, 128, 128, 77, 128, 128, 103, 80, 81, 128, 128, 49, 128, 128, 128, 128, 128,
128, 37, 128, 128, 76, 128, 128, 102, 128, 128, 128, 82, 128, 128, 50, 128, 128, 9, 128,
128, 128, 128, 75, 128, 128, 101, 128, 128, 104, 128, 128, 83, 128, 128, 51, 128, 128, 128,
36, 128, 74, 128, 128, 100, 128, 128, 119, 128, 105, 128, 128, 84, 128, 128, 52, 128, 10,
128, 128, 128, 128, 128, 128, 128, 118, 128, 120, 128, 106, 128, 128, 128, 128, 128, 128, 128,
35, 128, 73, 128, 99, 128, 117, 128, 127, 128, 121, 128, 107, 128, 85, 128, 53, 128, 11,
128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128,
34, 128, 72, 128, 98, 128, 116, 126, 128, 128, 128, 122, 108, 128, 86, 128, 54, 128, 12,
128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128,
33, 128, 71, 128, 97, 128, 115, 128, 125, 128, 123, 128, 109, 128, 87, 128, 55, 128, 13,
128, 128, 128, 128, 128, 128, 128, 114, 128, 124, 128, 110, 128, 128, 128, 128, 128, 128, 128,
32, 128, 70, 128, 128, 96, 128, 128, 113, 128, 111, 128, 128, 88, 128, 128, 56, 128, 14,
128, 128, 128, 69, 128, 128, 95, 128, 128, 112, 128, 128, 89, 128, 128, 57, 128, 128, 128,
128, 31, 128, 128, 68, 128, 128, 94, 128, 128, 128, 90, 128, 128, 58, 128, 128, 15, 128,
128, 128, 128, 128, 128, 67, 128, 128, 93, 92, 91, 128, 128, 59, 128, 128, 128, 128, 128,
128, 128, 30, 128, 128, 128, 66, 128, 128, 128, 128, 128, 60, 128, 128, 128, 16, 128, 128,
128, 128, 128, 29, 128, 128, 128, 65, 64, 63, 62, 61, 128, 128, 128, 17, 128, 128, 128,
128, 128, 128, 128, 28, 128, 128, 128, 128, 128, 128, 128, 128, 128, 18, 128, 128, 128, 128,
128, 128, 128, 128, 128, 27, 26, 25, 24, 23, 22, 21, 20, 19, 128, 128, 128, 128, 128,
};
byte index = PlanarLookTable [y*NUM_COLS_PLANAR+x];
return (index);
}
void GammaCorrection(){ //gamma correction function
byte r,g,b;
for (uint16_t i=0; i<128; 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);
}
}