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