 #include <16F876.h>
 #fuses XT,NOWDT,NOPUT,NOPROTECT
 #use delay(clock=4000000)
 #use standard_io(b)
 #include <lcd_portb.c>
/******************************************************************************/
 //Definicion de variables.
 int1 cambio,start,dato_recibido;
 int tiempo,longitud,i,j,command,address;
 int16 word;
 /*****************************************************************************/
 #INT_EXT
 void ext_isr(){
 if(cambio){
 set_timer0(0);
 tiempo=0;
 EXT_INT_EDGE(L_TO_H);
 cambio=1;
 }else{
 tiempo=get_timer0();
 EXT_INT_EDGE(H_TO_L);        
 cambio=0;
 }
 if((tiempo>140) && (tiempo<160)){   //"Start", si está entre 2240 y 2560 us.
 start=1;                        //Flag start activado.
 i=0;                            //contador de bits a 0.
 }
 if(start){
   if((tiempo>27) && (tiempo<55)){  //Entre 432 y 880 us, es cero.
   bit_clear(word,i);
   i++;
   }
   if((tiempo>65) && (tiempo<90)){   //Entre 1040 y 1440 us es uno.
   bit_set(word,i);
   i++;
   }
  }
 if(i==longitud){
 dato_recibido=1;
 EXT_INT_EDGE(H_TO_L);
 start=0;                        //para reiniciar lectura.
 }
}
/******************************************************************************/ 
 //Rutinas de separacion de comando y direccion.
 void take_address(void){
 i=longitud-1;
 address=0;
 for(j=0;j<longitud-7;j++){
   address= address<<1;
   address=address+bit_test(word,i);
   i--;
   }
 }
 
 void take_command(void){
 i=6;
 command=0;
 for(j=0;j<7;j++){
   command=command<<1;
   command=command+bit_test(word,i);
   i--;
   }
}
/******************************************************************************/
void main(){
   port_b_pullups(TRUE);   //Pull-up para RB0
   setup_timer_0(RTCC_INTERNAL | RTCC_DIV_16);    //configuracion del timer0.
   lcd_init();
   ext_int_edge(H_TO_L);                   //En canto de bajada se activa int.
   cambio=0;                                //control de cambio, para que comience a contar.
   longitud=0x0B;
   enable_interrupts(int_ext);               //habilita la interrupcion externa (Rb0).
   if(start){
      while(dato_recibido){
      dato_recibido=0;
      DISABLE_INTERRUPTS(INT_EXT);
      take_address();
      take_command();
      lcd_gotoxy(0,0);
      switch(command){
      case 0: printf(lcd_putc,"\fCanal 1");break;
      case 1: printf(lcd_putc,"\fCanal 2");break;
      case 2: printf(lcd_putc,"\fCanal 3");break;
      case 3: printf(lcd_putc,"\fCanal 4");break;
      case 4: printf(lcd_putc,"\fCanal 5");break;
      case 5: printf(lcd_putc,"\fCanal 6");break;
      case 6: printf(lcd_putc,"\fCanal 7");break;
      case 7: printf(lcd_putc,"\fCanal 8");break;
      case 8: printf(lcd_putc,"\fCanal 9");break;
      case 9: printf(lcd_putc,"\fCanal 0");break;
      case 16: printf(lcd_putc,"\fCanal +");break;
      case 17: printf(lcd_putc,"\fCanal -");break;
      case 18: printf(lcd_putc,"\fVolumen +");break;
      case 19: printf(lcd_putc,"\fVolumen -");break;
      case 20: printf(lcd_putc,"\fSilencio");break;
      case 47: printf(lcd_putc,"\fStandBy");break;
      default: printf(lcd_putc,"\fCom:%3U Adr:%2U",command,address);
      }
      ENABLE_INTERRUPTS(INT_EXT);
      }
   }

}
