]> git.zerfleddert.de Git - proxmark3-svn/blame - armsrc/iso14443.c
Client cleanup and restructuring. Stage 1...
[proxmark3-svn] / armsrc / iso14443.c
CommitLineData
6658905f 1//-----------------------------------------------------------------------------\r
2// Routines to support ISO 14443. This includes both the reader software and\r
3// the `fake tag' modes. At the moment only the Type B modulation is\r
4// supported.\r
5// Jonathan Westhues, split Nov 2006\r
6//-----------------------------------------------------------------------------\r
7#include <proxmark3.h>\r
8#include "apps.h"\r
7fe9b0b7 9#include "iso14443crc.h"\r
6658905f 10\r
11\r
12//static void GetSamplesFor14443(BOOL weTx, int n);\r
13\r
8caef540 14#define DEMOD_TRACE_SIZE 4096\r
15#define READER_TAG_BUFFER_SIZE 2048\r
16#define TAG_READER_BUFFER_SIZE 2048\r
17#define DMA_BUFFER_SIZE 1024\r
6658905f 18\r
19//=============================================================================\r
20// An ISO 14443 Type B tag. We listen for commands from the reader, using\r
21// a UART kind of thing that's implemented in software. When we get a\r
22// frame (i.e., a group of bytes between SOF and EOF), we check the CRC.\r
23// If it's good, then we can do something appropriate with it, and send\r
24// a response.\r
25//=============================================================================\r
26\r
27//-----------------------------------------------------------------------------\r
28// Code up a string of octets at layer 2 (including CRC, we don't generate\r
29// that here) so that they can be transmitted to the reader. Doesn't transmit\r
30// them yet, just leaves them ready to send in ToSend[].\r
31//-----------------------------------------------------------------------------\r
32static void CodeIso14443bAsTag(const BYTE *cmd, int len)\r
33{\r
34 int i;\r
35\r
36 ToSendReset();\r
37\r
38 // Transmit a burst of ones, as the initial thing that lets the\r
39 // reader get phase sync. This (TR1) must be > 80/fs, per spec,\r
40 // but tag that I've tried (a Paypass) exceeds that by a fair bit,\r
41 // so I will too.\r
42 for(i = 0; i < 20; i++) {\r
43 ToSendStuffBit(1);\r
44 ToSendStuffBit(1);\r
45 ToSendStuffBit(1);\r
46 ToSendStuffBit(1);\r
47 }\r
48\r
49 // Send SOF.\r
50 for(i = 0; i < 10; i++) {\r
51 ToSendStuffBit(0);\r
52 ToSendStuffBit(0);\r
53 ToSendStuffBit(0);\r
54 ToSendStuffBit(0);\r
55 }\r
56 for(i = 0; i < 2; i++) {\r
57 ToSendStuffBit(1);\r
58 ToSendStuffBit(1);\r
59 ToSendStuffBit(1);\r
60 ToSendStuffBit(1);\r
61 }\r
62\r
63 for(i = 0; i < len; i++) {\r
64 int j;\r
65 BYTE b = cmd[i];\r
66\r
67 // Start bit\r
68 ToSendStuffBit(0);\r
69 ToSendStuffBit(0);\r
70 ToSendStuffBit(0);\r
71 ToSendStuffBit(0);\r
72\r
73 // Data bits\r
74 for(j = 0; j < 8; j++) {\r
75 if(b & 1) {\r
76 ToSendStuffBit(1);\r
77 ToSendStuffBit(1);\r
78 ToSendStuffBit(1);\r
79 ToSendStuffBit(1);\r
80 } else {\r
81 ToSendStuffBit(0);\r
82 ToSendStuffBit(0);\r
83 ToSendStuffBit(0);\r
84 ToSendStuffBit(0);\r
85 }\r
86 b >>= 1;\r
87 }\r
88\r
89 // Stop bit\r
90 ToSendStuffBit(1);\r
91 ToSendStuffBit(1);\r
92 ToSendStuffBit(1);\r
93 ToSendStuffBit(1);\r
94 }\r
95\r
96 // Send SOF.\r
97 for(i = 0; i < 10; i++) {\r
98 ToSendStuffBit(0);\r
99 ToSendStuffBit(0);\r
100 ToSendStuffBit(0);\r
101 ToSendStuffBit(0);\r
102 }\r
103 for(i = 0; i < 10; i++) {\r
104 ToSendStuffBit(1);\r
105 ToSendStuffBit(1);\r
106 ToSendStuffBit(1);\r
107 ToSendStuffBit(1);\r
108 }\r
109\r
110 // Convert from last byte pos to length\r
111 ToSendMax++;\r
112\r
113 // Add a few more for slop\r
114 ToSendMax += 2;\r
115}\r
116\r
117//-----------------------------------------------------------------------------\r
118// The software UART that receives commands from the reader, and its state\r
119// variables.\r
120//-----------------------------------------------------------------------------\r
121static struct {\r
122 enum {\r
123 STATE_UNSYNCD,\r
124 STATE_GOT_FALLING_EDGE_OF_SOF,\r
125 STATE_AWAITING_START_BIT,\r
126 STATE_RECEIVING_DATA,\r
127 STATE_ERROR_WAIT\r
128 } state;\r
129 WORD shiftReg;\r
130 int bitCnt;\r
131 int byteCnt;\r
132 int byteCntMax;\r
133 int posCnt;\r
134 BYTE *output;\r
135} Uart;\r
136\r
0e25ae11 137/* Receive & handle a bit coming from the reader.\r
138 *\r
139 * LED handling:\r
140 * LED A -> ON once we have received the SOF and are expecting the rest.\r
141 * LED A -> OFF once we have received EOF or are in error state or unsynced\r
142 *\r
143 * Returns: true if we received a EOF\r
144 * false if we are still waiting for some more\r
145 */\r
6658905f 146static BOOL Handle14443UartBit(int bit)\r
147{\r
148 switch(Uart.state) {\r
149 case STATE_UNSYNCD:\r
0e25ae11 150 LED_A_OFF();\r
6658905f 151 if(!bit) {\r
152 // we went low, so this could be the beginning\r
153 // of an SOF\r
154 Uart.state = STATE_GOT_FALLING_EDGE_OF_SOF;\r
155 Uart.posCnt = 0;\r
156 Uart.bitCnt = 0;\r
157 }\r
158 break;\r
159\r
160 case STATE_GOT_FALLING_EDGE_OF_SOF:\r
161 Uart.posCnt++;\r
162 if(Uart.posCnt == 2) {\r
163 if(bit) {\r
164 if(Uart.bitCnt >= 10) {\r
165 // we've seen enough consecutive\r
166 // zeros that it's a valid SOF\r
167 Uart.posCnt = 0;\r
168 Uart.byteCnt = 0;\r
169 Uart.state = STATE_AWAITING_START_BIT;\r
0e25ae11 170 LED_A_ON(); // Indicate we got a valid SOF\r
6658905f 171 } else {\r
172 // didn't stay down long enough\r
173 // before going high, error\r
174 Uart.state = STATE_ERROR_WAIT;\r
175 }\r
176 } else {\r
177 // do nothing, keep waiting\r
178 }\r
179 Uart.bitCnt++;\r
180 }\r
181 if(Uart.posCnt >= 4) Uart.posCnt = 0;\r
182 if(Uart.bitCnt > 14) {\r
183 // Give up if we see too many zeros without\r
184 // a one, too.\r
185 Uart.state = STATE_ERROR_WAIT;\r
186 }\r
187 break;\r
188\r
189 case STATE_AWAITING_START_BIT:\r
190 Uart.posCnt++;\r
191 if(bit) {\r
192 if(Uart.posCnt > 25) {\r
193 // stayed high for too long between\r
194 // characters, error\r
195 Uart.state = STATE_ERROR_WAIT;\r
196 }\r
197 } else {\r
198 // falling edge, this starts the data byte\r
199 Uart.posCnt = 0;\r
200 Uart.bitCnt = 0;\r
201 Uart.shiftReg = 0;\r
202 Uart.state = STATE_RECEIVING_DATA;\r
0e25ae11 203 LED_A_ON(); // Indicate we're receiving\r
6658905f 204 }\r
205 break;\r
206\r
207 case STATE_RECEIVING_DATA:\r
208 Uart.posCnt++;\r
209 if(Uart.posCnt == 2) {\r
210 // time to sample a bit\r
211 Uart.shiftReg >>= 1;\r
212 if(bit) {\r
213 Uart.shiftReg |= 0x200;\r
214 }\r
215 Uart.bitCnt++;\r
216 }\r
217 if(Uart.posCnt >= 4) {\r
218 Uart.posCnt = 0;\r
219 }\r
220 if(Uart.bitCnt == 10) {\r
221 if((Uart.shiftReg & 0x200) && !(Uart.shiftReg & 0x001))\r
222 {\r
223 // this is a data byte, with correct\r
224 // start and stop bits\r
225 Uart.output[Uart.byteCnt] = (Uart.shiftReg >> 1) & 0xff;\r
226 Uart.byteCnt++;\r
227\r
228 if(Uart.byteCnt >= Uart.byteCntMax) {\r
229 // Buffer overflowed, give up\r
230 Uart.posCnt = 0;\r
231 Uart.state = STATE_ERROR_WAIT;\r
232 } else {\r
233 // so get the next byte now\r
234 Uart.posCnt = 0;\r
235 Uart.state = STATE_AWAITING_START_BIT;\r
236 }\r
237 } else if(Uart.shiftReg == 0x000) {\r
238 // this is an EOF byte\r
0e25ae11 239 LED_A_OFF(); // Finished receiving\r
6658905f 240 return TRUE;\r
241 } else {\r
242 // this is an error\r
243 Uart.posCnt = 0;\r
244 Uart.state = STATE_ERROR_WAIT;\r
245 }\r
246 }\r
247 break;\r
248\r
249 case STATE_ERROR_WAIT:\r
250 // We're all screwed up, so wait a little while\r
251 // for whatever went wrong to finish, and then\r
252 // start over.\r
253 Uart.posCnt++;\r
254 if(Uart.posCnt > 10) {\r
255 Uart.state = STATE_UNSYNCD;\r
256 }\r
257 break;\r
258\r
259 default:\r
260 Uart.state = STATE_UNSYNCD;\r
261 break;\r
262 }\r
263\r
0e25ae11 264 if (Uart.state == STATE_ERROR_WAIT) LED_A_OFF(); // Error\r
265\r
6658905f 266 return FALSE;\r
267}\r
268\r
269//-----------------------------------------------------------------------------\r
270// Receive a command (from the reader to us, where we are the simulated tag),\r
271// and store it in the given buffer, up to the given maximum length. Keeps\r
272// spinning, waiting for a well-framed command, until either we get one\r
273// (returns TRUE) or someone presses the pushbutton on the board (FALSE).\r
274//\r
275// Assume that we're called with the SSC (to the FPGA) and ADC path set\r
276// correctly.\r
277//-----------------------------------------------------------------------------\r
278static BOOL GetIso14443CommandFromReader(BYTE *received, int *len, int maxLen)\r
279{\r
280 BYTE mask;\r
281 int i, bit;\r
282\r
283 // Set FPGA mode to "simulated ISO 14443 tag", no modulation (listen\r
284 // only, since we are receiving, not transmitting).\r
0e25ae11 285 // Signal field is off with the appropriate LED\r
286 LED_D_OFF();\r
6658905f 287 FpgaWriteConfWord(\r
288 FPGA_MAJOR_MODE_HF_SIMULATOR | FPGA_HF_SIMULATOR_NO_MODULATION);\r
289\r
290\r
291 // Now run a `software UART' on the stream of incoming samples.\r
292 Uart.output = received;\r
293 Uart.byteCntMax = maxLen;\r
294 Uart.state = STATE_UNSYNCD;\r
295\r
296 for(;;) {\r
297 WDT_HIT();\r
298\r
299 if(BUTTON_PRESS()) return FALSE;\r
300\r
6949aca9 301 if(AT91C_BASE_SSC->SSC_SR & (AT91C_SSC_TXRDY)) {\r
302 AT91C_BASE_SSC->SSC_THR = 0x00;\r
6658905f 303 }\r
6949aca9 304 if(AT91C_BASE_SSC->SSC_SR & (AT91C_SSC_RXRDY)) {\r
305 BYTE b = (BYTE)AT91C_BASE_SSC->SSC_RHR;\r
6658905f 306\r
307 mask = 0x80;\r
308 for(i = 0; i < 8; i++, mask >>= 1) {\r
309 bit = (b & mask);\r
310 if(Handle14443UartBit(bit)) {\r
311 *len = Uart.byteCnt;\r
312 return TRUE;\r
313 }\r
314 }\r
315 }\r
316 }\r
317}\r
318\r
319//-----------------------------------------------------------------------------\r
320// Main loop of simulated tag: receive commands from reader, decide what\r
321// response to send, and send it.\r
322//-----------------------------------------------------------------------------\r
323void SimulateIso14443Tag(void)\r
324{\r
325 static const BYTE cmd1[] = { 0x05, 0x00, 0x08, 0x39, 0x73 };\r
326 static const BYTE response1[] = {\r
327 0x50, 0x82, 0x0d, 0xe1, 0x74, 0x20, 0x38, 0x19, 0x22,\r
328 0x00, 0x21, 0x85, 0x5e, 0xd7\r
329 };\r
330\r
331 BYTE *resp;\r
332 int respLen;\r
333\r
334 BYTE *resp1 = (((BYTE *)BigBuf) + 800);\r
335 int resp1Len;\r
336\r
337 BYTE *receivedCmd = (BYTE *)BigBuf;\r
338 int len;\r
339\r
340 int i;\r
341\r
342 int cmdsRecvd = 0;\r
343\r
344 memset(receivedCmd, 0x44, 400);\r
345\r
346 CodeIso14443bAsTag(response1, sizeof(response1));\r
347 memcpy(resp1, ToSend, ToSendMax); resp1Len = ToSendMax;\r
348\r
349 // We need to listen to the high-frequency, peak-detected path.\r
350 SetAdcMuxFor(GPIO_MUXSEL_HIPKD);\r
351 FpgaSetupSsc();\r
352\r
353 cmdsRecvd = 0;\r
354\r
355 for(;;) {\r
356 BYTE b1, b2;\r
357\r
358 if(!GetIso14443CommandFromReader(receivedCmd, &len, 100)) {\r
850427c8 359 Dbprintf("button pressed, received %d commands", cmdsRecvd);\r
360 break;\r
6658905f 361 }\r
362\r
363 // Good, look at the command now.\r
364\r
365 if(len == sizeof(cmd1) && memcmp(receivedCmd, cmd1, len)==0) {\r
366 resp = resp1; respLen = resp1Len;\r
367 } else {\r
850427c8 368 Dbprintf("new cmd from reader: len=%d, cmdsRecvd=%d", len, cmdsRecvd);\r
6658905f 369 // And print whether the CRC fails, just for good measure\r
370 ComputeCrc14443(CRC_14443_B, receivedCmd, len-2, &b1, &b2);\r
371 if(b1 != receivedCmd[len-2] || b2 != receivedCmd[len-1]) {\r
372 // Not so good, try again.\r
373 DbpString("+++CRC fail");\r
374 } else {\r
375 DbpString("CRC passes");\r
376 }\r
377 break;\r
378 }\r
379\r
380 memset(receivedCmd, 0x44, 32);\r
381\r
382 cmdsRecvd++;\r
383\r
384 if(cmdsRecvd > 0x30) {\r
385 DbpString("many commands later...");\r
386 break;\r
387 }\r
388\r
389 if(respLen <= 0) continue;\r
390\r
391 // Modulate BPSK\r
0e25ae11 392 // Signal field is off with the appropriate LED\r
393 LED_D_OFF();\r
6658905f 394 FpgaWriteConfWord(\r
395 FPGA_MAJOR_MODE_HF_SIMULATOR | FPGA_HF_SIMULATOR_MODULATE_BPSK);\r
6949aca9 396 AT91C_BASE_SSC->SSC_THR = 0xff;\r
6658905f 397 FpgaSetupSsc();\r
398\r
399 // Transmit the response.\r
400 i = 0;\r
401 for(;;) {\r
6949aca9 402 if(AT91C_BASE_SSC->SSC_SR & (AT91C_SSC_TXRDY)) {\r
6658905f 403 BYTE b = resp[i];\r
404\r
6949aca9 405 AT91C_BASE_SSC->SSC_THR = b;\r
6658905f 406\r
407 i++;\r
408 if(i > respLen) {\r
409 break;\r
410 }\r
411 }\r
6949aca9 412 if(AT91C_BASE_SSC->SSC_SR & (AT91C_SSC_RXRDY)) {\r
413 volatile BYTE b = (BYTE)AT91C_BASE_SSC->SSC_RHR;\r
6658905f 414 (void)b;\r
415 }\r
416 }\r
417 }\r
418}\r
419\r
420//=============================================================================\r
421// An ISO 14443 Type B reader. We take layer two commands, code them\r
422// appropriately, and then send them to the tag. We then listen for the\r
423// tag's response, which we leave in the buffer to be demodulated on the\r
424// PC side.\r
425//=============================================================================\r
426\r
427static struct {\r
428 enum {\r
429 DEMOD_UNSYNCD,\r
430 DEMOD_PHASE_REF_TRAINING,\r
431 DEMOD_AWAITING_FALLING_EDGE_OF_SOF,\r
432 DEMOD_GOT_FALLING_EDGE_OF_SOF,\r
433 DEMOD_AWAITING_START_BIT,\r
434 DEMOD_RECEIVING_DATA,\r
435 DEMOD_ERROR_WAIT\r
436 } state;\r
437 int bitCount;\r
438 int posCount;\r
439 int thisBit;\r
440 int metric;\r
441 int metricN;\r
442 WORD shiftReg;\r
443 BYTE *output;\r
444 int len;\r
445 int sumI;\r
446 int sumQ;\r
447} Demod;\r
448\r
0e25ae11 449/*\r
450 * Handles reception of a bit from the tag\r
451 *\r
452 * LED handling:\r
453 * LED C -> ON once we have received the SOF and are expecting the rest.\r
454 * LED C -> OFF once we have received EOF or are unsynced\r
455 *\r
456 * Returns: true if we received a EOF\r
457 * false if we are still waiting for some more\r
6949aca9 458 *\r
0e25ae11 459 */\r
6658905f 460static BOOL Handle14443SamplesDemod(int ci, int cq)\r
461{\r
462 int v;\r
463\r
464 // The soft decision on the bit uses an estimate of just the\r
465 // quadrant of the reference angle, not the exact angle.\r
466#define MAKE_SOFT_DECISION() { \\r
467 if(Demod.sumI > 0) { \\r
468 v = ci; \\r
469 } else { \\r
470 v = -ci; \\r
471 } \\r
472 if(Demod.sumQ > 0) { \\r
473 v += cq; \\r
474 } else { \\r
475 v -= cq; \\r
476 } \\r
477 }\r
478\r
479 switch(Demod.state) {\r
480 case DEMOD_UNSYNCD:\r
481 v = ci;\r
482 if(v < 0) v = -v;\r
483 if(cq > 0) {\r
484 v += cq;\r
485 } else {\r
486 v -= cq;\r
487 }\r
488 if(v > 40) {\r
489 Demod.posCount = 0;\r
490 Demod.state = DEMOD_PHASE_REF_TRAINING;\r
491 Demod.sumI = 0;\r
492 Demod.sumQ = 0;\r
493 }\r
494 break;\r
495\r
496 case DEMOD_PHASE_REF_TRAINING:\r
497 if(Demod.posCount < 8) {\r
498 Demod.sumI += ci;\r
499 Demod.sumQ += cq;\r
500 } else if(Demod.posCount > 100) {\r
501 // error, waited too long\r
502 Demod.state = DEMOD_UNSYNCD;\r
503 } else {\r
504 MAKE_SOFT_DECISION();\r
505 if(v < 0) {\r
506 Demod.state = DEMOD_AWAITING_FALLING_EDGE_OF_SOF;\r
507 Demod.posCount = 0;\r
508 }\r
509 }\r
510 Demod.posCount++;\r
511 break;\r
512\r
513 case DEMOD_AWAITING_FALLING_EDGE_OF_SOF:\r
514 MAKE_SOFT_DECISION();\r
515 if(v < 0) {\r
516 Demod.state = DEMOD_GOT_FALLING_EDGE_OF_SOF;\r
517 Demod.posCount = 0;\r
518 } else {\r
519 if(Demod.posCount > 100) {\r
520 Demod.state = DEMOD_UNSYNCD;\r
521 }\r
522 }\r
523 Demod.posCount++;\r
524 break;\r
525\r
526 case DEMOD_GOT_FALLING_EDGE_OF_SOF:\r
527 MAKE_SOFT_DECISION();\r
528 if(v > 0) {\r
529 if(Demod.posCount < 12) {\r
530 Demod.state = DEMOD_UNSYNCD;\r
531 } else {\r
0e25ae11 532 LED_C_ON(); // Got SOF\r
6658905f 533 Demod.state = DEMOD_AWAITING_START_BIT;\r
534 Demod.posCount = 0;\r
535 Demod.len = 0;\r
536 Demod.metricN = 0;\r
537 Demod.metric = 0;\r
538 }\r
539 } else {\r
540 if(Demod.posCount > 100) {\r
541 Demod.state = DEMOD_UNSYNCD;\r
542 }\r
543 }\r
544 Demod.posCount++;\r
545 break;\r
546\r
547 case DEMOD_AWAITING_START_BIT:\r
548 MAKE_SOFT_DECISION();\r
549 if(v > 0) {\r
550 if(Demod.posCount > 10) {\r
551 Demod.state = DEMOD_UNSYNCD;\r
552 }\r
553 } else {\r
554 Demod.bitCount = 0;\r
555 Demod.posCount = 1;\r
556 Demod.thisBit = v;\r
557 Demod.shiftReg = 0;\r
558 Demod.state = DEMOD_RECEIVING_DATA;\r
559 }\r
560 break;\r
561\r
562 case DEMOD_RECEIVING_DATA:\r
563 MAKE_SOFT_DECISION();\r
564 if(Demod.posCount == 0) {\r
565 Demod.thisBit = v;\r
566 Demod.posCount = 1;\r
567 } else {\r
568 Demod.thisBit += v;\r
569\r
570 if(Demod.thisBit > 0) {\r
571 Demod.metric += Demod.thisBit;\r
572 } else {\r
573 Demod.metric -= Demod.thisBit;\r
574 }\r
575 (Demod.metricN)++;\r
576\r
577 Demod.shiftReg >>= 1;\r
578 if(Demod.thisBit > 0) {\r
579 Demod.shiftReg |= 0x200;\r
580 }\r
581\r
582 Demod.bitCount++;\r
583 if(Demod.bitCount == 10) {\r
584 WORD s = Demod.shiftReg;\r
585 if((s & 0x200) && !(s & 0x001)) {\r
586 BYTE b = (s >> 1);\r
587 Demod.output[Demod.len] = b;\r
588 Demod.len++;\r
589 Demod.state = DEMOD_AWAITING_START_BIT;\r
590 } else if(s == 0x000) {\r
591 // This is EOF\r
0e25ae11 592 LED_C_OFF();\r
6658905f 593 return TRUE;\r
594 Demod.state = DEMOD_UNSYNCD;\r
595 } else {\r
596 Demod.state = DEMOD_UNSYNCD;\r
597 }\r
598 }\r
599 Demod.posCount = 0;\r
600 }\r
601 break;\r
602\r
603 default:\r
604 Demod.state = DEMOD_UNSYNCD;\r
605 break;\r
606 }\r
607\r
0e25ae11 608 if (Demod.state == DEMOD_UNSYNCD) LED_C_OFF(); // Not synchronized...\r
6658905f 609 return FALSE;\r
610}\r
611\r
0e25ae11 612/*\r
613 * Demodulate the samples we received from the tag\r
614 * weTx: set to 'TRUE' if we behave like a reader\r
615 * set to 'FALSE' if we behave like a snooper\r
6949aca9 616 * quiet: set to 'TRUE' to disable debug output\r
0e25ae11 617 */\r
fb25b483 618static void GetSamplesFor14443Demod(BOOL weTx, int n, BOOL quiet)\r
6658905f 619{\r
620 int max = 0;\r
621 BOOL gotFrame = FALSE;\r
622\r
623//# define DMA_BUFFER_SIZE 8\r
624 SBYTE *dmaBuf;\r
625\r
626 int lastRxCounter;\r
627 SBYTE *upTo;\r
628\r
629 int ci, cq;\r
630\r
631 int samples = 0;\r
632\r
633 // Clear out the state of the "UART" that receives from the tag.\r
634 memset(BigBuf, 0x44, 400);\r
635 Demod.output = (BYTE *)BigBuf;\r
636 Demod.len = 0;\r
637 Demod.state = DEMOD_UNSYNCD;\r
638\r
639 // And the UART that receives from the reader\r
640 Uart.output = (((BYTE *)BigBuf) + 1024);\r
641 Uart.byteCntMax = 100;\r
642 Uart.state = STATE_UNSYNCD;\r
643\r
644 // Setup for the DMA.\r
645 dmaBuf = (SBYTE *)(BigBuf + 32);\r
646 upTo = dmaBuf;\r
647 lastRxCounter = DMA_BUFFER_SIZE;\r
648 FpgaSetupSscDma((BYTE *)dmaBuf, DMA_BUFFER_SIZE);\r
649\r
0e25ae11 650 // Signal field is ON with the appropriate LED:\r
651 if (weTx) LED_D_ON(); else LED_D_OFF();\r
6658905f 652 // And put the FPGA in the appropriate mode\r
653 FpgaWriteConfWord(\r
654 FPGA_MAJOR_MODE_HF_READER_RX_XCORR | FPGA_HF_READER_RX_XCORR_848_KHZ |\r
655 (weTx ? 0 : FPGA_HF_READER_RX_XCORR_SNOOP));\r
656\r
657 for(;;) {\r
6949aca9 658 int behindBy = lastRxCounter - AT91C_BASE_PDC_SSC->PDC_RCR;\r
6658905f 659 if(behindBy > max) max = behindBy;\r
660\r
6949aca9 661 while(((lastRxCounter-AT91C_BASE_PDC_SSC->PDC_RCR) & (DMA_BUFFER_SIZE-1))\r
6658905f 662 > 2)\r
663 {\r
664 ci = upTo[0];\r
665 cq = upTo[1];\r
666 upTo += 2;\r
667 if(upTo - dmaBuf > DMA_BUFFER_SIZE) {\r
668 upTo -= DMA_BUFFER_SIZE;\r
6949aca9 669 AT91C_BASE_PDC_SSC->PDC_RNPR = (DWORD)upTo;\r
670 AT91C_BASE_PDC_SSC->PDC_RNCR = DMA_BUFFER_SIZE;\r
6658905f 671 }\r
672 lastRxCounter -= 2;\r
673 if(lastRxCounter <= 0) {\r
674 lastRxCounter += DMA_BUFFER_SIZE;\r
675 }\r
676\r
677 samples += 2;\r
678\r
679 Handle14443UartBit(1);\r
680 Handle14443UartBit(1);\r
681\r
682 if(Handle14443SamplesDemod(ci, cq)) {\r
683 gotFrame = 1;\r
684 }\r
685 }\r
6658905f 686\r
687 if(samples > 2000) {\r
688 break;\r
689 }\r
690 }\r
6949aca9 691 AT91C_BASE_PDC_SSC->PDC_PTCR = AT91C_PDC_RXTDIS;\r
850427c8 692 if (!quiet) Dbprintf("%x %x %x", max, gotFrame, Demod.len);\r
6658905f 693}\r
694\r
695//-----------------------------------------------------------------------------\r
696// Read the tag's response. We just receive a stream of slightly-processed\r
697// samples from the FPGA, which we will later do some signal processing on,\r
698// to get the bits.\r
699//-----------------------------------------------------------------------------\r
700/*static void GetSamplesFor14443(BOOL weTx, int n)\r
701{\r
702 BYTE *dest = (BYTE *)BigBuf;\r
703 int c;\r
704\r
705 FpgaWriteConfWord(\r
706 FPGA_MAJOR_MODE_HF_READER_RX_XCORR | FPGA_HF_READER_RX_XCORR_848_KHZ |\r
707 (weTx ? 0 : FPGA_HF_READER_RX_XCORR_SNOOP));\r
708\r
709 c = 0;\r
710 for(;;) {\r
6949aca9 711 if(AT91C_BASE_SSC->SSC_SR & (AT91C_SSC_TXRDY)) {\r
712 AT91C_BASE_SSC->SSC_THR = 0x43;\r
6658905f 713 }\r
6949aca9 714 if(AT91C_BASE_SSC->SSC_SR & (AT91C_SSC_RXRDY)) {\r
6658905f 715 SBYTE b;\r
6949aca9 716 b = (SBYTE)AT91C_BASE_SSC->SSC_RHR;\r
6658905f 717\r
718 dest[c++] = (BYTE)b;\r
719\r
720 if(c >= n) {\r
721 break;\r
722 }\r
723 }\r
724 }\r
725}*/\r
726\r
727//-----------------------------------------------------------------------------\r
728// Transmit the command (to the tag) that was placed in ToSend[].\r
729//-----------------------------------------------------------------------------\r
730static void TransmitFor14443(void)\r
731{\r
732 int c;\r
733\r
734 FpgaSetupSsc();\r
735\r
6949aca9 736 while(AT91C_BASE_SSC->SSC_SR & (AT91C_SSC_TXRDY)) {\r
737 AT91C_BASE_SSC->SSC_THR = 0xff;\r
6658905f 738 }\r
739\r
0e25ae11 740 // Signal field is ON with the appropriate Red LED\r
741 LED_D_ON();\r
742 // Signal we are transmitting with the Green LED\r
743 LED_B_ON();\r
744 FpgaWriteConfWord(\r
6658905f 745 FPGA_MAJOR_MODE_HF_READER_TX | FPGA_HF_READER_TX_SHALLOW_MOD);\r
746\r
747 for(c = 0; c < 10;) {\r
6949aca9 748 if(AT91C_BASE_SSC->SSC_SR & (AT91C_SSC_TXRDY)) {\r
749 AT91C_BASE_SSC->SSC_THR = 0xff;\r
6658905f 750 c++;\r
751 }\r
6949aca9 752 if(AT91C_BASE_SSC->SSC_SR & (AT91C_SSC_RXRDY)) {\r
753 volatile DWORD r = AT91C_BASE_SSC->SSC_RHR;\r
6658905f 754 (void)r;\r
755 }\r
756 WDT_HIT();\r
757 }\r
758\r
759 c = 0;\r
760 for(;;) {\r
6949aca9 761 if(AT91C_BASE_SSC->SSC_SR & (AT91C_SSC_TXRDY)) {\r
762 AT91C_BASE_SSC->SSC_THR = ToSend[c];\r
6658905f 763 c++;\r
764 if(c >= ToSendMax) {\r
765 break;\r
766 }\r
767 }\r
6949aca9 768 if(AT91C_BASE_SSC->SSC_SR & (AT91C_SSC_RXRDY)) {\r
769 volatile DWORD r = AT91C_BASE_SSC->SSC_RHR;\r
6658905f 770 (void)r;\r
771 }\r
772 WDT_HIT();\r
773 }\r
0e25ae11 774 LED_B_OFF(); // Finished sending\r
6658905f 775}\r
776\r
777//-----------------------------------------------------------------------------\r
778// Code a layer 2 command (string of octets, including CRC) into ToSend[],\r
779// so that it is ready to transmit to the tag using TransmitFor14443().\r
780//-----------------------------------------------------------------------------\r
781void CodeIso14443bAsReader(const BYTE *cmd, int len)\r
782{\r
783 int i, j;\r
784 BYTE b;\r
785\r
786 ToSendReset();\r
787\r
788 // Establish initial reference level\r
789 for(i = 0; i < 40; i++) {\r
790 ToSendStuffBit(1);\r
791 }\r
792 // Send SOF\r
793 for(i = 0; i < 10; i++) {\r
794 ToSendStuffBit(0);\r
795 }\r
796\r
797 for(i = 0; i < len; i++) {\r
798 // Stop bits/EGT\r
799 ToSendStuffBit(1);\r
800 ToSendStuffBit(1);\r
801 // Start bit\r
802 ToSendStuffBit(0);\r
803 // Data bits\r
804 b = cmd[i];\r
805 for(j = 0; j < 8; j++) {\r
806 if(b & 1) {\r
807 ToSendStuffBit(1);\r
808 } else {\r
809 ToSendStuffBit(0);\r
810 }\r
811 b >>= 1;\r
812 }\r
813 }\r
814 // Send EOF\r
815 ToSendStuffBit(1);\r
816 for(i = 0; i < 10; i++) {\r
817 ToSendStuffBit(0);\r
818 }\r
819 for(i = 0; i < 8; i++) {\r
820 ToSendStuffBit(1);\r
821 }\r
822\r
823 // And then a little more, to make sure that the last character makes\r
824 // it out before we switch to rx mode.\r
825 for(i = 0; i < 24; i++) {\r
826 ToSendStuffBit(1);\r
827 }\r
828\r
829 // Convert from last character reference to length\r
830 ToSendMax++;\r
831}\r
832\r
833//-----------------------------------------------------------------------------\r
834// Read an ISO 14443 tag. We send it some set of commands, and record the\r
6949aca9 835// responses.\r
836// The command name is misleading, it actually decodes the reponse in HEX\r
fb25b483 837// into the output buffer (read the result using hexsamples, not hisamples)\r
6658905f 838//-----------------------------------------------------------------------------\r
839void AcquireRawAdcSamplesIso14443(DWORD parameter)\r
840{\r
6658905f 841 BYTE cmd1[] = { 0x05, 0x00, 0x08, 0x39, 0x73 };\r
842\r
843 // Make sure that we start from off, since the tags are stateful;\r
844 // confusing things will happen if we don't reset them between reads.\r
6658905f 845 FpgaWriteConfWord(FPGA_MAJOR_MODE_OFF);\r
0e25ae11 846 LED_D_OFF();\r
6658905f 847 SpinDelay(200);\r
848\r
849 SetAdcMuxFor(GPIO_MUXSEL_HIPKD);\r
850 FpgaSetupSsc();\r
851\r
852 // Now give it time to spin up.\r
0e25ae11 853 // Signal field is on with the appropriate LED\r
854 LED_D_ON();\r
6658905f 855 FpgaWriteConfWord(\r
856 FPGA_MAJOR_MODE_HF_READER_RX_XCORR | FPGA_HF_READER_RX_XCORR_848_KHZ);\r
857 SpinDelay(200);\r
858\r
859 CodeIso14443bAsReader(cmd1, sizeof(cmd1));\r
860 TransmitFor14443();\r
0e25ae11 861// LED_A_ON();\r
fb25b483 862 GetSamplesFor14443Demod(TRUE, 2000, FALSE);\r
0e25ae11 863// LED_A_OFF();\r
6658905f 864}\r
6949aca9 865\r
fb25b483 866//-----------------------------------------------------------------------------\r
867// Read a SRI512 ISO 14443 tag.\r
6949aca9 868//\r
869// SRI512 tags are just simple memory tags, here we're looking at making a dump\r
870// of the contents of the memory. No anticollision algorithm is done, we assume\r
871// we have a single tag in the field.\r
872//\r
fb25b483 873// I tried to be systematic and check every answer of the tag, every CRC, etc...\r
874//-----------------------------------------------------------------------------\r
875void ReadSRI512Iso14443(DWORD parameter)\r
876{\r
850427c8 877 ReadSTMemoryIso14443(parameter,0x0F);\r
878}\r
879void ReadSRIX4KIso14443(DWORD parameter)\r
880{\r
881 ReadSTMemoryIso14443(parameter,0x7F);\r
882}\r
883\r
884void ReadSTMemoryIso14443(DWORD parameter,DWORD dwLast)\r
885{\r
6949aca9 886 BYTE i = 0x00;\r
fb25b483 887\r
888 // Make sure that we start from off, since the tags are stateful;\r
889 // confusing things will happen if we don't reset them between reads.\r
890 LED_D_OFF();\r
891 FpgaWriteConfWord(FPGA_MAJOR_MODE_OFF);\r
892 SpinDelay(200);\r
893\r
894 SetAdcMuxFor(GPIO_MUXSEL_HIPKD);\r
895 FpgaSetupSsc();\r
896\r
897 // Now give it time to spin up.\r
0e25ae11 898 // Signal field is on with the appropriate LED\r
899 LED_D_ON();\r
fb25b483 900 FpgaWriteConfWord(\r
901 FPGA_MAJOR_MODE_HF_READER_RX_XCORR | FPGA_HF_READER_RX_XCORR_848_KHZ);\r
902 SpinDelay(200);\r
6949aca9 903\r
fb25b483 904 // First command: wake up the tag using the INITIATE command\r
905 BYTE cmd1[] = { 0x06, 0x00, 0x97, 0x5b};\r
906 CodeIso14443bAsReader(cmd1, sizeof(cmd1));\r
907 TransmitFor14443();\r
0e25ae11 908// LED_A_ON();\r
fb25b483 909 GetSamplesFor14443Demod(TRUE, 2000,TRUE);\r
0e25ae11 910// LED_A_OFF();\r
6949aca9 911\r
912 if (Demod.len == 0) {\r
913 DbpString("No response from tag");\r
914 return;\r
915 } else {\r
850427c8 916 Dbprintf("Randomly generated UID from tag (+ 2 byte CRC): %x %x %x",\r
917 Demod.output[0], Demod.output[1],Demod.output[2]);\r
6949aca9 918 }\r
919 // There is a response, SELECT the uid\r
920 DbpString("Now SELECT tag:");\r
921 cmd1[0] = 0x0E; // 0x0E is SELECT\r
922 cmd1[1] = Demod.output[0];\r
fb25b483 923 ComputeCrc14443(CRC_14443_B, cmd1, 2, &cmd1[2], &cmd1[3]);\r
924 CodeIso14443bAsReader(cmd1, sizeof(cmd1));\r
925 TransmitFor14443();\r
0e25ae11 926// LED_A_ON();\r
fb25b483 927 GetSamplesFor14443Demod(TRUE, 2000,TRUE);\r
0e25ae11 928// LED_A_OFF();\r
6949aca9 929 if (Demod.len != 3) {\r
850427c8 930 Dbprintf("Expected 3 bytes from tag, got %d", Demod.len);\r
6949aca9 931 return;\r
932 }\r
933 // Check the CRC of the answer:\r
fb25b483 934 ComputeCrc14443(CRC_14443_B, Demod.output, 1 , &cmd1[2], &cmd1[3]);\r
935 if(cmd1[2] != Demod.output[1] || cmd1[3] != Demod.output[2]) {\r
6949aca9 936 DbpString("CRC Error reading select response.");\r
937 return;\r
938 }\r
939 // Check response from the tag: should be the same UID as the command we just sent:\r
940 if (cmd1[1] != Demod.output[0]) {\r
850427c8 941 Dbprintf("Bad response to SELECT from Tag, aborting: %x %x", cmd1[1], Demod.output[0]);\r
6949aca9 942 return;\r
943 }\r
944 // Tag is now selected,\r
945 // First get the tag's UID:\r
946 cmd1[0] = 0x0B;\r
947 ComputeCrc14443(CRC_14443_B, cmd1, 1 , &cmd1[1], &cmd1[2]);\r
1a093c19 948 CodeIso14443bAsReader(cmd1, 3); // Only first three bytes for this one\r
949 TransmitFor14443();\r
0e25ae11 950// LED_A_ON();\r
1a093c19 951 GetSamplesFor14443Demod(TRUE, 2000,TRUE);\r
0e25ae11 952// LED_A_OFF();\r
6949aca9 953 if (Demod.len != 10) {\r
850427c8 954 Dbprintf("Expected 10 bytes from tag, got %d", Demod.len);\r
6949aca9 955 return;\r
956 }\r
957 // The check the CRC of the answer (use cmd1 as temporary variable):\r
1a093c19 958 ComputeCrc14443(CRC_14443_B, Demod.output, 8, &cmd1[2], &cmd1[3]);\r
959 if(cmd1[2] != Demod.output[8] || cmd1[3] != Demod.output[9]) {\r
850427c8 960 Dbprintf("CRC Error reading block! - Below: expected, got %x %x",\r
961 (cmd1[2]<<8)+cmd1[3], (Demod.output[8]<<8)+Demod.output[9]);\r
6949aca9 962 // Do not return;, let's go on... (we should retry, maybe ?)\r
963 }\r
850427c8 964 Dbprintf("Tag UID (64 bits): %08x %08x",\r
965 (Demod.output[7]<<24) + (Demod.output[6]<<16) + (Demod.output[5]<<8) + Demod.output[4],\r
966 (Demod.output[3]<<24) + (Demod.output[2]<<16) + (Demod.output[1]<<8) + Demod.output[0]);\r
6949aca9 967\r
968 // Now loop to read all 16 blocks, address from 0 to 15\r
969 DbpString("Tag memory dump, block 0 to 15");\r
970 cmd1[0] = 0x08;\r
971 i = 0x00;\r
850427c8 972 dwLast++;\r
6949aca9 973 for (;;) {\r
850427c8 974 if (i == dwLast) {\r
6949aca9 975 DbpString("System area block (0xff):");\r
976 i = 0xff;\r
977 }\r
978 cmd1[1] = i;\r
fb25b483 979 ComputeCrc14443(CRC_14443_B, cmd1, 2, &cmd1[2], &cmd1[3]);\r
980 CodeIso14443bAsReader(cmd1, sizeof(cmd1));\r
981 TransmitFor14443();\r
0e25ae11 982// LED_A_ON();\r
fb25b483 983 GetSamplesFor14443Demod(TRUE, 2000,TRUE);\r
6949aca9 984// LED_A_OFF();\r
985 if (Demod.len != 6) { // Check if we got an answer from the tag\r
986 DbpString("Expected 6 bytes from tag, got less...");\r
987 return;\r
988 }\r
989 // The check the CRC of the answer (use cmd1 as temporary variable):\r
fb25b483 990 ComputeCrc14443(CRC_14443_B, Demod.output, 4, &cmd1[2], &cmd1[3]);\r
991 if(cmd1[2] != Demod.output[4] || cmd1[3] != Demod.output[5]) {\r
850427c8 992 Dbprintf("CRC Error reading block! - Below: expected, got %x %x",\r
993 (cmd1[2]<<8)+cmd1[3], (Demod.output[4]<<8)+Demod.output[5]);\r
6949aca9 994 // Do not return;, let's go on... (we should retry, maybe ?)\r
995 }\r
996 // Now print out the memory location:\r
850427c8 997 Dbprintf("Address=%x, Contents=%x, CRC=%x", i,\r
998 (Demod.output[3]<<24) + (Demod.output[2]<<16) + (Demod.output[1]<<8) + Demod.output[0],\r
999 (Demod.output[4]<<8)+Demod.output[5]);\r
6949aca9 1000 if (i == 0xff) {\r
1001 break;\r
1002 }\r
1003 i++;\r
1004 }\r
fb25b483 1005}\r
6949aca9 1006\r
6658905f 1007\r
1008//=============================================================================\r
1009// Finally, the `sniffer' combines elements from both the reader and\r
1010// simulated tag, to show both sides of the conversation.\r
1011//=============================================================================\r
1012\r
1013//-----------------------------------------------------------------------------\r
1014// Record the sequence of commands sent by the reader to the tag, with\r
1015// triggering so that we start recording at the point that the tag is moved\r
1016// near the reader.\r
1017//-----------------------------------------------------------------------------\r
0e25ae11 1018/*\r
1019 * Memory usage for this function, (within BigBuf)\r
8caef540 1020 * 0-4095 : Demodulated samples receive (4096 bytes) - DEMOD_TRACE_SIZE\r
1021 * 4096-6143 : Last Received command, 2048 bytes (reader->tag) - READER_TAG_BUFFER_SIZE\r
1022 * 6144-8191 : Last Received command, 2048 bytes(tag->reader) - TAG_READER_BUFFER_SIZE\r
1023 * 8192-9215 : DMA Buffer, 1024 bytes (samples) - DMA_BUFFER_SIZE\r
0e25ae11 1024 */\r
6658905f 1025void SnoopIso14443(void)\r
1026{\r
1027 // We won't start recording the frames that we acquire until we trigger;\r
1028 // a good trigger condition to get started is probably when we see a\r
1029 // response from the tag.\r
1030 BOOL triggered = FALSE;\r
1031\r
1032 // The command (reader -> tag) that we're working on receiving.\r
8caef540 1033 BYTE *receivedCmd = (BYTE *)(BigBuf) + DEMOD_TRACE_SIZE;\r
6658905f 1034 // The response (tag -> reader) that we're working on receiving.\r
8caef540 1035 BYTE *receivedResponse = (BYTE *)(BigBuf) + DEMOD_TRACE_SIZE + READER_TAG_BUFFER_SIZE;\r
6658905f 1036\r
1037 // As we receive stuff, we copy it from receivedCmd or receivedResponse\r
1038 // into trace, along with its length and other annotations.\r
1039 BYTE *trace = (BYTE *)BigBuf;\r
1040 int traceLen = 0;\r
1041\r
1042 // The DMA buffer, used to stream samples from the FPGA.\r
8caef540 1043 SBYTE *dmaBuf = (SBYTE *)(BigBuf) + DEMOD_TRACE_SIZE + READER_TAG_BUFFER_SIZE + TAG_READER_BUFFER_SIZE;\r
6658905f 1044 int lastRxCounter;\r
1045 SBYTE *upTo;\r
1046 int ci, cq;\r
1047 int maxBehindBy = 0;\r
1048\r
1049 // Count of samples received so far, so that we can include timing\r
1050 // information in the trace buffer.\r
1051 int samples = 0;\r
1052\r
0e25ae11 1053 // Initialize the trace buffer\r
8caef540 1054 memset(trace, 0x44, DEMOD_TRACE_SIZE);\r
6658905f 1055\r
1056 // Set up the demodulator for tag -> reader responses.\r
1057 Demod.output = receivedResponse;\r
1058 Demod.len = 0;\r
1059 Demod.state = DEMOD_UNSYNCD;\r
1060\r
1061 // And the reader -> tag commands\r
1062 memset(&Uart, 0, sizeof(Uart));\r
1063 Uart.output = receivedCmd;\r
1064 Uart.byteCntMax = 100;\r
1065 Uart.state = STATE_UNSYNCD;\r
1066\r
8caef540 1067 // Print some debug information about the buffer sizes\r
1068 Dbprintf("Snooping buffers initialized:");\r
1069 Dbprintf(" Trace: %i bytes", DEMOD_TRACE_SIZE);\r
1070 Dbprintf(" Reader -> tag: %i bytes", READER_TAG_BUFFER_SIZE);\r
1071 Dbprintf(" tag -> Reader: %i bytes", TAG_READER_BUFFER_SIZE);\r
1072 Dbprintf(" DMA: %i bytes", DMA_BUFFER_SIZE);\r
1073 \r
1074 // Use a counter for blinking the LED\r
1075 long ledCount=0;\r
1076 long ledFlashAt=200000;\r
1077 \r
6658905f 1078 // And put the FPGA in the appropriate mode\r
0e25ae11 1079 // Signal field is off with the appropriate LED\r
1080 LED_D_OFF();\r
6658905f 1081 FpgaWriteConfWord(\r
1082 FPGA_MAJOR_MODE_HF_READER_RX_XCORR | FPGA_HF_READER_RX_XCORR_848_KHZ |\r
1083 FPGA_HF_READER_RX_XCORR_SNOOP);\r
1084 SetAdcMuxFor(GPIO_MUXSEL_HIPKD);\r
1085\r
1086 // Setup for the DMA.\r
1087 FpgaSetupSsc();\r
1088 upTo = dmaBuf;\r
1089 lastRxCounter = DMA_BUFFER_SIZE;\r
1090 FpgaSetupSscDma((BYTE *)dmaBuf, DMA_BUFFER_SIZE);\r
6658905f 1091 // And now we loop, receiving samples.\r
1092 for(;;) {\r
8caef540 1093 // Blink the LED while Snooping\r
1094 ledCount++;\r
1095 if (ledCount == ledFlashAt) {\r
1096 LED_D_ON();\r
1097 }\r
1098 if (ledCount >= 2*ledFlashAt) {\r
1099 LED_D_OFF();\r
1100 ledCount=0;\r
1101 }\r
1102 \r
6949aca9 1103 int behindBy = (lastRxCounter - AT91C_BASE_PDC_SSC->PDC_RCR) &\r
6658905f 1104 (DMA_BUFFER_SIZE-1);\r
1105 if(behindBy > maxBehindBy) {\r
1106 maxBehindBy = behindBy;\r
0e25ae11 1107 if(behindBy > (DMA_BUFFER_SIZE-2)) { // TODO: understand whether we can increase/decrease as we want or not?\r
850427c8 1108 Dbprintf("blew circular buffer! behindBy=%x", behindBy);\r
6658905f 1109 goto done;\r
1110 }\r
1111 }\r
1112 if(behindBy < 2) continue;\r
1113\r
1114 ci = upTo[0];\r
1115 cq = upTo[1];\r
1116 upTo += 2;\r
1117 lastRxCounter -= 2;\r
1118 if(upTo - dmaBuf > DMA_BUFFER_SIZE) {\r
1119 upTo -= DMA_BUFFER_SIZE;\r
1120 lastRxCounter += DMA_BUFFER_SIZE;\r
6949aca9 1121 AT91C_BASE_PDC_SSC->PDC_RNPR = (DWORD) upTo;\r
1122 AT91C_BASE_PDC_SSC->PDC_RNCR = DMA_BUFFER_SIZE;\r
6658905f 1123 }\r
1124\r
1125 samples += 2;\r
1126\r
1127#define HANDLE_BIT_IF_BODY \\r
1128 if(triggered) { \\r
8caef540 1129 ledFlashAt=30000; \\r
6658905f 1130 trace[traceLen++] = ((samples >> 0) & 0xff); \\r
1131 trace[traceLen++] = ((samples >> 8) & 0xff); \\r
1132 trace[traceLen++] = ((samples >> 16) & 0xff); \\r
1133 trace[traceLen++] = ((samples >> 24) & 0xff); \\r
1134 trace[traceLen++] = 0; \\r
1135 trace[traceLen++] = 0; \\r
1136 trace[traceLen++] = 0; \\r
1137 trace[traceLen++] = 0; \\r
1138 trace[traceLen++] = Uart.byteCnt; \\r
1139 memcpy(trace+traceLen, receivedCmd, Uart.byteCnt); \\r
1140 traceLen += Uart.byteCnt; \\r
1141 if(traceLen > 1000) break; \\r
1142 } \\r
1143 /* And ready to receive another command. */ \\r
1144 memset(&Uart, 0, sizeof(Uart)); \\r
1145 Uart.output = receivedCmd; \\r
1146 Uart.byteCntMax = 100; \\r
1147 Uart.state = STATE_UNSYNCD; \\r
1148 /* And also reset the demod code, which might have been */ \\r
1149 /* false-triggered by the commands from the reader. */ \\r
1150 memset(&Demod, 0, sizeof(Demod)); \\r
1151 Demod.output = receivedResponse; \\r
1152 Demod.state = DEMOD_UNSYNCD; \\r
1153\r
1154 if(Handle14443UartBit(ci & 1)) {\r
1155 HANDLE_BIT_IF_BODY\r
1156 }\r
1157 if(Handle14443UartBit(cq & 1)) {\r
1158 HANDLE_BIT_IF_BODY\r
1159 }\r
1160\r
1161 if(Handle14443SamplesDemod(ci, cq)) {\r
1162 // timestamp, as a count of samples\r
1163 trace[traceLen++] = ((samples >> 0) & 0xff);\r
1164 trace[traceLen++] = ((samples >> 8) & 0xff);\r
1165 trace[traceLen++] = ((samples >> 16) & 0xff);\r
1166 trace[traceLen++] = 0x80 | ((samples >> 24) & 0xff);\r
1167 // correlation metric (~signal strength estimate)\r
1168 if(Demod.metricN != 0) {\r
1169 Demod.metric /= Demod.metricN;\r
1170 }\r
1171 trace[traceLen++] = ((Demod.metric >> 0) & 0xff);\r
1172 trace[traceLen++] = ((Demod.metric >> 8) & 0xff);\r
1173 trace[traceLen++] = ((Demod.metric >> 16) & 0xff);\r
1174 trace[traceLen++] = ((Demod.metric >> 24) & 0xff);\r
1175 // length\r
1176 trace[traceLen++] = Demod.len;\r
1177 memcpy(trace+traceLen, receivedResponse, Demod.len);\r
1178 traceLen += Demod.len;\r
8caef540 1179 if(traceLen > DEMOD_TRACE_SIZE) { \r
1180 DbpString("Reached trace limit");\r
1181 goto done;\r
1182 }\r
6658905f 1183\r
1184 triggered = TRUE;\r
6658905f 1185\r
1186 // And ready to receive another response.\r
1187 memset(&Demod, 0, sizeof(Demod));\r
1188 Demod.output = receivedResponse;\r
1189 Demod.state = DEMOD_UNSYNCD;\r
1190 }\r
0e25ae11 1191 WDT_HIT();\r
6658905f 1192\r
1193 if(BUTTON_PRESS()) {\r
1194 DbpString("cancelled");\r
1195 goto done;\r
1196 }\r
1197 }\r
1198\r
6658905f 1199done:\r
0e25ae11 1200 LED_D_OFF();\r
6949aca9 1201 AT91C_BASE_PDC_SSC->PDC_PTCR = AT91C_PDC_RXTDIS;\r
8caef540 1202 DbpString("Snoop statistics:");\r
1203 Dbprintf(" Max behind by: %i", maxBehindBy);\r
1204 Dbprintf(" Uart State: %x", Uart.state);\r
1205 Dbprintf(" Uart ByteCnt: %i", Uart.byteCnt);\r
1206 Dbprintf(" Uart ByteCntMax: %i", Uart.byteCntMax);\r
1207 Dbprintf(" Trace length: %i", traceLen);\r
6658905f 1208}\r
Impressum, Datenschutz