// 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);   
}     
Sign up for a free RoboForex demo forex trading with $50k in virtual money.