SX Specific IR to RS232 routine

for Sony and the code for 4MHz in PIC compatibility mode 
written with CC5XFree follows. see if u can figure it :-)

Rewritten by James Newton for the SX: UNTESTED!!!

//=============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)
 * james at sxlist.com
 * use CC1B for SX (LST)
 */

/*
  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         _sx28_
#include        <sx28.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






#ifdef _sx28_
	unsigned char x,y;
bank0	unsigned char r[4];
bank0	unsigned char med,min,max,rxBuf;
bank1	unsigned char buff[16];
bank2	unsigned char buff2[16];
#else
	unsigned char x,y,med,min,max,rxBuf;
	unsigned char r[4];
	unsigned char buff[16];
	unsigned char buff2[16];
	#endif


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
	#endif


#ifdef _sx28_
    #pragma config &= 0b11010011 // reg 1 = RTCC, no int on RTCC, RTCC internal, prescale, 1:16
      PORTA   = 0;
      PORTB   = 0;
      DDRA = DEF_TRISA;
      DDRA = DEF_TRISB;
	PA0 = 0;
	PA1 = 0;
	PA2 = 0;
	#endif


#ifdef _16f84_
        INTCON  = 0;                                    // no interrupts
        PCLATH  = 0;                                    // bank 0
        PORTA   = 0;
        PORTB   = 0;
        TRISA   = DEF_TRISA;
        TRISB   = DEF_TRISB;
        RP0     = 1;                                    // RAM bank 1
        RP0     = 0;                                    // RAM bank 0
	#endif


        while (1)
        {
                /* set vars to start */
                min  = 255;                             // min period
                max  = 0;                               // max period


                y    = 0;                               // pointer to buffer
                x    = 12;                              // only 12 bits


                /* 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
                {
//                        buff[y] = 0; 
//                        buff2[y] = 0; 
                        /* measure high pulse */
                        while (TMR0==0);                // wait TMR0 advance
                        while (IR_input==1)             // wait for 0
                        {
                                if (TMR0==0)            // timer overflow (4096us) ?
	goto	frame_end	; // yes, exit
                        }
                        buff[y] = TMR0;                 // store period
                        med = TMR0;                     // save high period
                        TMR0 = 0;                       // start counter


                        /* measure low pulse */


                        while (TMR0==0);                // wait TMR0 advance
                        while (IR_input==0);            // wait for 1
                        buff2[y] = TMR0;                // store period
                        med += TMR0;                    // total period
                        TMR0 = 0;                       // start counter
                        if (med>=max) max = med;        // find max
                        if (med<min)  min = med;        // find min


                        y++;                            // bump pointer
                        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;


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


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


                TxHexAscii(x*2);	//size
                TxSerial(0x20);
                TxHexAscii(med);
                TxEnter();


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


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


                TxEnter();
                LED = 0;
        }
}