]> git.zerfleddert.de Git - proxmark3-svn/blame - armsrc/lfops.c
Add printf, and start transitioning away from DbpInteger
[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
0fa9ca5b 9#include "hitag2.h"\r
9bea179a 10#include "../common/crc16.c"\r
11\r
6f5cb60c 12int sprintf(char *dest, const char *fmt, ...);\r
13\r
9bea179a 14void AcquireRawAdcSamples125k(BOOL at134khz)\r
15{\r
16 if(at134khz) {\r
17 FpgaSendCommand(FPGA_CMD_SET_DIVISOR, 88); //134.8Khz\r
18 FpgaWriteConfWord(FPGA_MAJOR_MODE_LF_READER);\r
19 } else {\r
20 FpgaSendCommand(FPGA_CMD_SET_DIVISOR, 95); //125Khz\r
21 FpgaWriteConfWord(FPGA_MAJOR_MODE_LF_READER);\r
22 }\r
23\r
24 // Connect the A/D to the peak-detected low-frequency path.\r
25 SetAdcMuxFor(GPIO_MUXSEL_LOPKD);\r
26\r
27 // Give it a bit of time for the resonant antenna to settle.\r
28 SpinDelay(50);\r
29\r
30 // Now set up the SSC to get the ADC samples that are now streaming at us.\r
31 FpgaSetupSsc();\r
32\r
33 // Now call the acquisition routine\r
34 DoAcquisition125k(at134khz);\r
35}\r
36\r
37// split into two routines so we can avoid timing issues after sending commands //\r
38void DoAcquisition125k(BOOL at134khz)\r
39{\r
40 BYTE *dest = (BYTE *)BigBuf;\r
41 int n = sizeof(BigBuf);\r
42 int i;\r
6f5cb60c 43 char output_string[64];\r
44 \r
9bea179a 45 memset(dest,0,n);\r
46 i = 0;\r
47 for(;;) {\r
6f5cb60c 48 if (AT91C_BASE_SSC->SSC_SR & AT91C_SSC_TXRDY) {\r
6949aca9 49 AT91C_BASE_SSC->SSC_THR = 0x43;\r
9bea179a 50 LED_D_ON();\r
51 }\r
6f5cb60c 52 if(AT91C_BASE_SSC->SSC_SR & AT91C_SSC_RXRDY) {\r
6949aca9 53 dest[i] = (BYTE)AT91C_BASE_SSC->SSC_RHR;\r
9bea179a 54 i++;\r
55 LED_D_OFF();\r
6f5cb60c 56 if (i >= n) break;\r
9bea179a 57 }\r
58 }\r
6f5cb60c 59 sprintf(output_string, "read samples, dest[0]=%x dest[1]=%x at134khz=%d",\r
60 dest[0], dest[1], at134khz);\r
61 DbpString(output_string);\r
9bea179a 62}\r
63\r
64void ModThenAcquireRawAdcSamples125k(int delay_off,int period_0,int period_1,BYTE *command)\r
65{\r
66 BOOL at134khz;\r
67\r
0fa9ca5b 68 /* Make sure the tag is reset */\r
69 FpgaWriteConfWord(FPGA_MAJOR_MODE_OFF);\r
70 SpinDelay(2500);\r
71 \r
9bea179a 72 // see if 'h' was specified\r
73 if(command[strlen((char *) command) - 1] == 'h')\r
74 at134khz= TRUE;\r
75 else\r
76 at134khz= FALSE;\r
77\r
78 if(at134khz) {\r
79 FpgaSendCommand(FPGA_CMD_SET_DIVISOR, 88); //134.8Khz\r
80 FpgaWriteConfWord(FPGA_MAJOR_MODE_LF_READER);\r
81 } else {\r
82 FpgaSendCommand(FPGA_CMD_SET_DIVISOR, 95); //125Khz\r
83 FpgaWriteConfWord(FPGA_MAJOR_MODE_LF_READER);\r
84 }\r
85\r
86 // Give it a bit of time for the resonant antenna to settle.\r
87 SpinDelay(50);\r
0fa9ca5b 88 // And a little more time for the tag to fully power up\r
89 SpinDelay(2000);\r
9bea179a 90\r
91 // Now set up the SSC to get the ADC samples that are now streaming at us.\r
92 FpgaSetupSsc();\r
93\r
94 // now modulate the reader field\r
95 while(*command != '\0' && *command != ' ')\r
96 {\r
97 FpgaWriteConfWord(FPGA_MAJOR_MODE_OFF);\r
98 LED_D_OFF();\r
99 SpinDelayUs(delay_off);\r
100 if(at134khz) {\r
101 FpgaSendCommand(FPGA_CMD_SET_DIVISOR, 88); //134.8Khz\r
102 FpgaWriteConfWord(FPGA_MAJOR_MODE_LF_READER);\r
103 } else {\r
104 FpgaSendCommand(FPGA_CMD_SET_DIVISOR, 95); //125Khz\r
105 FpgaWriteConfWord(FPGA_MAJOR_MODE_LF_READER);\r
106 }\r
107 LED_D_ON();\r
0fa9ca5b 108 if(*(command++) == '0') {\r
9bea179a 109 SpinDelayUs(period_0);\r
0fa9ca5b 110 } else {\r
9bea179a 111 SpinDelayUs(period_1);\r
112 }\r
0fa9ca5b 113 }\r
9bea179a 114 FpgaWriteConfWord(FPGA_MAJOR_MODE_OFF);\r
115 LED_D_OFF();\r
116 SpinDelayUs(delay_off);\r
117 if(at134khz) {\r
118 FpgaSendCommand(FPGA_CMD_SET_DIVISOR, 88); //134.8Khz\r
119 FpgaWriteConfWord(FPGA_MAJOR_MODE_LF_READER);\r
120 } else {\r
121 FpgaSendCommand(FPGA_CMD_SET_DIVISOR, 95); //125Khz\r
122 FpgaWriteConfWord(FPGA_MAJOR_MODE_LF_READER);\r
123 }\r
124\r
125 // now do the read\r
126 DoAcquisition125k(at134khz);\r
127}\r
128\r
7381e8f2 129/* blank r/w tag data stream\r
130...0000000000000000 01111111\r
1311010101010101010101010101010101010101010101010101010101010101010\r
1320011010010100001\r
13301111111\r
134101010101010101[0]000...\r
135\r
136[5555fe852c5555555555555555fe0000]\r
137*/\r
138void ReadTItag()\r
139{\r
140 // some hardcoded initial params\r
141 // when we read a TI tag we sample the zerocross line at 2Mhz\r
142 // TI tags modulate a 1 as 16 cycles of 123.2Khz\r
143 // TI tags modulate a 0 as 16 cycles of 134.2Khz\r
144 #define FSAMPLE 2000000\r
145 #define FREQLO 123200\r
146 #define FREQHI 134200\r
147\r
148 signed char *dest = (signed char *)BigBuf;\r
149 int n = sizeof(BigBuf);\r
150// int *dest = GraphBuffer;\r
151// int n = GraphTraceLen;\r
152\r
153 // 128 bit shift register [shift3:shift2:shift1:shift0]\r
154 DWORD shift3 = 0, shift2 = 0, shift1 = 0, shift0 = 0;\r
155\r
156 int i, cycles=0, samples=0;\r
157 // how many sample points fit in 16 cycles of each frequency\r
158 DWORD sampleslo = (FSAMPLE<<4)/FREQLO, sampleshi = (FSAMPLE<<4)/FREQHI;\r
159 // when to tell if we're close enough to one freq or another\r
160 DWORD threshold = (sampleslo - sampleshi + 1)>>1;\r
161\r
162 // TI tags charge at 134.2Khz\r
163 FpgaSendCommand(FPGA_CMD_SET_DIVISOR, 88); //134.8Khz\r
164\r
165 // Place FPGA in passthrough mode, in this mode the CROSS_LO line\r
166 // connects to SSP_DIN and the SSP_DOUT logic level controls\r
167 // whether we're modulating the antenna (high)\r
168 // or listening to the antenna (low)\r
169 FpgaWriteConfWord(FPGA_MAJOR_MODE_LF_PASSTHRU);\r
170\r
171 // get TI tag data into the buffer\r
172 AcquireTiType();\r
173\r
174 FpgaWriteConfWord(FPGA_MAJOR_MODE_OFF);\r
175\r
176 for (i=0; i<n-1; i++) {\r
177 // count cycles by looking for lo to hi zero crossings\r
178 if ( (dest[i]<0) && (dest[i+1]>0) ) {\r
179 cycles++;\r
180 // after 16 cycles, measure the frequency\r
181 if (cycles>15) {\r
182 cycles=0;\r
183 samples=i-samples; // number of samples in these 16 cycles\r
184\r
185 // TI bits are coming to us lsb first so shift them\r
186 // right through our 128 bit right shift register\r
187 shift0 = (shift0>>1) | (shift1 << 31);\r
188 shift1 = (shift1>>1) | (shift2 << 31);\r
189 shift2 = (shift2>>1) | (shift3 << 31);\r
190 shift3 >>= 1;\r
191\r
192 // check if the cycles fall close to the number\r
193 // expected for either the low or high frequency\r
194 if ( (samples>(sampleslo-threshold)) && (samples<(sampleslo+threshold)) ) {\r
195 // low frequency represents a 1\r
196 shift3 |= (1<<31);\r
197 } else if ( (samples>(sampleshi-threshold)) && (samples<(sampleshi+threshold)) ) {\r
198 // high frequency represents a 0\r
199 } else {\r
200 // probably detected a gay waveform or noise\r
201 // use this as gaydar or discard shift register and start again\r
202 shift3 = shift2 = shift1 = shift0 = 0;\r
203 }\r
204 samples = i;\r
205\r
206 // for each bit we receive, test if we've detected a valid tag\r
207\r
208 // if we see 17 zeroes followed by 6 ones, we might have a tag\r
209 // remember the bits are backwards\r
210 if ( ((shift0 & 0x7fffff) == 0x7e0000) ) {\r
211 // if start and end bytes match, we have a tag so break out of the loop\r
212 if ( ((shift0>>16)&0xff) == ((shift3>>8)&0xff) ) {\r
213 cycles = 0xF0B; //use this as a flag (ugly but whatever)\r
214 break;\r
215 }\r
216 }\r
217 }\r
218 }\r
219 }\r
220\r
221 // if flag is set we have a tag\r
222 if (cycles!=0xF0B) {\r
223 DbpString("Info: No valid tag detected.");\r
224 } else {\r
225 // put 64 bit data into shift1 and shift0\r
226 shift0 = (shift0>>24) | (shift1 << 8);\r
227 shift1 = (shift1>>24) | (shift2 << 8);\r
228\r
229 // align 16 bit crc into lower half of shift2\r
230 shift2 = ((shift2>>24) | (shift3 << 8)) & 0x0ffff;\r
231\r
232 // if r/w tag, check ident match\r
233 if ( shift3&(1<<15) ) {\r
234 DbpString("Info: TI tag is rewriteable");\r
235 // only 15 bits compare, last bit of ident is not valid\r
236 if ( ((shift3>>16)^shift0)&0x7fff ) {\r
237 DbpString("Error: Ident mismatch!");\r
238 } else {\r
239 DbpString("Info: TI tag ident is valid");\r
240 }\r
241 } else {\r
242 DbpString("Info: TI tag is readonly");\r
243 }\r
244\r
245 // WARNING the order of the bytes in which we calc crc below needs checking\r
246 // i'm 99% sure the crc algorithm is correct, but it may need to eat the\r
247 // bytes in reverse or something\r
248 // calculate CRC\r
249 DWORD crc=0;\r
250\r
251 crc = update_crc16(crc, (shift0)&0xff);\r
252 crc = update_crc16(crc, (shift0>>8)&0xff);\r
253 crc = update_crc16(crc, (shift0>>16)&0xff);\r
254 crc = update_crc16(crc, (shift0>>24)&0xff);\r
255 crc = update_crc16(crc, (shift1)&0xff);\r
256 crc = update_crc16(crc, (shift1>>8)&0xff);\r
257 crc = update_crc16(crc, (shift1>>16)&0xff);\r
258 crc = update_crc16(crc, (shift1>>24)&0xff);\r
259\r
6f5cb60c 260 char output_string[64];\r
261 sprintf(output_string, "Info: Tag data_hi=%x, data_lo=%x, crc=%x",\r
262 (unsigned int)shift1, (unsigned int)shift0, (unsigned int)shift2 & 0xFFFF);\r
263 DbpString(output_string);\r
7381e8f2 264 if (crc != (shift2&0xffff)) {\r
6f5cb60c 265 sprintf(output_string, "Error: CRC mismatch, expected %x", (unsigned int)crc);\r
266 DbpString(output_string);\r
7381e8f2 267 } else {\r
268 DbpString("Info: CRC is good");\r
269 }\r
270 }\r
271}\r
272\r
273void WriteTIbyte(BYTE b)\r
274{\r
275 int i = 0;\r
276\r
277 // modulate 8 bits out to the antenna\r
278 for (i=0; i<8; i++)\r
279 {\r
280 if (b&(1<<i)) {\r
281 // stop modulating antenna\r
6949aca9 282 LOW(GPIO_SSC_DOUT);\r
7381e8f2 283 SpinDelayUs(1000);\r
284 // modulate antenna\r
6949aca9 285 HIGH(GPIO_SSC_DOUT);\r
7381e8f2 286 SpinDelayUs(1000);\r
287 } else {\r
288 // stop modulating antenna\r
6949aca9 289 LOW(GPIO_SSC_DOUT);\r
7381e8f2 290 SpinDelayUs(300);\r
291 // modulate antenna\r
6949aca9 292 HIGH(GPIO_SSC_DOUT);\r
7381e8f2 293 SpinDelayUs(1700);\r
294 }\r
295 }\r
296}\r
297\r
9bea179a 298void AcquireTiType(void)\r
299{\r
7381e8f2 300 int i, j, n;\r
9bea179a 301 // tag transmission is <20ms, sampling at 2M gives us 40K samples max\r
302 // each sample is 1 bit stuffed into a DWORD so we need 1250 DWORDS\r
7381e8f2 303 #define TIBUFLEN 1250\r
9bea179a 304\r
305 // clear buffer\r
306 memset(BigBuf,0,sizeof(BigBuf));\r
307\r
308 // Set up the synchronous serial port\r
6949aca9 309 AT91C_BASE_PIOA->PIO_PDR = GPIO_SSC_DIN;\r
310 AT91C_BASE_PIOA->PIO_ASR = GPIO_SSC_DIN;\r
9bea179a 311\r
312 // steal this pin from the SSP and use it to control the modulation\r
6949aca9 313 AT91C_BASE_PIOA->PIO_PER = GPIO_SSC_DOUT;\r
314 AT91C_BASE_PIOA->PIO_OER = GPIO_SSC_DOUT;\r
9bea179a 315\r
6949aca9 316 AT91C_BASE_SSC->SSC_CR = AT91C_SSC_SWRST;\r
317 AT91C_BASE_SSC->SSC_CR = AT91C_SSC_RXEN | AT91C_SSC_TXEN;\r
9bea179a 318\r
6949aca9 319 // Sample at 2 Mbit/s, so TI tags are 16.2 vs. 14.9 clocks long\r
320 // 48/2 = 24 MHz clock must be divided by 12\r
321 AT91C_BASE_SSC->SSC_CMR = 12;\r
9bea179a 322\r
6949aca9 323 AT91C_BASE_SSC->SSC_RCMR = SSC_CLOCK_MODE_SELECT(0);\r
324 AT91C_BASE_SSC->SSC_RFMR = SSC_FRAME_MODE_BITS_IN_WORD(32) | AT91C_SSC_MSBF;\r
325 AT91C_BASE_SSC->SSC_TCMR = 0;\r
326 AT91C_BASE_SSC->SSC_TFMR = 0;\r
9bea179a 327\r
328 LED_D_ON();\r
329\r
330 // modulate antenna\r
6949aca9 331 HIGH(GPIO_SSC_DOUT);\r
9bea179a 332\r
333 // Charge TI tag for 50ms.\r
334 SpinDelay(50);\r
335\r
336 // stop modulating antenna and listen\r
6949aca9 337 LOW(GPIO_SSC_DOUT);\r
9bea179a 338\r
339 LED_D_OFF();\r
340\r
341 i = 0;\r
342 for(;;) {\r
6949aca9 343 if(AT91C_BASE_SSC->SSC_SR & AT91C_SSC_RXRDY) {\r
344 BigBuf[i] = AT91C_BASE_SSC->SSC_RHR; // store 32 bit values in buffer\r
345 i++; if(i >= TIBUFLEN) break;\r
346 }\r
347 WDT_HIT();\r
9bea179a 348 }\r
349\r
350 // return stolen pin to SSP\r
6949aca9 351 AT91C_BASE_PIOA->PIO_PDR = GPIO_SSC_DOUT;\r
352 AT91C_BASE_PIOA->PIO_ASR = GPIO_SSC_DIN | GPIO_SSC_DOUT;\r
9bea179a 353\r
7381e8f2 354 char *dest = (char *)BigBuf;\r
355 n = TIBUFLEN*32;\r
356 // unpack buffer\r
357 for (i=TIBUFLEN-1; i>=0; i--) {\r
358// DbpIntegers(0, 0, BigBuf[i]);\r
359 for (j=0; j<32; j++) {\r
360 if(BigBuf[i] & (1 << j)) {\r
361 dest[--n] = 1;\r
362 } else {\r
363 dest[--n] = -1;\r
364 }\r
9bea179a 365 }\r
366 }\r
367}\r
368\r
9bea179a 369// arguments: 64bit data split into 32bit idhi:idlo and optional 16bit crc\r
370// if crc provided, it will be written with the data verbatim (even if bogus)\r
371// if not provided a valid crc will be computed from the data and written.\r
372void WriteTItag(DWORD idhi, DWORD idlo, WORD crc)\r
373{\r
374\r
375 // WARNING the order of the bytes in which we calc crc below needs checking\r
376 // i'm 99% sure the crc algorithm is correct, but it may need to eat the\r
377 // bytes in reverse or something\r
378\r
379 if(crc == 0) {\r
380 crc = update_crc16(crc, (idlo)&0xff);\r
381 crc = update_crc16(crc, (idlo>>8)&0xff);\r
382 crc = update_crc16(crc, (idlo>>16)&0xff);\r
383 crc = update_crc16(crc, (idlo>>24)&0xff);\r
384 crc = update_crc16(crc, (idhi)&0xff);\r
385 crc = update_crc16(crc, (idhi>>8)&0xff);\r
386 crc = update_crc16(crc, (idhi>>16)&0xff);\r
387 crc = update_crc16(crc, (idhi>>24)&0xff);\r
388 }\r
6f5cb60c 389 char output_string[64];\r
390 sprintf(output_string, "Writing the following data to tag: %x, %x, %x",\r
391 (unsigned int) idhi, (unsigned int) idlo, crc);\r
392 DbpString(output_string);\r
9bea179a 393\r
394 // TI tags charge at 134.2Khz\r
395 FpgaSendCommand(FPGA_CMD_SET_DIVISOR, 88); //134.8Khz\r
396 // Place FPGA in passthrough mode, in this mode the CROSS_LO line\r
397 // connects to SSP_DIN and the SSP_DOUT logic level controls\r
398 // whether we're modulating the antenna (high)\r
399 // or listening to the antenna (low)\r
400 FpgaWriteConfWord(FPGA_MAJOR_MODE_LF_PASSTHRU);\r
401 LED_A_ON();\r
402\r
403 // steal this pin from the SSP and use it to control the modulation\r
6949aca9 404 AT91C_BASE_PIOA->PIO_PER = GPIO_SSC_DOUT;\r
6f5cb60c 405 AT91C_BASE_PIOA->PIO_OER = GPIO_SSC_DOUT;\r
9bea179a 406\r
407 // writing algorithm:\r
408 // a high bit consists of a field off for 1ms and field on for 1ms\r
409 // a low bit consists of a field off for 0.3ms and field on for 1.7ms\r
410 // initiate a charge time of 50ms (field on) then immediately start writing bits\r
411 // start by writing 0xBB (keyword) and 0xEB (password)\r
412 // then write 80 bits of data (or 64 bit data + 16 bit crc if you prefer)\r
413 // finally end with 0x0300 (write frame)\r
414 // all data is sent lsb firts\r
415 // finish with 15ms programming time\r
416\r
417 // modulate antenna\r
6949aca9 418 HIGH(GPIO_SSC_DOUT);\r
9bea179a 419 SpinDelay(50); // charge time\r
420\r
421 WriteTIbyte(0xbb); // keyword\r
422 WriteTIbyte(0xeb); // password\r
423 WriteTIbyte( (idlo )&0xff );\r
424 WriteTIbyte( (idlo>>8 )&0xff );\r
425 WriteTIbyte( (idlo>>16)&0xff );\r
426 WriteTIbyte( (idlo>>24)&0xff );\r
427 WriteTIbyte( (idhi )&0xff );\r
428 WriteTIbyte( (idhi>>8 )&0xff );\r
429 WriteTIbyte( (idhi>>16)&0xff );\r
430 WriteTIbyte( (idhi>>24)&0xff ); // data hi to lo\r
431 WriteTIbyte( (crc )&0xff ); // crc lo\r
432 WriteTIbyte( (crc>>8 )&0xff ); // crc hi\r
433 WriteTIbyte(0x00); // write frame lo\r
434 WriteTIbyte(0x03); // write frame hi\r
6949aca9 435 HIGH(GPIO_SSC_DOUT);\r
9bea179a 436 SpinDelay(50); // programming time\r
437\r
438 LED_A_OFF();\r
439\r
440 // get TI tag data into the buffer\r
441 AcquireTiType();\r
442\r
443 FpgaWriteConfWord(FPGA_MAJOR_MODE_OFF);\r
7381e8f2 444 DbpString("Now use tiread to check");\r
9bea179a 445}\r
446\r
447void SimulateTagLowFrequency(int period, int ledcontrol)\r
448{\r
449 int i;\r
450 BYTE *tab = (BYTE *)BigBuf;\r
451\r
452 FpgaWriteConfWord(FPGA_MAJOR_MODE_LF_SIMULATOR);\r
453\r
6949aca9 454 AT91C_BASE_PIOA->PIO_PER = GPIO_SSC_DOUT | GPIO_SSC_CLK;\r
9bea179a 455\r
6949aca9 456 AT91C_BASE_PIOA->PIO_OER = GPIO_SSC_DOUT;\r
457 AT91C_BASE_PIOA->PIO_ODR = GPIO_SSC_CLK;\r
9bea179a 458\r
459#define SHORT_COIL() LOW(GPIO_SSC_DOUT)\r
6949aca9 460#define OPEN_COIL() HIGH(GPIO_SSC_DOUT)\r
9bea179a 461\r
462 i = 0;\r
463 for(;;) {\r
6949aca9 464 while(!(AT91C_BASE_PIOA->PIO_PDSR & GPIO_SSC_CLK)) {\r
9bea179a 465 if(BUTTON_PRESS()) {\r
466 DbpString("Stopped");\r
467 return;\r
468 }\r
469 WDT_HIT();\r
470 }\r
471\r
472 if (ledcontrol)\r
473 LED_D_ON();\r
474\r
475 if(tab[i])\r
476 OPEN_COIL();\r
477 else\r
478 SHORT_COIL();\r
479\r
480 if (ledcontrol)\r
481 LED_D_OFF();\r
482\r
6949aca9 483 while(AT91C_BASE_PIOA->PIO_PDSR & GPIO_SSC_CLK) {\r
9bea179a 484 if(BUTTON_PRESS()) {\r
485 DbpString("Stopped");\r
486 return;\r
487 }\r
488 WDT_HIT();\r
489 }\r
490\r
491 i++;\r
492 if(i == period) i = 0;\r
493 }\r
494}\r
495\r
0fa9ca5b 496/* Provides a framework for bidirectional LF tag communication\r
497 * Encoding is currently Hitag2, but the general idea can probably\r
498 * be transferred to other encodings.\r
499 * \r
500 * The new FPGA code will, for the LF simulator mode, give on SSC_FRAME\r
501 * (PA15) a thresholded version of the signal from the ADC. Setting the\r
502 * ADC path to the low frequency peak detection signal, will enable a\r
503 * somewhat reasonable receiver for modulation on the carrier signal\r
504 * that is generated by the reader. The signal is low when the reader\r
505 * field is switched off, and high when the reader field is active. Due\r
506 * to the way that the signal looks like, mostly only the rising edge is\r
507 * useful, your mileage may vary.\r
508 * \r
509 * Neat perk: PA15 can not only be used as a bit-banging GPIO, but is also\r
510 * TIOA1, which can be used as the capture input for timer 1. This should\r
511 * make it possible to measure the exact edge-to-edge time, without processor\r
512 * intervention.\r
513 * \r
514 * Arguments: divisor is the divisor to be sent to the FPGA (e.g. 95 for 125kHz)\r
515 * t0 is the carrier frequency cycle duration in terms of MCK (384 for 125kHz)\r
516 * \r
517 * The following defines are in carrier periods: \r
518 */\r
519#define HITAG_T_0_MIN 15 /* T[0] should be 18..22 */ \r
520#define HITAG_T_1_MIN 24 /* T[1] should be 26..30 */\r
521#define HITAG_T_EOF 40 /* T_EOF should be > 36 */\r
522#define HITAG_T_WRESP 208 /* T_wresp should be 204..212 */\r
523\r
524static void hitag_handle_frame(int t0, int frame_len, char *frame);\r
525//#define DEBUG_RA_VALUES 1\r
526#define DEBUG_FRAME_CONTENTS 1\r
527void SimulateTagLowFrequencyBidir(int divisor, int t0)\r
528{\r
529#if DEBUG_RA_VALUES || DEBUG_FRAME_CONTENTS\r
530 int i = 0;\r
531#endif\r
532 char frame[10];\r
533 int frame_pos=0;\r
534 \r
535 DbpString("Starting Hitag2 emulator, press button to end");\r
536 hitag2_init();\r
537 \r
538 /* Set up simulator mode, frequency divisor which will drive the FPGA\r
6949aca9 539 * and analog mux selection.\r
0fa9ca5b 540 */\r
541 FpgaWriteConfWord(FPGA_MAJOR_MODE_LF_SIMULATOR);\r
542 FpgaSendCommand(FPGA_CMD_SET_DIVISOR, divisor);\r
543 SetAdcMuxFor(GPIO_MUXSEL_LOPKD);\r
544 RELAY_OFF();\r
545 \r
546 /* Set up Timer 1:\r
547 * Capture mode, timer source MCK/2 (TIMER_CLOCK1), TIOA is external trigger,\r
548 * external trigger rising edge, load RA on rising edge of TIOA, load RB on rising\r
6949aca9 549 * edge of TIOA. Assign PA15 to TIOA1 (peripheral B)\r
0fa9ca5b 550 */\r
551 \r
6949aca9 552 AT91C_BASE_PMC->PMC_PCER = (1 << AT91C_ID_TC1);\r
553 AT91C_BASE_PIOA->PIO_BSR = GPIO_SSC_FRAME;\r
554 AT91C_BASE_TC1->TC_CCR = AT91C_TC_CLKDIS;\r
555 AT91C_BASE_TC1->TC_CMR = TC_CMR_TCCLKS_TIMER_CLOCK1 |\r
556 AT91C_TC_ETRGEDG_RISING |\r
557 AT91C_TC_ABETRG |\r
558 AT91C_TC_LDRA_RISING |\r
559 AT91C_TC_LDRB_RISING;\r
560 AT91C_BASE_TC1->TC_CCR = AT91C_TC_CLKEN |\r
561 AT91C_TC_SWTRG;\r
0fa9ca5b 562 \r
563 /* calculate the new value for the carrier period in terms of TC1 values */\r
564 t0 = t0/2;\r
565 \r
566 int overflow = 0;\r
567 while(!BUTTON_PRESS()) {\r
568 WDT_HIT();\r
6949aca9 569 if(AT91C_BASE_TC1->TC_SR & AT91C_TC_LDRAS) {\r
570 int ra = AT91C_BASE_TC1->TC_RA;\r
0fa9ca5b 571 if((ra > t0*HITAG_T_EOF) | overflow) ra = t0*HITAG_T_EOF+1;\r
572#if DEBUG_RA_VALUES\r
573 if(ra > 255 || overflow) ra = 255;\r
574 ((char*)BigBuf)[i] = ra;\r
575 i = (i+1) % 8000;\r
576#endif\r
577 \r
578 if(overflow || (ra > t0*HITAG_T_EOF) || (ra < t0*HITAG_T_0_MIN)) {\r
579 /* Ignore */\r
580 } else if(ra >= t0*HITAG_T_1_MIN ) {\r
581 /* '1' bit */\r
582 if(frame_pos < 8*sizeof(frame)) {\r
583 frame[frame_pos / 8] |= 1<<( 7-(frame_pos%8) );\r
584 frame_pos++;\r
585 }\r
586 } else if(ra >= t0*HITAG_T_0_MIN) {\r
587 /* '0' bit */\r
588 if(frame_pos < 8*sizeof(frame)) {\r
589 frame[frame_pos / 8] |= 0<<( 7-(frame_pos%8) );\r
590 frame_pos++;\r
591 }\r
592 }\r
593 \r
594 overflow = 0;\r
595 LED_D_ON();\r
596 } else {\r
6949aca9 597 if(AT91C_BASE_TC1->TC_CV > t0*HITAG_T_EOF) {\r
0fa9ca5b 598 /* Minor nuisance: In Capture mode, the timer can not be\r
599 * stopped by a Compare C. There's no way to stop the clock\r
600 * in software, so we'll just have to note the fact that an\r
601 * overflow happened and the next loaded timer value might\r
602 * have wrapped. Also, this marks the end of frame, and the\r
603 * still running counter can be used to determine the correct\r
6949aca9 604 * time for the start of the reply.\r
0fa9ca5b 605 */ \r
606 overflow = 1;\r
607 \r
608 if(frame_pos > 0) {\r
609 /* Have a frame, do something with it */\r
610#if DEBUG_FRAME_CONTENTS\r
611 ((char*)BigBuf)[i++] = frame_pos;\r
612 memcpy( ((char*)BigBuf)+i, frame, 7);\r
613 i+=7;\r
614 i = i % sizeof(BigBuf);\r
615#endif\r
616 hitag_handle_frame(t0, frame_pos, frame);\r
617 memset(frame, 0, sizeof(frame));\r
618 }\r
619 frame_pos = 0;\r
620\r
621 }\r
622 LED_D_OFF();\r
623 }\r
624 }\r
625 DbpString("All done");\r
626}\r
627\r
628static void hitag_send_bit(int t0, int bit) {\r
629 if(bit == 1) {\r
630 /* Manchester: Loaded, then unloaded */\r
631 LED_A_ON();\r
632 SHORT_COIL();\r
6949aca9 633 while(AT91C_BASE_TC1->TC_CV < t0*15);\r
0fa9ca5b 634 OPEN_COIL();\r
6949aca9 635 while(AT91C_BASE_TC1->TC_CV < t0*31);\r
0fa9ca5b 636 LED_A_OFF();\r
637 } else if(bit == 0) {\r
638 /* Manchester: Unloaded, then loaded */\r
639 LED_B_ON();\r
640 OPEN_COIL();\r
6949aca9 641 while(AT91C_BASE_TC1->TC_CV < t0*15);\r
0fa9ca5b 642 SHORT_COIL();\r
6949aca9 643 while(AT91C_BASE_TC1->TC_CV < t0*31);\r
0fa9ca5b 644 LED_B_OFF();\r
645 }\r
6949aca9 646 AT91C_BASE_TC1->TC_CCR = AT91C_TC_SWTRG; /* Reset clock for the next bit */\r
0fa9ca5b 647 \r
648}\r
649static void hitag_send_frame(int t0, int frame_len, const char const * frame, int fdt)\r
650{\r
651 OPEN_COIL();\r
6949aca9 652 AT91C_BASE_PIOA->PIO_OER = GPIO_SSC_DOUT;\r
0fa9ca5b 653 \r
654 /* Wait for HITAG_T_WRESP carrier periods after the last reader bit,\r
655 * not that since the clock counts since the rising edge, but T_wresp is\r
656 * with respect to the falling edge, we need to wait actually (T_wresp - T_g)\r
6949aca9 657 * periods. The gap time T_g varies (4..10).\r
0fa9ca5b 658 */\r
6949aca9 659 while(AT91C_BASE_TC1->TC_CV < t0*(fdt-8));\r
0fa9ca5b 660\r
6949aca9 661 int saved_cmr = AT91C_BASE_TC1->TC_CMR;\r
662 AT91C_BASE_TC1->TC_CMR &= ~AT91C_TC_ETRGEDG; /* Disable external trigger for the clock */\r
663 AT91C_BASE_TC1->TC_CCR = AT91C_TC_SWTRG; /* Reset the clock and use it for response timing */\r
0fa9ca5b 664 \r
665 int i;\r
666 for(i=0; i<5; i++)\r
667 hitag_send_bit(t0, 1); /* Start of frame */\r
668 \r
669 for(i=0; i<frame_len; i++) {\r
670 hitag_send_bit(t0, !!(frame[i/ 8] & (1<<( 7-(i%8) ))) );\r
671 }\r
672 \r
673 OPEN_COIL();\r
6949aca9 674 AT91C_BASE_TC1->TC_CMR = saved_cmr;\r
0fa9ca5b 675}\r
676\r
677/* Callback structure to cleanly separate tag emulation code from the radio layer. */\r
678static int hitag_cb(const char* response_data, const int response_length, const int fdt, void *cb_cookie)\r
679{\r
680 hitag_send_frame(*(int*)cb_cookie, response_length, response_data, fdt);\r
681 return 0;\r
682}\r
683/* Frame length in bits, frame contents in MSBit first format */\r
684static void hitag_handle_frame(int t0, int frame_len, char *frame)\r
685{\r
686 hitag2_handle_command(frame, frame_len, hitag_cb, &t0);\r
687}\r
688\r
9bea179a 689// compose fc/8 fc/10 waveform\r
690static void fc(int c, int *n) {\r
691 BYTE *dest = (BYTE *)BigBuf;\r
692 int idx;\r
693\r
694 // for when we want an fc8 pattern every 4 logical bits\r
695 if(c==0) {\r
696 dest[((*n)++)]=1;\r
697 dest[((*n)++)]=1;\r
698 dest[((*n)++)]=0;\r
699 dest[((*n)++)]=0;\r
700 dest[((*n)++)]=0;\r
701 dest[((*n)++)]=0;\r
702 dest[((*n)++)]=0;\r
703 dest[((*n)++)]=0;\r
704 }\r
705 // an fc/8 encoded bit is a bit pattern of 11000000 x6 = 48 samples\r
706 if(c==8) {\r
707 for (idx=0; idx<6; idx++) {\r
708 dest[((*n)++)]=1;\r
709 dest[((*n)++)]=1;\r
710 dest[((*n)++)]=0;\r
711 dest[((*n)++)]=0;\r
712 dest[((*n)++)]=0;\r
713 dest[((*n)++)]=0;\r
714 dest[((*n)++)]=0;\r
715 dest[((*n)++)]=0;\r
716 }\r
717 }\r
718\r
719 // an fc/10 encoded bit is a bit pattern of 1110000000 x5 = 50 samples\r
720 if(c==10) {\r
721 for (idx=0; idx<5; idx++) {\r
722 dest[((*n)++)]=1;\r
723 dest[((*n)++)]=1;\r
724 dest[((*n)++)]=1;\r
725 dest[((*n)++)]=0;\r
726 dest[((*n)++)]=0;\r
727 dest[((*n)++)]=0;\r
728 dest[((*n)++)]=0;\r
729 dest[((*n)++)]=0;\r
730 dest[((*n)++)]=0;\r
731 dest[((*n)++)]=0;\r
732 }\r
733 }\r
734}\r
735\r
736// prepare a waveform pattern in the buffer based on the ID given then\r
737// simulate a HID tag until the button is pressed\r
738void CmdHIDsimTAG(int hi, int lo, int ledcontrol)\r
739{\r
740 int n=0, i=0;\r
741 /*\r
742 HID tag bitstream format\r
743 The tag contains a 44bit unique code. This is sent out MSB first in sets of 4 bits\r
744 A 1 bit is represented as 6 fc8 and 5 fc10 patterns\r
745 A 0 bit is represented as 5 fc10 and 6 fc8 patterns\r
746 A fc8 is inserted before every 4 bits\r
747 A special start of frame pattern is used consisting a0b0 where a and b are neither 0\r
748 nor 1 bits, they are special patterns (a = set of 12 fc8 and b = set of 10 fc10)\r
749 */\r
750\r
751 if (hi>0xFFF) {\r
752 DbpString("Tags can only have 44 bits.");\r
753 return;\r
754 }\r
755 fc(0,&n);\r
756 // special start of frame marker containing invalid bit sequences\r
757 fc(8, &n); fc(8, &n); // invalid\r
758 fc(8, &n); fc(10, &n); // logical 0\r
759 fc(10, &n); fc(10, &n); // invalid\r
760 fc(8, &n); fc(10, &n); // logical 0\r
761\r
762 WDT_HIT();\r
763 // manchester encode bits 43 to 32\r
764 for (i=11; i>=0; i--) {\r
765 if ((i%4)==3) fc(0,&n);\r
766 if ((hi>>i)&1) {\r
767 fc(10, &n); fc(8, &n); // low-high transition\r
768 } else {\r
769 fc(8, &n); fc(10, &n); // high-low transition\r
770 }\r
771 }\r
772\r
773 WDT_HIT();\r
774 // manchester encode bits 31 to 0\r
775 for (i=31; i>=0; i--) {\r
776 if ((i%4)==3) fc(0,&n);\r
777 if ((lo>>i)&1) {\r
778 fc(10, &n); fc(8, &n); // low-high transition\r
779 } else {\r
780 fc(8, &n); fc(10, &n); // high-low transition\r
781 }\r
782 }\r
783\r
784 if (ledcontrol)\r
785 LED_A_ON();\r
786 SimulateTagLowFrequency(n, ledcontrol);\r
787\r
788 if (ledcontrol)\r
789 LED_A_OFF();\r
790}\r
791\r
792\r
793// loop to capture raw HID waveform then FSK demodulate the TAG ID from it\r
794void CmdHIDdemodFSK(int findone, int *high, int *low, int ledcontrol)\r
795{\r
796 BYTE *dest = (BYTE *)BigBuf;\r
797 int m=0, n=0, i=0, idx=0, found=0, lastval=0;\r
798 DWORD hi=0, lo=0;\r
799\r
800 FpgaSendCommand(FPGA_CMD_SET_DIVISOR, 95); //125Khz\r
801 FpgaWriteConfWord(FPGA_MAJOR_MODE_LF_READER);\r
802\r
803 // Connect the A/D to the peak-detected low-frequency path.\r
804 SetAdcMuxFor(GPIO_MUXSEL_LOPKD);\r
805\r
806 // Give it a bit of time for the resonant antenna to settle.\r
807 SpinDelay(50);\r
808\r
809 // Now set up the SSC to get the ADC samples that are now streaming at us.\r
810 FpgaSetupSsc();\r
811\r
812 for(;;) {\r
813 WDT_HIT();\r
814 if (ledcontrol)\r
815 LED_A_ON();\r
816 if(BUTTON_PRESS()) {\r
817 DbpString("Stopped");\r
818 if (ledcontrol)\r
819 LED_A_OFF();\r
820 return;\r
821 }\r
822\r
823 i = 0;\r
824 m = sizeof(BigBuf);\r
825 memset(dest,128,m);\r
826 for(;;) {\r
6949aca9 827 if(AT91C_BASE_SSC->SSC_SR & (AT91C_SSC_TXRDY)) {\r
828 AT91C_BASE_SSC->SSC_THR = 0x43;\r
9bea179a 829 if (ledcontrol)\r
830 LED_D_ON();\r
831 }\r
6949aca9 832 if(AT91C_BASE_SSC->SSC_SR & (AT91C_SSC_RXRDY)) {\r
833 dest[i] = (BYTE)AT91C_BASE_SSC->SSC_RHR;\r
9bea179a 834 // we don't care about actual value, only if it's more or less than a\r
835 // threshold essentially we capture zero crossings for later analysis\r
836 if(dest[i] < 127) dest[i] = 0; else dest[i] = 1;\r
837 i++;\r
838 if (ledcontrol)\r
839 LED_D_OFF();\r
840 if(i >= m) {\r
841 break;\r
842 }\r
843 }\r
844 }\r
845\r
846 // FSK demodulator\r
847\r
848 // sync to first lo-hi transition\r
849 for( idx=1; idx<m; idx++) {\r
850 if (dest[idx-1]<dest[idx])\r
851 lastval=idx;\r
852 break;\r
853 }\r
854 WDT_HIT();\r
855\r
856 // count cycles between consecutive lo-hi transitions, there should be either 8 (fc/8)\r
857 // or 10 (fc/10) cycles but in practice due to noise etc we may end up with with anywhere\r
858 // between 7 to 11 cycles so fuzz it by treat anything <9 as 8 and anything else as 10\r
859 for( i=0; idx<m; idx++) {\r
860 if (dest[idx-1]<dest[idx]) {\r
861 dest[i]=idx-lastval;\r
862 if (dest[i] <= 8) {\r
863 dest[i]=1;\r
864 } else {\r
865 dest[i]=0;\r
866 }\r
867\r
868 lastval=idx;\r
869 i++;\r
870 }\r
871 }\r
872 m=i;\r
873 WDT_HIT();\r
874\r
875 // we now have a set of cycle counts, loop over previous results and aggregate data into bit patterns\r
876 lastval=dest[0];\r
877 idx=0;\r
878 i=0;\r
879 n=0;\r
880 for( idx=0; idx<m; idx++) {\r
881 if (dest[idx]==lastval) {\r
882 n++;\r
883 } else {\r
884 // a bit time is five fc/10 or six fc/8 cycles so figure out how many bits a pattern width represents,\r
885 // an extra fc/8 pattern preceeds every 4 bits (about 200 cycles) just to complicate things but it gets\r
886 // swallowed up by rounding\r
887 // expected results are 1 or 2 bits, any more and it's an invalid manchester encoding\r
888 // special start of frame markers use invalid manchester states (no transitions) by using sequences\r
889 // like 111000\r
890 if (dest[idx-1]) {\r
891 n=(n+1)/6; // fc/8 in sets of 6\r
892 } else {\r
893 n=(n+1)/5; // fc/10 in sets of 5\r
894 }\r
895 switch (n) { // stuff appropriate bits in buffer\r
896 case 0:\r
897 case 1: // one bit\r
898 dest[i++]=dest[idx-1];\r
899 break;\r
900 case 2: // two bits\r
901 dest[i++]=dest[idx-1];\r
902 dest[i++]=dest[idx-1];\r
903 break;\r
904 case 3: // 3 bit start of frame markers\r
905 dest[i++]=dest[idx-1];\r
906 dest[i++]=dest[idx-1];\r
907 dest[i++]=dest[idx-1];\r
908 break;\r
909 // When a logic 0 is immediately followed by the start of the next transmisson\r
910 // (special pattern) a pattern of 4 bit duration lengths is created.\r
911 case 4:\r
912 dest[i++]=dest[idx-1];\r
913 dest[i++]=dest[idx-1];\r
914 dest[i++]=dest[idx-1];\r
915 dest[i++]=dest[idx-1];\r
916 break;\r
917 default: // this shouldn't happen, don't stuff any bits\r
918 break;\r
919 }\r
920 n=0;\r
921 lastval=dest[idx];\r
922 }\r
923 }\r
924 m=i;\r
925 WDT_HIT();\r
926\r
927 // final loop, go over previously decoded manchester data and decode into usable tag ID\r
928 // 111000 bit pattern represent start of frame, 01 pattern represents a 1 and 10 represents a 0\r
929 for( idx=0; idx<m-6; idx++) {\r
930 // search for a start of frame marker\r
931 if ( dest[idx] && dest[idx+1] && dest[idx+2] && (!dest[idx+3]) && (!dest[idx+4]) && (!dest[idx+5]) )\r
932 {\r
933 found=1;\r
934 idx+=6;\r
935 if (found && (hi|lo)) {\r
6f5cb60c 936 char output_string[64];\r
937 sprintf(output_string, "TAG ID: %x %x %x", \r
938 (unsigned int) hi, (unsigned int) lo, (unsigned int) (lo>>1) & 0xFFFF);\r
939 DbpString(output_string);\r
9bea179a 940 /* if we're only looking for one tag */\r
941 if (findone)\r
942 {\r
943 *high = hi;\r
944 *low = lo;\r
945 return;\r
946 }\r
947 hi=0;\r
948 lo=0;\r
949 found=0;\r
950 }\r
951 }\r
952 if (found) {\r
953 if (dest[idx] && (!dest[idx+1]) ) {\r
954 hi=(hi<<1)|(lo>>31);\r
955 lo=(lo<<1)|0;\r
956 } else if ( (!dest[idx]) && dest[idx+1]) {\r
957 hi=(hi<<1)|(lo>>31);\r
958 lo=(lo<<1)|1;\r
959 } else {\r
960 found=0;\r
961 hi=0;\r
962 lo=0;\r
963 }\r
964 idx++;\r
965 }\r
966 if ( dest[idx] && dest[idx+1] && dest[idx+2] && (!dest[idx+3]) && (!dest[idx+4]) && (!dest[idx+5]) )\r
967 {\r
968 found=1;\r
969 idx+=6;\r
970 if (found && (hi|lo)) {\r
6f5cb60c 971 char output_string[64];\r
972 sprintf(output_string, "TAG ID: %x %x %x", \r
973 (unsigned int) hi, (unsigned int) lo, (unsigned int) (lo>>1) & 0xFFFF);\r
974 DbpString(output_string);\r
9bea179a 975 /* if we're only looking for one tag */\r
976 if (findone)\r
977 {\r
978 *high = hi;\r
979 *low = lo;\r
980 return;\r
981 }\r
982 hi=0;\r
983 lo=0;\r
984 found=0;\r
985 }\r
986 }\r
987 }\r
988 WDT_HIT();\r
989 }\r
990}\r
Impressum, Datenschutz