//Splendida 256 Spiral with random palletes
//fastled fibonacci 256 leds demo
//Yaroslaw Turbin 28-06-2022
//https://vk.com/ldirko
//https://www.reddit.com/user/ldirko/
//https://twitter.com/ldir_ko


#include <FastLED.h>

#define DATA_PIN    3                //set your leds datapin   change to 32 for m5 atom lite
#define LED_TYPE    WS2812B          //leds type
#define COLOR_ORDER GRB              //color order of leds

#define MAX_POWER_MILLIAMPS 700      //write here your power in milliamps. default i set 800 mA for safet

#define NUM_COLS_CILINDR 45          // resolution of cilindrical lookup table
#define NUM_ROWS_CILINDR 11          // resolution of cinindrical lookup table
#define NUM_LEDS_CILINDR NUM_COLS_CILINDR*NUM_ROWS_CILINDR

#define NUM_LEDS 256       

#define SECONDS_PER_PALETTE 15

byte brigtness = 255;
uint16_t lastSafeIndex = 256; 

CRGBPalette16 gCurrentPalette( CRGB::Black);
CRGBPalette16 gTargetPalette;  

CRGB leds [NUM_LEDS+1];


void setup() {

  next_Random_Pallete (CRGB (100,200,128));  
  FastLED.addLeds<LED_TYPE, DATA_PIN, COLOR_ORDER>(leds, NUM_LEDS);
  //uncomment this before upload sketch
  // .setCorrection( TypicalLEDStrip );
  // FastLED.setMaxPowerInVoltsAndMilliamps( 5, MAX_POWER_MILLIAMPS);   
  FastLED.setBrightness(brigtness);
  FastLED.clear();

}


const uint16_t FibonCilindrTable [] PROGMEM = {  // 45x11

  85, 256, 256, 86, 256, 110, 256, 111, 256, 134, 256, 135, 256, 158, 256, 256, 159, 182, 256, 256, 183, 256, 207, 256, 208, 256, 231, 256, 232, 256, 255, 256, 256, 12, 13, 256, 256, 36, 256, 38, 37, 61, 256, 256, 62,
  256, 88, 87, 108, 109, 256, 112, 132, 133, 256, 136, 156, 157, 256, 161, 160, 181, 256, 185, 184, 205, 206, 256, 209, 229, 230, 256, 233, 256, 254, 256, 10, 11, 14, 256, 34, 35, 256, 39, 256, 60, 256, 64, 63, 84,
  89, 106, 107, 256, 114, 113, 131, 256, 138, 137, 155, 256, 163, 162, 179, 180, 256, 186, 203, 204, 256, 211, 210, 228, 256, 235, 234, 252, 253, 256, 9, 16, 15, 256, 33, 256, 41, 40, 58, 59, 256, 65, 82, 83, 256,
  105, 256, 116, 115, 129, 130, 256, 139, 256, 154, 256, 164, 256, 178, 256, 188, 187, 202, 256, 256, 212, 226, 227, 256, 236, 256, 251, 256, 7, 8, 17, 256, 256, 32, 256, 42, 256, 57, 256, 67, 66, 81, 256, 91, 90,
  256, 117, 256, 128, 256, 256, 140, 152, 153, 256, 165, 256, 177, 256, 189, 256, 201, 256, 214, 213, 225, 256, 256, 237, 249, 250, 256, 6, 256, 18, 256, 30, 31, 256, 43, 256, 56, 256, 68, 256, 80, 256, 92, 256, 104,
  118, 256, 127, 256, 256, 141, 151, 256, 256, 166, 256, 176, 256, 190, 256, 200, 256, 215, 256, 224, 256, 256, 238, 248, 256, 256, 5, 256, 19, 256, 29, 256, 256, 44, 256, 55, 256, 69, 256, 79, 256, 93, 256, 103, 256,
  256, 126, 256, 256, 142, 150, 256, 256, 167, 256, 175, 256, 191, 256, 199, 256, 216, 256, 223, 256, 256, 239, 247, 256, 256, 4, 256, 20, 256, 28, 256, 256, 45, 256, 54, 256, 70, 256, 78, 256, 94, 256, 102, 256, 119,
  125, 256, 256, 143, 149, 256, 256, 168, 256, 174, 256, 192, 256, 198, 256, 217, 256, 222, 256, 256, 240, 246, 256, 256, 3, 256, 21, 256, 27, 256, 256, 46, 256, 53, 256, 71, 256, 77, 256, 95, 256, 101, 256, 120, 256,
  256, 256, 144, 148, 256, 256, 169, 256, 173, 256, 193, 256, 197, 256, 218, 256, 221, 256, 256, 241, 245, 256, 256, 2, 256, 22, 256, 26, 256, 256, 47, 256, 52, 256, 72, 256, 76, 256, 96, 256, 100, 256, 121, 256, 124,
  256, 145, 147, 256, 256, 170, 256, 172, 256, 194, 256, 196, 256, 219, 256, 220, 256, 256, 242, 244, 256, 256, 1, 256, 23, 256, 25, 256, 256, 48, 256, 51, 256, 73, 256, 75, 256, 97, 256, 99, 256, 122, 256, 123, 256,
  146, 256, 256, 256, 256, 256, 171, 256, 256, 256, 195, 256, 256, 256, 256, 256, 256, 243, 256, 256, 256, 0, 256, 24, 256, 256, 256, 256, 49, 256, 50, 256, 256, 256, 74, 256, 256, 256, 98, 256, 256, 256, 256, 256, 256,

};


void loop() {

   EVERY_N_SECONDS( SECONDS_PER_PALETTE ) {   //random change palettes
    CRGB mixColor = CRGB (random_two_shifts (),random_two_shifts (),random_two_shifts ());
    next_Random_Pallete (mixColor);
  }

  EVERY_N_MILLISECONDS(40) {   //blend current palette to next palette
    nblendPaletteTowardPalette( gCurrentPalette, gTargetPalette, 16);
  }

  Spiral(); 
  FastLED.show();
}


//main idea is generate random colors pallete 
//and mix random colors with one another color (color theory)
//this makes harmonic looking pallete vs poor random palette
void next_Random_Pallete (CRGB mixColor) {  
   
  for (int i = 0; i < 16; i++) {
    gTargetPalette[i] = CRGB(0, 0, 0);  
  }

  byte leightFill = random8(8,15); //keep two or more last indexes to total black for nice spiral look 

  for( int i = 0; i < 4; i++) {
    uint32_t randomColor32 = random_two_shifts();  //got 32 bit random number and split it to 3 random 8 bit below 

    byte r = (randomColor32 + mixColor.r)>>1;         //mix two value and divide by 2
    byte g = ((randomColor32>>8) + mixColor.g)>>1;    //same
    byte b = ((randomColor32>>16) + mixColor.b)>>1;   //same
    
    gTargetPalette[i*3] = CRGB (r, g, b);
    gTargetPalette[i*3+1] = CRGB (r, g, b);
    gTargetPalette[i*3+2] = CRGB (r, g, b);
      
  }
  gTargetPalette[12] = 0;
  gTargetPalette[13] = 0;
  gTargetPalette[14] = 0;
  gTargetPalette[15] = 0;

}


//Spiral_____________________________________

void Spiral () {

 uint16_t a=millis()/8;
 float scale = (sin(a/32*PI/180)*18)-6;

 float scale1 =0;
  for (int i = 0; i < NUM_COLS_CILINDR; i++) {
    for (int j = 0; j < NUM_ROWS_CILINDR; j++) {
      uint16_t index = XY_CILINDR(i,j);  
      if (index == lastSafeIndex)  continue;

      CRGB newcolor = ColorFromPalette( gCurrentPalette, (i*255/(NUM_COLS_CILINDR-1)+j*255/(NUM_ROWS_CILINDR-1))+(int)scale1+a+sin16(a)/16384, 255);
      nblend( leds[index], newcolor, 16);
    }
    scale1 += scale;
  }

}


//system procedures_____________________________________

uint16_t XY_CILINDR(byte x, byte y) {     // calculate index in leds from XY coordinates for cilindrical mapping
  uint16_t ledsindex = pgm_read_word (FibonCilindrTable+y*NUM_COLS_CILINDR+x);
return (ledsindex);
}


uint32_t random_two_shifts() {  //found this in https://cdn.hackaday.io/files/10721458687264/bh-badge-animate.c 
  static uint32_t r_z = 362436069, r_w = 521288629;

	r_z = 36969 * (r_z & 65535) + (r_z >> 16);
  r_w = 18000 * (r_w & 65535) + (r_w >> 16);

  return (r_z << 16) + r_w;
}
FPS: 0
Power: 0.00W