PDA

View Full Version : Manchester Coding / Decodeing for RF Modules



charudatt
- 4th January 2004, 06:44
Hello all,

I was looking for some example on Manchester Coding and Decoding for use with RF Modules.

Want to elimate the Holtek ICs

Any help

Thank you.

Melanie
- 4th January 2004, 10:13
Here is the secret of Manchester encoding/decoding in all it's simplicity... (in case any other reader wants to know why - it's to balance the data slicer in the receiver and help cancel out noise).

Encoding: 8 bit byte becomes 16 bits to transmit... zero's become "01" and ones become "10".

Decoding: 16 bits get deconstructed back to 8 bit byte... "01" gets turned back into a zero and "10" gets turned back into a one.

Example... you are sending byte $00 which is equal to %00000000... this get's turned into %0101010101010101.

Melanie

charudatt
- 4th January 2004, 12:46
Thank you for the information on Manchester.

But could you please explain me with a small example how this word is constructed for sending and how it is decoded when received.

Basically I am looking at hooking a PIC12C508 to the RF modules and trying to send and receive Mancheseter codes over RF.

Thank you.

Melanie
- 5th January 2004, 02:29
Very quick example (Caveat Emptor) since it's two-thirty in the morning and time I was getting my beauty sleep... there's probably better ways of doing this, but with matchsticks propping up my eyelids this is the best you're going to get out of me tonight...

CounterA var Byte
ErrorFlag var Bit
MyData var Byte
ManchesterWord var Word

' Subroutine Encodes Manchester Word
' Enter subroutine with data in MyData
' Exit Subroutine with encoded ManchesterWord
' MyData contents are destroyed on exit
EncodeManchester:
ManchesterWord=0
For CounterA=0 to 7
If MyData.0=0 then
ManchesterWord.14=1
else
ManchesterWord.15=1
endif
If CounterA<7 then ManchesterWord=ManchesterWord>>2
MyData=MyData>>1
Next CounterA
Return

' Subroutine Decodes Manchester Word
' Enter subroutine with encoded data in ManchesterWord
' Exit subroutine with decoded data in MyData
' ManchesterWord contents are destroyed on exit
' Also on exit, ErrorFlag=0 then Data is good
' ErrorFlag=1 then Data is suspect/corrupt
DecodeManchester:
ErrorFlag=0
For CounterA=0 to 7
If ManchesterWord.1=0 then
MyData.7=0
If ManchesterWord.0=0 then ErrorFlag=1
else
MyData.7=1
If ManchesterWord.0=1 then ErrorFlag=1
endif
ManchesterWord=ManchesterWord>>2
If CounterA<7 then MyData=MyData>>1
Return

Melanie

charudatt
- 5th January 2004, 03:12
Thank you very much for the same.

Last but not the least. How do I send it and Rx the same.

Thank for all that help.

I am sure this code and your inputs have helped a lot out there, especially me.

I shall try it and get back to you when I rx this information

regards

charudatt
- 5th January 2004, 03:20
Hello all / Melanie

I found this on the internet hope this also helps all.

Manchester encoding can be done in PBP nice and easy:
From: Ioannis Kyriakidis (I presume)

For d=0 TO 7
IF v.0[d]=0 Then
encoded.0[d*2]=0
encoded.0[d*2+1]=1
Else
encoded.0[d*2]=1
encoded.0[d*2+1]=0
EndIF
Next

d: number of bits to encode (8 bits)
v: byte to BE encoded
encoded: WORD sized variable holding the encoded
byte v.

Note that the encoded value is double size always.

Use the above lines as subroutine to encode a byte before transmission

Squibcakes
- 9th November 2005, 03:40
Mel,
Loooking at your code I'm a bit stumped.

How is each BIT in the MyData referenced to CounterA?

Also.... It looks like you are shifting through each BIT on Mydata on the last line:
MyData=MyData>1

But shouldn't it be: MyData=MyData>>1

I have read your FAQ on Bits, bytes and Words, but I can't relate your code here to the examples given in the FAQ.

But otherwise, the code looks like it should work.

Cheers
J

Melanie
- 9th November 2005, 08:38
Thanks for letting me know. Code has been up for eons and nobody spotted the typo before now!

Squibcakes
- 10th November 2005, 01:43
Hi Mel,

Yep I thought it had a bug, actually there is another ...(I swear I am not picking on you.... ) the NEXT counterA is missing in the EncodeManchester routine.

For a while I had a problem understanding how the shift right >> instruction ran. (Not using this before)

Also I assumed that the MyData BITS are stored in the registers as [0,1,2,3,4,5,6,7], but actually they are the other way around (same goes for the ManchesterWord bits).

Watching the code run through ICD makes a lot of sense. I have attached the code for anyone interested. It is fully working on a 16F628 chip and great to pause the code and swap a few bits in the manchesterword to trigger the ErrorFlag Bit.

Thanks again Melanie :)

Now then, where did I put those RF modules?.....

' ==========================
' DEVICE PROGRAMMING OPTIONS
' ==========================

' PRESET FUSES
@ DEVICE PIC16F628, WDT_ON
@ DEVICE PIC16F628, INTRC_OSC_NOCLKOUT
@ DEVICE PIC16F628, BOD_ON
@ DEVICE PIC16F628, PROTECT_OFF
@ DEVICE PIC16F628, MCLR_ON

' =============
' USER DEFINES
' =============
DEFINE OSC 4

' =================
' SET USART PARAMS
' =================

DEFINE HSER_RCSTA 90h ' Set receive register to receiver enabled
DEFINE HSER_TXSTA 24h
DEFINE HSER_BAUD 4800 ' Set baud rate
DEFINE HSER_SPBRG 51 ' Set SPBRG directly (normally set by HSER_BAUD)

' ===========================
' CONFIGURE COMPARATOR MODULE
' ===========================
CMCON = 7 ' TURN ANALOG COMPARATOR MODE OFF

' ==============
' PROGRAM VARS
' ==============
COUNTERA var Byte
ERRORFLAG var Bit
MYDATA var Byte
MANCHESTERWORD var Word

' ===================
' START
' ===================
START:
HSERIN [MYDATA]
HSEROUT ["ENTERED VALUE: ",MYDATA,13,10]
HSEROUT ["ENCODING TO MANCHESTER NOW",13,10]
GOSUB EncodeManchester
HSEROUT ["ENCODING COMPLETED",13,10]

PAUSE 1000

HSEROUT ["DECODING MANCHESTER NOW",13,10]
GOSUB DECODEMANCHESTER
HSEROUT ["DECODING COMPLETED",13,10]
IF ERRORFLAG THEN
HSEROUT ["VALUE CORRUPTED!: ",MYDATA,13,10,13,10]
ELSE
HSEROUT ["FINAL VALUE: ",MYDATA,13,10,13,10]
ENDIF
GOTO START:

' Subroutine Encodes Manchester Word
' Enter subroutine with data in MyData
' Exit Subroutine with encoded ManchesterWord
' MyData contents are destroyed on exit
ENCODEMANCHESTER:
ManchesterWord=0
For CounterA=0 to 7
If MyData.0=0 then
ManchesterWord.14=1
else
ManchesterWord.15=1
endif
If CounterA<7 then ManchesterWord=ManchesterWord>>2
MyData=MyData>>1
Next CounterA
Return

' Subroutine Decodes Manchester Word
' Enter subroutine with encoded data in ManchesterWord
' Exit subroutine with decoded data in MyData
' ManchesterWord contents are destroyed on exit
' Also on exit, ErrorFlag=0 then Data is good
' ErrorFlag=1 then Data is suspect/corrupt
DECODEMANCHESTER:
ErrorFlag=0
For CounterA=0 to 7
If ManchesterWord.1=0 then
MyData.7=0
If ManchesterWord.0=0 then ErrorFlag=1
else
MyData.7=1
If ManchesterWord.0=1 then ErrorFlag=1
endif
ManchesterWord=ManchesterWord>>2
If CounterA<7 then MyData=MyData>>1
NEXT COUNTERA
Return

charudatt
- 10th November 2005, 02:43
Thank you for your contribution ,Squibcakes.

Your code can be an excellent example for someone wanting RC5 over RF.

regards

a_critchlow
- 2nd February 2006, 20:36
hi all, i don't believe the decoding part of that code works! if you received an encoded stream of 0110100110011010 for example, this would raise the erro flag?

If ManchesterWord.1=0 then
MyData.7=0
If ManchesterWord.0=0 then ErrorFlag=1
else
MyData.7=1
If ManchesterWord.0=1 then ErrorFlag=1
endif



any help?





thanks.

Squibcakes
- 3rd February 2006, 01:03
Have you run the program and seen it work?

I just did and it works fine! Lets see, was the letter you typed in the letter "k"?

It decoded no problems for me.

The best way to inderstand this program is to step through it using ICD mode... its hard to explain without viewing the registers at work.

Good luck, and may the force be with you. :)

Cheers
J

Bruce
- 3rd February 2006, 05:03
There are probably a few hundred ways to do this, but here's a few that I've used with decent results.

The 1st version uses PBP's bit twiddling ability. Version 2 is a modified version of one originally done
by Les Johnson.

The .asm routine is considerably faster & smaller (knocks off 300 words) compared to the BASIC
bit-twiddling approach.


DEFINE LOADER_USED 1
DEFINE OSC 20

; compiled for an 18F2525. 882 words with MPASMWIN 5.01
X VAR BYTE
Y VAR BYTE ' Array index pointer for primary functions
Index VAR BYTE ' Array index pointer for encode/decode routines
BitCount VAR BYTE ' Bit counter
ByteIn VAR BYTE ' Byte to encode
ByteOut VAR BYTE ' Decoded byte
Manch VAR WORD ' Encoded manchester word
Enc_Dat VAR WORD[6] ' Word array for 6 manchester encoded words

GOTO Main ' Jump over encode/decode routines

Encode:
For Index = 0 to 7 ' loop 8-bits
Manch.0[(Index*2)] = ~ByteIn.0[Index] ' Encode bits 0,2,4,6,8,10,12,14 in Manch
Manch.0[(Index*2)+1] = ByteIn.0[Index]' Encode bits 1,3,5,7,9,11,13,15 in Manch
Next Index
Return

Decode::
For Index = 0 to 7 ' loop for 8 bits
ByteOut.0[Index] = ~Manch.0[Index<<1] ' ByteOut bits 0-7 = Manch bits 0,2,4,6,8,10,12,14
Next Index
Return

Main:
CLEAR ' Used for demo to start with all RAM clear
' Encode ASCII characters "A" to "F"
Y = 0 ' Start array index pointer at 0
FOR X = "A" to "F"
ByteIn = X
GOSUB Encode
Enc_Dat[Y] = Manch
HSEROUT ["Encoded ",ByteIn," = ",IBIN16 Enc_Dat[Y],13,10]
Y = Y + 1 ' Increment array index pointer
NEXT X

' Decode & print results
FOR Y = 0 to 5
Manch = Enc_Dat[Y]
GOSUB Decode
HSEROUT ["Decoded ",IBIN16 Manch," = ",ByteOut,13,10]
NEXT Y
PAUSE 10000
GOTO Main

END
And here's a much smaller version. A nice choice; especially for smaller PIC's, but it's somewhat harder
to understand at first glance if you're not familiar with .asm


DEFINE LOADER_USED 1
DEFINE OSC 20

; compiled for an 18F2525. 582 words with MPASMWIN 5.01
X VAR BYTE
Y VAR BYTE
BitCount VAR BYTE bank0 system ' Bank0 system so we don't need an underscore
ByteIn VAR BYTE bank0 system ' to access BASIC variables from assembler
ByteOut VAR BYTE bank0 system
Manch VAR WORD bank0 system ' Holds manchester encoded word
Temp VAR WORD bank0 system ' Temp var
Enc_Dat VAR WORD[6] ' Holds 6 manchester encoded words

GOTO Main ' Jump over encode/decode routines

ASM ; Note: For 14-bit core just change Rlcf to Rlf
; Manchester encode routine
_Encode
Movlw 8
Movwf BitCount
E_Repeat
Rlcf ByteIn,F ; Rotate MSB on ByteIn into carry & test for 1
Btfss STATUS,C ; If bit = 1 then skip to BitSet
Goto BitClr ; If bit = 0 then goto to BitClr
BitSet ; Bit was set, so encode 1 as 10
Rlcf Manch,F
Rlcf Manch+1,F
bcf STATUS,C
Rlcf Manch,F
Rlcf Manch+1,F
Goto E_Loop
BitClr ; Bit was clear, so encode 0 as 01
Rlcf Manch,F
Rlcf Manch+1,F
bsf STATUS,C
Rlcf Manch,F
Rlcf Manch+1,F
E_Loop
Decfsz BitCount,F
Goto E_Repeat
Return
ENDASM

ASM
; Manchester decode routine.
_Decode
Movf Manch+1,W
Movwf Temp+1
Movf Manch,W
Movwf Temp
Movlw 8
Movwf BitCount
Repeat
Rlcf Temp,F
Rlcf Temp+1,F
Rlcf ByteOut,F
Rlcf Temp,F
Rlcf Temp+1,F
Decfsz BitCount,F
Goto Repeat
Return
ENDASM

Main:
CLEAR ' Used for demo to start with all RAM clear
' Manchester encode ASCII characters "A" to "F"
Y = 0 ' Start array index pointer at 0
FOR X = "A" to "F"
ByteIn = X
CALL Encode
Enc_Dat[Y] = Manch
HSEROUT ["Encoded ",X," = ",IBIN16 Enc_Dat[Y],13,10]
Y = Y + 1 ' Increment array index pointer
NEXT X

' Decode & print results
FOR Y = 0 to 5
Manch = Enc_Dat[Y]
CALL Decode
HSEROUT ["Decoded ",IBIN16 Manch," = ",ByteOut,13,10]
NEXT Y
PAUSE 10000
GOTO Main

END
Toss in a few bytes for preamble & synch consisting of an equal 1's & 0's before the encoded data packet,
and you're off to the races....;}

a_critchlow
- 3rd February 2006, 09:15
Thanks for that bruce, would you be able to explain the line:

Manch.0[(Index*2)] = ~ByteIn.0[Index]

for me please? what are the parts in [] doing?





thanks

a_critchlow
- 3rd February 2006, 12:41
hi again, i have figured out how the encode part of the code works, i still cant get the last bit into my head though. The decodeing.

ByteOut.0[Index] = ~Manch.0[Index<<1]



After the equal sign it says to me when counter at 0, NOT Manch.0[Index<<1]. does this mean index(0) left one equaling 0? or shift left on Manch?





thanks.

Bruce
- 3rd February 2006, 14:05
Manch.0[(Index*2)] = ~ByteIn.0[Index]

If Index = 1 this would be Manch.bit2 = NOT ByteIn.bit1

a_critchlow
- 3rd February 2006, 14:28
what about ByteOut.0[Index] = ~Manch.0[Index<<1]


i dont get the [Index<<1] part?









thanks again

Bruce
- 3rd February 2006, 14:38
ByteOut.0[Index] = ~Manch.0[Index<<1]

This just shifts the bit index pointer left by 1. If you run this with a serial connection, MCS ICD, or through MPLAB sim you can see how everything is working.

a_critchlow
- 3rd February 2006, 14:54
to if index starts off and is equal to 0, this is shifted left to 1 and invert the value at 1 to give you the value for 0? this done each time to make up the 8bits.

If you take the encoded bit stream(example): 100110 and run it through the code it will come out like this: 100 (this is wrong as it should be 101)?



many thanks

Bruce
- 3rd February 2006, 15:25
How did you get 100 from %00100110?

The routines I posted take an 8-bit number as the input, and return a 16-bit encoded result.

ASCII characters A to F
..................... input............encoded output..........
Encoded A = %01000001 = %01 10 01 01 01 01 01 10
Encoded B = %01000010 = %01 10 01 01 01 01 10 01
Encoded C = %01000011 = %01 10 01 01 01 01 10 10
Encoded D = %01000100 = %01 10 01 01 01 10 01 01
Encoded E = %01000101 = %01 10 01 01 01 10 01 10
Encoded F = %01000110 = %01 10 01 01 01 10 10 01

If I feed in your value %00100110. I get %0101100101101001

a_critchlow
- 3rd February 2006, 15:31
i going from encoded to decoding..

the code says at counter 0 put into byteout.0 = invert of index pointer left 1.

this inverts a 1 to give you 0 when it should be 1.

it seems that you need to invert the first bit of the encoded data before you start moving through the rest of the code with <<1






regards
andrew

kireytir
- 16th July 2007, 08:39
Encode:
For d = 0 to 3 ' 4 bit
if v.0[d]=0 Then
encoded.0[d*2]=0
encoded.0[d*2+1]=1
else
encoded.0[d*2]=1
encoded.0[d*2+1]=0
endif
next
serout2 portb.0,396,[%1000,encoded]
goto basla
'd: number of bits to encode (8 bits)
'v: byte to BE encoded
'encoded: WORD sized variable holding the encoded
'byte v.


im using this manchester encoding but i didnt decode this pls help..

Ioannis
- 17th July 2007, 09:35
Here are the two subroutines to encode and decode the bi-phase or manchester scheme.

It works for sure.

Ioannis

Skyjumper
- 31st January 2009, 10:51
Even after years still usefull... I was reading this topic, cause I am searching for a true solution. In this topic I miss the 90 degrees phase shifting, I think only bytesize is doubled here. I read somewhere else that Manchester code is a bi-phase code with not only transitions on the beginning of a bit, but at the center of a bit as well. It is defined as a transition orientated code, not a bit orientated. But maybe I am wrong here, cause I am quite new to this, so can anyone explain me please ?