# 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:
. 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();

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
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:

• STOPspambarryxsSTOPspam at xs4all.nl shares this 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.
;
;
; 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: 2022/6/29 05:54, owner: JSAG-e_dgo-898, TOP NEW HELP FIND:  3.236.107.249:LOG IN

 ©2022 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?Please DO link to this page! Digg it! / MAKE! PIC 16F84 Sony IR to Serial converter

After you find an appropriate page, you are invited to your to this massmind site! (posts will be visible only to you before review) Just type a nice message (short messages are blocked as spam) in the box and press the Post button. (HTML welcomed, but not the <A tag: Instead, use the link box to link to another page. A tutorial is available Members can login to post directly, become page editors, and be credited for their posts.

Attn spammers: All posts are reviewed before being made visible to anyone other than the poster.
 Did you find what you needed? "No. I'm looking for: " "No. Take me to the search page." "No. Take me to the top so I can drill down by catagory" "No. I'm willing to pay for help, please refer me to a qualified consultant"

.