 
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; 
        } 
} 
  
  
Code:
+Hi, Here is a new routine to read the transmissions from a Sony type remote control. Unlike the ones I found on the site so far, this one is in ASM and is interrupt driven so allows the main control program to do something else while waiting for RC commands. Anyway, here is the code, Regards, Barry. ; Software to read the commands from a Sony remote control ; The timings in this file are for a clock speed of 400kHz. ; Different timings can be easily achieved by changing the ; cutoff constants and/or the timer prescaler. ; Because the reader routine is interrupt driven it allows ; a main program to run and control something on the basis ; of the current setting of the RC data variable. For ; example, it was developed originally to control a robot ; so the main program does the robot control and the ; interrupt routine reads the remote control. ; ; May be distributed under the terms of the Gnu Public ; License (GPL) ; ; Version: 0.1 ; (c) Barry Smith, 2002. R_W_SAVE equ 0x11 ; Saves W during interrupts R_ST_SAVE equ 0x12 ; Saves STATUS during interrupts R_NEED_BITS equ 0x13 ; Number of bits still needed R_CUR_DATA equ 0x15 ; Data being received R_OLD_DATA equ 0x16 ; Last read data R_SAVE_TMR equ 0x17 ; Save timer value at start of interrupt F_GOT_START equ 0 ; Got start flag F_RC_PIN equ 4 ; RB pin for RC T3_CUT equ 0x52 ; T3 cutoff timing T2_CUT equ 0x32 ; T2 cutoff timing list p=16F84A include P16F84A.inc __config ( _RC_OSC & _PWRTE_ON & _WDT_OFF & _CP_OFF ) org 0 goto main_start org 4 ; This is the routine called on interrupt. This happens when either ; a bit RB4:7 changes or the timer rolls over. ; First, save the W and STATUS details. The SWAPF is used because it ; does not effect the STATUS (Z) flags, unlike MOVF. movwf R_W_SAVE ; Save value of W swapf STATUS, W ; Save STATUS flags movwf R_ST_SAVE movf TMR0, W ; Store timer value now as its still movwf R_SAVE_TMR ; incrementing. clrf TMR0 ; Make sure timer doesn't fire again ; Now the main code which processes the events btfss INTCON, T0IF goto int_rb clrf R_NEED_BITS ; Reset everything clrf R_CUR_DATA goto int_end int_rb ; Interupt is on RB pin btfsc PORTB, F_RC_PIN goto int_pin_high clrf TMR0 ; Executed if pin is low goto int_end int_pin_high ; Pin has returned to high state movf R_SAVE_TMR, W sublw T3_CUT btfsc STATUS, C goto int_try_t2 ; incf PORTB, F movlw 0x08 movwf R_NEED_BITS goto int_end int_try_t2 movf R_NEED_BITS, F ; Check if more bits are btfsc STATUS, Z ; needed, otherwise end. goto int_end rrf R_CUR_DATA, F ; Prepare for next bit decf R_NEED_BITS, F movf R_SAVE_TMR, W sublw T2_CUT btfsc STATUS, C goto int_is_t1 bsf R_CUR_DATA, 7 goto int_bit_set int_is_t1 bcf R_CUR_DATA, 7 int_bit_set movf R_NEED_BITS, F btfss STATUS, Z goto int_end movf R_CUR_DATA, W movwf PORTB int_end ; Clear the interrupts movlw b'11111000' ; Clears the interrupt indicator bits andwf INTCON, F ; Restore pre-interrupt status for STATUS and W. swapf R_ST_SAVE, W movwf STATUS swapf R_W_SAVE, F ; Restore W value without changing swapf R_W_SAVE, W ; STATUS bits retfie main_start ; This is the initialisation section - the chip must be configured ; to use TMR0. The prescaler must be determined so that the timer ; will roll over during the quiet time between transmissions (about ; 35-40ms), but never during transmission, the longest pulse of ; which is about 1.8ms). This gives plenty of leeway. bsf STATUS, RP0 movlw b'11010000' ; Clears the zeros from the OPTION_REG andwf OPTION_REG, F ; setting internal clock. movlw b'00010000' movwf TRISB bcf STATUS, RP0 movlw b'10101000' ; Sets interrupts to occur on RB change movwf INTCON ; or timer overflow. clrf R_CUR_DATA clrf R_NEED_BITS mainloop goto mainloop end
| file: /Techref/microchip/irtoserial.htm, 16KB, , updated: 2005/1/5 11:53, local time: 2025/10/31 02:51, 
owner: JSAG-e_dgo-898, 
 
216.73.216.87,10-2-37-96:LOG IN | 
| ©2025 These pages are served without commercial sponsorship. (No popup ads, etc...).Bandwidth abuse increases hosting cost forcing sponsorship or shutdown. This server aggressively defends against automated copying for any reason including offline viewing, duplication, etc... Please respect this requirement and DO NOT RIP THIS SITE. Questions? <A HREF="http://www.piclist.com/tecHREF/microchip/irtoserial.htm"> PIC 16F84 Sony IR to Serial converter</A> | 
| Did you find what you needed? | 
|  PICList 2025 contributors: o List host: MIT, Site host massmind.org, Top posters @none found - Page Editors: James Newton, David Cary, and YOU! * Roman Black of Black Robotics donates from sales of Linistep stepper controller kits. * Ashley Roll of Digital Nemesis donates from sales of RCL-1 RS232 to TTL converters. * Monthly Subscribers: Gregg Rew. on-going support is MOST appreciated! * Contributors: Richard Seriani, Sr. | 
| Ashley Roll has put together a really nice little unit here. Leave off the MAX232 and keep these handy for the few times you need true RS232! | 
.