June 12, 2026
// --- PIN DEFINITIONS ---
const int irPin = 4; // PB4 (Physical Pin 3)
const int led1 = 0; // PB0 (Physical Pin 5)
const int led2 = 1; // PB1 (Physical Pin 6)
const int led3 = 2; // PB2 (Physical Pin 7)
// --- LED STATE VARIABLES ---
unsigned long lastLedUpdate = 0;
const unsigned long ledInterval = 40; // 40ms (0.04s) gap between LED stages
uint8_t currentLed = 0;
void setup() {
pinMode(irPin, OUTPUT);
pinMode(led1, OUTPUT);
pinMode(led2, OUTPUT);
pinMode(led3, OUTPUT);
}
// --- NON-BLOCKING LED ANIMATION ---
void updateLEDs() {
unsigned long currentMillis = millis();
// Check if 40ms have passed since the last update
if (currentMillis - lastLedUpdate >= ledInterval) {
lastLedUpdate = currentMillis;
// Turn all LEDs off first
digitalWrite(led1, LOW);
digitalWrite(led2, LOW);
digitalWrite(led3, LOW);
// Light the current LED in the sequence
if (currentLed == 0) digitalWrite(led1, HIGH);
else if (currentLed == 1) digitalWrite(led2, HIGH);
else if (currentLed == 2) digitalWrite(led3, HIGH);
// Advance to the next LED, looping back to 0 after 2
currentLed++;
if (currentLed > 2) currentLed = 0;
}
}
// --- SMART DELAY ---
// Replaces standard delay() so the LEDs keep animating during the gaps
void smartDelay(unsigned long ms) {
unsigned long start = millis();
while (millis() - start < ms) {
updateLEDs();
}
}
// --- IR CARRIER LOGIC ---
void mark(uint32_t time) {
TCCR1 = _BV(CTC1) | _BV(CS10);
GTCCR = _BV(PWM1B) | _BV(COM1B1);
OCR1C = 210;
OCR1B = 105;
customDelay(time);
}
void space(uint32_t time) {
TCCR1 = 0;
GTCCR = 0;
digitalWrite(irPin, LOW);
customDelay(time);
}
void customDelay(uint32_t us) {
while (us > 15000) {
delayMicroseconds(15000);
us -= 15000;
}
delayMicroseconds(us);
}
// --- MAIN LOOP ---
void loop() {
// Reset the LED sequence for a fresh run
currentLed = 0;
lastLedUpdate = millis();
for (uint8_t i = 0; i < totalCodes; i++) {
const uint8_t* currentCode = (const uint8_t*)pgm_read_word(&(allCodes[i]));
uint8_t len = codeLengths[i];
uint16_t baseUnit = baseUnits[i];
for (uint8_t rep = 0; rep < 2; rep++) {
for (uint8_t j = 0; j < len; j++) {
// Update the LED animation between every single bit transmission
updateLEDs();
uint8_t multiplier = pgm_read_byte(¤tCode[j]);
uint32_t duration = (uint32_t)multiplier * baseUnit;
if (j % 2 == 0) mark(duration);
else space(duration);
}
space(0);
// Keep LEDs animating during the 150ms intra-code gap
smartDelay(150);
}
// Keep LEDs animating during the 100ms inter-code gap
smartDelay(100);
}
// --- END OF CYCLE BEHAVIOR ---
// Turn all three LEDs on simultaneously
digitalWrite(led1, HIGH);
digitalWrite(led2, HIGH);
digitalWrite(led3, HIGH);
// Hold them on for exactly 1 second (standard delay is fine here
// since we explicitly want the animation paused while they are all lit)
delay(1000);
// Loop automatically restarts from the top, immediately resuming IR and sequential LEDs
}