// IR Remote - Arduino, ATMega168 // // IR Rcvr (term 1) -----------------> Digital Pin 8 // // Term 2 - GRD // Term 3 - +5 VDC // // copyright, Peter H Anderson, Baltimore, MD, Dec, '07 #include <avr\interrupt.h> #include <avr\io.h> volatile int tmr1_count; // used to count timer 1 interrupts volatile int tmr1_timeout_flag; volatile int tmr1_capture_flag; #define cbi(sfr, bit) (_SFR_BYTE(sfr) &= ~_BV(bit)) #define sbi(sfr, bit) (_SFR_BYTE(sfr) |= _BV(bit)) #define TRUE 1 #define FALSE 0 #define SUCCESS 1 #define FAILURE 0 ISR(TIMER1_OVF_vect) { --tmr1_count; if(tmr1_count == 0) { tmr1_timeout_flag = TRUE; } } ISR(TIMER1_CAPT_vect) { tmr1_capture_flag = TRUE; } void setup() { delay(5000); Serial.begin(9600); pinMode(13, OUTPUT); } void loop() { int code, n; code = fetch_sony_code(5, 4); Serial.println("....."); if (code >=0) { Serial.println(code, DEC); for (n=0; n<code+1; n++) { pinMode(13, OUTPUT); digitalWrite(13, HIGH); delay(200); digitalWrite(13, LOW); delay(200); } } else { Serial.println("Fail"); } delay(2000); } int fetch_sony_code(int num_tries, int time_out_num_secs) { long t[17], us[16]; int n, tries, status; int code = 0x00; // configure timer_1 TCCR1A = B00000000; // Timer1 in normal mode, WGM11 and WGM10 = 0 TCCR1B = B00000011; // WGM13 WGM12 = 0, // CS2, CS1, CS0 = 010 - prescale of 8, periodicity = 1/32 sec // 011 - 64 - 1/4 sec -- 4 us per tick // 100 - 256 - 1 sec -- 16 us per tick // 101 - 1024 - 4 secs cbi(ASSR, AS2); // use external clock for (tries=0; tries<num_tries; tries++) { status = capture(t, 17, time_out_num_secs); if (status == FAILURE) { //continue; } else { calc_differences(t, us, 16); for (n=0; n<16; n++) { Serial.println(us[n]); } if (us[0] < 2000) { return(-1); } for (n=0; n<8; n++) // check all of the odds for about 500 { if ((us[2*n+1] < 400) || (us[2*n+1] > 600)) { return(-1); } } for (n=0; n<8; n++) { if ((us[2*(n+1)] > 400) && (us[2*(n+1)] < 600)) { code &= ~(0x01 << n); } else if ((us[2*(n+1)] > 1000) && (us[2*(n+1)] < 1400)) { code |= (0x01 << n); } else { continue; //return(-1); } } return(code); } } return(-2); } int capture(long t[], int num_transitions, int time_out_num_secs) { int n, transition; tmr1_count = 0; TCNT1 = 0x0000; tmr1_timeout_flag = FALSE; tmr1_count = time_out_num_secs * 16; transition = 0; cbi(TCCR1B, ICES1); tmr1_capture_flag = FALSE; sbi(TIMSK1, TOIE1); // timer overflow sbi(TIMSK1, ICIE1); // input capture interrupt only sei(); for (n=0; n<num_transitions; n++) { while(1) { if (tmr1_timeout_flag) // more than 4 secs elapsed { // turn off interrupts and return failure cbi(TIMSK1, TOIE1); // timer overflow cbi(TIMSK1, ICIE1); // input capture interrupt only return(FAILURE); } if (tmr1_capture_flag == TRUE) { tmr1_capture_flag = FALSE; t[n] = ICR1; transition = !transition; if (transition) { sbi(TCCR1B, ICES1); } else { cbi(TCCR1B, ICES1); } break; } } } // turn off ints and return success cbi(TIMSK1, TOIE1); // timer overflow cbi(TIMSK1, ICIE1); // input capture interrupt only return(SUCCESS); } void calc_differences(long a[], long diffs[], int num) { int n; for (n=0; n<num; n++) { diffs[n] = a[n+1] - a[n]; if (diffs[n] < 0) { diffs[n] = 65536 + diffs[n]; } diffs[n] = 4 * diffs[n]; // 4 us per tick } } void print_registers(void) { // For debugging. Serial.println(); Serial.print("TCCR1A "); Serial.println(TCCR1A, HEX); Serial.print("TCCR1B "); Serial.println(TCCR1B, HEX); Serial.print("TIMSK1 "); Serial.println(TIMSK1, HEX); }