//https://editor.soulmatelights.com/gallery/843-squares-and-dots

//fix overflow in XY function

#include <FastLED.h>

#define LED_PIN  3

#define COLOR_ORDER GRB
#define CHIPSET     WS2811
#define BRIGHTNESS 255

// Params for width and height
const uint8_t kMatrixWidth = 26;
const uint8_t kMatrixHeight = 11;

// Param for different pixel layouts
const bool    kMatrixSerpentineLayout = true;
// Set 'kMatrixSerpentineLayout' to false if your pixels are
// laid out all running the same way, like this:

#define NUM_LEDS (kMatrixWidth * kMatrixHeight)
#define safety_pixel NUM_LEDS + 1

CRGB leds_plus_safety_pixel[ NUM_LEDS + 1];
CRGB* const leds( leds_plus_safety_pixel);

const byte sprites[2][3][3] = {1,1,1,1,0,1,1,1,1,0,0,0,0,1,0,0,0,0,};



void setup() {
  FastLED.addLeds<CHIPSET, LED_PIN, COLOR_ORDER>(leds, NUM_LEDS).setCorrection(TypicalSMD5050);
  FastLED.setBrightness( BRIGHTNESS );
}

// Demo that USES "XY" follows code below

void loop(){
  static uint8_t initscreen = 1; 
  if (initscreen) { initSCR(); initscreen = 0; } //run once
  
  EVERY_N_MILLISECONDS(300) {
    printSpr((random8(kMatrixWidth) % (kMatrixWidth / 3 + 1)) * 3, (random8(kMatrixHeight) % (kMatrixHeight / 3 + 1)) * 3, random8(2));
  } 

  FastLED.show();
}


void printSpr(byte x, byte y, byte numSpr) {
  byte hue = random8();

  byte y1 = y;
  for (int j = 0; j < 3; j++) {
    byte x1 = x;

    for (int i = 0; i < 3; i++) {
      uint16_t index = XY(x1, y1);
      if (sprites[numSpr][i][j]) leds[index].setHue(hue);
      else leds[index] = 0;
      x1++;
    }

    y1++;
  }
}

void initSCR() {
  for (byte x = 0; x < kMatrixWidth / 3+1 ; x++) {
    for (byte y = 0; y < kMatrixHeight / 3+1; y++) {
      printSpr(x * 3, y * 3, random8(2));
    }
  }
}


uint16_t XY( uint8_t x, uint8_t y)
{ 
  uint16_t i;

  if (x>=kMatrixWidth || y>=kMatrixHeight)  return safety_pixel;
  
  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;
}