#include <16F648A.h>
#use delay(clock=20000000)
#fuses NOWDT,HS, PUT, NOPROTECT, BROWNOUT, MCLR, NOLVP, NOCPD
#use rs232(baud=9600,parity=N,xmit=PIN_B2,rcv=PIN_B1,bits=8)
int1 get_RC5(void);

#define IR_INPUT PIN_B0         // the infrared receiver has to be connected to an
                                // interrupt-pin!
#define IR_STATUS (!input(IR_INPUT))  // invert the signal from the infrared receiver
typedef struct
{
int8 data[2];
int8 state;
} rc5_struct;
rc5_struct rc5;

#int_EXT
void EXT_isr(void)
{ 
   get_RC5();
}

int1 get_RC5(void)
{
   int16 tmp,t;
   int i;
   int1 inp;
   set_timer1(0);
   while(IR_STATUS==1);
   t=get_timer1();
   if ((t<400) || (t>800)) return 0;   // no RC5 code, abort decoding

   for (i=0;i<13;i++)
   {
      inp=IR_STATUS;
      set_timer1(0);
      while (IR_STATUS==inp)
      {
         t=get_timer1();
         if (t>800) return 0;   // no RC5 code, abort decoding
      }
      tmp<<=1;
      if (inp==0) tmp++;
      set_timer1(0);
      while (get_timer1()<776);  // a simple delay would work here as well
   }
   tmp=tmp | 0x3000;
   tmp=tmp & 0x37ff; // cut off togglebit
   rc5.data[0]=tmp & 0xff;  // device address
   tmp>>=8;
   rc5.data[1]=tmp & 0xff;  // command code
   rc5.state = 1;
   disable_interrupts(INT_EXT);
   return 1;
}
void main()
{
   setup_timer_0(RTCC_INTERNAL|RTCC_DIV_1);
   setup_timer_1(T1_INTERNAL|T1_DIV_BY_8);
   setup_timer_2(T2_DISABLED,0,1);
   setup_comparator(NC_NC_NC_NC);
   setup_vref(FALSE);
   enable_interrupts(INT_EXT);
   enable_interrupts(GLOBAL);
   rc5.state = 0;
printf("Device: %u\n", rc5.data[0]);    // display device address
   while(true)
   {
      if(rc5.state==1)  // did we receive a valid RC5 - command?
      {
        printf("Device: %u\n", rc5.data[0]);    // display device address
        printf("Command: %u\n", rc5.data[1]);     // display command code
         rc5.state = 0;
         enable_interrupts(INT_EXT);
      }
   }
}
