]> git.zerfleddert.de Git - proxmark3-svn/blame - armsrc/lfops.c
New FPGA code for bidirectional LF emulation
[proxmark3-svn] / armsrc / lfops.c
CommitLineData
9bea179a 1//-----------------------------------------------------------------------------\r
2// Miscellaneous routines for low frequency tag operations.\r
3// Tags supported here so far are Texas Instruments (TI), HID\r
4// Also routines for raw mode reading/simulating of LF waveform\r
5//\r
6//-----------------------------------------------------------------------------\r
7#include <proxmark3.h>\r
8#include "apps.h"\r
9#include "../common/crc16.c"\r
10\r
11void AcquireRawAdcSamples125k(BOOL at134khz)\r
12{\r
13 if(at134khz) {\r
14 FpgaSendCommand(FPGA_CMD_SET_DIVISOR, 88); //134.8Khz\r
15 FpgaWriteConfWord(FPGA_MAJOR_MODE_LF_READER);\r
16 } else {\r
17 FpgaSendCommand(FPGA_CMD_SET_DIVISOR, 95); //125Khz\r
18 FpgaWriteConfWord(FPGA_MAJOR_MODE_LF_READER);\r
19 }\r
20\r
21 // Connect the A/D to the peak-detected low-frequency path.\r
22 SetAdcMuxFor(GPIO_MUXSEL_LOPKD);\r
23\r
24 // Give it a bit of time for the resonant antenna to settle.\r
25 SpinDelay(50);\r
26\r
27 // Now set up the SSC to get the ADC samples that are now streaming at us.\r
28 FpgaSetupSsc();\r
29\r
30 // Now call the acquisition routine\r
31 DoAcquisition125k(at134khz);\r
32}\r
33\r
34// split into two routines so we can avoid timing issues after sending commands //\r
35void DoAcquisition125k(BOOL at134khz)\r
36{\r
37 BYTE *dest = (BYTE *)BigBuf;\r
38 int n = sizeof(BigBuf);\r
39 int i;\r
40\r
41 memset(dest,0,n);\r
42 i = 0;\r
43 for(;;) {\r
44 if(SSC_STATUS & (SSC_STATUS_TX_READY)) {\r
45 SSC_TRANSMIT_HOLDING = 0x43;\r
46 LED_D_ON();\r
47 }\r
48 if(SSC_STATUS & (SSC_STATUS_RX_READY)) {\r
49 dest[i] = (BYTE)SSC_RECEIVE_HOLDING;\r
50 i++;\r
51 LED_D_OFF();\r
52 if(i >= n) {\r
53 break;\r
54 }\r
55 }\r
56 }\r
57 DbpIntegers(dest[0], dest[1], at134khz);\r
58}\r
59\r
60void ModThenAcquireRawAdcSamples125k(int delay_off,int period_0,int period_1,BYTE *command)\r
61{\r
62 BOOL at134khz;\r
63\r
64 // see if 'h' was specified\r
65 if(command[strlen((char *) command) - 1] == 'h')\r
66 at134khz= TRUE;\r
67 else\r
68 at134khz= FALSE;\r
69\r
70 if(at134khz) {\r
71 FpgaSendCommand(FPGA_CMD_SET_DIVISOR, 88); //134.8Khz\r
72 FpgaWriteConfWord(FPGA_MAJOR_MODE_LF_READER);\r
73 } else {\r
74 FpgaSendCommand(FPGA_CMD_SET_DIVISOR, 95); //125Khz\r
75 FpgaWriteConfWord(FPGA_MAJOR_MODE_LF_READER);\r
76 }\r
77\r
78 // Give it a bit of time for the resonant antenna to settle.\r
79 SpinDelay(50);\r
80\r
81 // Now set up the SSC to get the ADC samples that are now streaming at us.\r
82 FpgaSetupSsc();\r
83\r
84 // now modulate the reader field\r
85 while(*command != '\0' && *command != ' ')\r
86 {\r
87 FpgaWriteConfWord(FPGA_MAJOR_MODE_OFF);\r
88 LED_D_OFF();\r
89 SpinDelayUs(delay_off);\r
90 if(at134khz) {\r
91 FpgaSendCommand(FPGA_CMD_SET_DIVISOR, 88); //134.8Khz\r
92 FpgaWriteConfWord(FPGA_MAJOR_MODE_LF_READER);\r
93 } else {\r
94 FpgaSendCommand(FPGA_CMD_SET_DIVISOR, 95); //125Khz\r
95 FpgaWriteConfWord(FPGA_MAJOR_MODE_LF_READER);\r
96 }\r
97 LED_D_ON();\r
98 if(*(command++) == '0')\r
99 SpinDelayUs(period_0);\r
100 else\r
101 SpinDelayUs(period_1);\r
102 }\r
103 FpgaWriteConfWord(FPGA_MAJOR_MODE_OFF);\r
104 LED_D_OFF();\r
105 SpinDelayUs(delay_off);\r
106 if(at134khz) {\r
107 FpgaSendCommand(FPGA_CMD_SET_DIVISOR, 88); //134.8Khz\r
108 FpgaWriteConfWord(FPGA_MAJOR_MODE_LF_READER);\r
109 } else {\r
110 FpgaSendCommand(FPGA_CMD_SET_DIVISOR, 95); //125Khz\r
111 FpgaWriteConfWord(FPGA_MAJOR_MODE_LF_READER);\r
112 }\r
113\r
114 // now do the read\r
115 DoAcquisition125k(at134khz);\r
116}\r
117\r
7381e8f2 118/* blank r/w tag data stream\r
119...0000000000000000 01111111\r
1201010101010101010101010101010101010101010101010101010101010101010\r
1210011010010100001\r
12201111111\r
123101010101010101[0]000...\r
124\r
125[5555fe852c5555555555555555fe0000]\r
126*/\r
127void ReadTItag()\r
128{\r
129 // some hardcoded initial params\r
130 // when we read a TI tag we sample the zerocross line at 2Mhz\r
131 // TI tags modulate a 1 as 16 cycles of 123.2Khz\r
132 // TI tags modulate a 0 as 16 cycles of 134.2Khz\r
133 #define FSAMPLE 2000000\r
134 #define FREQLO 123200\r
135 #define FREQHI 134200\r
136\r
137 signed char *dest = (signed char *)BigBuf;\r
138 int n = sizeof(BigBuf);\r
139// int *dest = GraphBuffer;\r
140// int n = GraphTraceLen;\r
141\r
142 // 128 bit shift register [shift3:shift2:shift1:shift0]\r
143 DWORD shift3 = 0, shift2 = 0, shift1 = 0, shift0 = 0;\r
144\r
145 int i, cycles=0, samples=0;\r
146 // how many sample points fit in 16 cycles of each frequency\r
147 DWORD sampleslo = (FSAMPLE<<4)/FREQLO, sampleshi = (FSAMPLE<<4)/FREQHI;\r
148 // when to tell if we're close enough to one freq or another\r
149 DWORD threshold = (sampleslo - sampleshi + 1)>>1;\r
150\r
151 // TI tags charge at 134.2Khz\r
152 FpgaSendCommand(FPGA_CMD_SET_DIVISOR, 88); //134.8Khz\r
153\r
154 // Place FPGA in passthrough mode, in this mode the CROSS_LO line\r
155 // connects to SSP_DIN and the SSP_DOUT logic level controls\r
156 // whether we're modulating the antenna (high)\r
157 // or listening to the antenna (low)\r
158 FpgaWriteConfWord(FPGA_MAJOR_MODE_LF_PASSTHRU);\r
159\r
160 // get TI tag data into the buffer\r
161 AcquireTiType();\r
162\r
163 FpgaWriteConfWord(FPGA_MAJOR_MODE_OFF);\r
164\r
165 for (i=0; i<n-1; i++) {\r
166 // count cycles by looking for lo to hi zero crossings\r
167 if ( (dest[i]<0) && (dest[i+1]>0) ) {\r
168 cycles++;\r
169 // after 16 cycles, measure the frequency\r
170 if (cycles>15) {\r
171 cycles=0;\r
172 samples=i-samples; // number of samples in these 16 cycles\r
173\r
174 // TI bits are coming to us lsb first so shift them\r
175 // right through our 128 bit right shift register\r
176 shift0 = (shift0>>1) | (shift1 << 31);\r
177 shift1 = (shift1>>1) | (shift2 << 31);\r
178 shift2 = (shift2>>1) | (shift3 << 31);\r
179 shift3 >>= 1;\r
180\r
181 // check if the cycles fall close to the number\r
182 // expected for either the low or high frequency\r
183 if ( (samples>(sampleslo-threshold)) && (samples<(sampleslo+threshold)) ) {\r
184 // low frequency represents a 1\r
185 shift3 |= (1<<31);\r
186 } else if ( (samples>(sampleshi-threshold)) && (samples<(sampleshi+threshold)) ) {\r
187 // high frequency represents a 0\r
188 } else {\r
189 // probably detected a gay waveform or noise\r
190 // use this as gaydar or discard shift register and start again\r
191 shift3 = shift2 = shift1 = shift0 = 0;\r
192 }\r
193 samples = i;\r
194\r
195 // for each bit we receive, test if we've detected a valid tag\r
196\r
197 // if we see 17 zeroes followed by 6 ones, we might have a tag\r
198 // remember the bits are backwards\r
199 if ( ((shift0 & 0x7fffff) == 0x7e0000) ) {\r
200 // if start and end bytes match, we have a tag so break out of the loop\r
201 if ( ((shift0>>16)&0xff) == ((shift3>>8)&0xff) ) {\r
202 cycles = 0xF0B; //use this as a flag (ugly but whatever)\r
203 break;\r
204 }\r
205 }\r
206 }\r
207 }\r
208 }\r
209\r
210 // if flag is set we have a tag\r
211 if (cycles!=0xF0B) {\r
212 DbpString("Info: No valid tag detected.");\r
213 } else {\r
214 // put 64 bit data into shift1 and shift0\r
215 shift0 = (shift0>>24) | (shift1 << 8);\r
216 shift1 = (shift1>>24) | (shift2 << 8);\r
217\r
218 // align 16 bit crc into lower half of shift2\r
219 shift2 = ((shift2>>24) | (shift3 << 8)) & 0x0ffff;\r
220\r
221 // if r/w tag, check ident match\r
222 if ( shift3&(1<<15) ) {\r
223 DbpString("Info: TI tag is rewriteable");\r
224 // only 15 bits compare, last bit of ident is not valid\r
225 if ( ((shift3>>16)^shift0)&0x7fff ) {\r
226 DbpString("Error: Ident mismatch!");\r
227 } else {\r
228 DbpString("Info: TI tag ident is valid");\r
229 }\r
230 } else {\r
231 DbpString("Info: TI tag is readonly");\r
232 }\r
233\r
234 // WARNING the order of the bytes in which we calc crc below needs checking\r
235 // i'm 99% sure the crc algorithm is correct, but it may need to eat the\r
236 // bytes in reverse or something\r
237 // calculate CRC\r
238 DWORD crc=0;\r
239\r
240 crc = update_crc16(crc, (shift0)&0xff);\r
241 crc = update_crc16(crc, (shift0>>8)&0xff);\r
242 crc = update_crc16(crc, (shift0>>16)&0xff);\r
243 crc = update_crc16(crc, (shift0>>24)&0xff);\r
244 crc = update_crc16(crc, (shift1)&0xff);\r
245 crc = update_crc16(crc, (shift1>>8)&0xff);\r
246 crc = update_crc16(crc, (shift1>>16)&0xff);\r
247 crc = update_crc16(crc, (shift1>>24)&0xff);\r
248\r
249 DbpString("Info: Tag data_hi, data_lo, crc = ");\r
250 DbpIntegers(shift1, shift0, shift2&0xffff);\r
251 if (crc != (shift2&0xffff)) {\r
252 DbpString("Error: CRC mismatch, expected");\r
253 DbpIntegers(0, 0, crc);\r
254 } else {\r
255 DbpString("Info: CRC is good");\r
256 }\r
257 }\r
258}\r
259\r
260void WriteTIbyte(BYTE b)\r
261{\r
262 int i = 0;\r
263\r
264 // modulate 8 bits out to the antenna\r
265 for (i=0; i<8; i++)\r
266 {\r
267 if (b&(1<<i)) {\r
268 // stop modulating antenna\r
269 PIO_OUTPUT_DATA_CLEAR = (1<<GPIO_SSC_DOUT);\r
270 SpinDelayUs(1000);\r
271 // modulate antenna\r
272 PIO_OUTPUT_DATA_SET = (1<<GPIO_SSC_DOUT);\r
273 SpinDelayUs(1000);\r
274 } else {\r
275 // stop modulating antenna\r
276 PIO_OUTPUT_DATA_CLEAR = (1<<GPIO_SSC_DOUT);\r
277 SpinDelayUs(300);\r
278 // modulate antenna\r
279 PIO_OUTPUT_DATA_SET = (1<<GPIO_SSC_DOUT);\r
280 SpinDelayUs(1700);\r
281 }\r
282 }\r
283}\r
284\r
9bea179a 285void AcquireTiType(void)\r
286{\r
7381e8f2 287 int i, j, n;\r
9bea179a 288 // tag transmission is <20ms, sampling at 2M gives us 40K samples max\r
289 // each sample is 1 bit stuffed into a DWORD so we need 1250 DWORDS\r
7381e8f2 290 #define TIBUFLEN 1250\r
9bea179a 291\r
292 // clear buffer\r
293 memset(BigBuf,0,sizeof(BigBuf));\r
294\r
295 // Set up the synchronous serial port\r
296 PIO_DISABLE = (1<<GPIO_SSC_DIN);\r
297 PIO_PERIPHERAL_A_SEL = (1<<GPIO_SSC_DIN);\r
298\r
299 // steal this pin from the SSP and use it to control the modulation\r
300 PIO_ENABLE = (1<<GPIO_SSC_DOUT);\r
301 PIO_OUTPUT_ENABLE = (1<<GPIO_SSC_DOUT);\r
302\r
303 SSC_CONTROL = SSC_CONTROL_RESET;\r
304 SSC_CONTROL = SSC_CONTROL_RX_ENABLE | SSC_CONTROL_TX_ENABLE;\r
305\r
306 // Sample at 2 Mbit/s, so TI tags are 16.2 vs. 14.9 clocks long\r
307 // 48/2 = 24 MHz clock must be divided by 12\r
308 SSC_CLOCK_DIVISOR = 12;\r
309\r
310 SSC_RECEIVE_CLOCK_MODE = SSC_CLOCK_MODE_SELECT(0);\r
311 SSC_RECEIVE_FRAME_MODE = SSC_FRAME_MODE_BITS_IN_WORD(32) | SSC_FRAME_MODE_MSB_FIRST;\r
312 SSC_TRANSMIT_CLOCK_MODE = 0;\r
313 SSC_TRANSMIT_FRAME_MODE = 0;\r
314\r
315 LED_D_ON();\r
316\r
317 // modulate antenna\r
318 PIO_OUTPUT_DATA_SET = (1<<GPIO_SSC_DOUT);\r
319\r
320 // Charge TI tag for 50ms.\r
321 SpinDelay(50);\r
322\r
323 // stop modulating antenna and listen\r
324 PIO_OUTPUT_DATA_CLEAR = (1<<GPIO_SSC_DOUT);\r
325\r
326 LED_D_OFF();\r
327\r
328 i = 0;\r
329 for(;;) {\r
330 if(SSC_STATUS & SSC_STATUS_RX_READY) {\r
331 BigBuf[i] = SSC_RECEIVE_HOLDING; // store 32 bit values in buffer\r
7381e8f2 332 i++; if(i >= TIBUFLEN) break;\r
9bea179a 333 }\r
334 WDT_HIT();\r
335 }\r
336\r
337 // return stolen pin to SSP\r
338 PIO_DISABLE = (1<<GPIO_SSC_DOUT);\r
339 PIO_PERIPHERAL_A_SEL = (1<<GPIO_SSC_DIN) | (1<<GPIO_SSC_DOUT);\r
9bea179a 340\r
7381e8f2 341 char *dest = (char *)BigBuf;\r
342 n = TIBUFLEN*32;\r
343 // unpack buffer\r
344 for (i=TIBUFLEN-1; i>=0; i--) {\r
345// DbpIntegers(0, 0, BigBuf[i]);\r
346 for (j=0; j<32; j++) {\r
347 if(BigBuf[i] & (1 << j)) {\r
348 dest[--n] = 1;\r
349 } else {\r
350 dest[--n] = -1;\r
351 }\r
9bea179a 352 }\r
353 }\r
354}\r
355\r
9bea179a 356// arguments: 64bit data split into 32bit idhi:idlo and optional 16bit crc\r
357// if crc provided, it will be written with the data verbatim (even if bogus)\r
358// if not provided a valid crc will be computed from the data and written.\r
359void WriteTItag(DWORD idhi, DWORD idlo, WORD crc)\r
360{\r
361\r
362 // WARNING the order of the bytes in which we calc crc below needs checking\r
363 // i'm 99% sure the crc algorithm is correct, but it may need to eat the\r
364 // bytes in reverse or something\r
365\r
366 if(crc == 0) {\r
367 crc = update_crc16(crc, (idlo)&0xff);\r
368 crc = update_crc16(crc, (idlo>>8)&0xff);\r
369 crc = update_crc16(crc, (idlo>>16)&0xff);\r
370 crc = update_crc16(crc, (idlo>>24)&0xff);\r
371 crc = update_crc16(crc, (idhi)&0xff);\r
372 crc = update_crc16(crc, (idhi>>8)&0xff);\r
373 crc = update_crc16(crc, (idhi>>16)&0xff);\r
374 crc = update_crc16(crc, (idhi>>24)&0xff);\r
375 }\r
376 DbpString("Writing the following data to tag:");\r
377 DbpIntegers(idhi, idlo, crc);\r
378\r
379 // TI tags charge at 134.2Khz\r
380 FpgaSendCommand(FPGA_CMD_SET_DIVISOR, 88); //134.8Khz\r
381 // Place FPGA in passthrough mode, in this mode the CROSS_LO line\r
382 // connects to SSP_DIN and the SSP_DOUT logic level controls\r
383 // whether we're modulating the antenna (high)\r
384 // or listening to the antenna (low)\r
385 FpgaWriteConfWord(FPGA_MAJOR_MODE_LF_PASSTHRU);\r
386 LED_A_ON();\r
387\r
388 // steal this pin from the SSP and use it to control the modulation\r
389 PIO_ENABLE = (1<<GPIO_SSC_DOUT);\r
390 PIO_OUTPUT_ENABLE = (1<<GPIO_SSC_DOUT);\r
391\r
392 // writing algorithm:\r
393 // a high bit consists of a field off for 1ms and field on for 1ms\r
394 // a low bit consists of a field off for 0.3ms and field on for 1.7ms\r
395 // initiate a charge time of 50ms (field on) then immediately start writing bits\r
396 // start by writing 0xBB (keyword) and 0xEB (password)\r
397 // then write 80 bits of data (or 64 bit data + 16 bit crc if you prefer)\r
398 // finally end with 0x0300 (write frame)\r
399 // all data is sent lsb firts\r
400 // finish with 15ms programming time\r
401\r
402 // modulate antenna\r
403 PIO_OUTPUT_DATA_SET = (1<<GPIO_SSC_DOUT);\r
404 SpinDelay(50); // charge time\r
405\r
406 WriteTIbyte(0xbb); // keyword\r
407 WriteTIbyte(0xeb); // password\r
408 WriteTIbyte( (idlo )&0xff );\r
409 WriteTIbyte( (idlo>>8 )&0xff );\r
410 WriteTIbyte( (idlo>>16)&0xff );\r
411 WriteTIbyte( (idlo>>24)&0xff );\r
412 WriteTIbyte( (idhi )&0xff );\r
413 WriteTIbyte( (idhi>>8 )&0xff );\r
414 WriteTIbyte( (idhi>>16)&0xff );\r
415 WriteTIbyte( (idhi>>24)&0xff ); // data hi to lo\r
416 WriteTIbyte( (crc )&0xff ); // crc lo\r
417 WriteTIbyte( (crc>>8 )&0xff ); // crc hi\r
418 WriteTIbyte(0x00); // write frame lo\r
419 WriteTIbyte(0x03); // write frame hi\r
420 PIO_OUTPUT_DATA_SET = (1<<GPIO_SSC_DOUT);\r
421 SpinDelay(50); // programming time\r
422\r
423 LED_A_OFF();\r
424\r
425 // get TI tag data into the buffer\r
426 AcquireTiType();\r
427\r
428 FpgaWriteConfWord(FPGA_MAJOR_MODE_OFF);\r
7381e8f2 429 DbpString("Now use tiread to check");\r
9bea179a 430}\r
431\r
432void SimulateTagLowFrequency(int period, int ledcontrol)\r
433{\r
434 int i;\r
435 BYTE *tab = (BYTE *)BigBuf;\r
436\r
437 FpgaWriteConfWord(FPGA_MAJOR_MODE_LF_SIMULATOR);\r
438\r
439 PIO_ENABLE = (1 << GPIO_SSC_DOUT) | (1 << GPIO_SSC_CLK);\r
440\r
441 PIO_OUTPUT_ENABLE = (1 << GPIO_SSC_DOUT);\r
442 PIO_OUTPUT_DISABLE = (1 << GPIO_SSC_CLK);\r
443\r
444#define SHORT_COIL() LOW(GPIO_SSC_DOUT)\r
445#define OPEN_COIL() HIGH(GPIO_SSC_DOUT)\r
446\r
447 i = 0;\r
448 for(;;) {\r
449 while(!(PIO_PIN_DATA_STATUS & (1<<GPIO_SSC_CLK))) {\r
450 if(BUTTON_PRESS()) {\r
451 DbpString("Stopped");\r
452 return;\r
453 }\r
454 WDT_HIT();\r
455 }\r
456\r
457 if (ledcontrol)\r
458 LED_D_ON();\r
459\r
460 if(tab[i])\r
461 OPEN_COIL();\r
462 else\r
463 SHORT_COIL();\r
464\r
465 if (ledcontrol)\r
466 LED_D_OFF();\r
467\r
468 while(PIO_PIN_DATA_STATUS & (1<<GPIO_SSC_CLK)) {\r
469 if(BUTTON_PRESS()) {\r
470 DbpString("Stopped");\r
471 return;\r
472 }\r
473 WDT_HIT();\r
474 }\r
475\r
476 i++;\r
477 if(i == period) i = 0;\r
478 }\r
479}\r
480\r
481// compose fc/8 fc/10 waveform\r
482static void fc(int c, int *n) {\r
483 BYTE *dest = (BYTE *)BigBuf;\r
484 int idx;\r
485\r
486 // for when we want an fc8 pattern every 4 logical bits\r
487 if(c==0) {\r
488 dest[((*n)++)]=1;\r
489 dest[((*n)++)]=1;\r
490 dest[((*n)++)]=0;\r
491 dest[((*n)++)]=0;\r
492 dest[((*n)++)]=0;\r
493 dest[((*n)++)]=0;\r
494 dest[((*n)++)]=0;\r
495 dest[((*n)++)]=0;\r
496 }\r
497 // an fc/8 encoded bit is a bit pattern of 11000000 x6 = 48 samples\r
498 if(c==8) {\r
499 for (idx=0; idx<6; idx++) {\r
500 dest[((*n)++)]=1;\r
501 dest[((*n)++)]=1;\r
502 dest[((*n)++)]=0;\r
503 dest[((*n)++)]=0;\r
504 dest[((*n)++)]=0;\r
505 dest[((*n)++)]=0;\r
506 dest[((*n)++)]=0;\r
507 dest[((*n)++)]=0;\r
508 }\r
509 }\r
510\r
511 // an fc/10 encoded bit is a bit pattern of 1110000000 x5 = 50 samples\r
512 if(c==10) {\r
513 for (idx=0; idx<5; idx++) {\r
514 dest[((*n)++)]=1;\r
515 dest[((*n)++)]=1;\r
516 dest[((*n)++)]=1;\r
517 dest[((*n)++)]=0;\r
518 dest[((*n)++)]=0;\r
519 dest[((*n)++)]=0;\r
520 dest[((*n)++)]=0;\r
521 dest[((*n)++)]=0;\r
522 dest[((*n)++)]=0;\r
523 dest[((*n)++)]=0;\r
524 }\r
525 }\r
526}\r
527\r
528// prepare a waveform pattern in the buffer based on the ID given then\r
529// simulate a HID tag until the button is pressed\r
530void CmdHIDsimTAG(int hi, int lo, int ledcontrol)\r
531{\r
532 int n=0, i=0;\r
533 /*\r
534 HID tag bitstream format\r
535 The tag contains a 44bit unique code. This is sent out MSB first in sets of 4 bits\r
536 A 1 bit is represented as 6 fc8 and 5 fc10 patterns\r
537 A 0 bit is represented as 5 fc10 and 6 fc8 patterns\r
538 A fc8 is inserted before every 4 bits\r
539 A special start of frame pattern is used consisting a0b0 where a and b are neither 0\r
540 nor 1 bits, they are special patterns (a = set of 12 fc8 and b = set of 10 fc10)\r
541 */\r
542\r
543 if (hi>0xFFF) {\r
544 DbpString("Tags can only have 44 bits.");\r
545 return;\r
546 }\r
547 fc(0,&n);\r
548 // special start of frame marker containing invalid bit sequences\r
549 fc(8, &n); fc(8, &n); // invalid\r
550 fc(8, &n); fc(10, &n); // logical 0\r
551 fc(10, &n); fc(10, &n); // invalid\r
552 fc(8, &n); fc(10, &n); // logical 0\r
553\r
554 WDT_HIT();\r
555 // manchester encode bits 43 to 32\r
556 for (i=11; i>=0; i--) {\r
557 if ((i%4)==3) fc(0,&n);\r
558 if ((hi>>i)&1) {\r
559 fc(10, &n); fc(8, &n); // low-high transition\r
560 } else {\r
561 fc(8, &n); fc(10, &n); // high-low transition\r
562 }\r
563 }\r
564\r
565 WDT_HIT();\r
566 // manchester encode bits 31 to 0\r
567 for (i=31; i>=0; i--) {\r
568 if ((i%4)==3) fc(0,&n);\r
569 if ((lo>>i)&1) {\r
570 fc(10, &n); fc(8, &n); // low-high transition\r
571 } else {\r
572 fc(8, &n); fc(10, &n); // high-low transition\r
573 }\r
574 }\r
575\r
576 if (ledcontrol)\r
577 LED_A_ON();\r
578 SimulateTagLowFrequency(n, ledcontrol);\r
579\r
580 if (ledcontrol)\r
581 LED_A_OFF();\r
582}\r
583\r
584\r
585// loop to capture raw HID waveform then FSK demodulate the TAG ID from it\r
586void CmdHIDdemodFSK(int findone, int *high, int *low, int ledcontrol)\r
587{\r
588 BYTE *dest = (BYTE *)BigBuf;\r
589 int m=0, n=0, i=0, idx=0, found=0, lastval=0;\r
590 DWORD hi=0, lo=0;\r
591\r
592 FpgaSendCommand(FPGA_CMD_SET_DIVISOR, 95); //125Khz\r
593 FpgaWriteConfWord(FPGA_MAJOR_MODE_LF_READER);\r
594\r
595 // Connect the A/D to the peak-detected low-frequency path.\r
596 SetAdcMuxFor(GPIO_MUXSEL_LOPKD);\r
597\r
598 // Give it a bit of time for the resonant antenna to settle.\r
599 SpinDelay(50);\r
600\r
601 // Now set up the SSC to get the ADC samples that are now streaming at us.\r
602 FpgaSetupSsc();\r
603\r
604 for(;;) {\r
605 WDT_HIT();\r
606 if (ledcontrol)\r
607 LED_A_ON();\r
608 if(BUTTON_PRESS()) {\r
609 DbpString("Stopped");\r
610 if (ledcontrol)\r
611 LED_A_OFF();\r
612 return;\r
613 }\r
614\r
615 i = 0;\r
616 m = sizeof(BigBuf);\r
617 memset(dest,128,m);\r
618 for(;;) {\r
619 if(SSC_STATUS & (SSC_STATUS_TX_READY)) {\r
620 SSC_TRANSMIT_HOLDING = 0x43;\r
621 if (ledcontrol)\r
622 LED_D_ON();\r
623 }\r
624 if(SSC_STATUS & (SSC_STATUS_RX_READY)) {\r
625 dest[i] = (BYTE)SSC_RECEIVE_HOLDING;\r
626 // we don't care about actual value, only if it's more or less than a\r
627 // threshold essentially we capture zero crossings for later analysis\r
628 if(dest[i] < 127) dest[i] = 0; else dest[i] = 1;\r
629 i++;\r
630 if (ledcontrol)\r
631 LED_D_OFF();\r
632 if(i >= m) {\r
633 break;\r
634 }\r
635 }\r
636 }\r
637\r
638 // FSK demodulator\r
639\r
640 // sync to first lo-hi transition\r
641 for( idx=1; idx<m; idx++) {\r
642 if (dest[idx-1]<dest[idx])\r
643 lastval=idx;\r
644 break;\r
645 }\r
646 WDT_HIT();\r
647\r
648 // count cycles between consecutive lo-hi transitions, there should be either 8 (fc/8)\r
649 // or 10 (fc/10) cycles but in practice due to noise etc we may end up with with anywhere\r
650 // between 7 to 11 cycles so fuzz it by treat anything <9 as 8 and anything else as 10\r
651 for( i=0; idx<m; idx++) {\r
652 if (dest[idx-1]<dest[idx]) {\r
653 dest[i]=idx-lastval;\r
654 if (dest[i] <= 8) {\r
655 dest[i]=1;\r
656 } else {\r
657 dest[i]=0;\r
658 }\r
659\r
660 lastval=idx;\r
661 i++;\r
662 }\r
663 }\r
664 m=i;\r
665 WDT_HIT();\r
666\r
667 // we now have a set of cycle counts, loop over previous results and aggregate data into bit patterns\r
668 lastval=dest[0];\r
669 idx=0;\r
670 i=0;\r
671 n=0;\r
672 for( idx=0; idx<m; idx++) {\r
673 if (dest[idx]==lastval) {\r
674 n++;\r
675 } else {\r
676 // a bit time is five fc/10 or six fc/8 cycles so figure out how many bits a pattern width represents,\r
677 // an extra fc/8 pattern preceeds every 4 bits (about 200 cycles) just to complicate things but it gets\r
678 // swallowed up by rounding\r
679 // expected results are 1 or 2 bits, any more and it's an invalid manchester encoding\r
680 // special start of frame markers use invalid manchester states (no transitions) by using sequences\r
681 // like 111000\r
682 if (dest[idx-1]) {\r
683 n=(n+1)/6; // fc/8 in sets of 6\r
684 } else {\r
685 n=(n+1)/5; // fc/10 in sets of 5\r
686 }\r
687 switch (n) { // stuff appropriate bits in buffer\r
688 case 0:\r
689 case 1: // one bit\r
690 dest[i++]=dest[idx-1];\r
691 break;\r
692 case 2: // two bits\r
693 dest[i++]=dest[idx-1];\r
694 dest[i++]=dest[idx-1];\r
695 break;\r
696 case 3: // 3 bit start of frame markers\r
697 dest[i++]=dest[idx-1];\r
698 dest[i++]=dest[idx-1];\r
699 dest[i++]=dest[idx-1];\r
700 break;\r
701 // When a logic 0 is immediately followed by the start of the next transmisson\r
702 // (special pattern) a pattern of 4 bit duration lengths is created.\r
703 case 4:\r
704 dest[i++]=dest[idx-1];\r
705 dest[i++]=dest[idx-1];\r
706 dest[i++]=dest[idx-1];\r
707 dest[i++]=dest[idx-1];\r
708 break;\r
709 default: // this shouldn't happen, don't stuff any bits\r
710 break;\r
711 }\r
712 n=0;\r
713 lastval=dest[idx];\r
714 }\r
715 }\r
716 m=i;\r
717 WDT_HIT();\r
718\r
719 // final loop, go over previously decoded manchester data and decode into usable tag ID\r
720 // 111000 bit pattern represent start of frame, 01 pattern represents a 1 and 10 represents a 0\r
721 for( idx=0; idx<m-6; idx++) {\r
722 // search for a start of frame marker\r
723 if ( dest[idx] && dest[idx+1] && dest[idx+2] && (!dest[idx+3]) && (!dest[idx+4]) && (!dest[idx+5]) )\r
724 {\r
725 found=1;\r
726 idx+=6;\r
727 if (found && (hi|lo)) {\r
728 DbpString("TAG ID");\r
729 DbpIntegers(hi, lo, (lo>>1)&0xffff);\r
730 /* if we're only looking for one tag */\r
731 if (findone)\r
732 {\r
733 *high = hi;\r
734 *low = lo;\r
735 return;\r
736 }\r
737 hi=0;\r
738 lo=0;\r
739 found=0;\r
740 }\r
741 }\r
742 if (found) {\r
743 if (dest[idx] && (!dest[idx+1]) ) {\r
744 hi=(hi<<1)|(lo>>31);\r
745 lo=(lo<<1)|0;\r
746 } else if ( (!dest[idx]) && dest[idx+1]) {\r
747 hi=(hi<<1)|(lo>>31);\r
748 lo=(lo<<1)|1;\r
749 } else {\r
750 found=0;\r
751 hi=0;\r
752 lo=0;\r
753 }\r
754 idx++;\r
755 }\r
756 if ( dest[idx] && dest[idx+1] && dest[idx+2] && (!dest[idx+3]) && (!dest[idx+4]) && (!dest[idx+5]) )\r
757 {\r
758 found=1;\r
759 idx+=6;\r
760 if (found && (hi|lo)) {\r
761 DbpString("TAG ID");\r
762 DbpIntegers(hi, lo, (lo>>1)&0xffff);\r
763 /* if we're only looking for one tag */\r
764 if (findone)\r
765 {\r
766 *high = hi;\r
767 *low = lo;\r
768 return;\r
769 }\r
770 hi=0;\r
771 lo=0;\r
772 found=0;\r
773 }\r
774 }\r
775 }\r
776 WDT_HIT();\r
777 }\r
778}\r
Impressum, Datenschutz