/* ATtiny84 IR Remote Control Tool (NEC) David Johnson-Davies - www.technoblogy.com - 25th March 2015 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 char Buffer[] = {Dash, Dash, Dash}; char dp = -1; // Decimal point position 0 to 3 char 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< 4950) return 0; // Bottle out } while (digitalRead(IRin) == LOW); WaitWhile(HIGH); // Wait for end of space // Read address and command for (char i=0; i<2; i++) { address = data; mask = 1; data = 0; do { start = TCNT1; WaitWhile(LOW); WaitWhile(HIGH); if (microsecs(start) > 1680) data = data | mask; mask = mask << 1; } while (mask); } command = data; return address<<16 | (command & 0xFFFF); } // IR transmitter ********************************************** const int top = 209; // 8000000/210 = 38kHz const int match = 156; // pulses with 25% mark/space ratio // Set up Timer/Counter1 to output PCM on OC1A void SetupPCM () { TCCR1A = 3<> 16) & 0xFFFF; TCNT1 = 0; // Start counting from 0 // Send AGC tone Pulse(342, 171); data = address; for (char i=0; i<2; i++) { mask = 1; do { if (data & mask) Pulse(21, 64); else Pulse(21, 21); mask = mask << 1; } while (mask); data = command; } Pulse(21, 0); } // Setup ********************************************** void setup() { ReorderBits(); } void loop() { long rccode, code; // Display mode rccode = 0; do { SetupDisplay(); do { if (rccode) { DisplayHex(rccode>>24 & 0x0FF); delay(500); DisplayHex(rccode>>12 & 0xFFF); delay(500); DisplayHex(rccode & 0xFFF); delay(500); } code = ReadNEC(); if (code) rccode = code; } while (code != 0); // Pressed button - send IR code TIMSK1 = 0<