/*
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);
}