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