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