/*
  Derived from the "less intellectually satisfying"
  12-pin 72-LED charlieplexed layout from:
  https://www.clock-it.net/charlieplexing-led-clocks/
*/

#include <RTClib.h>
#include <TimerOne.h>

RTC_DS1307 rtc;

const byte pins[] = {2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13};
const byte anodes[] = {9, 0, 1, 2, 3, 4, 0, 1, 2, 3, 4, 0, 1, 2, 3, 4, 0, 1, 2, 3, 4, 0, 1, 2, 3, 4, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 5, 6, 7, 8, 9, 5, 6, 7, 8, 9, 5, 6, 7, 8, 9, 5, 6, 7, 8, 9, 5, 6, 7, 8, 11, 11, 11, 11, 11, 11, 10, 10, 10, 10, 10, 10};
const byte cathodes[] = {0, 10, 10, 10, 10, 10, 9, 9, 9, 9, 9, 8, 8, 8, 8, 8, 7, 7, 7, 7, 7, 6, 6, 6, 6, 6, 5, 5, 5, 5, 5, 11, 11, 11, 11, 11, 4, 4, 4, 4, 4, 3, 3, 3, 3, 3, 2, 2, 2, 2, 2, 1, 1, 1, 1, 1, 0, 0, 0, 0, 10, 9, 8, 7, 6, 5, 5, 4, 3, 2, 1, 0};

volatile byte hour = 0;
volatile byte minute = 0;
volatile byte second = 0;

void charlieplex() {
  static byte ledno = 0;
  static byte anode = pins[0];
  static byte cathode = pins[0];
  pinMode(anode, INPUT);
  pinMode(cathode, INPUT);
  switch (ledno) {
    case 0:
      anode = pins[anodes[60 + hour]];
      cathode = pins[cathodes[60 + hour]];
      break;
    case 1:
      anode = pins[anodes[minute]];
      cathode = pins[cathodes[minute]];
      break;
    case 2:
      anode = pins[anodes[second]];
      cathode = pins[cathodes[second]];
      break;
  }
  pinMode(cathode, OUTPUT);
  pinMode(anode, OUTPUT);
  digitalWrite(cathode, LOW);
  digitalWrite(anode, HIGH);
  ledno = (ledno + 1) % 3;
}

void setup() {
  for (byte pin = 0; pin < sizeof(pins); pin++)
    pinMode(pins[pin], INPUT);
  rtc.begin();
  Timer1.initialize(33333); // 10Hz refresh for low CPU usage in Wokwi
  // Timer1.initialize(333); // 1kHz refresh for reduced flicker on real hardware
  Timer1.attachInterrupt(charlieplex);
}

void loop() {
  DateTime now = rtc.now();
  hour = now.hour() % 12;
  minute = now.minute() % 60;
  second = now.second() % 60;
  delay(100);
}
GND5VSDASCLSQWRTCDS1307+