PIC Specific RS232 / IR routine

for Sony and the code for 16F84@4MHz written with CC5XFree 
follows. see if u can figure it :-) 
//=============cut--here================================= 
/* 
 * IR reception 
 * 05/Sep/1999 JLS & CAE 
 * jls at certi.ufsc.br 
 * cae at certi.ufsc.br 
 * CC5xFree v3.0E (www.bknd.com) 
 */ 

/* 
  Sony Data format: 12 bits 

  Bit zero: 

  400 
  +--+   +... 
  |  |   | 
  +  +---+ 
      800 

  Bit one: 

  400 
  +--+      +... 
  |  |      | 
  +  +------+ 
       1400 

  Frame: 
               400    400 
  --+          +--+   +--+      +--+ 
    |          |  |   |  |      |  | 
    +---2600---+  +---+  +------+  +... 
                   800     1400 

  Decoding algorithm: 
  - Detect 2600us pulse, 
  - measure next high pulse as P1 (400us) 
  - measure next low  pulse as P2 (800/1400us) 
  - store min(P1) 
  - store max(P2) 
  After all measurements: 
  - calculate mean = (max-min)/2 + min 
  - For all (P1,P2) measured: 
    . Add P1+P2=P3 
    . If P3< mean => bit is zero 
    . If P3>=mean => bit is one 

  Measures with Timer0 & Prescaler:16 
    2600us = 162 
    1400us = 87 
     800us = 50 
     400us = 25 

     400+800  = 25+50 = 75 
     400+1400 = 25+87 = 112 
     mean ~= (112-75)/2+75 = 18+75 = 93 
*/ 

#define         _16f84_ 
#include        <16f84.h> 

#ifdef _12C508_ 
        bit     _TxOUT          @ GP0; 
        bit     RxD_pin         @ GP1; 
        bit     IR_input        @ GP2; 
#else 
        #define RP0             STATUS.5 
        #pragma update_RP 0   /* OFF */ 
        #define DEF_TRISA       0 
        #define DEF_TRISB       6 
        bit     Rele            @ PORTA.1; 

        bit     IR_input        @ PORTB.1; 
        bit     RxD_pin         @ PORTB.2; 
        bit     _TxOUT          @ PORTB.3; 
        bit     LED             @ PORTB.4; 
#endif 

unsigned char size,x,y,med,min,max,rxBuf; 

unsigned char r[4]; 
unsigned char buff[32]; 

void TxSerial (unsigned char txBuf); 

/*--------------------------------------------------------------------------*/ 
void TxEnter (void) { 
/*--------------------------------------------------------------------------*/ 
        TxSerial(0xD); 
        TxSerial(0xA); 
} 

/*--------------------------------------------------------------------------*/ 
void TxHexAscii (unsigned char in) { 
/*--------------------------------------------------------------------------*/ 
        unsigned char Hex; 

        Hex = swap(in);                 // upper nibble 
        Hex &= 0x0F; 
        if (Hex<10) Hex += 0x30; 
        else Hex += 0x37; 
        TxSerial(Hex); 
        Hex = in & 0x0F; 
        if (Hex<0x0A) Hex += 0x30; 
        else Hex += 0x37; 
        TxSerial(Hex); 
} 

/*--------------------------------------------------------------------------*/ 
void Delay_uSeg (unsigned char timeout) { 
/*--------------------------------------------------------------------------*/ 
        // delay = 3*timeout + 7uS (including call and return) 

        while (1) { 
                timeout--; 
                if (timeout==0) { 
                        nop(); 
                        nop(); 
                        return; 
                } 
        } 
} 

/*--------------------------------------------------------------------------*/ 
void TxSerial (unsigned char txBuf) { 
/*--------------------------------------------------------------------------*/ 

/* 
 ;---------------------------------------------------------------------------* 
 ; Transmit 1 start bit Lo, 8 data bits and 1 stop bit Hi at 9600 bps 
 ; No Parity 
 ; Byte time = 1.040 mS 
 ; Bit  time = 104 uS (0.16% erro w/4.00 Mhz Internal RC) 
 ; Input : W = byte to be transmitted 
 ; Output: byte transmitted by serial pin 
 ;---------------------------------------------------------------------------* 
*/ 

    char idx; 

        while (1) 
        { 
                Carry = 0;                      // start bit 
                for (idx=10; idx; idx--)        // 3us 
                { 
                        _TxOUT = Carry;         // 4us 
                        Delay_uSeg(28);         // 91us (28*3+7) 
                        Carry  = 1;             // 1us 
                        txBuf  = rr(txBuf);     // 1us 
                        nop();                  // 1us 
                }                               // 3us 
                return; 
        } 
} 

/*--------------------------------------------------------------------------*/ 
void RxSerial (void) { 
/*--------------------------------------------------------------------------*/ 

/* 
 ;---------------------------------------------------------------------------* 
 ; Receives 1 start bit Lo, 8 data bits and 1 stop bit Hi at 9600 bps 
 ; No Parity 
 ; Byte time = 1.040 mS 
 ; Bit  time = 104 uS (0.16% erro w/4.00 Mhz Internal RC) 
 ; 
 ; False start bit check 
 ; 
 ; Start bit hunting timeout = 4*1.283ms 
 ; 
 ; Input  : none 
 ; Output : Carry = 1 => success 
 ;          rxBuf = input byte 
 ;          Carry = 0 => error (timeout or stop bit=0) 
 ;---------------------------------------------------------------------------* 
*/ 
        char idx; 

        rxBuf = 4;                              // 5.135 ms timeout 
        idx   = 0; 

        while (1) 
        { 
                while (RxD_pin)                 // input "high" 
                { 
                        if ((-- idx)==0) 
                        { 
                                if ((-- rxBuf)==0) 
                                { 
                                        Carry = 0; 
                                        return; 
                                } 
                        } 
                } 

                Delay_uSeg(14);                 // 1/2 bit delay (14*3+7) 
                if (RxD_pin) 
                        continue;               // false start bit detection 

                rxBuf = 0x80;                   // 8 bits counter and reception buffer 
                nop(); 
                nop();                          // timming adjustment 

                do 
                { 
                        Delay_uSeg(30);         // (30*3+7)us 
                        Carry = RxD_pin;        // bit read 
                        rxBuf = rr(rxBuf);      // store and count 
                } 
                while (Carry==0); 
                Delay_uSeg(30);                 // 1 bit delay 
                nop();                          // timming adjustment 
                Carry = RxD_pin;                // stop bit read 
                return;                         // 100 us availiable 
        } 
} 
  

/*--------------------------------------------------------------------------*/ 
void main (void) { 
/*--------------------------------------------------------------------------*/ 

#ifdef _12C508_ 
//      OSCCAL  = W;                                    // OscCal Value - OTP part 
        OSCCAL  = 0xB0;                                 // OscCal Value - Windowed part 
        GPIO    = 0x00; 
        TRIS    = 0x08;                                 // GP3 input 
        OPTION  = 0b11000011;                           // Prescaler Timer0 1:16 
#else 
        INTCON  = 0;                                    // no interrupts 
        PCLATH  = 0;                                    // bank 0 
        PORTA   = 0; 
        PORTB   = 0; 
        RP0     = 1;                                    // RAM bank 1 
        TRISA   = DEF_TRISA; 
        TRISB   = DEF_TRISB; 
        OPTION  = 0b11000011;                           // Prescaler Timer0 1:16 
        RP0     = 0;                                    // RAM bank 0 
#endif 

        while (1) 
        { 
                /* set vars to start */ 

                FSR  = buff;                            // pointer to buffer 
                x    = 12;                              // only 12 bits 
                size = 0;                               // word size in bits 
                min  = 255;                             // min period 
                max  = 0;                               // max period 

                /* start bit management */ 

                while (IR_input==1);                    // wait for 0 
                /* 2600us start bit */ 
                while (IR_input==0);                    // wait for 1 

                TMR0 = 0;                               // start counter 
                do 
                { 
                        /* measure high pulse */ 

                        INDF = 0;                       // period: default to zero 
                        while (TMR0==0);                // wait TMR0 advance 
                        while (IR_input==1)             // wait for 0 
                        { 
                                if (TMR0==0)            // timer overflow (4096us) ? 
                                        goto frame_end; // yes, exit 
                        } 
                        INDF = TMR0;                    // store period 
                        TMR0 = 0;                       // start counter 
                        med = INDF;                     // save high period 
                        FSR++;                          // bump pointer 
                        INDF = 0;                       // period: default to zero 
                        size++;                         // inc bit counter 

                        /* measure low pulse */ 

                        while (TMR0==0);                // wait TMR0 advance 
                        while (IR_input==0);            // wait for 1 
                        INDF = TMR0;                    // store period 
                        TMR0 = 0;                       // start counter 
                        med += INDF;                    // total period 
                        if (med>=max) max = med;        // find max 
                        if (med<min)  min = med;        // find min 
                        FSR++;                          // bump pointer 
                        size++;                         // inc period counter 
                        x--;                            // dec max bits 
                } 
                while (x); 
frame_end: 
                LED = 1; 
                med  = max - min; 
                med /= 2; 
                med += min; 

                r[0] = 0; 
                r[1] = 0; 
                r[2] = 0; 
                r[3] = 0; 

                FSR  = buff; 
                FSR += size; 
                x = size/2; 
                do 
                { 
                        Carry = 0; 
                        r[3] = rl(r[3]); 
                        r[2] = rl(r[2]); 
                        r[1] = rl(r[1]); 
                        r[0] = rl(r[0]); 
                        FSR--; 
                        max = INDF; 
                        FSR--; 
                        max += INDF; 
                        if (max>=med) r[3]++; 
                } while (--x); 

                /* now r[0],r[1],r[2], r[3] has the frame */ 
                /* Tx the periods and the encoded word */ 

                TxHexAscii(size); 
                TxSerial(0x20); 
                TxHexAscii(med); 
                TxEnter(); 

                for(x=0;x<size; x++) 
                { 
                        TxHexAscii(buff[x]); 
                        TxSerial(0x20); 
                } 
                TxEnter(); 

                TxHexAscii(r[0]); 
                TxHexAscii(r[1]); 
                TxHexAscii(r[2]); 
                TxHexAscii(r[3]); 

                TxEnter(); 
                LED = 0; 
        } 
} 
  
  

Interested:

Code: