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/24 13:18,
owner: JSAG-e_dgo-898,
216.73.216.188,10-3-157-36: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://massmind.ecomorder.com/techref/microchip/irtoserial.htm"> PIC 16F84 Sony IR to Serial converter</A> |
| Did you find what you needed? |
Welcome to ecomorder.com! |
|
The Backwoods Guide to Computer Lingo |
.