/* ATtiny84 IR Remote Control Tool v3 David Johnson-Davies - www.technoblogy.com - 9th February 2018 ATtiny84 @ 8 MHz (internal oscillator; BOD disabled) CC BY 4.0 Licensed under a Creative Commons Attribution 4.0 International license: http://creativecommons.org/licenses/by/4.0/ */ // Seven-segment definitions const int charArrayLen = 18; char charArray[] = { // ABCDEFG Segments 0b1111110, // 0 0b0110000, // 1 0b1101101, // 2 0b1111001, // 3 0b0110011, // 4 0b1011011, // 5 0b1011111, // 6 0b1110000, // 7 0b1111111, // 8 0b1111011, // 9 0b1110111, // 10 "A" 0b0011111, // 11 "B" 0b1001110, // 12 "C" 0b0111101, // 13 "D" 0b1001111, // 14 "E" 0b1000111, // 15 "F" 0b0000000, // 16 Space 0b0000001 // 17 '-' }; const int Dash = 17; const int Space = 16; const int ndigits = 3; volatile int Buffer[] = {Dash, Dash, Dash}; char dp = -1; // Decimal point position 0 to 3 int digit = 0; // Pin assignments char Digits[] = {PIN_B2, PIN_B1, PIN_B0}; // Segments must all go to port A; this specifies how they're wired up: // g f e d c b a char Segments[] = {1, 7, 5, 4, 3, 6, 2}; const int dpSeg = PIN_B0; const int IRin = PIN_A0; const int Button = PIN_A0; const int IRout = PIN_A6; // Display multiplexer ********************************************** void ReorderBits() { char segs, newsegs; for (int i=0; i> 1; } charArray[i]=newsegs; } } void DisplayNextDigit() { pinMode(Digits[digit], INPUT); digit = (digit+1) % ndigits; char segs = charArray[Buffer[digit]]; // Display decimal point? if (digit == dp) { pinMode(dpSeg, OUTPUT); digitalWrite(dpSeg, LOW); } else pinMode(dpSeg, INPUT); DDRA = 0; // All inputs // Set display segments segs = segs & 0xFE; PORTA = ~segs; // 1 = high DDRA = segs; // 1 = output except PA0 pinMode(Digits[digit], OUTPUT); digitalWrite(Digits[digit], HIGH); } // Display a three-digit hexadecimal number void DisplayHex(int n) { for (int d=0; d<3; d++) { Buffer[d]=((n>>((2-d)*4)) & 0x0F); } } // Display characters void Display (char c) { for (int d=0; d<3; d++) Buffer[d]=c; } // Set up Timer/Counter1 to multiplex the display void SetupDisplay () { TCCR1A = 0< 1718) return 0; // Bottle out } while (digitalRead(IRin) == state); } while (1); } // IR transmitter ********************************************** const int top = 221; // 8000000/222 = 36kHz const int match = 165; // pulses with 25% mark/space ratio // Set up Timer/Counter1 to output PCM on OC1A void SetupPCM () { TCCR1A = 3<>(13-b) & 1; for (char i=0; i<2; i++) { if (nextbit) OCR1A = top; else OCR1A = match; // Wait for 32 Timer/Counter1 overflows for (int c=0; c<32; c++) { while ((TIFR1 & 1) == 0); TIFR1 = 1; } nextbit = !nextbit; } } } // Setup ********************************************** void setup() { ReorderBits(); } void loop() { int rccode, code; // Display mode rccode = 0; do { SetupDisplay(); do { if (rccode) DisplayHex(rccode & 0x7ff); else Display(Dash); if (rccode & 0x800) dp = 0; else dp=-1; code = ReadRC5(); if (code) rccode = code; } while (code != 0); // Pressed button - send IR code TIMSK1 = 0<