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.
Code:gettag: 'THEORY: '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 'units. '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 testing: 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 NEXT B1 search: 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 ELSE b3 = B3 + 1 IF (B3 < 5) THEN search 'after 5 good pulses try to read tag ENDIF '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 startloop: 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 PAUSEUS 12 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 ENDIF 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 ELSE PAUSEUS 100 'pause to equalize the execution time of the 'two IF options ENDIF NEXT B1 '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 ELSE 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 ENDIF ENDIF NEXT B1 '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 exitloop: LOW RFIDON GOSUB tagout 'subroutine to serout the tag ID. RETURN




Bookmarks