// hardware dependent
#define is_SIGNAL_IR() (IR_PIN==0)
#define is_IDLE_IR() (IR_PIN==1)
#define set_TIME_IR(tm) IR_TIME=tm
#define get_TIME_IR() IR_TIME
// definition
#define nIRtimeBase 1 // 1uS
#define nIRtolerance 30 // +/- 30%
#define defIRtime 889 // 889uS RC-5/RC-5X 1 physical (half logic) bit time
#define minIRtime ((((((100-nIRtolerance)*defIRtime)*10)/(nIRtimeBase*100))+5)/10)
#define maxIRtime ((((((100+nIRtolerance)*defIRtime)*10)/(nIRtimeBase*100))+5)/10)
// parameter declaration
U8 gIRstat; // IR state number
enum { stIR_NONE=0, stIR_IDLE, stIR_SIGNAL };
U16 gIRdata; // IR data (14 logic bits)
#define add_Data_0_IR() gIRdata <<= 1
#define add_Data_1_IR() gIRdata <<= 1; gIRdata |= 1
U8 gIRcount; // IR bit counter
#define nIRcount (14*2) // 14 logic bits = 28 physical bits
U8 gIRruntime; // IR running time (counting only if gIRstat != stIR_NONE)
#define nIRruntime 25000 // 25mS: 14*(889+889)=24.892mS
BIT bIRphysicalBitCount; // 0:1st physical bit, 1:2nd physical bit
BIT bIRphysicalBitData; // last physical bit data
BIT bIRnewHit; // 1:new IR code is received
VOID InitIR( VOID ) // initial IR engine
{
gIRstat = stIR_NONE;
bIRnewHit = FALSE;
// hardware dependent: set correct snapped interrupt edge setting
}
VOID TimeoutIR( VOID ) // check IR running timeout
{
if( gIRstat != stIR_NONE) {
if( gIRruntime > nIRruntime ) { // timeout
InitIR();
}
}
}
VOID PollIR( VOID ) // put it in ISR (trigger when IR_PIN edge is changed)
{
U8 mIRtime;
mIRtime = get_IR_TIME(); set_IR_TIME(0);
switch( gIRstat ) {
case stIR_NONE:
if( is_SIGNAL_IR() ) { // 1st logic bit (start bit) is 1 (01)
// IR engine is starting
gIRstat++; // gIRstat = stIR_IDLE;
gIRruntime = 0; // IR running time is counting
gIRdata = 0; // it is not necessary if mask unused bits before using it
gIRcount = 1; // as hit 1st physical bit
bIRphysicalBitCount = 1; // ready to process 2nd physical bit
return;
}
return;
case stIR_IDLE: // now is IR.IDLE signal (process last SIGNAL)
if( mIRtime > 2*maxIRtime ) { // time > 2t
goto _error_IDLE_PollIR; // last signal too long
}
if( mIRtime < 1*minIRtime ) { // time < 1t
goto _error_IDLE_PollIR; // last signal too short
}
bIRphysicalBitData = 0; // now is IDLE
if( bIRphysicalBitCount == 0 ) { // now is 1st physical bit (1x)
if( mIRtime > 2*minIRtime ) { // time > 2t
goto _error_IDLE_PollIR; // bad code, bi-phase no this (11) combination
}
bIRphysicalBitCount = 1; // ready to process 2nd physical bit
} else { // now is 2nd physical bit (01)
add_Data_1_IR(); // add logic bit data 1 (01)
if( mIRtime < 2*minIRtime ) { // time < 2t
bIRphysicalBitCount = 0; // ready to process 1st physical bit
} else { // time >= 2t, it is 011 (extra physical bit)
gIRcount++; // add extra physical bit count
bIRphysicalBitCount = 1; // ready to process 2nd physical bit
}
}
break;
case stIR_SIGNAL: // now is IR.SIGNAL signal (process last IDLE)
if( mIRtime > 2*maxIRtime ) { // time > 2t
goto _error_SIGNAL_PollIR; // last signal too long
}
if( mIRtime < 1*minIRtime ) { // time < 1t
goto _error_SIGNAL_PollIR; // last signal too short
}
bIRphysicalBitData = 1; // now is SIGNAL
if( bIRphysicalBitCount == 0 ) { // now is 1st physical bit (0x)
if( mIRtime > 2*minIRtime ) { // time > 2t
goto _error_SIGNAL_PollIR; // bad code, bi-phase no this (00) combination
}
bIRphysicalBitCount = 1; // ready to process 2nd physical bit
} else { // now is 2nd physical bit (10)
add_Data_0_IR(); // add logic bit data 0 (10)
if( mIRtime < 2*minIRtime ) { // time < 2t
bIRphysicalBitCount = 0; // ready to process 1st physical bit
} else { // time >= 2t, it is 100 (extra physical bit)
gIRcount++; // add extra physical bit count
bIRphysicalBitCount = 1; // ready to process 2nd physical bit
}
}
break;
}
// ready to process next physical bit
gIRcount++;
if( gIRcount >= nIRcount ) { // the last physical bit
goto _complete_check_PollIR;
}
if( gIRcount == nIRcount-1 ) { // the 27th physical bit
if( bIRphysicalBitData == 0 ) { // now is 0 as complete, due to no more new edge will be changed
bIRphysicalBitCount = 0; // as ready to process 1st physical bit
add_Data_0_IR(); // add logic bit data 0 (10)
goto _complete_check_PollIR;
}
}
// the 1~27th physical bit
gIRstat = bIRphysicalBitData == 0 ? stIR_SIGNAL : stIR_IDLE; // swap state
// hardware dependent: toggle snapped interrupt edge setting
return;
_complete_check_PollIR:
if( bIRphysicalBitCount == 0 ) { // correct, no any pending physical bit
InitIR();
// ex: check Start Bit, process Toggle(Repeat) Bit, translate Address/Command Bits....
bIRnewHit = TRUE;
return;
}
_error_IDLE_PollIR:
_error_SIGNAL_PollIR:
InitIR();
return;
}
VOID main( VOID )
{
InitIR(); // initial IR engine
while(1) { // main endless polling loop
if( bIRnewHit == TRUE ) { // new IR code is coming
bIRnewHit = FALSE;
// process IR event here
}
TimeoutIR(); // check IR running timeout
}
}
It is a hardware dependent macro to get a time value from real hardware TIMER or something.CMOS said:I didnt quite understand "#define get_TIME_IR() IR_TIME"...Can you explain this?
#define IR_TIME TMR0
#define nIRtimeBase 32
#define IR_TIME TMR0
U8 gIR_TIME;
#define set_TIME_IR(tm) gIR_TIME = IR_TIME
#define get_TIME_IR() (IR_TIME - gIR_TIME)
#define nIRtimeBase 32
#define IR RB0
/*--------------------------------------------------------------
*
* RC5_RECEIVE - Checks IR receiver and returns the following:
*
* 0: no meaningful IR data present
* !0: 14 bit RC5 packet
*
*-------------------------------------------------------------*/
unsigned int
rc5_receive(void)
{
unsigned int message;
unsigned char i, cnt, IR_old;
message = 0;
if (!IR) { // in middle of start bit
for (i=0;i<14;i++) {
message = message << 1 + IR;
cnt = 6; // wait 1500ms (just before middle of
next bit at 1778ms)
do {
DelayUs(250);
} while (--cnt);
IR_old = IR;
cnt = 50;
do {
DelayUs(10);
} while (IR_old == IR & --cnt);
if (!cnt) return (0); // cnt = 0 indicates timeout - return 0
}
}
return (message);
}
metal said:I found this simple code a while ago, its really simple.
I have not tested it my self yet.
Use RB0 interrupt to be able todetect RC5 incomming packets. As the code shows, the interrupt has to be triggered on the rising edge of RB0 pin, means from 0 to 1 change.
/*------ RC5 decoder program Version 1.0 (by btbass) 'bob the bass' 4MHz clock
;------ RC5 code is 14 bits each of 1.8mS duration with carrier frequency of 36KHz.
;------ A '0' is a mid pulse transition from high to low.
;------ A '1' is a mid pulse transition from low to high.
;------ The first 2 bits are always 1, for timing calibration.
;------ The next bit is the toggle bit, indicating a new keypress.
;------ Then 5 bits of address and 6 bits of command code.
;------ The IR receiver inverts the data stream. (check, but most do!)
;------ This program uses the first 2 bits to calibrate the timing of one pulse length.
;------ It then waits 3/4 pulse length and looks at the input.
;------ If its high, it waits for a low '0'.
;------ If it's low, it waits for a high '1', then resets the timer on the transition.
;------ It returns 0x01 if the code is ok and 0x00 if an error.
;------ The rc5 system address is returned in address, the command in command.
;------ The toggle bit is bit 5 of the address byte.
;------ Using a 4 Meg xtal with timer divided by 128. */
#include <pic.h>
#include "rc5decode.h"
/*--- globals ---*/
unsigned char command;
unsigned char address;
unsigned char temp;
unsigned char timer;
unsigned char rc5valid;
/*--- rc5 decode function ---*/
unsigned char rc5Decode(void)
{
#asm
;------ calibrate timing
bcf 3,5 ;select bank 0
clrf TMR ;start timer
call Wlow ;get the pulse length
call Whigh
btfsc TMR,7 ;test for timer overflow
goto codeError ;bail out
movf TMR,w ;save pulse length
clrf TMR ;start timer
movwf _timer ;take the pulse length,
movwf _temp ;save it
bcf 3,0 ;clear carry
rrf _temp,f ;divide by 2
bcf 3,0 ;clear carry
rrf _temp,f ;divide by 4
movf _temp,w ;and subtract to get
subwf _timer,f ;3/4 pulse length
movlw 0x0c
movwf _temp ;init bit counter
;------ wait for start of data
nextBit movf _timer,w ;wait 3/4 pulse length
subwf TMR,w
btfss 3,2 ;take a look
goto nextBit
;------ start of data stream
btfss IR_IN ;if its high
goto waitlow ;gonna be an 0
;------ wait for high 1
call Whigh ;if its low
bsf 3,0 ;gonna be a 1
goto clock
;------ wait for low 0
waitlow call Wlow
bcf 3,0 ;gonna be an 0
;------ clock data
clock clrf TMR ;restart timer
rlf _command,f ;save the bit
rlf _address,f
decfsz _temp,f ;done all bits?
goto nextBit
;------ get system address, toggle bit and command code
movf _command,w ;copy low byte
movwf _temp ;into temp
rlf _temp,f ;need to shift 2 bits
rlf _address,f ;into address
rlf _temp,f
rlf _address,f ;system address is 5 bits
movlw 0x3f ;mask system address + toggle bit
andwf _address,f
movlw 0x3f ;mask command code
andwf _command,f ;command code is 6 bits
goto rc5ok ;done ok
;------ wait while low
Wlow btfsc TMR,7 ;test for timer overflow
return ;bail out
btfss IR_IN
goto Wlow
return
;------ wait while high
Whigh btfsc TMR,7 ;test for timer overflow
return ;bail out
btfsc IR_IN
goto Whigh
return
rc5ok movlw 0x01
movwf _rc5valid
goto rc5end
codeError clrf _rc5valid
rc5end nop
#endasm
return rc5valid;
}
/*--- End of File ---*/
/*--- rc5decode.h ---*/
#ifndef RC5DECODE
#define RC5DECODE
/*--- Function prototype ---*/
unsigned char rc5Decode(void);
/*---- globals ---*/
extern unsigned char command; /* rc5 command code */
extern unsigned char address; /* rc5 system address */
extern unsigned char rc5valid; /* valid rc5 data flag */
#endif
/*--- Macros ---*/
#define IR_IN _PORTB,0 /* Infra Red input pin */
#define TMR _TMR0 /* Pulse timer */
/*--- rc5 infra red codes ---*/
#define SYSTEM_ADD 0x10 /* System address */
#define RC5_VOL_UP 0x10 /* VOL+ */
#define RC5_VOL_DOWN 0x11 /* VOL- */
#define RC5_PHONO 0x01 /* PHONO */
#define RC5_TUNER 0x02 /* TUNER */
#define RC5_CD 0x03 /* CD */
#define RC5_AV 0x04 /* AV */
#define RC5_AUX1 0x08 /* AUX1 */
#define RC5_AUX2 0x09 /* AUX2 */
#define RC5_MUTE 0x0D /* MUTE */
/*--- End of file ---*/
//Main.c
/*------ RC5 decoder program Version 1.0 (by btbass) 'bob the bass' 4MHz clock
;------ RC5 code is 14 bits each of 1.8mS duration with carrier frequency of 36KHz.
;------ A '0' is a mid pulse transition from high to low.
;------ A '1' is a mid pulse transition from low to high.
;------ The first 2 bits are always 1, for timing calibration.
;------ The next bit is the toggle bit, indicating a new keypress.
;------ Then 5 bits of address and 6 bits of command code.
;------ The IR receiver inverts the data stream. (check, but most do!)
;------ This program uses the first 2 bits to calibrate the timing of one pulse length.
;------ It then waits 3/4 pulse length and looks at the input.
;------ If its high, it waits for a low '0'.
;------ If it's low, it waits for a high '1', then resets the timer on the transition.
;------ It returns 0x01 if the code is ok and 0x00 if an error.
;------ The rc5 system address is returned in address, the command in command.
;------ The toggle bit is bit 5 of the address byte.
;------ Using a 4 Meg xtal with timer divided by 128. */
#include <pic.h>
#include <stdio.h>
#include "rc5decode.h"
__CONFIG(INTIO & WDTDIS & PWRTEN & MCLRDIS);
/*--- globals ---*/
unsigned char command;
unsigned char address;
unsigned char temp;
unsigned char timer;
unsigned char rc5valid;
#define PORTBIT(adr, bit) ((unsigned)(&adr)*8+(bit))
static bit IR_PIN @ PORTBIT(GPIO, 2);
/*--- rc5 decode function ---*/
//static void interrupt
unsigned char rc5decode(void)
{
#asm
;------ calibrate timing
bcf 3,5 ;select bank 0
clrf TMR ;start timer
call Wlow ;get the pulse length
call Whigh
btfsc TMR,7 ;test for timer overflow
goto codeError ;bail out
movf TMR,w ;save pulse length
clrf TMR ;start timer
movwf _timer ;take the pulse length,
movwf _temp ;save it
bcf 3,0 ;clear carry
rrf _temp,f ;divide by 2
bcf 3,0 ;clear carry
rrf _temp,f ;divide by 4
movf _temp,w ;and subtract to get
subwf _timer,f ;3/4 pulse length
movlw 0x0c
movwf _temp ;init bit counter
;------ wait for start of data
nextBit movf _timer,w ;wait 3/4 pulse length
subwf TMR,w
btfss 3,2 ;take a look
goto nextBit
;------ start of data stream
btfss IR_IN ;if its high
goto waitlow ;gonna be an 0
;------ wait for high 1
call Whigh ;if its low
bsf 3,0 ;gonna be a 1
goto clock
;------ wait for low 0
waitlow call Wlow
bcf 3,0 ;gonna be an 0
;------ clock data
clock clrf TMR ;restart timer
rlf _command,f ;save the bit
rlf _address,f
decfsz _temp,f ;done all bits?
goto nextBit
;------ get system address, toggle bit and command code
movf _command,w ;copy low byte
movwf _temp ;into temp
rlf _temp,f ;need to shift 2 bits
rlf _address,f ;into address
rlf _temp,f
rlf _address,f ;system address is 5 bits
movlw 0x3f ;mask system address + toggle bit
andwf _address,f
movlw 0x3f ;mask command code
andwf _command,f ;command code is 6 bits
goto rc5ok ;done ok
;------ wait while low
Wlow btfsc TMR,7 ;test for timer overflow
return ;bail out
btfss IR_IN
goto Wlow
return
;------ wait while high
Whigh btfsc TMR,7 ;test for timer overflow
return ;bail out
btfsc IR_IN
goto Whigh
return
rc5ok movlw 0x01
movwf _rc5valid
goto rc5end
codeError clrf _rc5valid
rc5end nop
#endasm
return rc5valid;
}
static void interrupt
isr(void)
{
if(rc5decode())
{
address &= 0x1F;
if(address == REMOTE_ADDRESS)
printf("%d\r\n",command);
//printf("Address:%d\r\nCommand:%d\r\n\n",address,command);
}
INTF = 0;
}
void main(void)
{
OSCCAL = _READ_OSCCAL_DATA(); // restore oscillator calibration
CMCON = 0x07; // turn off comparator
TRISIO = 0x3E;
OPTION = 0x06;
INTE = 1; // enable the external interrupt
GIE = 1; // Global interrupt enable
while(1);
}
/*--- End of File ---*/
//Serial.c
/*
* Serial port driver (uses bit-banging)
* for 16Cxx series parts.
*
* IMPORTANT: Compile this file with FULL optimization
*
* Copyright (C)1996 HI-TECH Software.
* Freely distributable.
*/
#include <pic.h>
/*
* Tunable parameters
*/
/* Transmit and Receive port bits */
#define SERIAL_PORT GPIO
#define SERIAL_TRIS TRISIO
#define TX_PIN 0
#define RX_PIN 1
/* Xtal frequency */
#define XTAL 4000000
/* Baud rate */
#define BRATE 9600
/* Don't change anything else */
#define SCALER 10000000
#define ITIME 4*SCALER/XTAL /* Instruction cycle time */
#if BRATE > 1200
#define DLY 3 /* cycles per null loop */
#define TX_OHEAD 13 /* overhead cycles per loop */
#else
#define DLY 9 /* cycles per null loop */
#define TX_OHEAD 14
#endif
#define RX_OHEAD 12 /* receiver overhead per loop */
#define DELAY(ohead) (((SCALER/BRATE)-(ohead*ITIME))/(DLY*ITIME))
static bit TxData @ (unsigned)&SERIAL_PORT*8+TX_PIN; /* Map TxData to pin */
static bit RxData @ (unsigned)&SERIAL_PORT*8+RX_PIN; /* Map RxData to pin */
#define INIT_PORT SERIAL_TRIS |= 1<<RX_PIN /* set up I/O direction */
void
putch(char c)
{
unsigned char bitno;
#if BRATE > 1200
unsigned char dly;
#else
unsigned int dly;
#endif
INIT_PORT;
TxData = 0; /* start bit */
bitno = 12;
do {
dly = DELAY(TX_OHEAD); /* wait one bit time */
do
/* waiting in delay loop */ ;
while(--dly);
if(c & 1)
TxData = 1;
if(!(c & 1))
TxData = 0;
c = (c >> 1) | 0x80;
} while(--bitno);
NOP();
}
char
getch(void)
{
unsigned char c, bitno;
#if BRATE > 1200
unsigned char dly;
#else
unsigned int dly;
#endif
for(;;) {
while(RxData)
continue; /* wait for start bit */
dly = DELAY(3)/2;
do
/* waiting in delay loop */ ;
while(--dly);
if(RxData)
continue; /* twas just noise */
bitno = 8;
c = 0;
do {
dly = DELAY(RX_OHEAD);
do
/* waiting in delay loop */ ;
while(--dly);
c = (c >> 1) | (RxData << 7);
} while(--bitno);
return c;
}
}
char
getche(void)
{
char c;
putch(c = getch());
return c;
}
/*--- rc5decode.h ---*/
#ifndef RC5DECODE
#define RC5DECODE
/*--- Function prototype ---*/
unsigned char rc5Decode(void);
/*---- globals ---*/
extern unsigned char command; /* rc5 command code */
extern unsigned char address; /* rc5 system address */
extern unsigned char rc5valid; /* valid rc5 data flag */
#endif
/*--- Macros ---*/
#define REMOTE_ADDRESS 19
#define IR_IN _GPIO,2 /* Infra Red input pin */
#define TMR _TMR0 /* Pulse timer */
/*--- rc5 infra red codes ---*/
#define SYSTEM_ADD 0x10 /* System address */
#define RC5_VOL_UP 0x10 /* VOL+ */
#define RC5_VOL_DOWN 0x11 /* VOL- */
#define RC5_PHONO 0x01 /* PHONO */
#define RC5_TUNER 0x02 /* TUNER */
#define RC5_CD 0x03 /* CD */
#define RC5_AV 0x04 /* AV */
#define RC5_AUX1 0x08 /* AUX1 */
#define RC5_AUX2 0x09 /* AUX2 */
#define RC5_MUTE 0x0D /* MUTE */
/*--- End of file ---*/
We use cookies and similar technologies for the following purposes:
Do you accept cookies and these technologies?
We use cookies and similar technologies for the following purposes:
Do you accept cookies and these technologies?