| Author |
Message |
CMOS
Joined: 06 Jan 2004 Posts: 810 Helped: 39 Location: USA
|
10 Oct 2006 17:07 pic rc5 |
|
|
|
|
Can anyone share C code for decoding RC5 signals using PIC microcontoller? I've googled for days and all the code that I found used delays to sample the signal..which causes problem when RC5 signal timings are slightly different than standard. None of them actually uses manchester decoding.
I am looking for a code like the BASCOM 8051/AVR compilers internal library has. Till date its the best RC5 decoding code I have found...it works for any damn RC5 remote...irrespective of timing variations.
Now I am looking for similar code for PIC. Anyone please?
|
|
| Back to top |
|
 |
cesarman
Joined: 01 Apr 2006 Posts: 14 Helped: 1
|
10 Oct 2006 20:55 rc5 pic |
|
|
|
|
mm C, i don know any library, but same to bascom only Proton 3.0 has RC5 library, and Sony IR Protocols library. but is in Basic.
Example
Device = 16F877
RC5IN_PIN = PORTC.0 ' Choose the port and pin for the infrared sensor
DIM RC5_WORD as WORD ' Create a WORD variable to receive the data
DIM RC5_COMMAND as RC5_WORD.Lowbyte ' Alias the COMMAND byte to RC5_WORD low byte
DIM RC5_SYSTEM as RC5_WORD.Highbyte ' Alias the COMMAND byte to RC5_WORD high byte
ALL_DIGITAL = ON ' Make all pins digital mode
Cls ' Clear the LCD
While 1 = 1 ' Create an infinite loop
Repeat
RC5_WORD = RC5In ' Receive a signal from the infrared sensor
Until RC5_COMMAND<> 255 ' Keep looking until a valid header found
Print at 1,1,"SYSTEM ",Dec RC5_SYSTEM," " ' Display the SYSTEM value
Print at 2,1,"COMMAND ",Dec RC5_COMMAND," " ' Display the COMMAND value
Wend
|
|
| Back to top |
|
 |
CMOS
Joined: 06 Jan 2004 Posts: 810 Helped: 39 Location: USA
|
11 Oct 2006 18:18 rc5 code |
|
|
|
|
C code would be really helpful. Anyone please?
Anyways, thanks for your reply cesarman.
|
|
| Back to top |
|
 |
yager
Joined: 28 May 2001 Posts: 116 Helped: 19
|
12 Oct 2006 1:33 pic rc5 decoder |
|
|
|
|
To suppose the IR receiver chip will filter out the carrier, and define the modulated carrier is SIGNAL, other is IDLE.
In fact, to decode Philips RC-5/RC-5X (bi-phase/Manchester coding) is similar to others (such like NEC/Sony).
An important trick for robust implementation is: tolerance. (ex: SIGNAL will be short if distance is long)
All of them are only tracking/measuring the tolerances of SIGNAL and IDLE time.
Well, here are the modified code (remove useless code for RC5), FYR.
| Code: |
// 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 |
| Code: |
// 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) |
| Code: |
// 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 |
| Code: |
VOID InitIR( VOID ) // initial IR engine
{
gIRstat = stIR_NONE;
bIRnewHit = FALSE;
// hardware dependent: set correct snapped interrupt edge setting
} |
| Code: |
VOID TimeoutIR( VOID ) // check IR running timeout
{
if( gIRstat != stIR_NONE) {
if( gIRruntime > nIRruntime ) { // timeout
InitIR();
}
}
} |
This PollIR can be processed by fast polling loop (due to RC5 bit time) or interrupt driven.
To suppose to use interupt driven here. The Port Change or External INT are well done. But it is only called when the edge of IR signal is changed.
| Code: |
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;
} |
Actually, the stIR_IDLE and stIR_SIGNAL states can be merged together for saving code space.
But I still split them and use 'goto' (non-structued coding style) for easy reading.
Besides, we have to process 1st and last physical bit carefully.
1st physical bit: it is hidden (as IDLE) because RC5's start logic bit is 1 (01)
last physical bit: it will be hidden if last logic bit is 0 (10)
| Code: |
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
}
} |
The above code will not handle the Toggle(Repeat) Bit. (RC5/RC5X used it to notify the key is repeating)
It also will not check the 2nd Start Bit. It should be 1 if RC5. RC5X (Extended RC-5) inverted it as the 7th (MSB) Command Bit.
Last, for more IR Remote Control informations, I suggest the San Bergmans's Knowledge Base pages: http://www.sbprojects.com/knowledge/ir/ir.htm
He made great works.
|
|
| Back to top |
|
 |
CMOS
Joined: 06 Jan 2004 Posts: 810 Helped: 39 Location: USA
|
12 Oct 2006 16:52 rc5 protocol pic |
|
|
|
|
yager, I didnt quite understand "#define get_TIME_IR() IR_TIME"...Can you explain this?
Thanks a lot anyways
|
|
| Back to top |
|
 |
yager
Joined: 28 May 2001 Posts: 116 Helped: 19
|
12 Oct 2006 22:27 rc5 c code |
|
|
|
|
| CMOS wrote: |
| I didnt quite understand "#define get_TIME_IR() IR_TIME"...Can you explain this? |
It is a hardware dependent macro to get a time value from real hardware TIMER or something.
In fact, we have to consider it with 'set_TIME_IR' and 'nIRtimeBase' together.
1. to suppose to use 8-bit hardware timer as our IR timer and it is used for IR only
the 'maxIRtime' will be 2312 (2t = 4624), so use your PIC's timer0 and set 1:32 prescaler (clock source: fosc/4, with internal 4MHz), ie:
| Code: |
#define IR_TIME TMR0
#define nIRtimeBase 32 |
2. as the above, but the IR timer is shared with others
we have to treat the timer0 as free running timer and:
| Code: |
#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 |
Since they are hardware dependent parts, so I split them to increase the code portability.
i.e. we do not need to modify the core, just adjust them for other platform or different hardware settings (8MHz OSC, 16-bit timer.....)
BTW, to implement these time critical code by internal OSC, we have to consider the Oscillator Accuracy.
The PIC is good enough: +/- 1% at 25oC, +/- 2% at 0~85oC for a wide working voltage
|
|
| Back to top |
|
 |
CMOS
Joined: 06 Jan 2004 Posts: 810 Helped: 39 Location: USA
|
13 Oct 2006 6:23 rc5 ccs |
|
|
|
|
Ok...I got it now. I'll try that out and let you know the results.
Thanks a lot.
|
|
| Back to top |
|
 |
btbass
Joined: 20 Jul 2001 Posts: 1187 Helped: 113 Location: Oberon
|
13 Oct 2006 23:46 rc5 decoder pic |
|
|
|
|
I posted a RC5 decoder in asm some time ago. This calibrates the timing every time and uses Manchester coding. It works well! To use it in a C program, compile it to a lib and just link it in.
http://www.edaboard.com/viewtopic.php?t=73538&highlight=rc5
Well it was some time ago, just had a look at what I done.
This code kicks ass!
|
|
| Back to top |
|
 |
Code Warrior
Joined: 30 Dec 2004 Posts: 224 Helped: 7
|
14 Oct 2006 11:06 rc5 with pic ccs |
|
|
|
|
| How to code for 8051 microcontroller in asm.
|
|
| Back to top |
|
 |
metal
Joined: 21 Dec 2004 Posts: 369 Helped: 13
|
14 Oct 2006 19:04 pic rc5 code |
|
|
|
|
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.
| Code: |
/*--------------------------------------------------------------
*
* 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);
}
|
[/quote]
|
|
| Back to top |
|
 |
CMOS
Joined: 06 Jan 2004 Posts: 810 Helped: 39 Location: USA
|
16 Oct 2006 14:26 rc5 pic code |
|
|
|
|
| metal wrote: |
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.
|
I already have similar kind of code. It doesnt work with all types of RC5 remotes. If there is slight difference in signal timings, you have to sit and trim the counter values. Instead if you use manchester decoding, you can derive the clock from signal itself solving the problem of timing variations.
|
|
| Back to top |
|
 |
metal
Joined: 21 Dec 2004 Posts: 369 Helped: 13
|
16 Oct 2006 18:57 rc5 coding in pic |
|
|
|
|
Hi,
As I have already stated, I have not tested this code.
Any way, you are completely right about that, and I have read this kind of info regarding the use of mancheter decoding in order to derive the clock from the RC5 signal it self inorder to detect the leading and trailing edges of the RC5 signal.
I don't know if the code posted by yager does this kind of manchester decoding. Any way, we still need a real simple and reliable code to do that.
I am still a beginner @ C coding, hence I will be watching this thread and see what result we get, hopefully we will end with a good code for RC5 decoding.
Regards
|
|
| Back to top |
|
 |
CMOS
Joined: 06 Jan 2004 Posts: 810 Helped: 39 Location: USA
|
16 Oct 2006 19:12 pic rc-5 |
|
|
|
|
| Yea...I am in the process of testing yage's code. It actually does manchester decoding. Will post out the results soon.
|
|
| Back to top |
|
 |
btbass
Joined: 20 Jul 2001 Posts: 1187 Helped: 113 Location: Oberon
|
16 Oct 2006 21:32 rc5 pic c |
|
|
|
|
Working RC5 decoder thats calibrates timing and uses Manchester decoding.
Call routine from interrupt when RB0 goes low, or call by polling IR input pin and call when it goes low.
| Code: |
/*------ 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 ---*/
|
Header file
| Code: |
/*--- 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 ---*/
|
Last edited by btbass on 17 Oct 2006 12:48; edited 1 time in total |
|
| Back to top |
|
 |
Google AdSense

|
16 Oct 2006 21:32 Ads |
|
|
|
|
|
|
| Back to top |
|
 |
metal
Joined: 21 Dec 2004 Posts: 369 Helped: 13
|
17 Oct 2006 5:53 philips rc5 codes |
|
|
|
|
Hi,
Thanks for sharing the code btbass. I would like to know what IR receiver chip I can use with this code, also how to connect it to PIC RB0 pin. Do I have to invert it, or just copnnect it to the IR receiver without any inversion.
Another thing, how can I know that a remote control unit is using RC5 protocol. I mean what kind of well known TVs that use it. For example we all know that sony TVs does use SIRC, and philips TVs use RC5.
Here we have non-branded remote control units shops that have no brands, just tell the shop man what TV brand you have, and he gives you the remote control unit that replaces the broken old one.
Regards
|
|
| Back to top |
|
 |
yousafzai
Joined: 01 Jun 2006 Posts: 259 Helped: 6
|
17 Oct 2006 8:27 rc5 c code for pic |
|
|
|
|
| is RC5 the same as sony SIRC....
|
|
| Back to top |
|
 |
metal
Joined: 21 Dec 2004 Posts: 369 Helped: 13
|
17 Oct 2006 8:37 pic ir rc5 |
|
|
|
|
| No, they are different. I don't know what the exact difference, but according to my knowledge, they are different.
|
|
| Back to top |
|
 |
btbass
Joined: 20 Jul 2001 Posts: 1187 Helped: 113 Location: Oberon
|
17 Oct 2006 12:50 philips rc5 code |
|
|
|
|
I use a IS1U60 from RS, order code 577-897. But there are a lot of other similar receivers available.
This is a 3 terminal device, 5V, GND and output. It has an optical filter, an amplifier, demodulator and output driver all inside so you just take the output pin straight into the Pic input pin. The only other component needed is a 0.1uF decoupling cap accross its supply rail.
RC5 is a Philips protocol, but is also used by some other manufacturers.
PS. Please recopy the code, I made a typo translating the asm to c function.
|
|
| Back to top |
|
 |
CMOS
Joined: 06 Jan 2004 Posts: 810 Helped: 39 Location: USA
|
17 Oct 2006 20:33 rc5 code yager |
|
|
|
|
Hi btbass,
I tried your code with 12F629, and it is working like charm.
My conenctions are like this
GPIO2 = IR Receiver
GPIO1 = RX Pin (MAX232)
GPIO0 = TX Pin (MAX232)
Thanks a lot buddy!!
Here is the full code.
| Code: |
//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 ---*/
|
| Code: |
//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;
}
|
| Code: |
/*--- 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 ---*/
|
|
|
| Back to top |
|
 |
CMOS
Joined: 06 Jan 2004 Posts: 810 Helped: 39 Location: USA
|
20 Oct 2006 7:35 rc5 c source encoder |
|
|
|
|
Hi btbass,
Your code is working well but sometimes I get data even though no switch on remote is pressed. Is there any way to filter this??
And yager, I tried your code several times but it doesn't seem to work
Is it possible for you to post a working example? I want to compare btbass and your code's performance.
Thanks.
|
|
| Back to top |
|
 |
btbass
Joined: 20 Jul 2001 Posts: 1187 Helped: 113 Location: Oberon
|
20 Oct 2006 13:22 rc5 pic example |
|
|
|
|
Good to hear the code works ok for you.
As for the noise, first check that there isnt something else transmitting. I once had a problem and it turned out that my laptop was intermitantly sending out ir signals.
also, the IS1U60 has quite a good optical filter that blocks out non ir sources.
I will try to optimise the code so that when it is calibrating the pulse length, it checks that it is close to 1.8mS long and rejects it if it isnt.
Also, after using the results, set rc5valid to false.
To get better results, a resonator or xtal is better than a rc oscillator for clock source, but with a 12F629 I dont suppose you have that choice!
|
|
| Back to top |
|
 |
CMOS
Joined: 06 Jan 2004 Posts: 810 Helped: 39 Location: USA
|
20 Oct 2006 19:16 rc5 code pic |
|
|
|
|
I think even my laptop is doing the same thing....I'll try turning off the laptop and see if it is the culprit.
I can even use Crystal with 12F629. I'll also try and see if it gives better results.
|
|
| Back to top |
|
 |
yager
Joined: 28 May 2001 Posts: 116 Helped: 19
|
21 Oct 2006 8:36 rc5 pic |
|
|
|
|
| CMOS wrote: |
Hi btbass,
Your code is working well but sometimes I get data even though no switch on remote is pressed. Is there any way to filter this?? |
I encountered it before, but my problem was coming from the IR Receiver Chip.
To try to enlarge the capacitor between its VCC and GND. (I used 4.7uF)
| CMOS wrote: |
And yager, I tried your code several times but it doesn't seem to work . |
Really?! Actaully, I ripped it from my production code
which it is working for Mircosoft-Philips RC6 for XP MCE (Media Center Edition).
Since it can receive RC6 and learn/transmit any raw IR data stream under 32~455KHz carrier,
so I cut/modified to support RC5 from the big one. The core idea should be working, I think.
| CMOS wrote: |
| Is it possible for you to post a working example? |
Well, I will base on the above code and build a working one to meet your target hardware (PIC12F629 @ internal 4MHz OSC, GPIO0=TX, GPIO2=IR).
EDIT:
Here is the working one. No any true interrupt be used, all of them by polling.
RC5.h
| Code: |
#include <12F629.h>
#FUSES NOWDT //No Watch Dog Timer
#FUSES INTRC_IO //Internal RC Osc, no CLKOUT
#FUSES NOCPD //No EE protection
#FUSES NOPROTECT //Code not protected from reading
#FUSES NOMCLR //Master Clear pin used for I/O
#FUSES PUT //Power Up Timer
#FUSES NOBROWNOUT //No brownout reset
#use delay(clock=4000000)
#use rs232(baud=9600,parity=N,xmit=PIN_A0,rcv=PIN_A1,bits=8) |
RC5.c
| Code: |
#include "RC5.h"
typedef unsigned int8 U8;
typedef unsigned int16 U16;
typedef int1 BIT;
#define VOID void
#pragma use fast_io (A)
#pragma byte GPIO = 0x05
#pragma byte TMR0 = 0x01
#pragma byte INTCON = 0x0B
#pragma byte PIR1 = 0x0C
#pragma bit TMR1F = PIR1.0
#pragma byte IOC = 0x96
#pragma bit IR_IOC = IOC.2
#pragma bit IR_PIN = GPIO.2
#pragma bit IR_INT = INTCON.0
#define IR_TIME TMR0
#define enable_INT_IR() IR_IOC = 1
#define clr_INT_IR() IR_PIN = 1; IR_INT = 0
#define is_INT_IR() (IR_INT != 0)
#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
#define nIRtimeBase 32 // 32uS
#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)
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 30000 // 25mS: 14*(889+889)=24.892mS
//#define timeout_RUNTIME_IR() (get_timer1() > nIRruntime)
#define timeout_RUNTIME_IR() (TMR1F != 0)
#define set_RUNTIME_IR(tm) set_timer1(65536UL-(tm)); TMR1F = 0
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
enable_INT_IR();
clr_INT_IR();
}
VOID TimeoutIR( VOID ) // check IR running timeout
{
if( gIRstat != stIR_NONE) {
if( timeout_RUNTIME_IR() ) { // timeout
InitIR();
}
}
}
VOID PollIR( VOID ) // put it in ISR (trigger when IR_PIN edge is changed)
{
U8 mIRtime;
mIRtime = get_TIME_IR(); set_TIME_IR(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
set_RUNTIME_IR(nIRruntime); // 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
//-clr_INT_IR();
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()
{
port_a_pullups(0xFF);
setup_timer_0(RTCC_INTERNAL|RTCC_DIV_32);
setup_timer_1(T1_INTERNAL|T1_DIV_BY_1);
// TODO: USER CODE!!
printf( "IR\n" );
InitIR();
while(TRUE) {
if( is_INT_IR() ) {
clr_INT_IR();
PollIR();
if( bIRnewHit == TRUE ) { // new IR code is coming
bIRnewHit = FALSE;
// process IR event here
printf( "%4lX\n", gIRdata );
}
}
TimeoutIR();
}
} |
Here is the whole project file which you can build it with CCS v4.012.
Just build or burn & play.
|
|
| Back to top |
|
 |
CMOS
Joined: 06 Jan 2004 Posts: 810 Helped: 39 Location: USA
|
21 Oct 2006 20:05 c code for rc5 for pic |
|
|
|
|
Ok..cool. Will try that out and post the results soon.
Thanks for your efforts and help.
|
|
| Back to top |
|
 |
btbass
Joined: 20 Jul 2001 Posts: 1187 Helped: 113 Location: Oberon
|
25 Oct 2006 16:03 ccs rc5 |
|
|
|
|
Hi CMOS
I have added pulse length checking to the code. It does not check the real time length of the first pulse due to the variations in timing from different handsets, but checks that subsequent pulses are within limits of the first calibrated pulse time. Checking that we have received 12 pulses of equal length makes the algorithm less susceptible to false reception. This adds a few extra lines to the code and a couple more variables. I have removed 'rc5valid' variable from the code but the function returns 1 or 0 so you can still use code like
If(rc5Decode()){
//valid code;
}
else{
//invalid code;
}
| Code: |
/*------ RC5 decoder program Version 1.1 (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 to calibrate timing.
;------ 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.
;------ Then it checks that the pulse length was within limits of the calibrated pulse.
;------ 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 pulse;
unsigned char HiLimit;
unsigned char LoLimit;
/*--- 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
retlw 0x00 ;bail out
movf TMR,w ;save pulse length
clrf TMR ;start timer
movwf _timer ;take the pulse length,
movwf _temp ;save it
;------ init limits
movwf _HiLimit;
incf _HiLimit
incf _HiLimit
movwf _LoLimit
decf _LoLimit
decf _LoLimit
;------ calculate delay
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
call CheckIt ;check pulse length
movwf _pulse
btfsc _pulse,0
retlw 0x00 ;bail out
bsf 3,0 ;gonna be a 1
goto clock
;------ wait for low 0
waitlow call Wlow
call CheckIt ;check pulse length
movwf _pulse
btfsc _pulse,0
retlw 0x00 ;bail out
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
retlw 0x01 ;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
;------ check pulse length
CheckIt movf TMR,w ;save pulse length
movwf _pulse
subwf _LoLimit,w ;compare with low limit
btfsc 3,2 ;equal to low limit?
retlw 0x00 ;pulse ok
btfsc 3,0
retlw 0x01 ;less then low limit!
movf _pulse,w ;get pulse length
subwf _HiLimit,w ;compare with high limit
btfsc 3,2 ;equal to high limit?
retlw 0x00 ;pulse ok
btfss 3,0
retlw 0x01 ;greater then high limit!
retlw 0x00 ;pulse ok
#endasm
}
/*--- End of File ---*/
|
Header file:
| Code: |
/*--- 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 */
#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 ---*/
|
I did try to write it all in C, but even when I try to help it, the Hi-Tech compiler adds a load of lines of code, increasing the size of the function quite a lot. The reason behind trying to keep the code as small as possible is that at the moment, decoding an RC5 command takes about 25mS. In a lot of applications, this is not a problem, but for some real time applications, tying the micro up for 25mS is not on. So the next step is to make it an interrupt driven function, whereby it is called on every transition of the IR input pin, updates it's state and returns as quickly as possible back to the main program flow.
|
|
| Back to top |
|
 |
CMOS
Joined: 06 Jan 2004 Posts: 810 Helped: 39 Location: USA
|
25 Oct 2006 17:13 pic rc5 ir |
|
|
|
|
Hi btbass,
Thanks. I'll also try your new code.
In the mean time, I tested Yager's code. It is simply mind-blowing. I kept the circuit running nearly for 48 hours and not a single false data was received!! WOW...People you can consider this as the best RC5 decoder for PIC. Awsome man!! You ROCK
Thanks once again Yager and btbass.
|
|
| Back to top |
|
 |
CMOS
Joined: 06 Jan 2004 Posts: 810 Helped: 39 Location: USA
|
27 Oct 2006 10:31 ir rc5 pic |
|
|
|
|
Hi btbass.....I also tried your code for nearly 48 hours and sorry to say that it gives out about 1 false data every hour or so. However it can be filtered out if you allow data to be sent to serial port only if received address matches the defined one [if(address == REMOTE_ADDRESS)].
The code still needs tweaking.
In Yager's code I did not put any address comparison, yet it never gave out any false data.
Anyways thanks both of you for your time and efforts. CHEERS!
|
|
| Back to top |
|
 |
btbass
Joined: 20 Jul 2001 Posts: 1187 Helped: 113 Location: Oberon
|
27 Oct 2006 23:53 pic ir rc-5 #int |
|
|
|
|
Hi CMOS, thanks for your efforts in testing the code.
What did you do to test the code and get the results? What was your test set up?
Perhaps my code has advantages in size when space is tight?
I am working on my interrupt driven version, will post it when done.
|
|
| Back to top |
|
 |
CMOS
Joined: 06 Jan 2004 Posts: 810 Helped: 39 Location: USA
|
28 Oct 2006 18:32 12f629 rc5 |
|
|
|
|
Hi btbass,
My setup is not very special. The circuit include PIC12F629, MAX232 and 5V regulated power supply. Hyper-Terminal was used to monitor the data coming from serial port. With this setup I noticed that about every hour I got false data. And the weired thing was each time data received was 63 (0x3F - All data bits logic 1 !!).
Also if you are talking about the code effeciency....Here are the results with HiTech and CCS compilers (i.e. Your code in HITECH and Yager's code in CCS)
HITECH
Total ROM used 811 words (79.3%)
Total RAM used 48 bytes (75.0%)
CCS
ROM used: 354 (35%)
RAM used: 12 (19%)
Don't you think these results are surprising?? These are not totally dependent on your code but also on the the "stdio" library (printf). But still there is drastic difference!! And people still consider Hi-Tech as Industry Standard for PICs??
|
|
| Back to top |
|
 |
metal
Joined: 21 Dec 2004 Posts: 369 Helped: 13
|
28 Oct 2006 18:46 yager rc5 |
|
|
|
|
Hello CMOS,
I have tested Yager's SIRC code as well on PIC16F877A, its CCS~328 words. I had the same results you got with Yager's RC5 code, it was really stable and error free.
I also wrote a small delphi software that receives the data from the COM port and controls winamp, results were just amazing and accurate.
My IR module receiver was really bad, even if I put my finger infornt of it, I get wrong data with my code for SIRC, but when I used Yager's SIRC code, it did not matter how good my IR receiver is. I concluded that if I use a real high quality IR receiver, I can say its going to be error free.
As a matter of fact, Yager's method is very brilliant, and works well in most noisy situations for both RC5 and SIRC, which is a must in a good code.
Tonight I will test Yager's SIRC ode for PICC, and report the code size and results as well.
Thank you all for the great efforts
|
|
| Back to top |
|
 |