]> git.zerfleddert.de Git - proxmark3-svn/blame - armsrc/iso15693.c
Clean up data types, some header cleanup, etc.
[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"
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
f7e3ed82 69static void CodeIso15693AsReader(uint8_t *cmd, int n)
15c4dc5a 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//-----------------------------------------------------------------------------
f7e3ed82 149static uint16_t Crc(uint8_t *v, int n)
15c4dc5a 150{
f7e3ed82 151 uint32_t reg;
15c4dc5a 152 int i, j;
153
154 reg = 0xffff;
155 for(i = 0; i < n; i++) {
f7e3ed82 156 reg = reg ^ ((uint32_t)v[i]);
15c4dc5a 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
169char *strcat(char *dest, const char *src)
170{
171 size_t dest_len = strlen(dest);
172 size_t i;
e30c654b 173
15c4dc5a 174 for (i = 0 ; src[i] != '\0' ; i++)
175 dest[dest_len + i] = src[i];
176 dest[dest_len + i] = '\0';
e30c654b 177
15c4dc5a 178 return dest;
179}
180
181////////////////////////////////////////// code to do 'itoa'
182
183/* reverse: reverse string s in place */
184void 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 */
196void 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//-----------------------------------------------------------------------------
218static void BuildIdentifyRequest(void)
219{
f7e3ed82 220 uint8_t cmd[5];
15c4dc5a 221
f7e3ed82 222 uint16_t crc;
15c4dc5a 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
f7e3ed82 238static void __attribute__((unused)) BuildSysInfoRequest(uint8_t *uid)
15c4dc5a 239{
f7e3ed82 240 uint8_t cmd[12];
15c4dc5a 241
f7e3ed82 242 uint16_t crc;
15c4dc5a 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
f7e3ed82 267static void BuildSelectRequest( uint8_t uid[])
15c4dc5a 268{
269
270// uid[6]=0x31; // this is getting ignored - the uid array is not happening...
f7e3ed82 271 uint8_t cmd[12];
15c4dc5a 272
f7e3ed82 273 uint16_t crc;
15c4dc5a 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
f7e3ed82 306static void __attribute__((unused)) BuildReadBlockRequest(uint8_t *uid, uint8_t blockNumber )
15c4dc5a 307{
f7e3ed82 308 uint8_t cmd[13];
15c4dc5a 309
f7e3ed82 310 uint16_t crc;
15c4dc5a 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
f7e3ed82 337static void __attribute__((unused)) BuildReadMultiBlockRequest(uint8_t *uid)
15c4dc5a 338{
f7e3ed82 339 uint8_t cmd[14];
15c4dc5a 340
f7e3ed82 341 uint16_t crc;
15c4dc5a 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
f7e3ed82 370static void __attribute__((unused)) BuildArbitraryRequest(uint8_t *uid,uint8_t CmdCode)
15c4dc5a 371{
f7e3ed82 372 uint8_t cmd[14];
15c4dc5a 373
f7e3ed82 374 uint16_t crc;
15c4dc5a 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
f7e3ed82 404static void __attribute__((unused)) BuildArbitraryCustomRequest(uint8_t uid[], uint8_t CmdCode)
15c4dc5a 405{
f7e3ed82 406 uint8_t cmd[14];
15c4dc5a 407
f7e3ed82 408 uint16_t crc;
15c4dc5a 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{
f7e3ed82 444 uint8_t cmd[12];
15c4dc5a 445
f7e3ed82 446 uint16_t crc;
15c4dc5a 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//-----------------------------------------------------------------------------
f7e3ed82 471static void TransmitTo15693Tag(const uint8_t *cmd, int len, int *samples, int *wait)
15c4dc5a 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)) {
f7e3ed82 485// volatile uint32_t r = AT91C_BASE_SSC->SSC_RHR;
15c4dc5a 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)) {
f7e3ed82 501 volatile uint32_t r = AT91C_BASE_SSC->SSC_RHR;
15c4dc5a 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//-----------------------------------------------------------------------------
f7e3ed82 512static void TransmitTo15693Reader(const uint8_t *cmd, int len, int *samples, int *wait)
15c4dc5a 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)) {
f7e3ed82 530 volatile uint32_t r = AT91C_BASE_SSC->SSC_RHR;
15c4dc5a 531 (void)r;
532 }
533 WDT_HIT();
534 }
535 *samples = (c + *wait) << 3;
536}
537
f7e3ed82 538static int GetIso15693AnswerFromTag(uint8_t *receivedResponse, int maxLen, int *samples, int *elapsed)
15c4dc5a 539{
540 int c = 0;
f7e3ed82 541 uint8_t *dest = (uint8_t *)BigBuf;
15c4dc5a 542 int getNext = 0;
543
f7e3ed82 544 int8_t prev = 0;
15c4dc5a 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)) {
f7e3ed82 556 int8_t b;
557 b = (int8_t)AT91C_BASE_SSC->SSC_RHR;
15c4dc5a 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) {
f7e3ed82 564 int8_t r;
15c4dc5a 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
f7e3ed82 577 dest[c++] = (uint8_t)r;
15c4dc5a 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
f7e3ed82 622 uint8_t outBuf[20];
15c4dc5a 623 memset(outBuf, 0, sizeof(outBuf));
f7e3ed82 624 uint8_t mask = 0x01;
15c4dc5a 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 }
f7e3ed82 663// uint8_t str1 [8];
15c4dc5a 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
f7e3ed82 685static int GetIso15693AnswerFromSniff(uint8_t *receivedResponse, int maxLen, int *samples, int *elapsed)
15c4dc5a 686{
687 int c = 0;
f7e3ed82 688 uint8_t *dest = (uint8_t *)BigBuf;
15c4dc5a 689 int getNext = 0;
690
f7e3ed82 691 int8_t prev = 0;
15c4dc5a 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)) {
f7e3ed82 703 int8_t b;
704 b = (int8_t)AT91C_BASE_SSC->SSC_RHR;
15c4dc5a 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) {
f7e3ed82 711 int8_t r;
15c4dc5a 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
f7e3ed82 724 dest[c++] = (uint8_t)r;
15c4dc5a 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
f7e3ed82 769 uint8_t outBuf[20];
15c4dc5a 770 memset(outBuf, 0, sizeof(outBuf));
f7e3ed82 771 uint8_t mask = 0x01;
15c4dc5a 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 }
f7e3ed82 810// uint8_t str1 [8];
15c4dc5a 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//-----------------------------------------------------------------------------
835void AcquireRawAdcSamplesIso15693(void)
836{
837 int c = 0;
f7e3ed82 838 uint8_t *dest = (uint8_t *)BigBuf;
15c4dc5a 839 int getNext = 0;
840
f7e3ed82 841 int8_t prev = 0;
15c4dc5a 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)) {
f7e3ed82 865 volatile uint32_t r = AT91C_BASE_SSC->SSC_RHR;
15c4dc5a 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)) {
f7e3ed82 880 int8_t b;
881 b = (int8_t)AT91C_BASE_SSC->SSC_RHR;
15c4dc5a 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) {
f7e3ed82 888 int8_t r;
15c4dc5a 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
f7e3ed82 901 dest[c++] = (uint8_t)r;
15c4dc5a 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//-----------------------------------------------------------------------------
f7e3ed82 919void ReaderIso15693(uint32_t parameter)
15c4dc5a 920{
921 LED_A_ON();
922 LED_B_ON();
923 LED_C_OFF();
924 LED_D_OFF();
925
926//DbpString(parameter);
927
f7e3ed82 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
15c4dc5a 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
f7e3ed82 967 uint8_t TagUID[7]; // where we hold the uid for hi15reader
15c4dc5a 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//-----------------------------------------------------------------------------
f7e3ed82 1057void SimTagIso15693(uint32_t parameter)
15c4dc5a 1058{
1059 LED_A_ON();
1060 LED_B_ON();
1061 LED_C_OFF();
1062 LED_D_OFF();
1063
f7e3ed82 1064 uint8_t *answer1 = (((uint8_t *)BigBuf) + 3660); //
15c4dc5a 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