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