View Full Version : Reading in Manchester code

- 10th March 2009, 21:55
I searched and searched for a way for a pic to handle incoming manchester code, and found no useful examples. I noted that converting binary code to manchester and vice-versa is easy when you have the numbers in hand, but reading in a manchester signal is a bit tricky, especially if you do not want to rely heavily on the timing capability of the PIC or the signal source. So, after a bit of struggling, I came up with the subroutine below. I typed in some lengthly notes to help make sense of the whole thing. I don't list the variables I used, but they should be more or less apparent, and some are discussed in the notes. The variable polltime determines how long to wait for incoming manchester code, and must be defined before running the subroutine. Note that this code works with a PIC16F688 receiving data from a U2270B RFID reader. If you want a schematic for the reader setup, just download the U2270B datasheet. I followed the second application example except that I tied the CFE pin to ground. If the whole parity setup makes no sense, go to this page: http://www.priority1design.com.au/em4100_protocol.html

To the PICBASIC gurus: I'm not a professional programmer or engineer, so I would appreciate any pointers in the direction of more elegant code.

To my fellow hacks: I hope this proves useful.

'This subroutine reads in manchester code from a U2270B RFID
'reader. The reader frequency is (in this case) set at 125kHz,
'and the manchester output is at 1/64 of this frequency (1953b/s
'or 512us per bit when a tag is present. The output from the
'reader sends pulses to the pin designated RFIDIN. If no tag
'is present these pulses are random in length and generally
'longer than 600uS. If a tag is present, the pulses conform to
'a bit rate of about 1953 bits/sec or 512us per bit. The
'Manchester code will consist of long pulses (about 512us each)
'and short ones (about 256us). I use a PIC16F688 with the
'internal oscillator set to 8MHz. Hence, the units of PULSIN
'are 5us periods, so PULSIN should measure a short pulse as
'about 50 units (256us/5us) and a long pulse as about 100 units
'(512us/5us). In practice these periods are about 55 and 110
'When a tag is present it will transmit its code over and over.
'There is a string of nine ones preceding the actual code data.
'After determining that pulses of appropriate length are coming
'in, the subroutine looks for 9 high bits. It is
'impossible to get nine high bits anywhere in the actual
'data stream because of the parity setup. When the PIC gets
'nine high bits in a row, it begins storing data
'into a 7 byte array called ID. The data are read in by noting
'the state of the output pin and then waiting for the transition
'that should occur as part of every bit. After the transition is
'detected, there is a pause to wait until the transmission enters
'the pre-transition phase. Then the state of the pin is stored and
'the wait begins again. This way the PIC uses the regular
'transitions to time the data transfer as opposed to relying
'heavily on the internal timer. When all of the tag data are read
'(55 bits in all) the subroutine performs a parity check (both
'row and column parity of a 4 by 10 matrix) and filters out the
'parity bits to yield a 5 byte array called RFID with the five
'bytes that make up the actual tag code.
HIGH RFIDON 'Sets U2270B standby pin to high
PAUSE 50 'pause to let antenna coil power up.
W2 = 0 'counts number of read attempts
B3 = 0 'counts number of consecutive correct pulses
FOR B1 = 4 to 0 STEP -1 'set RFID array to $FFFFFFFFFF
RFID[B1] = $FF 'designates no tag read
W2 = w2 + 1
IF W2 >= polltime THEN exitloop
PULSIN RFIDIN, 0, W1 'look for a low pulse of appropriate length
IF (W1 < 40) OR (W1 > 115) THEN 'pulses out of range are noise
b3 = 0
GOTO search
b3 = B3 + 1
IF (B3 < 5) THEN search 'after 5 good pulses try to read tag

'The following loop reads bits, waits for nine 1's and then stores
'the data in ID byte array.
B3 = 0 'This byte counts the number of ones read initially
B5 = 0 'counts attempts to read nine 1's
PAR = 0 'set parity storage bit to zero
FOR B1 = 55 to 0 STEP -1
PAUSEUS 200 'pause to enter the pre-transition phase of next bit
ID.0(B1) = RFIDIN 'save state of RFIDIN pin to ID array
'note that the state of the RFID pin at
'the pretransition phase corresponds to the
'actual value of the bit (0 to 1 = 0 and 1
'to 0 = 1).
B6 = 0 'this will count the waiting loops below
REPEAT 'wait for next transition
B6 = B6 + 1 'counts waiting instances
IF B6 > 50 THEN testing 'Exit If no transition
UNTIL RFIDIN <> ID.0(b1) 'exit loop
IF B3 < 9 THEN 'Count consectuve 1's if needed
B5 = B5 + 1 'count attempts
IF B5 >= 150 THEN 'Exit If nine 1's are not
B3 = 0 'read in 150 bits
GOTO search
B3 = (B3 + 1) * ID.0(B1) 'Add to B3 if 1 was read;
'set B3 to zero if 0 was read
'then start over.
GOTO startloop 'B1 does not advance until after nine
'1's are read
PAUSEUS 100 'pause to equalize the execution time of the
'two IF options


'Paritycheck: First a row check and then column checks.
'Every 5th bit is a row parity bit for the previous four
'Bits 5 through 2 are column parity bits for four columns.
'SEROUT2 SDOUT,16468,[DEC W2, 10, 13]
PAR = 0 'parity storage (bit variable, 1 or 0, so 1 + 1 = 0)
B0 = 0 'stores 4 column parity bits
B2 = 4 'Counter to denote row parity bits and to sort column parity bits
B5 = 39 'Counter for sorting ID data into RFID array
FOR B1 = 55 to 1 step -1 '55 steps for 55 bits
iF B2 = 0 THEN 'When B2 = 0 then we have a parity bit
IF (PAR <> ID.0(b1)) AND (b1 > 5) THEN testing
PAR = 0 'reset parity bit
B2 = 4 'reset counter
B2 = B2 - 1 'Max 4, min 0
PAR = PAR + ID.0(b1) 'add to row parity bit
IF B1 > 6 THEN 'Don't do parity calcs with last bits
b0.0(B2) = B0.0(B2) + ID.0(b1) 'column parity bits saved
'in last 4 B0 bits
RFID.0(B5) = ID.0(b1)
B5 = B5 - 1
'column check
B1 = (ID[0] >> 2)//%00010000 'extract parity bits to last 4 bits of B1
IF B0 <> B1 then testing 'compare B0 and B1 for parity check
GOSUB tagout 'subroutine to serout the tag ID.