]> git.zerfleddert.de Git - proxmark3-svn/blame - armsrc/iso15693.c
Split str* and mem* into string.[ch]
[proxmark3-svn] / armsrc / iso15693.c
CommitLineData
15c4dc5a 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//-----------------------------------------------------------------------------
e30c654b 11#include "proxmark3.h"
f7e3ed82 12#include "util.h"
15c4dc5a 13#include "apps.h"
9ab7a6c7 14#include "string.h"
15c4dc5a 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
f7e3ed82 70static void CodeIso15693AsReader(uint8_t *cmd, int n)
15c4dc5a 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//-----------------------------------------------------------------------------
f7e3ed82 150static uint16_t Crc(uint8_t *v, int n)
15c4dc5a 151{
f7e3ed82 152 uint32_t reg;
15c4dc5a 153 int i, j;
154
155 reg = 0xffff;
156 for(i = 0; i < n; i++) {
f7e3ed82 157 reg = reg ^ ((uint32_t)v[i]);
15c4dc5a 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
170char *strcat(char *dest, const char *src)
171{
172 size_t dest_len = strlen(dest);
173 size_t i;
e30c654b 174
15c4dc5a 175 for (i = 0 ; src[i] != '\0' ; i++)
176 dest[dest_len + i] = src[i];
177 dest[dest_len + i] = '\0';
e30c654b 178
15c4dc5a 179 return dest;
180}
181
182////////////////////////////////////////// code to do 'itoa'
183
184/* reverse: reverse string s in place */
185void 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 */
197void 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//-----------------------------------------------------------------------------
219static void BuildIdentifyRequest(void)
220{
f7e3ed82 221 uint8_t cmd[5];
15c4dc5a 222
f7e3ed82 223 uint16_t crc;
15c4dc5a 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
f7e3ed82 239static void __attribute__((unused)) BuildSysInfoRequest(uint8_t *uid)
15c4dc5a 240{
f7e3ed82 241 uint8_t cmd[12];
15c4dc5a 242
f7e3ed82 243 uint16_t crc;
15c4dc5a 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
f7e3ed82 268static void BuildSelectRequest( uint8_t uid[])
15c4dc5a 269{
270
271// uid[6]=0x31; // this is getting ignored - the uid array is not happening...
f7e3ed82 272 uint8_t cmd[12];
15c4dc5a 273
f7e3ed82 274 uint16_t crc;
15c4dc5a 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
f7e3ed82 307static void __attribute__((unused)) BuildReadBlockRequest(uint8_t *uid, uint8_t blockNumber )
15c4dc5a 308{
f7e3ed82 309 uint8_t cmd[13];
15c4dc5a 310
f7e3ed82 311 uint16_t crc;
15c4dc5a 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
f7e3ed82 338static void __attribute__((unused)) BuildReadMultiBlockRequest(uint8_t *uid)
15c4dc5a 339{
f7e3ed82 340 uint8_t cmd[14];
15c4dc5a 341
f7e3ed82 342 uint16_t crc;
15c4dc5a 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
f7e3ed82 371static void __attribute__((unused)) BuildArbitraryRequest(uint8_t *uid,uint8_t CmdCode)
15c4dc5a 372{
f7e3ed82 373 uint8_t cmd[14];
15c4dc5a 374
f7e3ed82 375 uint16_t crc;
15c4dc5a 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
f7e3ed82 405static void __attribute__((unused)) BuildArbitraryCustomRequest(uint8_t uid[], uint8_t CmdCode)
15c4dc5a 406{
f7e3ed82 407 uint8_t cmd[14];
15c4dc5a 408
f7e3ed82 409 uint16_t crc;
15c4dc5a 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{
f7e3ed82 445 uint8_t cmd[12];
15c4dc5a 446
f7e3ed82 447 uint16_t crc;
15c4dc5a 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//-----------------------------------------------------------------------------
f7e3ed82 472static void TransmitTo15693Tag(const uint8_t *cmd, int len, int *samples, int *wait)
15c4dc5a 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)) {
f7e3ed82 486// volatile uint32_t r = AT91C_BASE_SSC->SSC_RHR;
15c4dc5a 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)) {
f7e3ed82 502 volatile uint32_t r = AT91C_BASE_SSC->SSC_RHR;
15c4dc5a 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//-----------------------------------------------------------------------------
f7e3ed82 513static void TransmitTo15693Reader(const uint8_t *cmd, int len, int *samples, int *wait)
15c4dc5a 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)) {
f7e3ed82 531 volatile uint32_t r = AT91C_BASE_SSC->SSC_RHR;
15c4dc5a 532 (void)r;
533 }
534 WDT_HIT();
535 }
536 *samples = (c + *wait) << 3;
537}
538
f7e3ed82 539static int GetIso15693AnswerFromTag(uint8_t *receivedResponse, int maxLen, int *samples, int *elapsed)
15c4dc5a 540{
541 int c = 0;
f7e3ed82 542 uint8_t *dest = (uint8_t *)BigBuf;
15c4dc5a 543 int getNext = 0;
544
f7e3ed82 545 int8_t prev = 0;
15c4dc5a 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)) {
f7e3ed82 557 int8_t b;
558 b = (int8_t)AT91C_BASE_SSC->SSC_RHR;
15c4dc5a 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) {
f7e3ed82 565 int8_t r;
15c4dc5a 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
f7e3ed82 578 dest[c++] = (uint8_t)r;
15c4dc5a 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
f7e3ed82 623 uint8_t outBuf[20];
15c4dc5a 624 memset(outBuf, 0, sizeof(outBuf));
f7e3ed82 625 uint8_t mask = 0x01;
15c4dc5a 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 }
f7e3ed82 664// uint8_t str1 [8];
15c4dc5a 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
f7e3ed82 686static int GetIso15693AnswerFromSniff(uint8_t *receivedResponse, int maxLen, int *samples, int *elapsed)
15c4dc5a 687{
688 int c = 0;
f7e3ed82 689 uint8_t *dest = (uint8_t *)BigBuf;
15c4dc5a 690 int getNext = 0;
691
f7e3ed82 692 int8_t prev = 0;
15c4dc5a 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)) {
f7e3ed82 704 int8_t b;
705 b = (int8_t)AT91C_BASE_SSC->SSC_RHR;
15c4dc5a 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) {
f7e3ed82 712 int8_t r;
15c4dc5a 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
f7e3ed82 725 dest[c++] = (uint8_t)r;
15c4dc5a 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
f7e3ed82 770 uint8_t outBuf[20];
15c4dc5a 771 memset(outBuf, 0, sizeof(outBuf));
f7e3ed82 772 uint8_t mask = 0x01;
15c4dc5a 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 }
f7e3ed82 811// uint8_t str1 [8];
15c4dc5a 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//-----------------------------------------------------------------------------
836void AcquireRawAdcSamplesIso15693(void)
837{
838 int c = 0;
f7e3ed82 839 uint8_t *dest = (uint8_t *)BigBuf;
15c4dc5a 840 int getNext = 0;
841
f7e3ed82 842 int8_t prev = 0;
15c4dc5a 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)) {
f7e3ed82 866 volatile uint32_t r = AT91C_BASE_SSC->SSC_RHR;
15c4dc5a 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)) {
f7e3ed82 881 int8_t b;
882 b = (int8_t)AT91C_BASE_SSC->SSC_RHR;
15c4dc5a 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) {
f7e3ed82 889 int8_t r;
15c4dc5a 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
f7e3ed82 902 dest[c++] = (uint8_t)r;
15c4dc5a 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//-----------------------------------------------------------------------------
f7e3ed82 920void ReaderIso15693(uint32_t parameter)
15c4dc5a 921{
922 LED_A_ON();
923 LED_B_ON();
924 LED_C_OFF();
925 LED_D_OFF();
926
927//DbpString(parameter);
928
f7e3ed82 929 //uint8_t *answer0 = (((uint8_t *)BigBuf) + 3560); // allow 100 bytes per reponse (way too much)
930 uint8_t *answer1 = (((uint8_t *)BigBuf) + 3660); //
931 uint8_t *answer2 = (((uint8_t *)BigBuf) + 3760);
932 uint8_t *answer3 = (((uint8_t *)BigBuf) + 3860);
933 //uint8_t *TagUID= (((uint8_t *)BigBuf) + 3960); // where we hold the uid for hi15reader
15c4dc5a 934// int answerLen0 = 0;
935 int answerLen1 = 0;
936 int answerLen2 = 0;
937 int answerLen3 = 0;
938
939 // Blank arrays
940 memset(BigBuf + 3660, 0, 300);
941
942 // Setup SSC
943 FpgaSetupSsc();
944
945 // Start from off (no field generated)
946 FpgaWriteConfWord(FPGA_MAJOR_MODE_OFF);
947 SpinDelay(200);
948
949 SetAdcMuxFor(GPIO_MUXSEL_HIPKD);
950 FpgaSetupSsc();
951
952 // Give the tags time to energize
953 FpgaWriteConfWord(FPGA_MAJOR_MODE_HF_READER_RX_XCORR);
954 SpinDelay(200);
955
956 LED_A_ON();
957 LED_B_OFF();
958 LED_C_OFF();
959 LED_D_OFF();
960
961 int samples = 0;
962 int tsamples = 0;
963 int wait = 0;
964 int elapsed = 0;
965
966 // FIRST WE RUN AN INVENTORY TO GET THE TAG UID
967 // THIS MEANS WE CAN PRE-BUILD REQUESTS TO SAVE CPU TIME
f7e3ed82 968 uint8_t TagUID[7]; // where we hold the uid for hi15reader
15c4dc5a 969
970// BuildIdentifyRequest();
971// //TransmitTo15693Tag(ToSend,ToSendMax+3,&tsamples, &wait);
972// TransmitTo15693Tag(ToSend,ToSendMax,&tsamples, &wait); // No longer ToSendMax+3
973// // Now wait for a response
974// responseLen0 = GetIso15693AnswerFromTag(receivedAnswer0, 100, &samples, &elapsed) ;
975// if (responseLen0 >=12) // we should do a better check than this
976// {
977// // really we should check it is a valid mesg
978// // but for now just grab what we think is the uid
979// TagUID[0] = receivedAnswer0[2];
980// TagUID[1] = receivedAnswer0[3];
981// TagUID[2] = receivedAnswer0[4];
982// TagUID[3] = receivedAnswer0[5];
983// TagUID[4] = receivedAnswer0[6];
984// TagUID[5] = receivedAnswer0[7];
985// TagUID[6] = receivedAnswer0[8]; // IC Manufacturer code
986// DbpIntegers(TagUID[6],TagUID[5],TagUID[4]);
987//}
988
989 // Now send the IDENTIFY command
990 BuildIdentifyRequest();
991 //TransmitTo15693Tag(ToSend,ToSendMax+3,&tsamples, &wait);
992 TransmitTo15693Tag(ToSend,ToSendMax,&tsamples, &wait); // No longer ToSendMax+3
993 // Now wait for a response
994 answerLen1 = GetIso15693AnswerFromTag(answer1, 100, &samples, &elapsed) ;
995
996 if (answerLen1 >=12) // we should do a better check than this
997 {
998
999 TagUID[0] = answer1[2];
1000 TagUID[1] = answer1[3];
1001 TagUID[2] = answer1[4];
1002 TagUID[3] = answer1[5];
1003 TagUID[4] = answer1[6];
1004 TagUID[5] = answer1[7];
1005 TagUID[6] = answer1[8]; // IC Manufacturer code
1006
1007 // Now send the SELECT command
1008 BuildSelectRequest(TagUID);
1009 TransmitTo15693Tag(ToSend,ToSendMax,&tsamples, &wait); // No longer ToSendMax+3
1010 // Now wait for a response
1011 answerLen2 = GetIso15693AnswerFromTag(answer2, 100, &samples, &elapsed);
1012
1013 // Now send the MULTI READ command
1014// BuildArbitraryRequest(*TagUID,parameter);
1015 BuildArbitraryCustomRequest(TagUID,parameter);
1016// BuildReadBlockRequest(*TagUID,parameter);
1017// BuildSysInfoRequest(*TagUID);
1018 //TransmitTo15693Tag(ToSend,ToSendMax+3,&tsamples, &wait);
1019 TransmitTo15693Tag(ToSend,ToSendMax,&tsamples, &wait); // No longer ToSendMax+3
1020 // Now wait for a response
1021 answerLen3 = GetIso15693AnswerFromTag(answer3, 100, &samples, &elapsed) ;
1022
1023 }
1024
1025 Dbprintf("%d octets read from IDENTIFY request: %x %x %x %x %x %x %x %x %x", answerLen1,
1026 answer1[0], answer1[1], answer1[2],
1027 answer1[3], answer1[4], answer1[5],
1028 answer1[6], answer1[7], answer1[8]);
1029
1030 Dbprintf("%d octets read from SELECT request: %x %x %x %x %x %x %x %x %x", answerLen2,
1031 answer2[0], answer2[1], answer2[2],
1032 answer2[3], answer2[4], answer2[5],
1033 answer2[6], answer2[7], answer2[8]);
1034
1035 Dbprintf("%d octets read from XXX request: %x %x %x %x %x %x %x %x %x", answerLen3,
1036 answer3[0], answer3[1], answer3[2],
1037 answer3[3], answer3[4], answer3[5],
1038 answer3[6], answer3[7], answer3[8]);
1039
1040
1041// str2[0]=0;
1042// for(i = 0; i < responseLen3; i++) {
1043// itoa(str1,receivedAnswer3[i]);
1044// strcat(str2,str1);
1045// }
1046// DbpString(str2);
1047
1048 LED_A_OFF();
1049 LED_B_OFF();
1050 LED_C_OFF();
1051 LED_D_OFF();
1052}
1053
1054//-----------------------------------------------------------------------------
1055// Simulate an ISO15693 TAG, perform anti-collision and then print any reader commands
1056// all demodulation performed in arm rather than host. - greg
1057//-----------------------------------------------------------------------------
f7e3ed82 1058void SimTagIso15693(uint32_t parameter)
15c4dc5a 1059{
1060 LED_A_ON();
1061 LED_B_ON();
1062 LED_C_OFF();
1063 LED_D_OFF();
1064
f7e3ed82 1065 uint8_t *answer1 = (((uint8_t *)BigBuf) + 3660); //
15c4dc5a 1066 int answerLen1 = 0;
1067
1068 // Blank arrays
1069 memset(answer1, 0, 100);
1070
1071 // Setup SSC
1072 FpgaSetupSsc();
1073
1074 // Start from off (no field generated)
1075 FpgaWriteConfWord(FPGA_MAJOR_MODE_OFF);
1076 SpinDelay(200);
1077
1078 SetAdcMuxFor(GPIO_MUXSEL_HIPKD);
1079 FpgaSetupSsc();
1080
1081 // Give the tags time to energize
1082// FpgaWriteConfWord(FPGA_MAJOR_MODE_HF_READER_RX_XCORR); // NO GOOD FOR SIM TAG!!!!
1083 SpinDelay(200);
1084
1085 LED_A_OFF();
1086 LED_B_OFF();
1087 LED_C_ON();
1088 LED_D_OFF();
1089
1090 int samples = 0;
1091 int tsamples = 0;
1092 int wait = 0;
1093 int elapsed = 0;
1094
1095 answerLen1 = GetIso15693AnswerFromSniff(answer1, 100, &samples, &elapsed) ;
1096
1097 if (answerLen1 >=1) // we should do a better check than this
1098 {
1099 // Build a suitable reponse to the reader INVENTORY cocmmand
1100 BuildInventoryResponse();
1101 TransmitTo15693Reader(ToSend,ToSendMax, &tsamples, &wait);
1102 }
1103
1104 Dbprintf("%d octets read from reader command: %x %x %x %x %x %x %x %x %x", answerLen1,
1105 answer1[0], answer1[1], answer1[2],
1106 answer1[3], answer1[4], answer1[5],
1107 answer1[6], answer1[7], answer1[8]);
1108
1109 LED_A_OFF();
1110 LED_B_OFF();
1111 LED_C_OFF();
1112 LED_D_OFF();
1113}
Impressum, Datenschutz