//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 61
#define NUM_COLS_CILINDR 24 // resolution for cilindrical lookup table
#define NUM_ROWS_CILINDR 5
#define NUM_COLS_PLANAR 11 // resolution for planar lookup table
#define NUM_ROWS_PLANAR 15
#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 = {firePlanar,patternPlanar, 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!=61) 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!=61) {
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!=61) 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!=61) 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!=61) 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!=61) 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!=61)
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!=61)
leds[index] = HeatColor(qsub8 (inoise8 (i * 60 , j * 60+ 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!=61)
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, 24, 25, 61, 26, 42, 61, 43, 61, 54, 61, 61, 61, 60, 61, 61, 61};
static const byte offs [] = {4, 3, 2, 1, 0};
byte index = CilindricalLookTable [(y<<2)+x%4] ;
if (index!=61) {index+= (x>>2)*offs[y];}
return (index);
}
byte XY_planar (byte x, byte y) {
static const byte PlanarLookTable [] ={
61,61,61,61,23,0,1,61,61,61,61,
61,61,61,22,61,61,61,2,61,61,61,
61,61,21,61,41,24,25,61,3,61,61,
61,20,61,40,61,42,61,26,61,4,61,
61,61,39,61,53,61,43,61,27,61,61,
19,61,61,52,61,54,61,44,61,61,5,
61,61,38,61,59,61,55,61,28,61,61,
18,61,61,51,61,60,61,45,61,61,6,
61,61,37,61,58,61,56,61,29,61,61,
17,61,61,50,61,57,61,46,61,61,7,
61,61,36,61,49,61,47,61,30,61,61,
61,16,61,35,61,48,61,31,61,8,61,
61,61,15,61,34,33,32,61,9,61,61,
61,61,61,14,61,61,61,10,61,61,61,
61,61,61,61,13,12,11,61,61,61,61};
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<61; 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);
}
}