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