#include <FastLED.h>
// #include <DS3232RTC.h>    // for normal Arduino project
#include "DS3232RTC.h"       // for Wokwi simulation

#define NUM_LEDS 288
#define DATA_PIN 6
#define BRIGHTNESS 255      // more brightness is better for wokwi, was 50

CRGB leds[NUM_LEDS];
#define columns 24
#define rows 12

DS3232RTC myRTC(false);
tmElements_t tm;

uint8_t col;
uint8_t row;
int r;
uint8_t number = 0;
uint8_t xpos = 1;  //x=column
uint8_t ypos = 1;  //y=row
uint8_t hr10;
uint8_t hr1;
uint8_t min10;
uint8_t min1;

const uint8_t digits[10][35] = {
  { 14, 26, 38, 50, 3, 15, 51, 63, 4, 40, 64, 5, 29, 41, 65, 6, 42, 66, 7, 31, 67, 8, 32, 44, 68, 9, 33, 69, 10, 70, 23, 35, 47, 59 },
  { 26, 38, 50, 15, 51, 4, 52, 5, 17, 29, 53, 18, 54, 19, 55, 20, 56, 9, 21, 57, 69, 10, 70, 11, 23, 35, 47, 59, 71 },
  { 14, 26, 38, 50, 3, 63, 4, 16, 28, 64, 29, 65, 18, 54, 7, 43, 8, 32, 44, 56, 68, 9, 69, 10, 70, 11, 23, 35, 47, 59 },
  { 14, 26, 38, 50, 3, 63, 4, 16, 28, 64, 29, 65, 18, 54, 19, 55, 8, 20, 32, 68, 9, 69, 10, 70, 23, 35, 47, 59 },
  { 26, 38, 50, 27, 51, 16, 52, 17, 53, 6, 42, 66, 7, 67, 8, 20, 32, 44, 68, 45, 69, 46, 70, 47, 59, 71 },
  { 2, 14, 26, 38, 50, 62, 3, 63, 4, 64, 5, 29, 41, 53, 6, 42, 19, 55, 32, 68, 9, 21, 33, 69, 10, 70, 23, 35, 47, 59 },
  { 26, 38, 50, 62, 15, 63, 16, 52, 64, 5, 41, 6, 42, 54, 7, 67, 8, 32, 68, 9, 33, 45, 69, 10, 70, 23, 35, 47, 59 },
  { 2, 14, 26, 38, 50, 62, 3, 63, 4, 16, 28, 40, 64, 41, 65, 42, 66, 31, 67, 32, 56, 21, 57, 22, 46, 23, 35, 47 },
  { 14, 26, 38, 50, 3, 63, 4, 28, 40, 64, 5, 41, 65, 18, 54, 7, 67, 8, 32, 44, 68, 9, 45, 69, 10, 70, 23, 35, 47, 59 },
  { 14, 26, 38, 50, 3, 63, 4, 28, 40, 64, 5, 41, 65, 6, 66, 19, 31, 67, 32, 68, 9, 21, 57, 10, 58, 11, 23, 35, 47 }
};

void setup() {
  Serial.begin(9600);
  FastLED.addLeds<WS2812B, DATA_PIN, GRB>(leds, NUM_LEDS);
  FastLED.setBrightness(BRIGHTNESS);
  FastLED.clear();
  delay(500);
}

void loop() {
  delay(100);
  FastLED.show();
  FastLED.clear();
  RTC.read(tm);
  displaytime();
  flashborder();
}

void displaytime() {
  hr10 = tm.Hour / 10;
  hr1 = tm.Hour % 10;
  min10 = tm.Minute / 10;
  min1 = tm.Minute % 10;
  Displaynumber(hr10, 1, 1);
  Displaynumber(hr1, 7, 1);
  Displaynumber(min10, 13, 1);
  Displaynumber(min1, 19, 1);
  if (xpos >= columns) 
    xpos = 0;
  if (ypos > rows) 
    ypos = 0;
}

void Displaynumber(uint8_t number, uint8_t xpos, uint8_t ypos) {
  for (uint8_t i = 0; i < 35; i++) {
    uint8_t pixelnumber = digits[number][i];
    if (pixelnumber == 0) 
      return 32767;
    uint8_t x = (pixelnumber / 12) + xpos;
    uint8_t y = ((pixelnumber - 1) % 12) + ypos;
    if (x > columns) 
      x = x - columns;
    if (y > rows) 
      y = y - rows;
    r = { calcLEDposition(x, y) };
    leds[r] += CHSV(number * 25 + xpos * 5, 255, 255);
  }
}

void flashborder() {
  if (tm.Second % 2 == 0) {
    leds[276] = CRGB::White;
    leds[287] = CRGB::White;
    leds[11] = CRGB::White;
    leds[0] = CRGB::White;
  }
}

int calcLEDposition(uint8_t col, uint8_t row) {  //Calculate the position of the LED to light up. column & row 0 are not displayed, 'overscan'areas! This is used to hide away artefacts at position 0,0 which I got otherwise
  if (row == 0 || col == 0) {
    return 32767;
  }
  if (col % 2 == 0) {
    int r = (300 - ((col * 12) + row));
    return r;
  } else {
    int r = (300 - ((col * 12) + (13 - row)));
    return r;
  }
}
GND5VSDASCLSQWRTCDS1307+