]> cvs.zerfleddert.de Git - proxmark3-svn/blob - armsrc/iso15693.c
Jerry-rig a simply hysteresis based receiver into hi_read_tx. Output is via SSC_DIN...
[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 *receivedAnswer0 = (((BYTE *)BigBuf) + 3560); // allow 100 bytes per reponse (way too much)
930 BYTE *receivedAnswer1 = (((BYTE *)BigBuf) + 3660); //
931 BYTE *receivedAnswer2 = (((BYTE *)BigBuf) + 3760);
932 BYTE *receivedAnswer3 = (((BYTE *)BigBuf) + 3860);
933 //BYTE *TagUID= (((BYTE *)BigBuf) + 3960); // where we hold the uid for hi15reader
934 // int responseLen0 = 0;
935 int responseLen1 = 0;
936 int responseLen2 = 0;
937 int responseLen3 = 0;
938
939 // Blank arrays
940 int j;
941 for(j = 0; j < 100; j++) {
942 receivedAnswer3[j] = 0;
943 receivedAnswer2[j] =0;
944 receivedAnswer1[j] = 0;
945 receivedAnswer0[j] = 0;
946 }
947
948 // Setup SSC
949 FpgaSetupSsc();
950
951 // Start from off (no field generated)
952 FpgaWriteConfWord(FPGA_MAJOR_MODE_OFF);
953 SpinDelay(200);
954
955 SetAdcMuxFor(GPIO_MUXSEL_HIPKD);
956 FpgaSetupSsc();
957
958 // Give the tags time to energize
959 FpgaWriteConfWord(FPGA_MAJOR_MODE_HF_READER_RX_XCORR);
960 SpinDelay(200);
961
962 LED_A_ON();
963 LED_B_OFF();
964 LED_C_OFF();
965 LED_D_OFF();
966
967 int samples = 0;
968 int tsamples = 0;
969 int wait = 0;
970 int elapsed = 0;
971
972 // FIRST WE RUN AN INVENTORY TO GET THE TAG UID
973 // THIS MEANS WE CAN PRE-BUILD REQUESTS TO SAVE CPU TIME
974 BYTE TagUID[7]; // where we hold the uid for hi15reader
975
976 // BuildIdentifyRequest();
977 // //TransmitTo15693Tag(ToSend,ToSendMax+3,&tsamples, &wait);
978 // TransmitTo15693Tag(ToSend,ToSendMax,&tsamples, &wait); // No longer ToSendMax+3
979 // // Now wait for a response
980 // responseLen0 = GetIso15693AnswerFromTag(receivedAnswer0, 100, &samples, &elapsed) ;
981 // if (responseLen0 >=12) // we should do a better check than this
982 // {
983 // // really we should check it is a valid mesg
984 // // but for now just grab what we think is the uid
985 // TagUID[0] = receivedAnswer0[2];
986 // TagUID[1] = receivedAnswer0[3];
987 // TagUID[2] = receivedAnswer0[4];
988 // TagUID[3] = receivedAnswer0[5];
989 // TagUID[4] = receivedAnswer0[6];
990 // TagUID[5] = receivedAnswer0[7];
991 // TagUID[6] = receivedAnswer0[8]; // IC Manufacturer code
992 // DbpIntegers(TagUID[6],TagUID[5],TagUID[4]);
993 //}
994
995 // Now send the IDENTIFY command
996 BuildIdentifyRequest();
997 //TransmitTo15693Tag(ToSend,ToSendMax+3,&tsamples, &wait);
998 TransmitTo15693Tag(ToSend,ToSendMax,&tsamples, &wait); // No longer ToSendMax+3
999 // Now wait for a response
1000 responseLen1 = GetIso15693AnswerFromTag(receivedAnswer1, 100, &samples, &elapsed) ;
1001
1002 if (responseLen1 >=12) // we should do a better check than this
1003 {
1004
1005 TagUID[0] = receivedAnswer1[2];
1006 TagUID[1] = receivedAnswer1[3];
1007 TagUID[2] = receivedAnswer1[4];
1008 TagUID[3] = receivedAnswer1[5];
1009 TagUID[4] = receivedAnswer1[6];
1010 TagUID[5] = receivedAnswer1[7];
1011 TagUID[6] = receivedAnswer1[8]; // IC Manufacturer code
1012
1013 // Now send the SELECT command
1014 BuildSelectRequest(TagUID);
1015 TransmitTo15693Tag(ToSend,ToSendMax,&tsamples, &wait); // No longer ToSendMax+3
1016 // Now wait for a response
1017 responseLen2 = GetIso15693AnswerFromTag(receivedAnswer2, 100, &samples, &elapsed);
1018
1019 // Now send the MULTI READ command
1020 // BuildArbitraryRequest(*TagUID,parameter);
1021 BuildArbitraryCustomRequest(TagUID,parameter);
1022 // BuildReadBlockRequest(*TagUID,parameter);
1023 // BuildSysInfoRequest(*TagUID);
1024 //TransmitTo15693Tag(ToSend,ToSendMax+3,&tsamples, &wait);
1025 TransmitTo15693Tag(ToSend,ToSendMax,&tsamples, &wait); // No longer ToSendMax+3
1026 // Now wait for a response
1027 responseLen3 = GetIso15693AnswerFromTag(receivedAnswer3, 100, &samples, &elapsed) ;
1028
1029 }
1030
1031 char str1 [4];
1032 //char str2 [200];
1033 int i;
1034
1035 itoa(responseLen1,str1);
1036 strcat(str1," octets read from IDENTIFY request");
1037 DbpString(str1);
1038 for(i = 0; i < responseLen1; i+=3) {
1039 DbpIntegers(receivedAnswer1[i],receivedAnswer1[i+1],receivedAnswer1[i+2]);
1040 }
1041
1042 itoa(responseLen2,str1);
1043 strcat(str1," octets read from SELECT request");
1044 DbpString(str1);
1045 for(i = 0; i < responseLen2; i+=3) {
1046 DbpIntegers(receivedAnswer2[i],receivedAnswer2[i+1],receivedAnswer2[i+2]);
1047 }
1048
1049 itoa(responseLen3,str1);
1050 strcat(str1," octets read from XXX request");
1051 DbpString(str1);
1052 for(i = 0; i < responseLen3; i+=3) {
1053 DbpIntegers(receivedAnswer3[i],receivedAnswer3[i+1],receivedAnswer3[i+2]);
1054 }
1055
1056 // str2[0]=0;
1057 // for(i = 0; i < responseLen3; i++) {
1058 // itoa(str1,receivedAnswer3[i]);
1059 // strcat(str2,str1);
1060 // }
1061 // DbpString(str2);
1062
1063 LED_A_OFF();
1064 LED_B_OFF();
1065 LED_C_OFF();
1066 LED_D_OFF();
1067 }
1068
1069 //-----------------------------------------------------------------------------
1070 // Simulate an ISO15693 TAG, perform anti-collision and then print any reader commands
1071 // all demodulation performed in arm rather than host. - greg
1072 //-----------------------------------------------------------------------------
1073 void SimTagIso15693(DWORD parameter)
1074 {
1075 LED_A_ON();
1076 LED_B_ON();
1077 LED_C_OFF();
1078 LED_D_OFF();
1079
1080 //DbpString(parameter);
1081
1082 BYTE *receivedAnswer0 = (((BYTE *)BigBuf) + 3560); // allow 100 bytes per reponse (way too much)
1083 BYTE *receivedAnswer1 = (((BYTE *)BigBuf) + 3660); //
1084 BYTE *receivedAnswer2 = (((BYTE *)BigBuf) + 3760);
1085 BYTE *receivedAnswer3 = (((BYTE *)BigBuf) + 3860);
1086 //BYTE *TagUID= (((BYTE *)BigBuf) + 3960); // where we hold the uid for hi15reader
1087 // int responseLen0 = 0;
1088 int responseLen1 = 0;
1089 // int responseLen2 = 0;
1090 // int responseLen3 = 0;
1091
1092 // Blank arrays
1093 int j;
1094 for(j = 0; j < 100; j++) {
1095 receivedAnswer3[j] = 0;
1096 receivedAnswer2[j] =0;
1097 receivedAnswer1[j] = 0;
1098 receivedAnswer0[j] = 0;
1099 }
1100
1101 // Setup SSC
1102 FpgaSetupSsc();
1103
1104 // Start from off (no field generated)
1105 FpgaWriteConfWord(FPGA_MAJOR_MODE_OFF);
1106 SpinDelay(200);
1107
1108 SetAdcMuxFor(GPIO_MUXSEL_HIPKD);
1109 FpgaSetupSsc();
1110
1111 // Give the tags time to energize
1112 // FpgaWriteConfWord(FPGA_MAJOR_MODE_HF_READER_RX_XCORR); // NO GOOD FOR SIM TAG!!!!
1113 SpinDelay(200);
1114
1115 LED_A_OFF();
1116 LED_B_OFF();
1117 LED_C_ON();
1118 LED_D_OFF();
1119
1120 int samples = 0;
1121 int tsamples = 0;
1122 int wait = 0;
1123 int elapsed = 0;
1124
1125 // FIRST WE RUN AN INVENTORY TO GET THE TAG UID
1126 // THIS MEANS WE CAN PRE-BUILD REQUESTS TO SAVE CPU TIME
1127 // BYTE TagUID[7]; // where we hold the uid for hi15reader
1128
1129 // Now send the IDENTIFY command
1130 // BuildIdentifyRequest();
1131 // TransmitTo15693Tag(ToSend,ToSendMax,&tsamples, &wait); // No longer ToSendMax+3
1132
1133 // Now wait for a command from the reader
1134 responseLen1=0;
1135 // while(responseLen1=0) {
1136 // if(BUTTON_PRESS()) break;
1137 responseLen1 = GetIso15693AnswerFromSniff(receivedAnswer1, 100, &samples, &elapsed) ;
1138 // }
1139
1140 if (responseLen1 >=1) // we should do a better check than this
1141 {
1142 // Build a suitable reponse to the reader INVENTORY cocmmand
1143 BuildInventoryResponse();
1144 TransmitTo15693Reader(ToSend,ToSendMax,&tsamples, &wait);
1145
1146 // Now wait for a command from the reader
1147 // responseLen2 = GetIso15693AnswerFromTag(receivedAnswer2, 100, &samples, &elapsed);
1148
1149 // Now wait for a command from the reader
1150 // responseLen3 = GetIso15693AnswerFromTag(receivedAnswer3, 100, &samples, &elapsed) ;
1151
1152 }
1153
1154 char str1 [4];
1155 //char str2 [200];
1156 int i;
1157
1158 itoa(responseLen1,str1);
1159 strcat(str1," octets read from reader command");
1160 DbpString(str1);
1161 for(i = 0; i < responseLen1; i+=3) {
1162 DbpIntegers(receivedAnswer1[i],receivedAnswer1[i+1],receivedAnswer1[i+2]);
1163 }
1164
1165 // itoa(responseLen2,str1);
1166 // strcat(str1," octets read from SELECT request");
1167 // DbpString(str1);
1168 // for(i = 0; i < responseLen2; i+=3) {
1169 // DbpIntegers(receivedAnswer2[i],receivedAnswer2[i+1],receivedAnswer2[i+2]);
1170 // }
1171 //
1172 // itoa(responseLen3,str1);
1173 // strcat(str1," octets read from XXX request");
1174 // DbpString(str1);
1175 // for(i = 0; i < responseLen3; i+=3) {
1176 // DbpIntegers(receivedAnswer3[i],receivedAnswer3[i+1],receivedAnswer3[i+2]);
1177 // }
1178
1179 // str2[0]=0;
1180 // for(i = 0; i < responseLen3; i++) {
1181 // itoa(str1,receivedAnswer3[i]);
1182 // strcat(str2,str1);
1183 // }
1184 // DbpString(str2);
1185
1186 LED_A_OFF();
1187 LED_B_OFF();
1188 LED_C_OFF();
1189 LED_D_OFF();
1190 }
Impressum, Datenschutz