// 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);
}