/*
  SquareSwirl
  FasLED "2-D blur" demo on 16x16 matrix
  by Mark Kriegsman
  https://gist.github.com/kriegsman
*/
#include <FastLED.h>

#define LED_PIN  3
#define LED_TYPE WS2811
#define COLOR_ORDER GRB

const uint8_t kSquareWidth = 16;
const uint8_t kBorderWidth = 2;

#define NUM_LEDS (kSquareWidth * kSquareWidth)

CRGB leds[NUM_LEDS];

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

void loop()
{
  // Apply some blurring to whatever's already on the matrix
  // Note that we never actually clear the matrix, we just constantly
  // blur it repeatedly.  Since the blurring is 'lossy', there's
  // an automatic trend toward black -- by design.
  uint8_t blurAmount = beatsin8(2, 10, 255);

  blur2d( leds, kSquareWidth, kSquareWidth, blurAmount);

  // Use two out-of-sync sine waves
  uint8_t  i = beatsin8( 91, kBorderWidth, kSquareWidth - kBorderWidth);
  uint8_t  j = beatsin8(109, kBorderWidth, kSquareWidth - kBorderWidth);

  // Also calculate some reflections
  uint8_t ni = (kSquareWidth - 1) - i;
  uint8_t nj = (kSquareWidth - 1) - j;

  // The color of each point shifts over time, each at a different speed.
  uint16_t ms = millis();

  leds[XY( i, j)] += CHSV(ms / 11, 200, 255);
  leds[XY( j, i)] += CHSV(ms / 13, 200, 255);
  leds[XY(ni, nj)] += CHSV(ms / 17, 200, 255);
  leds[XY(nj, ni)] += CHSV(ms / 29, 200, 255);
  leds[XY( i, nj)] += CHSV(ms / 37, 200, 255);
  leds[XY(ni, j)] += CHSV(ms / 41, 200, 255);

  FastLED.show();
}

// Trivial XY function for the 8x8 grid; use a different XY
// function for different matrix grids.  See XYMatrix example for code.
uint16_t XY( uint8_t x, uint8_t y) {
  return (y * kSquareWidth) + x;
}