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