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