//240 LED ring cilindrical map swirl
//Fastled rgb led demo
//Yaroslaw Turbin, 02.02.2021
//https://vk.com/ldirko
//https://www.reddit.com/user/ldirko/
//https://twitter.com/ldir_ko

//https://wokwi.com/arduino/projects/289422434310816264

#include <FastLED.h>

#define LED_PIN     3
#define NUM_COLS    60
#define NUM_ROWS    8
#define NUM_LEDS    240
#define LED_TYPE    WS2812
#define COLOR_ORDER GRB
CRGB leds[241];
CRGB ledsbuff [NUM_COLS * NUM_ROWS];


void setup() {
  FastLED.addLeds<LED_TYPE, LED_PIN, COLOR_ORDER>(leds, NUM_LEDS);
}

void loop() {
  static int speed;
  EVERY_N_MILLISECONDS(150) {
    speed++;
  }; //80 - speed of effect
  EVERY_N_MILLISECONDS(80) {  //80 - speed of effect
    fadeToBlackBy(ledsbuff, 480, 120);

    for (byte i = 0; i < 60; i += 10) {

      byte hue = 180 + random8(15);
      randomWalk((i + speed) % 60, 0, hue);

      byte ind = i + random8(3);
      hue = 200 + random8(10);
      if (ledsbuff[XY(ind, 3)]) randomWalk((ind + speed) % 60, 3, hue);

      ind = i - random8(4);
      hue = 200 + random8(10);
      if (ledsbuff[XY(ind, 4)]) randomWalk((ind + speed) % 60, 4, hue);

    }
    blur2d (ledsbuff, NUM_COLS, NUM_ROWS, 48);
  }

  ledsbuff_to_buff();
  LEDS.show();
}

void ledsbuff_to_buff() {
  int indexbuff = 0;
  for (byte j = 0; j < NUM_ROWS; j++) {
    for (byte i = 0; i < NUM_COLS; i++) {
      byte index = XY_cilindrical(i, j);
      if (index != 241) leds [index] = ledsbuff[indexbuff];
      indexbuff++;
    }
  }
}

void randomWalk (int  x, byte y, byte hue) {
  int a = millis();
  for (byte i = y; i < NUM_ROWS; i++) {
    byte xoffset = sin8(i * 160 + a) / 125;

    if ( random8(2)) ledsbuff[XY(x += xoffset, i)] += (i>0) ? CHSV(hue,255-i*32,255) : CHSV(0,100,255);
    else ledsbuff[XY(x -= xoffset, i)] += (i>0) ? CHSV(hue,255-i*32,255) : CHSV(0,255,255);
  }
}

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

uint16_t XY(uint8_t x, uint8_t y) {
  if (x >= NUM_COLS) x = NUM_COLS - 1;
  if (y >= NUM_ROWS) y = NUM_ROWS - 1;
  return y * NUM_COLS + x;
}