//source: https://editor.soulmatelights.com/gallery/1479-2dd-pr-centering

#include "FastLED.h"
#define DATA_PIN 2
#define BRIGHTNESS 255
#define NUM_LEDS 256
#define COLS 16
#define ROWS 16
#define LED_TYPE    WS2812B
#define COLOR_ORDER GRB
CRGB leds[NUM_LEDS];
//#define FRAMES_PER_SECOND 60
const uint8_t kMatrixWidth = 16;
const uint8_t kMatrixHeight = 16;

const bool    kMatrixSerpentineLayout = false;

uint8_t ZVoffset = 0;
uint32_t effTimer;
#define COLS_HALF  COLS/2
#define ROWS_HALF  ROWS/2
#define radius COLS_HALF

int16_t ZVcalcRadius(int16_t x, int16_t y) {
  x *= x;
  y *= y;
  int16_t radi = sin8(x + y);
  return radi;
}

int16_t ZVcalcDist(uint8_t x, uint8_t y, float center_x, float center_y) {
  int16_t a = (center_y - y - .5);
  int16_t b = (center_x - x - .5);
  int16_t dist = ZVcalcRadius(a, b);
  return dist;
}


void setup() {
  FastLED.addLeds<LED_TYPE,DATA_PIN,COLOR_ORDER>(leds, NUM_LEDS); //setCorrection(TypicalLEDStrip);
  //FastLED.addLeds<LED_TYPE,DATA_PIN,CLK_PIN,COLOR_ORDER>(leds, NUM_LEDS).setCorrection(TypicalLEDStrip);
  FastLED.setBrightness(BRIGHTNESS);
 //Serial.begin(115200);
}

void loop() 
{
  effTimer =sin8(millis()/6000)/10;
  EVERY_N_MILLISECONDS(1) {
    ZVoffset += 6;
  }
  
  for (int x = 0; x < COLS; x++) {
    for (int y = 0; y < ROWS; y++) {
      int dist = ZVcalcDist(x, y, COLS_HALF, ROWS_HALF);
      
      // exclude outside of circle
      int brightness = 1;
      if (dist += radius) {
        brightness = map(dist, -effTimer,radius, 255, 110);
        brightness += ZVoffset;
        brightness = sin8(brightness);
      }
      
      int index = XY(x, y);
      int hue = map(dist, radius,-3,  125, 255);
      leds[index] = CHSV(hue, 255, brightness);
    }
  }

      FastLED.show();

}

uint16_t XY( uint8_t x, uint8_t y)
{
  uint16_t i;
  if( kMatrixSerpentineLayout == false) {
    i = (y * kMatrixWidth) + x;
  }
  if( kMatrixSerpentineLayout == true) {
    if( y & 0x01) {
      // Odd rows run backwards
      uint8_t reverseX = (kMatrixWidth - 1) - x;
      i = (y * kMatrixWidth) + reverseX;
    } else {
      // Even rows run forwards
      i = (y * kMatrixWidth) + x;
    }
  }
  return i;
}