]> git.zerfleddert.de Git - proxmark3-svn/blame - armsrc/iso15693.c
marcan's patch until he gets commit access. Remove C library's includes from the...
[proxmark3-svn] / armsrc / iso15693.c
CommitLineData
6658905f 1//-----------------------------------------------------------------------------\r
2// Routines to support ISO 15693. This includes both the reader software and\r
3// the `fake tag' modes, but at the moment I've implemented only the reader\r
4// stuff, and that barely.\r
5// Jonathan Westhues, split Nov 2006\r
6\r
7// Modified by Greg Jones, Jan 2009 to perform modulation onboard in arm rather than on PC\r
8// Also added additional reader commands (SELECT, READ etc.)\r
9\r
10//-----------------------------------------------------------------------------\r
11#include <proxmark3.h>\r
12#include "apps.h"\r
6658905f 13\r
14// FROM winsrc\prox.h //////////////////////////////////\r
15#define arraylen(x) (sizeof(x)/sizeof((x)[0]))\r
16\r
17//-----------------------------------------------------------------------------\r
18// Map a sequence of octets (~layer 2 command) into the set of bits to feed\r
19// to the FPGA, to transmit that command to the tag.\r
20//-----------------------------------------------------------------------------\r
21\r
6658905f 22 // The sampling rate is 106.353 ksps/s, for T = 18.8 us\r
23\r
f7c64b57 24 // SOF defined as\r
6658905f 25 // 1) Unmodulated time of 56.64us\r
26 // 2) 24 pulses of 423.75khz\r
27 // 3) logic '1' (unmodulated for 18.88us followed by 8 pulses of 423.75khz)\r
28\r
29 static const int FrameSOF[] = {\r
30 -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,\r
31 -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,\r
32 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,\r
33 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,\r
34 -1, -1, -1, -1,\r
35 -1, -1, -1, -1,\r
36 1, 1, 1, 1,\r
37 1, 1, 1, 1\r
38 };\r
39 static const int Logic0[] = {\r
40 1, 1, 1, 1,\r
41 1, 1, 1, 1,\r
42 -1, -1, -1, -1,\r
43 -1, -1, -1, -1\r
44 };\r
45 static const int Logic1[] = {\r
46 -1, -1, -1, -1,\r
47 -1, -1, -1, -1,\r
48 1, 1, 1, 1,\r
49 1, 1, 1, 1\r
50 };\r
51\r
f7c64b57 52 // EOF defined as\r
6658905f 53 // 1) logic '0' (8 pulses of 423.75khz followed by unmodulated for 18.88us)\r
54 // 2) 24 pulses of 423.75khz\r
55 // 3) Unmodulated time of 56.64us\r
56\r
57 static const int FrameEOF[] = {\r
58 1, 1, 1, 1,\r
59 1, 1, 1, 1,\r
60 -1, -1, -1, -1,\r
61 -1, -1, -1, -1,\r
62 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,\r
63 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,\r
64 -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,\r
65 -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1\r
66 };\r
67\r
6658905f 68static void CodeIso15693AsReader(BYTE *cmd, int n)\r
69{\r
70 int i, j;\r
71\r
72 ToSendReset();\r
73\r
74 // Give it a bit of slack at the beginning\r
75 for(i = 0; i < 24; i++) {\r
76 ToSendStuffBit(1);\r
77 }\r
78\r
79 ToSendStuffBit(0);\r
80 ToSendStuffBit(1);\r
81 ToSendStuffBit(1);\r
82 ToSendStuffBit(1);\r
83 ToSendStuffBit(1);\r
84 ToSendStuffBit(0);\r
85 ToSendStuffBit(1);\r
86 ToSendStuffBit(1);\r
87 for(i = 0; i < n; i++) {\r
88 for(j = 0; j < 8; j += 2) {\r
89 int these = (cmd[i] >> j) & 3;\r
90 switch(these) {\r
91 case 0:\r
92 ToSendStuffBit(1);\r
93 ToSendStuffBit(0);\r
94 ToSendStuffBit(1);\r
95 ToSendStuffBit(1);\r
96 ToSendStuffBit(1);\r
97 ToSendStuffBit(1);\r
98 ToSendStuffBit(1);\r
99 ToSendStuffBit(1);\r
100 break;\r
101 case 1:\r
102 ToSendStuffBit(1);\r
103 ToSendStuffBit(1);\r
104 ToSendStuffBit(1);\r
105 ToSendStuffBit(0);\r
106 ToSendStuffBit(1);\r
107 ToSendStuffBit(1);\r
108 ToSendStuffBit(1);\r
109 ToSendStuffBit(1);\r
110 break;\r
111 case 2:\r
112 ToSendStuffBit(1);\r
113 ToSendStuffBit(1);\r
114 ToSendStuffBit(1);\r
115 ToSendStuffBit(1);\r
116 ToSendStuffBit(1);\r
117 ToSendStuffBit(0);\r
118 ToSendStuffBit(1);\r
119 ToSendStuffBit(1);\r
120 break;\r
121 case 3:\r
122 ToSendStuffBit(1);\r
123 ToSendStuffBit(1);\r
124 ToSendStuffBit(1);\r
125 ToSendStuffBit(1);\r
126 ToSendStuffBit(1);\r
127 ToSendStuffBit(1);\r
128 ToSendStuffBit(1);\r
129 ToSendStuffBit(0);\r
130 break;\r
131 }\r
132 }\r
133 }\r
134 ToSendStuffBit(1);\r
135 ToSendStuffBit(1);\r
136 ToSendStuffBit(0);\r
137 ToSendStuffBit(1);\r
138\r
139 // And slack at the end, too.\r
140 for(i = 0; i < 24; i++) {\r
141 ToSendStuffBit(1);\r
142 }\r
143}\r
144\r
145//-----------------------------------------------------------------------------\r
146// The CRC used by ISO 15693.\r
147//-----------------------------------------------------------------------------\r
148static WORD Crc(BYTE *v, int n)\r
149{\r
150 DWORD reg;\r
151 int i, j;\r
152\r
153 reg = 0xffff;\r
154 for(i = 0; i < n; i++) {\r
155 reg = reg ^ ((DWORD)v[i]);\r
156 for (j = 0; j < 8; j++) {\r
157 if (reg & 0x0001) {\r
158 reg = (reg >> 1) ^ 0x8408;\r
159 } else {\r
160 reg = (reg >> 1);\r
161 }\r
162 }\r
163 }\r
164\r
165 return ~reg;\r
166}\r
167\r
f7c64b57 168char *strcat(char *dest, const char *src)\r
169{\r
170 size_t dest_len = strlen(dest);\r
171 size_t i;\r
172 \r
173 for (i = 0 ; src[i] != '\0' ; i++)\r
174 dest[dest_len + i] = src[i];\r
175 dest[dest_len + i] = '\0';\r
6658905f 176 \r
f7c64b57 177 return dest;\r
178}\r
6658905f 179\r
f7c64b57 180////////////////////////////////////////// code to do 'itoa'\r
6658905f 181\r
182/* reverse: reverse string s in place */\r
183void reverse(char s[])\r
184{\r
185 int c, i, j;\r
186\r
187 for (i = 0, j = strlen(s)-1; i<j; i++, j--) {\r
188 c = s[i];\r
189 s[i] = s[j];\r
190 s[j] = c;\r
191 }\r
192}\r
193\r
194/* itoa: convert n to characters in s */\r
195void itoa(int n, char s[])\r
196{\r
197 int i, sign;\r
198\r
199 if ((sign = n) < 0) /* record sign */\r
200 n = -n; /* make n positive */\r
201 i = 0;\r
202 do { /* generate digits in reverse order */\r
203 s[i++] = n % 10 + '0'; /* get next digit */\r
204 } while ((n /= 10) > 0); /* delete it */\r
205 if (sign < 0)\r
206 s[i++] = '-';\r
207 s[i] = '\0';\r
208 reverse(s);\r
f7c64b57 209}\r
6658905f 210\r
211//////////////////////////////////////// END 'itoa' CODE\r
212\r
6658905f 213//-----------------------------------------------------------------------------\r
214// Encode (into the ToSend buffers) an identify request, which is the first\r
215// thing that you must send to a tag to get a response.\r
216//-----------------------------------------------------------------------------\r
217static void BuildIdentifyRequest(void)\r
218{\r
219 BYTE cmd[5];\r
220\r
221 WORD crc;\r
222 // one sub-carrier, inventory, 1 slot, fast rate\r
223 // AFI is at bit 5 (1<<4) when doing an INVENTORY\r
f7c64b57 224 cmd[0] = (1 << 2) | (1 << 5) | (1 << 1);\r
6658905f 225 // inventory command code\r
226 cmd[1] = 0x01;\r
227 // no mask\r
228 cmd[2] = 0x00;\r
229 //Now the CRC\r
230 crc = Crc(cmd, 3);\r
231 cmd[3] = crc & 0xff;\r
232 cmd[4] = crc >> 8;\r
233\r
234 CodeIso15693AsReader(cmd, sizeof(cmd));\r
235}\r
236\r
83288efc 237static void __attribute__((unused)) BuildSysInfoRequest(BYTE *uid)\r
6658905f 238{\r
239 BYTE cmd[12];\r
240\r
241 WORD crc;\r
242 // If we set the Option_Flag in this request, the VICC will respond with the secuirty status of the block\r
243 // followed by teh block data\r
244 // one sub-carrier, inventory, 1 slot, fast rate\r
245 cmd[0] = (1 << 5) | (1 << 1); // no SELECT bit\r
246 // System Information command code\r
247 cmd[1] = 0x2B;\r
248 // UID may be optionally specified here\r
249 // 64-bit UID\r
250 cmd[2] = 0x32;\r
251 cmd[3]= 0x4b;\r
252 cmd[4] = 0x03;\r
253 cmd[5] = 0x01;\r
254 cmd[6] = 0x00;\r
255 cmd[7] = 0x10;\r
f7c64b57 256 cmd[8] = 0x05;\r
257 cmd[9]= 0xe0; // always e0 (not exactly unique)\r
6658905f 258 //Now the CRC\r
f7c64b57 259 crc = Crc(cmd, 10); // the crc needs to be calculated over 2 bytes\r
6658905f 260 cmd[10] = crc & 0xff;\r
261 cmd[11] = crc >> 8;\r
262\r
263 CodeIso15693AsReader(cmd, sizeof(cmd));\r
264}\r
265\r
266static void BuildSelectRequest( BYTE uid[])\r
267{\r
f7c64b57 268\r
6658905f 269// uid[6]=0x31; // this is getting ignored - the uid array is not happening...\r
270 BYTE cmd[12];\r
271\r
272 WORD crc;\r
273 // one sub-carrier, inventory, 1 slot, fast rate\r
274 //cmd[0] = (1 << 2) | (1 << 5) | (1 << 1); // INVENTROY FLAGS\r
275 cmd[0] = (1 << 4) | (1 << 5) | (1 << 1); // Select and addressed FLAGS\r
276 // SELECT command code\r
277 cmd[1] = 0x25;\r
278 // 64-bit UID\r
279// cmd[2] = uid[0];//0x32;\r
280// cmd[3]= uid[1];//0x4b;\r
281// cmd[4] = uid[2];//0x03;\r
282// cmd[5] = uid[3];//0x01;\r
283// cmd[6] = uid[4];//0x00;\r
284// cmd[7] = uid[5];//0x10;\r
f7c64b57 285// cmd[8] = uid[6];//0x05;\r
6658905f 286 cmd[2] = 0x32;//\r
f7c64b57 287 cmd[3] = 0x4b;\r
6658905f 288 cmd[4] = 0x03;\r
289 cmd[5] = 0x01;\r
290 cmd[6] = 0x00;\r
291 cmd[7] = 0x10;\r
292 cmd[8] = 0x05; // infineon?\r
293\r
f7c64b57 294 cmd[9]= 0xe0; // always e0 (not exactly unique)\r
6658905f 295\r
296// DbpIntegers(cmd[8],cmd[7],cmd[6]);\r
297 // Now the CRC\r
f7c64b57 298 crc = Crc(cmd, 10); // the crc needs to be calculated over 10 bytes\r
6658905f 299 cmd[10] = crc & 0xff;\r
300 cmd[11] = crc >> 8;\r
301\r
302 CodeIso15693AsReader(cmd, sizeof(cmd));\r
303}\r
304\r
83288efc 305static void __attribute__((unused)) BuildReadBlockRequest(BYTE *uid, BYTE blockNumber )\r
6658905f 306{\r
307 BYTE cmd[13];\r
308\r
309 WORD crc;\r
310 // If we set the Option_Flag in this request, the VICC will respond with the secuirty status of the block\r
311 // followed by teh block data\r
312 // one sub-carrier, inventory, 1 slot, fast rate\r
313 cmd[0] = (1 << 6)| (1 << 5) | (1 << 1); // no SELECT bit\r
314 // READ BLOCK command code\r
315 cmd[1] = 0x20;\r
316 // UID may be optionally specified here\r
317 // 64-bit UID\r
318 cmd[2] = 0x32;\r
319 cmd[3]= 0x4b;\r
320 cmd[4] = 0x03;\r
321 cmd[5] = 0x01;\r
322 cmd[6] = 0x00;\r
323 cmd[7] = 0x10;\r
f7c64b57 324 cmd[8] = 0x05;\r
325 cmd[9]= 0xe0; // always e0 (not exactly unique)\r
6658905f 326 // Block number to read\r
327 cmd[10] = blockNumber;//0x00;\r
328 //Now the CRC\r
f7c64b57 329 crc = Crc(cmd, 11); // the crc needs to be calculated over 2 bytes\r
6658905f 330 cmd[11] = crc & 0xff;\r
331 cmd[12] = crc >> 8;\r
332\r
333 CodeIso15693AsReader(cmd, sizeof(cmd));\r
334}\r
335\r
83288efc 336static void __attribute__((unused)) BuildReadMultiBlockRequest(BYTE *uid)\r
6658905f 337{\r
338 BYTE cmd[14];\r
339\r
340 WORD crc;\r
341 // If we set the Option_Flag in this request, the VICC will respond with the secuirty status of the block\r
342 // followed by teh block data\r
343 // one sub-carrier, inventory, 1 slot, fast rate\r
344 cmd[0] = (1 << 5) | (1 << 1); // no SELECT bit\r
345 // READ Multi BLOCK command code\r
346 cmd[1] = 0x23;\r
347 // UID may be optionally specified here\r
348 // 64-bit UID\r
349 cmd[2] = 0x32;\r
350 cmd[3]= 0x4b;\r
351 cmd[4] = 0x03;\r
352 cmd[5] = 0x01;\r
353 cmd[6] = 0x00;\r
354 cmd[7] = 0x10;\r
f7c64b57 355 cmd[8] = 0x05;\r
356 cmd[9]= 0xe0; // always e0 (not exactly unique)\r
6658905f 357 // First Block number to read\r
358 cmd[10] = 0x00;\r
359 // Number of Blocks to read\r
360 cmd[11] = 0x2f; // read quite a few\r
361 //Now the CRC\r
f7c64b57 362 crc = Crc(cmd, 12); // the crc needs to be calculated over 2 bytes\r
6658905f 363 cmd[12] = crc & 0xff;\r
364 cmd[13] = crc >> 8;\r
365\r
366 CodeIso15693AsReader(cmd, sizeof(cmd));\r
367}\r
368\r
83288efc 369static void __attribute__((unused)) BuildArbitraryRequest(BYTE *uid,BYTE CmdCode)\r
6658905f 370{\r
371 BYTE cmd[14];\r
372\r
373 WORD crc;\r
374 // If we set the Option_Flag in this request, the VICC will respond with the secuirty status of the block\r
375 // followed by teh block data\r
376 // one sub-carrier, inventory, 1 slot, fast rate\r
377 cmd[0] = (1 << 5) | (1 << 1); // no SELECT bit\r
378 // READ BLOCK command code\r
379 cmd[1] = CmdCode;\r
380 // UID may be optionally specified here\r
381 // 64-bit UID\r
382 cmd[2] = 0x32;\r
383 cmd[3]= 0x4b;\r
384 cmd[4] = 0x03;\r
385 cmd[5] = 0x01;\r
386 cmd[6] = 0x00;\r
387 cmd[7] = 0x10;\r
f7c64b57 388 cmd[8] = 0x05;\r
389 cmd[9]= 0xe0; // always e0 (not exactly unique)\r
6658905f 390 // Parameter\r
391 cmd[10] = 0x00;\r
392 cmd[11] = 0x0a;\r
393\r
394// cmd[12] = 0x00;\r
395// cmd[13] = 0x00; //Now the CRC\r
f7c64b57 396 crc = Crc(cmd, 12); // the crc needs to be calculated over 2 bytes\r
6658905f 397 cmd[12] = crc & 0xff;\r
398 cmd[13] = crc >> 8;\r
399\r
400 CodeIso15693AsReader(cmd, sizeof(cmd));\r
401}\r
402\r
83288efc 403static void __attribute__((unused)) BuildArbitraryCustomRequest(BYTE uid[], BYTE CmdCode)\r
6658905f 404{\r
405 BYTE cmd[14];\r
406\r
407 WORD crc;\r
408 // If we set the Option_Flag in this request, the VICC will respond with the secuirty status of the block\r
409 // followed by teh block data\r
410 // one sub-carrier, inventory, 1 slot, fast rate\r
411 cmd[0] = (1 << 5) | (1 << 1); // no SELECT bit\r
412 // READ BLOCK command code\r
413 cmd[1] = CmdCode;\r
414 // UID may be optionally specified here\r
415 // 64-bit UID\r
416 cmd[2] = 0x32;\r
417 cmd[3]= 0x4b;\r
418 cmd[4] = 0x03;\r
419 cmd[5] = 0x01;\r
420 cmd[6] = 0x00;\r
421 cmd[7] = 0x10;\r
f7c64b57 422 cmd[8] = 0x05;\r
423 cmd[9]= 0xe0; // always e0 (not exactly unique)\r
6658905f 424 // Parameter\r
425 cmd[10] = 0x05; // for custom codes this must be manufcturer code\r
426 cmd[11] = 0x00;\r
427\r
428// cmd[12] = 0x00;\r
429// cmd[13] = 0x00; //Now the CRC\r
f7c64b57 430 crc = Crc(cmd, 12); // the crc needs to be calculated over 2 bytes\r
6658905f 431 cmd[12] = crc & 0xff;\r
432 cmd[13] = crc >> 8;\r
433\r
434 CodeIso15693AsReader(cmd, sizeof(cmd));\r
435}\r
436\r
437/////////////////////////////////////////////////////////////////////////\r
438// Now the VICC>VCD responses when we are simulating a tag\r
439////////////////////////////////////////////////////////////////////\r
440\r
441 static void BuildInventoryResponse(void)\r
442{\r
443 BYTE cmd[12];\r
444\r
445 WORD crc;\r
446 // one sub-carrier, inventory, 1 slot, fast rate\r
447 // AFI is at bit 5 (1<<4) when doing an INVENTORY\r
f7c64b57 448 cmd[0] = 0; //(1 << 2) | (1 << 5) | (1 << 1);\r
6658905f 449 cmd[1] = 0;\r
450 // 64-bit UID\r
451 cmd[2] = 0x32;\r
452 cmd[3]= 0x4b;\r
453 cmd[4] = 0x03;\r
454 cmd[5] = 0x01;\r
455 cmd[6] = 0x00;\r
456 cmd[7] = 0x10;\r
f7c64b57 457 cmd[8] = 0x05;\r
6658905f 458 cmd[9]= 0xe0;\r
459 //Now the CRC\r
460 crc = Crc(cmd, 10);\r
461 cmd[10] = crc & 0xff;\r
462 cmd[11] = crc >> 8;\r
463\r
464 CodeIso15693AsReader(cmd, sizeof(cmd));\r
465}\r
466\r
6658905f 467//-----------------------------------------------------------------------------\r
468// Transmit the command (to the tag) that was placed in ToSend[].\r
469//-----------------------------------------------------------------------------\r
470static void TransmitTo15693Tag(const BYTE *cmd, int len, int *samples, int *wait)\r
471{\r
472 int c;\r
473\r
474// FpgaWriteConfWord(FPGA_MAJOR_MODE_HF_ISO14443A | FPGA_HF_ISO14443A_READER_MOD);\r
475 FpgaWriteConfWord(FPGA_MAJOR_MODE_HF_READER_TX);\r
476 if(*wait < 10) { *wait = 10; }\r
477\r
478// for(c = 0; c < *wait;) {\r
6949aca9 479// if(AT91C_BASE_SSC->SSC_SR & (AT91C_SSC_TXRDY)) {\r
480// AT91C_BASE_SSC->SSC_THR = 0x00; // For exact timing!\r
6658905f 481// c++;\r
482// }\r
6949aca9 483// if(AT91C_BASE_SSC->SSC_SR & (AT91C_SSC_RXRDY)) {\r
484// volatile DWORD r = AT91C_BASE_SSC->SSC_RHR;\r
6658905f 485// (void)r;\r
486// }\r
487// WDT_HIT();\r
488// }\r
489\r
490 c = 0;\r
491 for(;;) {\r
6949aca9 492 if(AT91C_BASE_SSC->SSC_SR & (AT91C_SSC_TXRDY)) {\r
493 AT91C_BASE_SSC->SSC_THR = cmd[c];\r
6658905f 494 c++;\r
495 if(c >= len) {\r
496 break;\r
497 }\r
498 }\r
6949aca9 499 if(AT91C_BASE_SSC->SSC_SR & (AT91C_SSC_RXRDY)) {\r
500 volatile DWORD r = AT91C_BASE_SSC->SSC_RHR;\r
6658905f 501 (void)r;\r
502 }\r
503 WDT_HIT();\r
504 }\r
505 *samples = (c + *wait) << 3;\r
506}\r
507\r
6658905f 508//-----------------------------------------------------------------------------\r
509// Transmit the command (to the reader) that was placed in ToSend[].\r
510//-----------------------------------------------------------------------------\r
511static void TransmitTo15693Reader(const BYTE *cmd, int len, int *samples, int *wait)\r
512{\r
513 int c;\r
514\r
515// FpgaWriteConfWord(FPGA_MAJOR_MODE_HF_READER_TX);\r
516 FpgaWriteConfWord(FPGA_MAJOR_MODE_HF_SIMULATOR); // No requirement to energise my coils\r
517 if(*wait < 10) { *wait = 10; }\r
518\r
519 c = 0;\r
520 for(;;) {\r
6949aca9 521 if(AT91C_BASE_SSC->SSC_SR & (AT91C_SSC_TXRDY)) {\r
522 AT91C_BASE_SSC->SSC_THR = cmd[c];\r
6658905f 523 c++;\r
524 if(c >= len) {\r
525 break;\r
526 }\r
527 }\r
6949aca9 528 if(AT91C_BASE_SSC->SSC_SR & (AT91C_SSC_RXRDY)) {\r
529 volatile DWORD r = AT91C_BASE_SSC->SSC_RHR;\r
6658905f 530 (void)r;\r
531 }\r
532 WDT_HIT();\r
533 }\r
534 *samples = (c + *wait) << 3;\r
535}\r
536\r
f7c64b57 537static int GetIso15693AnswerFromTag(BYTE *receivedResponse, int maxLen, int *samples, int *elapsed)\r
6658905f 538{\r
539 int c = 0;\r
540 BYTE *dest = (BYTE *)BigBuf;\r
541 int getNext = 0;\r
542\r
6658905f 543 SBYTE prev = 0;\r
544\r
545// NOW READ RESPONSE\r
546 FpgaWriteConfWord(FPGA_MAJOR_MODE_HF_READER_RX_XCORR);\r
547 //spindelay(60); // greg - experiment to get rid of some of the 0 byte/failed reads\r
548 c = 0;\r
549 getNext = FALSE;\r
550 for(;;) {\r
6949aca9 551 if(AT91C_BASE_SSC->SSC_SR & (AT91C_SSC_TXRDY)) {\r
552 AT91C_BASE_SSC->SSC_THR = 0x43;\r
6658905f 553 }\r
6949aca9 554 if(AT91C_BASE_SSC->SSC_SR & (AT91C_SSC_RXRDY)) {\r
6658905f 555 SBYTE b;\r
6949aca9 556 b = (SBYTE)AT91C_BASE_SSC->SSC_RHR;\r
6658905f 557\r
558 // The samples are correlations against I and Q versions of the\r
559 // tone that the tag AM-modulates, so every other sample is I,\r
560 // every other is Q. We just want power, so abs(I) + abs(Q) is\r
561 // close to what we want.\r
562 if(getNext) {\r
563 SBYTE r;\r
564\r
565 if(b < 0) {\r
566 r = -b;\r
567 } else {\r
568 r = b;\r
569 }\r
570 if(prev < 0) {\r
571 r -= prev;\r
572 } else {\r
573 r += prev;\r
574 }\r
575\r
576 dest[c++] = (BYTE)r;\r
577\r
578 if(c >= 2000) {\r
579 break;\r
580 }\r
581 } else {\r
582 prev = b;\r
583 }\r
584\r
585 getNext = !getNext;\r
586 }\r
587 }\r
588\r
589//////////////////////////////////////////\r
590/////////// DEMODULATE ///////////////////\r
591//////////////////////////////////////////\r
592\r
593 int i, j;\r
f7c64b57 594 int max = 0, maxPos=0;\r
6658905f 595\r
596 int skip = 4;\r
597\r
6658905f 598// if(GraphTraceLen < 1000) return; // THIS CHECKS FOR A BUFFER TO SMALL\r
599\r
600 // First, correlate for SOF\r
601 for(i = 0; i < 100; i++) {\r
602 int corr = 0;\r
603 for(j = 0; j < arraylen(FrameSOF); j += skip) {\r
604 corr += FrameSOF[j]*dest[i+(j/skip)];\r
605 }\r
606 if(corr > max) {\r
607 max = corr;\r
608 maxPos = i;\r
609 }\r
610 }\r
611// DbpString("SOF at %d, correlation %d", maxPos,max/(arraylen(FrameSOF)/skip));\r
612\r
613 int k = 0; // this will be our return value\r
614\r
615 // greg - If correlation is less than 1 then there's little point in continuing\r
f7c64b57 616 if ((max/(arraylen(FrameSOF)/skip)) >= 1)\r
6658905f 617 {\r
618\r
619 i = maxPos + arraylen(FrameSOF)/skip;\r
f7c64b57 620\r
6658905f 621 BYTE outBuf[20];\r
622 memset(outBuf, 0, sizeof(outBuf));\r
623 BYTE mask = 0x01;\r
624 for(;;) {\r
625 int corr0 = 0, corr1 = 0, corrEOF = 0;\r
626 for(j = 0; j < arraylen(Logic0); j += skip) {\r
627 corr0 += Logic0[j]*dest[i+(j/skip)];\r
628 }\r
629 for(j = 0; j < arraylen(Logic1); j += skip) {\r
630 corr1 += Logic1[j]*dest[i+(j/skip)];\r
631 }\r
632 for(j = 0; j < arraylen(FrameEOF); j += skip) {\r
633 corrEOF += FrameEOF[j]*dest[i+(j/skip)];\r
634 }\r
635 // Even things out by the length of the target waveform.\r
636 corr0 *= 4;\r
637 corr1 *= 4;\r
638\r
639 if(corrEOF > corr1 && corrEOF > corr0) {\r
640// DbpString("EOF at %d", i);\r
641 break;\r
642 } else if(corr1 > corr0) {\r
643 i += arraylen(Logic1)/skip;\r
644 outBuf[k] |= mask;\r
645 } else {\r
646 i += arraylen(Logic0)/skip;\r
647 }\r
648 mask <<= 1;\r
649 if(mask == 0) {\r
650 k++;\r
651 mask = 0x01;\r
652 }\r
653 if((i+(int)arraylen(FrameEOF)) >= 2000) {\r
654 DbpString("ran off end!");\r
655 break;\r
656 }\r
657 }\r
658 if(mask != 0x01) {\r
659 DbpString("error, uneven octet! (discard extra bits!)");\r
660/// DbpString(" mask=%02x", mask);\r
661 }\r
662// BYTE str1 [8];\r
663// itoa(k,str1);\r
664// strcat(str1," octets read");\r
665\r
666// DbpString( str1); // DbpString("%d octets", k);\r
667\r
668// for(i = 0; i < k; i+=3) {\r
669// //DbpString("# %2d: %02x ", i, outBuf[i]);\r
670// DbpIntegers(outBuf[i],outBuf[i+1],outBuf[i+2]);\r
671// }\r
672\r
673 for(i = 0; i < k; i++) {\r
674 receivedResponse[i] = outBuf[i];\r
f7c64b57 675 }\r
6658905f 676 } // "end if correlation > 0" (max/(arraylen(FrameSOF)/skip))\r
677 return k; // return the number of bytes demodulated\r
678\r
679/// DbpString("CRC=%04x", Iso15693Crc(outBuf, k-2));\r
680\r
6658905f 681}\r
682\r
683// Now the GetISO15693 message from sniffing command\r
f7c64b57 684static int GetIso15693AnswerFromSniff(BYTE *receivedResponse, int maxLen, int *samples, int *elapsed)\r
6658905f 685{\r
686 int c = 0;\r
687 BYTE *dest = (BYTE *)BigBuf;\r
688 int getNext = 0;\r
689\r
6658905f 690 SBYTE prev = 0;\r
691\r
692// NOW READ RESPONSE\r
693 FpgaWriteConfWord(FPGA_MAJOR_MODE_HF_READER_RX_XCORR);\r
694 //spindelay(60); // greg - experiment to get rid of some of the 0 byte/failed reads\r
695 c = 0;\r
696 getNext = FALSE;\r
697 for(;;) {\r
6949aca9 698 if(AT91C_BASE_SSC->SSC_SR & (AT91C_SSC_TXRDY)) {\r
699 AT91C_BASE_SSC->SSC_THR = 0x43;\r
6658905f 700 }\r
6949aca9 701 if(AT91C_BASE_SSC->SSC_SR & (AT91C_SSC_RXRDY)) {\r
6658905f 702 SBYTE b;\r
6949aca9 703 b = (SBYTE)AT91C_BASE_SSC->SSC_RHR;\r
6658905f 704\r
705 // The samples are correlations against I and Q versions of the\r
706 // tone that the tag AM-modulates, so every other sample is I,\r
707 // every other is Q. We just want power, so abs(I) + abs(Q) is\r
708 // close to what we want.\r
709 if(getNext) {\r
710 SBYTE r;\r
711\r
712 if(b < 0) {\r
713 r = -b;\r
714 } else {\r
715 r = b;\r
716 }\r
717 if(prev < 0) {\r
718 r -= prev;\r
719 } else {\r
720 r += prev;\r
721 }\r
722\r
723 dest[c++] = (BYTE)r;\r
724\r
725 if(c >= 20000) {\r
726 break;\r
727 }\r
728 } else {\r
729 prev = b;\r
730 }\r
731\r
732 getNext = !getNext;\r
733 }\r
734 }\r
735\r
736//////////////////////////////////////////\r
737/////////// DEMODULATE ///////////////////\r
738//////////////////////////////////////////\r
739\r
740 int i, j;\r
f7c64b57 741 int max = 0, maxPos=0;\r
6658905f 742\r
743 int skip = 4;\r
744\r
6658905f 745// if(GraphTraceLen < 1000) return; // THIS CHECKS FOR A BUFFER TO SMALL\r
746\r
747 // First, correlate for SOF\r
748 for(i = 0; i < 19000; i++) {\r
749 int corr = 0;\r
750 for(j = 0; j < arraylen(FrameSOF); j += skip) {\r
751 corr += FrameSOF[j]*dest[i+(j/skip)];\r
752 }\r
753 if(corr > max) {\r
754 max = corr;\r
755 maxPos = i;\r
756 }\r
757 }\r
758// DbpString("SOF at %d, correlation %d", maxPos,max/(arraylen(FrameSOF)/skip));\r
759\r
760 int k = 0; // this will be our return value\r
761\r
762 // greg - If correlation is less than 1 then there's little point in continuing\r
f7c64b57 763 if ((max/(arraylen(FrameSOF)/skip)) >= 1) // THIS SHOULD BE 1\r
6658905f 764 {\r
765\r
766 i = maxPos + arraylen(FrameSOF)/skip;\r
f7c64b57 767\r
6658905f 768 BYTE outBuf[20];\r
769 memset(outBuf, 0, sizeof(outBuf));\r
770 BYTE mask = 0x01;\r
771 for(;;) {\r
772 int corr0 = 0, corr1 = 0, corrEOF = 0;\r
773 for(j = 0; j < arraylen(Logic0); j += skip) {\r
774 corr0 += Logic0[j]*dest[i+(j/skip)];\r
775 }\r
776 for(j = 0; j < arraylen(Logic1); j += skip) {\r
777 corr1 += Logic1[j]*dest[i+(j/skip)];\r
778 }\r
779 for(j = 0; j < arraylen(FrameEOF); j += skip) {\r
780 corrEOF += FrameEOF[j]*dest[i+(j/skip)];\r
781 }\r
782 // Even things out by the length of the target waveform.\r
783 corr0 *= 4;\r
784 corr1 *= 4;\r
785\r
786 if(corrEOF > corr1 && corrEOF > corr0) {\r
787// DbpString("EOF at %d", i);\r
788 break;\r
789 } else if(corr1 > corr0) {\r
790 i += arraylen(Logic1)/skip;\r
791 outBuf[k] |= mask;\r
792 } else {\r
793 i += arraylen(Logic0)/skip;\r
794 }\r
795 mask <<= 1;\r
796 if(mask == 0) {\r
797 k++;\r
798 mask = 0x01;\r
799 }\r
800 if((i+(int)arraylen(FrameEOF)) >= 2000) {\r
801 DbpString("ran off end!");\r
802 break;\r
803 }\r
804 }\r
805 if(mask != 0x01) {\r
806 DbpString("error, uneven octet! (discard extra bits!)");\r
807/// DbpString(" mask=%02x", mask);\r
808 }\r
809// BYTE str1 [8];\r
810// itoa(k,str1);\r
811// strcat(str1," octets read");\r
812\r
813// DbpString( str1); // DbpString("%d octets", k);\r
814\r
815// for(i = 0; i < k; i+=3) {\r
816// //DbpString("# %2d: %02x ", i, outBuf[i]);\r
817// DbpIntegers(outBuf[i],outBuf[i+1],outBuf[i+2]);\r
818// }\r
819\r
820 for(i = 0; i < k; i++) {\r
821 receivedResponse[i] = outBuf[i];\r
f7c64b57 822 }\r
6658905f 823 } // "end if correlation > 0" (max/(arraylen(FrameSOF)/skip))\r
824 return k; // return the number of bytes demodulated\r
825\r
826/// DbpString("CRC=%04x", Iso15693Crc(outBuf, k-2));\r
6658905f 827}\r
828\r
6658905f 829//-----------------------------------------------------------------------------\r
830// Start to read an ISO 15693 tag. We send an identify request, then wait\r
831// for the response. The response is not demodulated, just left in the buffer\r
832// so that it can be downloaded to a PC and processed there.\r
833//-----------------------------------------------------------------------------\r
834void AcquireRawAdcSamplesIso15693(void)\r
835{\r
836 int c = 0;\r
837 BYTE *dest = (BYTE *)BigBuf;\r
838 int getNext = 0;\r
839\r
840 SBYTE prev = 0;\r
841\r
842 BuildIdentifyRequest();\r
843\r
844 SetAdcMuxFor(GPIO_MUXSEL_HIPKD);\r
845\r
846 // Give the tags time to energize\r
847 FpgaWriteConfWord(FPGA_MAJOR_MODE_HF_READER_RX_XCORR);\r
848 SpinDelay(100);\r
849\r
850 // Now send the command\r
851 FpgaSetupSsc();\r
852 FpgaWriteConfWord(FPGA_MAJOR_MODE_HF_READER_TX);\r
853\r
854 c = 0;\r
855 for(;;) {\r
6949aca9 856 if(AT91C_BASE_SSC->SSC_SR & (AT91C_SSC_TXRDY)) {\r
857 AT91C_BASE_SSC->SSC_THR = ToSend[c];\r
6658905f 858 c++;\r
859 if(c == ToSendMax+3) {\r
860 break;\r
861 }\r
862 }\r
6949aca9 863 if(AT91C_BASE_SSC->SSC_SR & (AT91C_SSC_RXRDY)) {\r
864 volatile DWORD r = AT91C_BASE_SSC->SSC_RHR;\r
6658905f 865 (void)r;\r
866 }\r
867 WDT_HIT();\r
868 }\r
869\r
870 FpgaWriteConfWord(FPGA_MAJOR_MODE_HF_READER_RX_XCORR);\r
871\r
872 c = 0;\r
873 getNext = FALSE;\r
874 for(;;) {\r
6949aca9 875 if(AT91C_BASE_SSC->SSC_SR & (AT91C_SSC_TXRDY)) {\r
876 AT91C_BASE_SSC->SSC_THR = 0x43;\r
6658905f 877 }\r
6949aca9 878 if(AT91C_BASE_SSC->SSC_SR & (AT91C_SSC_RXRDY)) {\r
6658905f 879 SBYTE b;\r
6949aca9 880 b = (SBYTE)AT91C_BASE_SSC->SSC_RHR;\r
6658905f 881\r
882 // The samples are correlations against I and Q versions of the\r
883 // tone that the tag AM-modulates, so every other sample is I,\r
884 // every other is Q. We just want power, so abs(I) + abs(Q) is\r
885 // close to what we want.\r
886 if(getNext) {\r
887 SBYTE r;\r
888\r
889 if(b < 0) {\r
890 r = -b;\r
891 } else {\r
892 r = b;\r
893 }\r
894 if(prev < 0) {\r
895 r -= prev;\r
896 } else {\r
897 r += prev;\r
898 }\r
899\r
900 dest[c++] = (BYTE)r;\r
901\r
902 if(c >= 2000) {\r
903 break;\r
904 }\r
905 } else {\r
906 prev = b;\r
907 }\r
908\r
909 getNext = !getNext;\r
910 }\r
911 }\r
912}\r
913\r
6658905f 914//-----------------------------------------------------------------------------\r
915// Simulate an ISO15693 reader, perform anti-collision and then attempt to read a sector\r
916// all demodulation performed in arm rather than host. - greg\r
917//-----------------------------------------------------------------------------\r
918void ReaderIso15693(DWORD parameter)\r
919{\r
920 LED_A_ON();\r
921 LED_B_ON();\r
922 LED_C_OFF();\r
923 LED_D_OFF();\r
924\r
6658905f 925//DbpString(parameter);\r
926\r
850427c8 927 //BYTE *answer0 = (((BYTE *)BigBuf) + 3560); // allow 100 bytes per reponse (way too much)\r
928 BYTE *answer1 = (((BYTE *)BigBuf) + 3660); //\r
929 BYTE *answer2 = (((BYTE *)BigBuf) + 3760);\r
930 BYTE *answer3 = (((BYTE *)BigBuf) + 3860);\r
f7c64b57 931 //BYTE *TagUID= (((BYTE *)BigBuf) + 3960); // where we hold the uid for hi15reader\r
850427c8 932// int answerLen0 = 0;\r
933 int answerLen1 = 0;\r
934 int answerLen2 = 0;\r
935 int answerLen3 = 0;\r
6658905f 936\r
937 // Blank arrays\r
850427c8 938 memset(BigBuf + 3660, 0, 300);\r
6658905f 939\r
940 // Setup SSC\r
941 FpgaSetupSsc();\r
942\r
943 // Start from off (no field generated)\r
944 FpgaWriteConfWord(FPGA_MAJOR_MODE_OFF);\r
945 SpinDelay(200);\r
946\r
947 SetAdcMuxFor(GPIO_MUXSEL_HIPKD);\r
948 FpgaSetupSsc();\r
949\r
950 // Give the tags time to energize\r
951 FpgaWriteConfWord(FPGA_MAJOR_MODE_HF_READER_RX_XCORR);\r
952 SpinDelay(200);\r
953\r
954 LED_A_ON();\r
955 LED_B_OFF();\r
956 LED_C_OFF();\r
957 LED_D_OFF();\r
958\r
959 int samples = 0;\r
960 int tsamples = 0;\r
961 int wait = 0;\r
962 int elapsed = 0;\r
963\r
964 // FIRST WE RUN AN INVENTORY TO GET THE TAG UID\r
965 // THIS MEANS WE CAN PRE-BUILD REQUESTS TO SAVE CPU TIME\r
f7c64b57 966 BYTE TagUID[7]; // where we hold the uid for hi15reader\r
6658905f 967\r
968// BuildIdentifyRequest();\r
f7c64b57 969// //TransmitTo15693Tag(ToSend,ToSendMax+3,&tsamples, &wait);\r
6658905f 970// TransmitTo15693Tag(ToSend,ToSendMax,&tsamples, &wait); // No longer ToSendMax+3\r
971// // Now wait for a response\r
f7c64b57 972// responseLen0 = GetIso15693AnswerFromTag(receivedAnswer0, 100, &samples, &elapsed) ;\r
6658905f 973// if (responseLen0 >=12) // we should do a better check than this\r
974// {\r
975// // really we should check it is a valid mesg\r
976// // but for now just grab what we think is the uid\r
977// TagUID[0] = receivedAnswer0[2];\r
978// TagUID[1] = receivedAnswer0[3];\r
979// TagUID[2] = receivedAnswer0[4];\r
980// TagUID[3] = receivedAnswer0[5];\r
981// TagUID[4] = receivedAnswer0[6];\r
982// TagUID[5] = receivedAnswer0[7];\r
983// TagUID[6] = receivedAnswer0[8]; // IC Manufacturer code\r
f7c64b57 984// DbpIntegers(TagUID[6],TagUID[5],TagUID[4]);\r
6658905f 985//}\r
986\r
987 // Now send the IDENTIFY command\r
988 BuildIdentifyRequest();\r
f7c64b57 989 //TransmitTo15693Tag(ToSend,ToSendMax+3,&tsamples, &wait);\r
6658905f 990 TransmitTo15693Tag(ToSend,ToSendMax,&tsamples, &wait); // No longer ToSendMax+3\r
991 // Now wait for a response\r
850427c8 992 answerLen1 = GetIso15693AnswerFromTag(answer1, 100, &samples, &elapsed) ;\r
f7c64b57 993\r
850427c8 994 if (answerLen1 >=12) // we should do a better check than this\r
6658905f 995 {\r
f7c64b57 996\r
850427c8 997 TagUID[0] = answer1[2];\r
998 TagUID[1] = answer1[3];\r
999 TagUID[2] = answer1[4];\r
1000 TagUID[3] = answer1[5];\r
1001 TagUID[4] = answer1[6];\r
1002 TagUID[5] = answer1[7];\r
1003 TagUID[6] = answer1[8]; // IC Manufacturer code\r
f7c64b57 1004\r
6658905f 1005 // Now send the SELECT command\r
f7c64b57 1006 BuildSelectRequest(TagUID);\r
6658905f 1007 TransmitTo15693Tag(ToSend,ToSendMax,&tsamples, &wait); // No longer ToSendMax+3\r
1008 // Now wait for a response\r
850427c8 1009 answerLen2 = GetIso15693AnswerFromTag(answer2, 100, &samples, &elapsed);\r
6658905f 1010\r
1011 // Now send the MULTI READ command\r
1012// BuildArbitraryRequest(*TagUID,parameter);\r
f7c64b57 1013 BuildArbitraryCustomRequest(TagUID,parameter);\r
6658905f 1014// BuildReadBlockRequest(*TagUID,parameter);\r
1015// BuildSysInfoRequest(*TagUID);\r
f7c64b57 1016 //TransmitTo15693Tag(ToSend,ToSendMax+3,&tsamples, &wait);\r
1017 TransmitTo15693Tag(ToSend,ToSendMax,&tsamples, &wait); // No longer ToSendMax+3\r
6658905f 1018 // Now wait for a response\r
850427c8 1019 answerLen3 = GetIso15693AnswerFromTag(answer3, 100, &samples, &elapsed) ;\r
6658905f 1020\r
1021 }\r
1022\r
850427c8 1023 Dbprintf("%d octets read from IDENTIFY request: %x %x %x %x %x %x %x %x %x", answerLen1,\r
1024 answer1[0], answer1[1], answer1[2],\r
1025 answer1[3], answer1[4], answer1[5],\r
1026 answer1[6], answer1[7], answer1[8]);\r
6658905f 1027\r
850427c8 1028 Dbprintf("%d octets read from SELECT request: %x %x %x %x %x %x %x %x %x", answerLen2,\r
1029 answer2[0], answer2[1], answer2[2],\r
1030 answer2[3], answer2[4], answer2[5],\r
1031 answer2[6], answer2[7], answer2[8]);\r
6658905f 1032\r
850427c8 1033 Dbprintf("%d octets read from XXX request: %x %x %x %x %x %x %x %x %x", answerLen3,\r
1034 answer3[0], answer3[1], answer3[2],\r
1035 answer3[3], answer3[4], answer3[5],\r
1036 answer3[6], answer3[7], answer3[8]);\r
6658905f 1037\r
6658905f 1038\r
1039// str2[0]=0;\r
1040// for(i = 0; i < responseLen3; i++) {\r
1041// itoa(str1,receivedAnswer3[i]);\r
1042// strcat(str2,str1);\r
1043// }\r
f7c64b57 1044// DbpString(str2);\r
6658905f 1045\r
1046 LED_A_OFF();\r
1047 LED_B_OFF();\r
1048 LED_C_OFF();\r
1049 LED_D_OFF();\r
6658905f 1050}\r
1051\r
6658905f 1052//-----------------------------------------------------------------------------\r
1053// Simulate an ISO15693 TAG, perform anti-collision and then print any reader commands\r
1054// all demodulation performed in arm rather than host. - greg\r
1055//-----------------------------------------------------------------------------\r
1056void SimTagIso15693(DWORD parameter)\r
1057{\r
1058 LED_A_ON();\r
1059 LED_B_ON();\r
1060 LED_C_OFF();\r
1061 LED_D_OFF();\r
1062\r
850427c8 1063 BYTE *answer1 = (((BYTE *)BigBuf) + 3660); //\r
1064 int answerLen1 = 0;\r
6658905f 1065\r
1066 // Blank arrays\r
850427c8 1067 memset(answer1, 0, 100);\r
6658905f 1068\r
1069 // Setup SSC\r
1070 FpgaSetupSsc();\r
1071\r
1072 // Start from off (no field generated)\r
1073 FpgaWriteConfWord(FPGA_MAJOR_MODE_OFF);\r
1074 SpinDelay(200);\r
1075\r
1076 SetAdcMuxFor(GPIO_MUXSEL_HIPKD);\r
1077 FpgaSetupSsc();\r
1078\r
1079 // Give the tags time to energize\r
1080// FpgaWriteConfWord(FPGA_MAJOR_MODE_HF_READER_RX_XCORR); // NO GOOD FOR SIM TAG!!!!\r
1081 SpinDelay(200);\r
1082\r
1083 LED_A_OFF();\r
1084 LED_B_OFF();\r
1085 LED_C_ON();\r
1086 LED_D_OFF();\r
1087\r
1088 int samples = 0;\r
1089 int tsamples = 0;\r
1090 int wait = 0;\r
1091 int elapsed = 0;\r
1092\r
850427c8 1093 answerLen1 = GetIso15693AnswerFromSniff(answer1, 100, &samples, &elapsed) ;\r
6658905f 1094\r
850427c8 1095 if (answerLen1 >=1) // we should do a better check than this\r
6658905f 1096 {\r
1097 // Build a suitable reponse to the reader INVENTORY cocmmand\r
f7c64b57 1098 BuildInventoryResponse();\r
850427c8 1099 TransmitTo15693Reader(ToSend,ToSendMax, &tsamples, &wait);\r
6658905f 1100 }\r
1101\r
850427c8 1102 Dbprintf("%d octets read from reader command: %x %x %x %x %x %x %x %x %x", answerLen1,\r
1103 answer1[0], answer1[1], answer1[2],\r
1104 answer1[3], answer1[4], answer1[5],\r
1105 answer1[6], answer1[7], answer1[8]);\r
6658905f 1106\r
1107 LED_A_OFF();\r
1108 LED_B_OFF();\r
1109 LED_C_OFF();\r
1110 LED_D_OFF();\r
f7c64b57 1111}\r
Impressum, Datenschutz