viknes1985
Joined: 03 Sep 2008 Posts: 8 Helped: 1
|
20 Jan 2009 15:38 manchester code |
|
|
|
|
Hi, I tried to get help from many people on machester decoding. No one could help. So i started to read the manchester code. The idea is, if the width of the pulse is 90us, pic start to sample after 45us. So it would always stay in the middle of the pulse. This is so far i got to, but no idea why this never works. anyone, please help Please help. I'll work on myself on decoding, for now, i just want to read the code from EM4001. If you've any other method, let me know (viknes1985(at)hotmail.com)
| Code: |
#include <16F877A.h>
//#FUSES XT,NOWDT,NOPROTECT,NOPUT, HS, NOLVP
#FUSES NOWDT //No Watch Dog Timer
#FUSES HS //High speed Osc (> 4mhz)
#FUSES NOPUT //No Power Up Timer
#FUSES NOPROTECT //Code not protected from reading
#FUSES NODEBUG //No Debug mode for ICD
#FUSES NOBROWNOUT //No brownout reset
#FUSES NOLVP
#use delay(clock=20000000)
#use rs232(baud=9600,xmit=PIN_B6,rcv=PIN_B7,stream=TOPC)
//#use rs232(baud=9600,xmit=PIN_D7,rcv=PIN_D6,stream=SIGNAL)
//#byte a_port = 5 //Port you want to use
#byte b_port = 6
//#byte d_port = 8
#int_ccp1
void main ()
{
//SET_TRIS_A(0x0A);
SET_TRIS_B(0x81);
setup_ccp1(CCP_CAPTURE_RE); // to know the starting point
if (CCP_1) //if there's any rising edge
{
delay_us(45); //shift to half of the pulse
while (TRUE)
{
int x=0;
while (x<=64) //for 64 bits
{
if (input(PIN_B0)) //from u2270 output (manchester code)
fputc('1'); //show 1 when high
else
fputc('0'); // show 0 when low
delay_us(90); //shift to next pulse
x++;
}
delay_ms(1000);
fputs(" Next 64 bits ");
}
}
else
{
fputs(" Not Yet find the rising edge ");
}
} |
|
|
btbass
Joined: 20 Jul 2001 Posts: 1187 Helped: 113 Location: Oberon
|
21 Jan 2009 19:43 decoding manchester code |
|
|
|
|
The Pic16C56 is a very early pic microprocessor, If a C56 can do it, then a later device like the Pic16F877a should be able to.
Look for application note 'AN744' which describes a decoder for the Pic16f872 written in C. You might be able to port that code. One thing about Pic microprossesors is that they share common modules. The registers have the same names. So code say, written for an A/D converter for one Pic16F variant will more then likely compile and run on a different Pic16F variant. Porting code between variants is quite easy. Normaly you just have to change the configuration fuses and a couple of register names.
I have written a Manchester decoder for Philips RC5. I know this is a lot slower and shorter, but I did find you can not trust the timing, if there is a small error, it accumalates over the data lenght and screws up the decoding. With RC5, the first 2 bits are always 1, so I used the first 2 bits to calibrate the timing. On every new command the timing is recalibrated and it works ok.
Here is the code, it is a C function but the code is written in assmbler, maybe give you some ideas.
Header file:
| Code: |
/*--- rc5decode.h ---*/
#ifndef RC5DECODE_H
#define RC5DECODE_H
#include "types.h"
/*--- Function prototype ---*/
uint8_t rc5Decode(void);
/*---- globals ---*/
extern uint8_t command; /* rc5 command code */
extern uint8_t address; /* rc5 system address */
#endif
/*--- Macros ---*/
#define IR_IN _GPIO,0 /* Infra Red input pin */
#define TMR _TMR0 /* Pulse timer */
/*--- End of file ---*/
|
RC5 Manchester decoder.
| Code: |
/*------ RC5 decoder program Version 1.0 '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 ---*/
uint8_t command = 48;
uint8_t address;
uint8_t temp;
uint8_t timer;
uint8_t pulse;
uint8_t HiLimit;
uint8_t LoLimit;
/*--- rc5 decode function ---*/
uint8_t 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
;------ Clear result regs
clrf _address
clrf _command
;------ 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 ---*/
|
|
|