Initial Arduino Code for IR Transmission


May 1, 2026


#include <avr/pgmspace.h>

// Define each code as a separate array in PROGMEM
const uint16_t c0[] PROGMEM = {3456, 1728, 432, 432, 432, 1296, 432, 432, 432, 432, 432, 432, 432, 432, 432, 432, 432, 432, 432, 432, 432, 432, 432, 432, 432, 432, 432, 432, 432, 1296, 432, 432, 432, 432, 432, 432, 432, 432, 432, 432, 432, 432, 432, 432, 432, 432, 432, 432, 432, 1296, 432, 432, 432, 432, 432, 432, 432, 432, 432, 432, 432, 432, 432, 432, 432, 432, 432, 1296, 432, 432, 432, 1296, 432, 1296, 432, 1296, 432, 1296, 432, 432, 432, 432, 432, 1296, 432, 432, 432, 1296, 432, 1296, 432, 1296, 432, 1296, 432, 432, 432, 1296, 432, 74736};
const uint16_t c1[] PROGMEM = {3680, 3680, 460, 1840, 460, 1840, 460, 1840, 460, 1840, 460, 920, 460, 920, 460, 1840, 460, 920, 460, 1840, 460, 920, 460, 1840, 460, 920, 460, 920, 460, 920, 460, 920, 460, 920, 460, 1840, 460, 1840, 460, 920, 460, 1840, 460, 920, 460, 1840, 460, 920, 460, 1840, 460, 6900};
const uint16_t c2[] PROGMEM = {3680, 3680, 460, 1840, 460, 1840, 460, 1840, 460, 1840, 460, 920, 460, 920, 460, 1840, 460, 1840, 460, 1840, 460, 920, 460, 1840, 460, 920, 460, 920, 460, 920, 460, 920, 460, 920, 460, 1840, 460, 1840, 460, 920, 460, 920, 460, 920, 460, 1840, 460, 920, 460, 1840, 460, 6900};
const uint16_t c3[] PROGMEM = {9024, 4512, 564, 1692, 564, 1692, 564, 1692, 564, 564, 564, 564, 564, 564, 564, 564, 564, 564, 564, 1692, 564, 1692, 564, 1692, 564, 564, 564, 564, 564, 564, 564, 564, 564, 564, 564, 564, 564, 1692, 564, 564, 564, 564, 564, 564, 564, 564, 564, 564, 564, 564, 564, 1692, 564, 564, 564, 1692, 564, 1692, 564, 1692, 564, 1692, 564, 1692, 564, 1692, 564, 43992};

// A master table of all codes and their lengths
const uint16_t* const allCodes[] PROGMEM = {c0, c1, c2, c3};
const uint8_t codeLengths[] = {99, 52, 52, 68}; // Number of values in each array
const uint8_t totalCodes = 4;

void setup() {
  pinMode(1, OUTPUT); // PB1 (Physical Pin 6)
}

void mark(uint16_t time) {
  // 38kHz carrier logic for 8MHz ATtiny85
  TCCR1 = _BV(CTC1) | _BV(PWM1A) | _BV(COM1A0) | _BV(CS10);
  OCR1C = 104; // (8,000,000 / 38,000 / 2) - 1 approx 104
  customDelay(time);
}

void space(uint16_t time) {
  TCCR1 = 0; // Turn off carrier
  digitalWrite(1, LOW);
  customDelay(time);
}

// Handles durations longer than 16383us which delayMicroseconds fails at
void customDelay(uint16_t us) {
  while (us > 15000) {
    delayMicroseconds(15000);
    us -= 15000;
  }
  delayMicroseconds(us);
}

void loop() {
  for (uint8_t i = 0; i < totalCodes; i++) {
    // Get pointer to the current code array from PROGMEM
    uint16_t* currentCode = (uint16_t*)pgm_read_word(&(allCodes[i]));
    uint8_t len = codeLengths[i];

    for (uint8_t j = 0; j < len; j++) {
      uint16_t duration = pgm_read_word(&currentCode[j]);
      if (j % 2 == 0) mark(duration); // Even = Pulse
      else space(duration);           // Odd = Gap
    }
    
    space(0); // Ensure off
    delay(200); // 200ms gap between different TV codes
  }
  
  delay(10000); // Wait 10 seconds before starting the whole list again
}