// === 32-LED Charlieplex Auto-Cycle (Arduino Nano) ===
// P0..P6 = D2..D8 (through 220Ω each)
#include <Arduino.h>
const uint8_t NODES[7] = {2,3,4,5,6,7,8};
const uint8_t NUM_LEDS = 32;
struct Pair { uint8_t hi, lo; };
// LED map (weeks layout)
const Pair LEDMAP[NUM_LEDS] = {
// Week 1
{1,0},{2,0},{3,0},{4,0},{5,0},{6,0},{0,1},
// Week 2
{2,1},{3,1},{4,1},{5,1},{0,2},{1,2},{3,2},
// Week 3
{4,2},{5,2},{6,2},{0,3},{1,3},{2,3},{4,3},
// Week 4
{5,3},{6,3},{0,4},{1,4},{2,4},{3,4},{5,4},
// Week 5
{6,4},{0,5},{1,5},{2,5}
};
// -------------------- Charlieplex core --------------------
void allHiZ() {
for (uint8_t i=0; i<7; i++) pinMode(NODES[i], INPUT);
}
void pulseOne(uint8_t idx, unsigned int us) {
allHiZ();
auto p = LEDMAP[idx];
pinMode(NODES[p.hi], OUTPUT); digitalWrite(NODES[p.hi], HIGH);
pinMode(NODES[p.lo], OUTPUT); digitalWrite(NODES[p.lo], LOW);
delayMicroseconds(us);
}
// -------------------- Animations --------------------
void playAnimations() {
Serial.println(F(">> Animation Mode <<"));
// 1. Chase forward
for (uint8_t r=0; r<2; r++) {
for (uint8_t i=0; i<NUM_LEDS; i++) pulseOne(i, 800);
}
// 2. Bounce
for (uint8_t r=0; r<2; r++) {
for (int i=0; i<NUM_LEDS; i++) pulseOne(i, 600);
for (int i=NUM_LEDS-1; i>=0; i--) pulseOne(i, 600);
}
// 3. Blink all
for (uint8_t r=0; r<4; r++) {
for (uint8_t i=0; i<NUM_LEDS; i++) pulseOne(i, 700);
delay(150);
}
// 4. Wave (week by week)
for (uint8_t w=0; w<5; w++) {
for (uint8_t d=0; d<7 && w*7+d<NUM_LEDS; d++) {
pulseOne(w*7+d, 1200);
}
}
Serial.println(F(">> Animation Done <<"));
}
// Fancy animation: rainbow comet sweep
void rainbowComet(uint8_t cycles = 2, uint8_t trail = 6, uint8_t wait = 50) {
Serial.println(F(">> Rainbow Comet Animation <<"));
for (uint8_t c = 0; c < cycles; c++) {
for (uint16_t i = 0; i < NUM_LEDS + trail; i++) {
strip.clear();
for (int t = 0; t < trail; t++) {
int pos = i - t;
if (pos >= 0 && pos < NUM_LEDS) {
// Pick a rainbow color for the comet head
uint32_t color = strip.gamma32(strip.ColorHSV((i * 65536L / NUM_LEDS) + (t * 3000)));
// Fade trail (darker further back)
uint8_t fade = 255 - (t * (255 / trail));
uint8_t r = (uint8_t)((color >> 16) & 0xFF) * fade / 255;
uint8_t g = (uint8_t)((color >> 8) & 0xFF) * fade / 255;
uint8_t b = (uint8_t)(color & 0xFF) * fade / 255;
strip.setPixelColor(pos, r, g, b);
}
}
strip.show();
delay(wait);
}
}
Serial.println(F(">> Rainbow Comet Done <<"));
}
// -------------------- Setup & Loop --------------------
void setup() {
allHiZ();
Serial.begin(115200);
while (!Serial) {}
Serial.println(F("\n== Charlieplex Calendar Auto Boot =="));
}
void loop() {
// Cycle through all LEDs one by one
for (uint8_t i=0; i<NUM_LEDS; i++) {
pulseOne(i, 1500); // show one LED
delay(100); // hold for half a second
}
if (nowMs - pressStart > 800 && !longHandled) {
// Long press: show streak + rainbow comet
uint8_t streak = calcStreak(todayIdx);
flashStreak(todayIdx, streak);
rainbowComet(); // << new fun animation
drawCalendar(todayIdx, dim);
longHandled = true;
beep(60);
}
// After finishing all LEDs → play animations
playAnimations();
}
P0 (D2)
P1 (D3)
P2 (D4)
P3 (D5)
P4 (D6)
P5 (D7)
P6 (D8)