]> git.zerfleddert.de Git - proxmark3-svn/blame - armsrc/iso15693.c
setting svn:eol-style=native on files, part 1
[proxmark3-svn] / armsrc / iso15693.c
CommitLineData
15c4dc5a 1//-----------------------------------------------------------------------------
bd20f8f4 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//-----------------------------------------------------------------------------
15c4dc5a 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.
bd20f8f4 12// Modified to perform modulation onboard in arm rather than on PC
15c4dc5a 13// Also added additional reader commands (SELECT, READ etc.)
15c4dc5a 14//-----------------------------------------------------------------------------
bd20f8f4 15
e30c654b 16#include "proxmark3.h"
f7e3ed82 17#include "util.h"
15c4dc5a 18#include "apps.h"
9ab7a6c7 19#include "string.h"
15c4dc5a 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
f7e3ed82 75static void CodeIso15693AsReader(uint8_t *cmd, int n)
15c4dc5a 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//-----------------------------------------------------------------------------
f7e3ed82 155static uint16_t Crc(uint8_t *v, int n)
15c4dc5a 156{
f7e3ed82 157 uint32_t reg;
15c4dc5a 158 int i, j;
159
160 reg = 0xffff;
161 for(i = 0; i < n; i++) {
f7e3ed82 162 reg = reg ^ ((uint32_t)v[i]);
15c4dc5a 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
175char *strcat(char *dest, const char *src)
176{
177 size_t dest_len = strlen(dest);
178 size_t i;
e30c654b 179
15c4dc5a 180 for (i = 0 ; src[i] != '\0' ; i++)
181 dest[dest_len + i] = src[i];
182 dest[dest_len + i] = '\0';
e30c654b 183
15c4dc5a 184 return dest;
185}
186
187////////////////////////////////////////// code to do 'itoa'
188
189/* reverse: reverse string s in place */
190void 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 */
202void 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//-----------------------------------------------------------------------------
224static void BuildIdentifyRequest(void)
225{
f7e3ed82 226 uint8_t cmd[5];
15c4dc5a 227
f7e3ed82 228 uint16_t crc;
15c4dc5a 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
f7e3ed82 244static void __attribute__((unused)) BuildSysInfoRequest(uint8_t *uid)
15c4dc5a 245{
f7e3ed82 246 uint8_t cmd[12];
15c4dc5a 247
f7e3ed82 248 uint16_t crc;
15c4dc5a 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
f7e3ed82 273static void BuildSelectRequest( uint8_t uid[])
15c4dc5a 274{
275
276// uid[6]=0x31; // this is getting ignored - the uid array is not happening...
f7e3ed82 277 uint8_t cmd[12];
15c4dc5a 278
f7e3ed82 279 uint16_t crc;
15c4dc5a 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
f7e3ed82 312static void __attribute__((unused)) BuildReadBlockRequest(uint8_t *uid, uint8_t blockNumber )
15c4dc5a 313{
f7e3ed82 314 uint8_t cmd[13];
15c4dc5a 315
f7e3ed82 316 uint16_t crc;
15c4dc5a 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
f7e3ed82 343static void __attribute__((unused)) BuildReadMultiBlockRequest(uint8_t *uid)
15c4dc5a 344{
f7e3ed82 345 uint8_t cmd[14];
15c4dc5a 346
f7e3ed82 347 uint16_t crc;
15c4dc5a 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
f7e3ed82 376static void __attribute__((unused)) BuildArbitraryRequest(uint8_t *uid,uint8_t CmdCode)
15c4dc5a 377{
f7e3ed82 378 uint8_t cmd[14];
15c4dc5a 379
f7e3ed82 380 uint16_t crc;
15c4dc5a 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
f7e3ed82 410static void __attribute__((unused)) BuildArbitraryCustomRequest(uint8_t uid[], uint8_t CmdCode)
15c4dc5a 411{
f7e3ed82 412 uint8_t cmd[14];
15c4dc5a 413
f7e3ed82 414 uint16_t crc;
15c4dc5a 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{
f7e3ed82 450 uint8_t cmd[12];
15c4dc5a 451
f7e3ed82 452 uint16_t crc;
15c4dc5a 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//-----------------------------------------------------------------------------
f7e3ed82 477static void TransmitTo15693Tag(const uint8_t *cmd, int len, int *samples, int *wait)
15c4dc5a 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)) {
f7e3ed82 491// volatile uint32_t r = AT91C_BASE_SSC->SSC_RHR;
15c4dc5a 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)) {
f7e3ed82 507 volatile uint32_t r = AT91C_BASE_SSC->SSC_RHR;
15c4dc5a 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//-----------------------------------------------------------------------------
f7e3ed82 518static void TransmitTo15693Reader(const uint8_t *cmd, int len, int *samples, int *wait)
15c4dc5a 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)) {
f7e3ed82 536 volatile uint32_t r = AT91C_BASE_SSC->SSC_RHR;
15c4dc5a 537 (void)r;
538 }
539 WDT_HIT();
540 }
541 *samples = (c + *wait) << 3;
542}
543
f7e3ed82 544static int GetIso15693AnswerFromTag(uint8_t *receivedResponse, int maxLen, int *samples, int *elapsed)
15c4dc5a 545{
546 int c = 0;
f7e3ed82 547 uint8_t *dest = (uint8_t *)BigBuf;
15c4dc5a 548 int getNext = 0;
549
f7e3ed82 550 int8_t prev = 0;
15c4dc5a 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)) {
f7e3ed82 562 int8_t b;
563 b = (int8_t)AT91C_BASE_SSC->SSC_RHR;
15c4dc5a 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) {
f7e3ed82 570 int8_t r;
15c4dc5a 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
f7e3ed82 583 dest[c++] = (uint8_t)r;
15c4dc5a 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
f7e3ed82 628 uint8_t outBuf[20];
15c4dc5a 629 memset(outBuf, 0, sizeof(outBuf));
f7e3ed82 630 uint8_t mask = 0x01;
15c4dc5a 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 }
f7e3ed82 669// uint8_t str1 [8];
15c4dc5a 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
f7e3ed82 691static int GetIso15693AnswerFromSniff(uint8_t *receivedResponse, int maxLen, int *samples, int *elapsed)
15c4dc5a 692{
693 int c = 0;
f7e3ed82 694 uint8_t *dest = (uint8_t *)BigBuf;
15c4dc5a 695 int getNext = 0;
696
f7e3ed82 697 int8_t prev = 0;
15c4dc5a 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)) {
f7e3ed82 709 int8_t b;
710 b = (int8_t)AT91C_BASE_SSC->SSC_RHR;
15c4dc5a 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) {
f7e3ed82 717 int8_t r;
15c4dc5a 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
f7e3ed82 730 dest[c++] = (uint8_t)r;
15c4dc5a 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
f7e3ed82 775 uint8_t outBuf[20];
15c4dc5a 776 memset(outBuf, 0, sizeof(outBuf));
f7e3ed82 777 uint8_t mask = 0x01;
15c4dc5a 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 }
f7e3ed82 816// uint8_t str1 [8];
15c4dc5a 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//-----------------------------------------------------------------------------
841void AcquireRawAdcSamplesIso15693(void)
842{
843 int c = 0;
f7e3ed82 844 uint8_t *dest = (uint8_t *)BigBuf;
15c4dc5a 845 int getNext = 0;
846
f7e3ed82 847 int8_t prev = 0;
15c4dc5a 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)) {
f7e3ed82 871 volatile uint32_t r = AT91C_BASE_SSC->SSC_RHR;
15c4dc5a 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)) {
f7e3ed82 886 int8_t b;
887 b = (int8_t)AT91C_BASE_SSC->SSC_RHR;
15c4dc5a 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) {
f7e3ed82 894 int8_t r;
15c4dc5a 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
f7e3ed82 907 dest[c++] = (uint8_t)r;
15c4dc5a 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//-----------------------------------------------------------------------------
f7e3ed82 925void ReaderIso15693(uint32_t parameter)
15c4dc5a 926{
927 LED_A_ON();
928 LED_B_ON();
929 LED_C_OFF();
930 LED_D_OFF();
931
932//DbpString(parameter);
933
f7e3ed82 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
15c4dc5a 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
f7e3ed82 973 uint8_t TagUID[7]; // where we hold the uid for hi15reader
15c4dc5a 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//-----------------------------------------------------------------------------
f7e3ed82 1063void SimTagIso15693(uint32_t parameter)
15c4dc5a 1064{
1065 LED_A_ON();
1066 LED_B_ON();
1067 LED_C_OFF();
1068 LED_D_OFF();
1069
f7e3ed82 1070 uint8_t *answer1 = (((uint8_t *)BigBuf) + 3660); //
15c4dc5a 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