]> git.zerfleddert.de Git - proxmark3-svn/blame - armsrc/iso14443.c
mifare client update
[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
356 DbpIntegers(cmdsRecvd, 0, 0);\r
357 DbpString("button press");\r
358 break;\r
359 }\r
360\r
361 // Good, look at the command now.\r
362\r
363 if(len == sizeof(cmd1) && memcmp(receivedCmd, cmd1, len)==0) {\r
364 resp = resp1; respLen = resp1Len;\r
365 } else {\r
366 DbpString("new cmd from reader:");\r
367 DbpIntegers(len, 0x1234, cmdsRecvd);\r
368 // And print whether the CRC fails, just for good measure\r
369 ComputeCrc14443(CRC_14443_B, receivedCmd, len-2, &b1, &b2);\r
370 if(b1 != receivedCmd[len-2] || b2 != receivedCmd[len-1]) {\r
371 // Not so good, try again.\r
372 DbpString("+++CRC fail");\r
373 } else {\r
374 DbpString("CRC passes");\r
375 }\r
376 break;\r
377 }\r
378\r
379 memset(receivedCmd, 0x44, 32);\r
380\r
381 cmdsRecvd++;\r
382\r
383 if(cmdsRecvd > 0x30) {\r
384 DbpString("many commands later...");\r
385 break;\r
386 }\r
387\r
388 if(respLen <= 0) continue;\r
389\r
390 // Modulate BPSK\r
0e25ae11 391 // Signal field is off with the appropriate LED\r
392 LED_D_OFF();\r
6658905f 393 FpgaWriteConfWord(\r
394 FPGA_MAJOR_MODE_HF_SIMULATOR | FPGA_HF_SIMULATOR_MODULATE_BPSK);\r
6949aca9 395 AT91C_BASE_SSC->SSC_THR = 0xff;\r
6658905f 396 FpgaSetupSsc();\r
397\r
398 // Transmit the response.\r
399 i = 0;\r
400 for(;;) {\r
6949aca9 401 if(AT91C_BASE_SSC->SSC_SR & (AT91C_SSC_TXRDY)) {\r
6658905f 402 BYTE b = resp[i];\r
403\r
6949aca9 404 AT91C_BASE_SSC->SSC_THR = b;\r
6658905f 405\r
406 i++;\r
407 if(i > respLen) {\r
408 break;\r
409 }\r
410 }\r
6949aca9 411 if(AT91C_BASE_SSC->SSC_SR & (AT91C_SSC_RXRDY)) {\r
412 volatile BYTE b = (BYTE)AT91C_BASE_SSC->SSC_RHR;\r
6658905f 413 (void)b;\r
414 }\r
415 }\r
416 }\r
417}\r
418\r
419//=============================================================================\r
420// An ISO 14443 Type B reader. We take layer two commands, code them\r
421// appropriately, and then send them to the tag. We then listen for the\r
422// tag's response, which we leave in the buffer to be demodulated on the\r
423// PC side.\r
424//=============================================================================\r
425\r
426static struct {\r
427 enum {\r
428 DEMOD_UNSYNCD,\r
429 DEMOD_PHASE_REF_TRAINING,\r
430 DEMOD_AWAITING_FALLING_EDGE_OF_SOF,\r
431 DEMOD_GOT_FALLING_EDGE_OF_SOF,\r
432 DEMOD_AWAITING_START_BIT,\r
433 DEMOD_RECEIVING_DATA,\r
434 DEMOD_ERROR_WAIT\r
435 } state;\r
436 int bitCount;\r
437 int posCount;\r
438 int thisBit;\r
439 int metric;\r
440 int metricN;\r
441 WORD shiftReg;\r
442 BYTE *output;\r
443 int len;\r
444 int sumI;\r
445 int sumQ;\r
446} Demod;\r
447\r
0e25ae11 448/*\r
449 * Handles reception of a bit from the tag\r
450 *\r
451 * LED handling:\r
452 * LED C -> ON once we have received the SOF and are expecting the rest.\r
453 * LED C -> OFF once we have received EOF or are unsynced\r
454 *\r
455 * Returns: true if we received a EOF\r
456 * false if we are still waiting for some more\r
6949aca9 457 *\r
0e25ae11 458 */\r
6658905f 459static BOOL Handle14443SamplesDemod(int ci, int cq)\r
460{\r
461 int v;\r
462\r
463 // The soft decision on the bit uses an estimate of just the\r
464 // quadrant of the reference angle, not the exact angle.\r
465#define MAKE_SOFT_DECISION() { \\r
466 if(Demod.sumI > 0) { \\r
467 v = ci; \\r
468 } else { \\r
469 v = -ci; \\r
470 } \\r
471 if(Demod.sumQ > 0) { \\r
472 v += cq; \\r
473 } else { \\r
474 v -= cq; \\r
475 } \\r
476 }\r
477\r
478 switch(Demod.state) {\r
479 case DEMOD_UNSYNCD:\r
480 v = ci;\r
481 if(v < 0) v = -v;\r
482 if(cq > 0) {\r
483 v += cq;\r
484 } else {\r
485 v -= cq;\r
486 }\r
487 if(v > 40) {\r
488 Demod.posCount = 0;\r
489 Demod.state = DEMOD_PHASE_REF_TRAINING;\r
490 Demod.sumI = 0;\r
491 Demod.sumQ = 0;\r
492 }\r
493 break;\r
494\r
495 case DEMOD_PHASE_REF_TRAINING:\r
496 if(Demod.posCount < 8) {\r
497 Demod.sumI += ci;\r
498 Demod.sumQ += cq;\r
499 } else if(Demod.posCount > 100) {\r
500 // error, waited too long\r
501 Demod.state = DEMOD_UNSYNCD;\r
502 } else {\r
503 MAKE_SOFT_DECISION();\r
504 if(v < 0) {\r
505 Demod.state = DEMOD_AWAITING_FALLING_EDGE_OF_SOF;\r
506 Demod.posCount = 0;\r
507 }\r
508 }\r
509 Demod.posCount++;\r
510 break;\r
511\r
512 case DEMOD_AWAITING_FALLING_EDGE_OF_SOF:\r
513 MAKE_SOFT_DECISION();\r
514 if(v < 0) {\r
515 Demod.state = DEMOD_GOT_FALLING_EDGE_OF_SOF;\r
516 Demod.posCount = 0;\r
517 } else {\r
518 if(Demod.posCount > 100) {\r
519 Demod.state = DEMOD_UNSYNCD;\r
520 }\r
521 }\r
522 Demod.posCount++;\r
523 break;\r
524\r
525 case DEMOD_GOT_FALLING_EDGE_OF_SOF:\r
526 MAKE_SOFT_DECISION();\r
527 if(v > 0) {\r
528 if(Demod.posCount < 12) {\r
529 Demod.state = DEMOD_UNSYNCD;\r
530 } else {\r
0e25ae11 531 LED_C_ON(); // Got SOF\r
6658905f 532 Demod.state = DEMOD_AWAITING_START_BIT;\r
533 Demod.posCount = 0;\r
534 Demod.len = 0;\r
535 Demod.metricN = 0;\r
536 Demod.metric = 0;\r
537 }\r
538 } else {\r
539 if(Demod.posCount > 100) {\r
540 Demod.state = DEMOD_UNSYNCD;\r
541 }\r
542 }\r
543 Demod.posCount++;\r
544 break;\r
545\r
546 case DEMOD_AWAITING_START_BIT:\r
547 MAKE_SOFT_DECISION();\r
548 if(v > 0) {\r
549 if(Demod.posCount > 10) {\r
550 Demod.state = DEMOD_UNSYNCD;\r
551 }\r
552 } else {\r
553 Demod.bitCount = 0;\r
554 Demod.posCount = 1;\r
555 Demod.thisBit = v;\r
556 Demod.shiftReg = 0;\r
557 Demod.state = DEMOD_RECEIVING_DATA;\r
558 }\r
559 break;\r
560\r
561 case DEMOD_RECEIVING_DATA:\r
562 MAKE_SOFT_DECISION();\r
563 if(Demod.posCount == 0) {\r
564 Demod.thisBit = v;\r
565 Demod.posCount = 1;\r
566 } else {\r
567 Demod.thisBit += v;\r
568\r
569 if(Demod.thisBit > 0) {\r
570 Demod.metric += Demod.thisBit;\r
571 } else {\r
572 Demod.metric -= Demod.thisBit;\r
573 }\r
574 (Demod.metricN)++;\r
575\r
576 Demod.shiftReg >>= 1;\r
577 if(Demod.thisBit > 0) {\r
578 Demod.shiftReg |= 0x200;\r
579 }\r
580\r
581 Demod.bitCount++;\r
582 if(Demod.bitCount == 10) {\r
583 WORD s = Demod.shiftReg;\r
584 if((s & 0x200) && !(s & 0x001)) {\r
585 BYTE b = (s >> 1);\r
586 Demod.output[Demod.len] = b;\r
587 Demod.len++;\r
588 Demod.state = DEMOD_AWAITING_START_BIT;\r
589 } else if(s == 0x000) {\r
590 // This is EOF\r
0e25ae11 591 LED_C_OFF();\r
6658905f 592 return TRUE;\r
593 Demod.state = DEMOD_UNSYNCD;\r
594 } else {\r
595 Demod.state = DEMOD_UNSYNCD;\r
596 }\r
597 }\r
598 Demod.posCount = 0;\r
599 }\r
600 break;\r
601\r
602 default:\r
603 Demod.state = DEMOD_UNSYNCD;\r
604 break;\r
605 }\r
606\r
0e25ae11 607 if (Demod.state == DEMOD_UNSYNCD) LED_C_OFF(); // Not synchronized...\r
6658905f 608 return FALSE;\r
609}\r
610\r
0e25ae11 611/*\r
612 * Demodulate the samples we received from the tag\r
613 * weTx: set to 'TRUE' if we behave like a reader\r
614 * set to 'FALSE' if we behave like a snooper\r
6949aca9 615 * quiet: set to 'TRUE' to disable debug output\r
0e25ae11 616 */\r
fb25b483 617static void GetSamplesFor14443Demod(BOOL weTx, int n, BOOL quiet)\r
6658905f 618{\r
619 int max = 0;\r
620 BOOL gotFrame = FALSE;\r
621\r
622//# define DMA_BUFFER_SIZE 8\r
623 SBYTE *dmaBuf;\r
624\r
625 int lastRxCounter;\r
626 SBYTE *upTo;\r
627\r
628 int ci, cq;\r
629\r
630 int samples = 0;\r
631\r
632 // Clear out the state of the "UART" that receives from the tag.\r
633 memset(BigBuf, 0x44, 400);\r
634 Demod.output = (BYTE *)BigBuf;\r
635 Demod.len = 0;\r
636 Demod.state = DEMOD_UNSYNCD;\r
637\r
638 // And the UART that receives from the reader\r
639 Uart.output = (((BYTE *)BigBuf) + 1024);\r
640 Uart.byteCntMax = 100;\r
641 Uart.state = STATE_UNSYNCD;\r
642\r
643 // Setup for the DMA.\r
644 dmaBuf = (SBYTE *)(BigBuf + 32);\r
645 upTo = dmaBuf;\r
646 lastRxCounter = DMA_BUFFER_SIZE;\r
647 FpgaSetupSscDma((BYTE *)dmaBuf, DMA_BUFFER_SIZE);\r
648\r
0e25ae11 649 // Signal field is ON with the appropriate LED:\r
650 if (weTx) LED_D_ON(); else LED_D_OFF();\r
6658905f 651 // And put the FPGA in the appropriate mode\r
652 FpgaWriteConfWord(\r
653 FPGA_MAJOR_MODE_HF_READER_RX_XCORR | FPGA_HF_READER_RX_XCORR_848_KHZ |\r
654 (weTx ? 0 : FPGA_HF_READER_RX_XCORR_SNOOP));\r
655\r
656 for(;;) {\r
6949aca9 657 int behindBy = lastRxCounter - AT91C_BASE_PDC_SSC->PDC_RCR;\r
6658905f 658 if(behindBy > max) max = behindBy;\r
659\r
6949aca9 660 while(((lastRxCounter-AT91C_BASE_PDC_SSC->PDC_RCR) & (DMA_BUFFER_SIZE-1))\r
6658905f 661 > 2)\r
662 {\r
663 ci = upTo[0];\r
664 cq = upTo[1];\r
665 upTo += 2;\r
666 if(upTo - dmaBuf > DMA_BUFFER_SIZE) {\r
667 upTo -= DMA_BUFFER_SIZE;\r
6949aca9 668 AT91C_BASE_PDC_SSC->PDC_RNPR = (DWORD)upTo;\r
669 AT91C_BASE_PDC_SSC->PDC_RNCR = DMA_BUFFER_SIZE;\r
6658905f 670 }\r
671 lastRxCounter -= 2;\r
672 if(lastRxCounter <= 0) {\r
673 lastRxCounter += DMA_BUFFER_SIZE;\r
674 }\r
675\r
676 samples += 2;\r
677\r
678 Handle14443UartBit(1);\r
679 Handle14443UartBit(1);\r
680\r
681 if(Handle14443SamplesDemod(ci, cq)) {\r
682 gotFrame = 1;\r
683 }\r
684 }\r
6658905f 685\r
686 if(samples > 2000) {\r
687 break;\r
688 }\r
689 }\r
6949aca9 690 AT91C_BASE_PDC_SSC->PDC_PTCR = AT91C_PDC_RXTDIS;\r
fb25b483 691 if (!quiet) DbpIntegers(max, gotFrame, Demod.len);\r
6658905f 692}\r
693\r
694//-----------------------------------------------------------------------------\r
695// Read the tag's response. We just receive a stream of slightly-processed\r
696// samples from the FPGA, which we will later do some signal processing on,\r
697// to get the bits.\r
698//-----------------------------------------------------------------------------\r
699/*static void GetSamplesFor14443(BOOL weTx, int n)\r
700{\r
701 BYTE *dest = (BYTE *)BigBuf;\r
702 int c;\r
703\r
704 FpgaWriteConfWord(\r
705 FPGA_MAJOR_MODE_HF_READER_RX_XCORR | FPGA_HF_READER_RX_XCORR_848_KHZ |\r
706 (weTx ? 0 : FPGA_HF_READER_RX_XCORR_SNOOP));\r
707\r
708 c = 0;\r
709 for(;;) {\r
6949aca9 710 if(AT91C_BASE_SSC->SSC_SR & (AT91C_SSC_TXRDY)) {\r
711 AT91C_BASE_SSC->SSC_THR = 0x43;\r
6658905f 712 }\r
6949aca9 713 if(AT91C_BASE_SSC->SSC_SR & (AT91C_SSC_RXRDY)) {\r
6658905f 714 SBYTE b;\r
6949aca9 715 b = (SBYTE)AT91C_BASE_SSC->SSC_RHR;\r
6658905f 716\r
717 dest[c++] = (BYTE)b;\r
718\r
719 if(c >= n) {\r
720 break;\r
721 }\r
722 }\r
723 }\r
724}*/\r
725\r
726//-----------------------------------------------------------------------------\r
727// Transmit the command (to the tag) that was placed in ToSend[].\r
728//-----------------------------------------------------------------------------\r
729static void TransmitFor14443(void)\r
730{\r
731 int c;\r
732\r
733 FpgaSetupSsc();\r
734\r
6949aca9 735 while(AT91C_BASE_SSC->SSC_SR & (AT91C_SSC_TXRDY)) {\r
736 AT91C_BASE_SSC->SSC_THR = 0xff;\r
6658905f 737 }\r
738\r
0e25ae11 739 // Signal field is ON with the appropriate Red LED\r
740 LED_D_ON();\r
741 // Signal we are transmitting with the Green LED\r
742 LED_B_ON();\r
743 FpgaWriteConfWord(\r
6658905f 744 FPGA_MAJOR_MODE_HF_READER_TX | FPGA_HF_READER_TX_SHALLOW_MOD);\r
745\r
746 for(c = 0; c < 10;) {\r
6949aca9 747 if(AT91C_BASE_SSC->SSC_SR & (AT91C_SSC_TXRDY)) {\r
748 AT91C_BASE_SSC->SSC_THR = 0xff;\r
6658905f 749 c++;\r
750 }\r
6949aca9 751 if(AT91C_BASE_SSC->SSC_SR & (AT91C_SSC_RXRDY)) {\r
752 volatile DWORD r = AT91C_BASE_SSC->SSC_RHR;\r
6658905f 753 (void)r;\r
754 }\r
755 WDT_HIT();\r
756 }\r
757\r
758 c = 0;\r
759 for(;;) {\r
6949aca9 760 if(AT91C_BASE_SSC->SSC_SR & (AT91C_SSC_TXRDY)) {\r
761 AT91C_BASE_SSC->SSC_THR = ToSend[c];\r
6658905f 762 c++;\r
763 if(c >= ToSendMax) {\r
764 break;\r
765 }\r
766 }\r
6949aca9 767 if(AT91C_BASE_SSC->SSC_SR & (AT91C_SSC_RXRDY)) {\r
768 volatile DWORD r = AT91C_BASE_SSC->SSC_RHR;\r
6658905f 769 (void)r;\r
770 }\r
771 WDT_HIT();\r
772 }\r
0e25ae11 773 LED_B_OFF(); // Finished sending\r
6658905f 774}\r
775\r
776//-----------------------------------------------------------------------------\r
777// Code a layer 2 command (string of octets, including CRC) into ToSend[],\r
778// so that it is ready to transmit to the tag using TransmitFor14443().\r
779//-----------------------------------------------------------------------------\r
780void CodeIso14443bAsReader(const BYTE *cmd, int len)\r
781{\r
782 int i, j;\r
783 BYTE b;\r
784\r
785 ToSendReset();\r
786\r
787 // Establish initial reference level\r
788 for(i = 0; i < 40; i++) {\r
789 ToSendStuffBit(1);\r
790 }\r
791 // Send SOF\r
792 for(i = 0; i < 10; i++) {\r
793 ToSendStuffBit(0);\r
794 }\r
795\r
796 for(i = 0; i < len; i++) {\r
797 // Stop bits/EGT\r
798 ToSendStuffBit(1);\r
799 ToSendStuffBit(1);\r
800 // Start bit\r
801 ToSendStuffBit(0);\r
802 // Data bits\r
803 b = cmd[i];\r
804 for(j = 0; j < 8; j++) {\r
805 if(b & 1) {\r
806 ToSendStuffBit(1);\r
807 } else {\r
808 ToSendStuffBit(0);\r
809 }\r
810 b >>= 1;\r
811 }\r
812 }\r
813 // Send EOF\r
814 ToSendStuffBit(1);\r
815 for(i = 0; i < 10; i++) {\r
816 ToSendStuffBit(0);\r
817 }\r
818 for(i = 0; i < 8; i++) {\r
819 ToSendStuffBit(1);\r
820 }\r
821\r
822 // And then a little more, to make sure that the last character makes\r
823 // it out before we switch to rx mode.\r
824 for(i = 0; i < 24; i++) {\r
825 ToSendStuffBit(1);\r
826 }\r
827\r
828 // Convert from last character reference to length\r
829 ToSendMax++;\r
830}\r
831\r
832//-----------------------------------------------------------------------------\r
833// Read an ISO 14443 tag. We send it some set of commands, and record the\r
6949aca9 834// responses.\r
835// The command name is misleading, it actually decodes the reponse in HEX\r
fb25b483 836// into the output buffer (read the result using hexsamples, not hisamples)\r
6658905f 837//-----------------------------------------------------------------------------\r
838void AcquireRawAdcSamplesIso14443(DWORD parameter)\r
839{\r
6658905f 840 BYTE cmd1[] = { 0x05, 0x00, 0x08, 0x39, 0x73 };\r
841\r
842 // Make sure that we start from off, since the tags are stateful;\r
843 // confusing things will happen if we don't reset them between reads.\r
6658905f 844 FpgaWriteConfWord(FPGA_MAJOR_MODE_OFF);\r
0e25ae11 845 LED_D_OFF();\r
6658905f 846 SpinDelay(200);\r
847\r
848 SetAdcMuxFor(GPIO_MUXSEL_HIPKD);\r
849 FpgaSetupSsc();\r
850\r
851 // Now give it time to spin up.\r
0e25ae11 852 // Signal field is on with the appropriate LED\r
853 LED_D_ON();\r
6658905f 854 FpgaWriteConfWord(\r
855 FPGA_MAJOR_MODE_HF_READER_RX_XCORR | FPGA_HF_READER_RX_XCORR_848_KHZ);\r
856 SpinDelay(200);\r
857\r
858 CodeIso14443bAsReader(cmd1, sizeof(cmd1));\r
859 TransmitFor14443();\r
0e25ae11 860// LED_A_ON();\r
fb25b483 861 GetSamplesFor14443Demod(TRUE, 2000, FALSE);\r
0e25ae11 862// LED_A_OFF();\r
6658905f 863}\r
6949aca9 864\r
fb25b483 865//-----------------------------------------------------------------------------\r
866// Read a SRI512 ISO 14443 tag.\r
6949aca9 867//\r
868// SRI512 tags are just simple memory tags, here we're looking at making a dump\r
869// of the contents of the memory. No anticollision algorithm is done, we assume\r
870// we have a single tag in the field.\r
871//\r
fb25b483 872// I tried to be systematic and check every answer of the tag, every CRC, etc...\r
873//-----------------------------------------------------------------------------\r
874void ReadSRI512Iso14443(DWORD parameter)\r
875{\r
c86cc308 876 ReadSTMemoryIso14443(parameter,0x0F);
877}
878void ReadSRIX4KIso14443(DWORD parameter)
879{
880 ReadSTMemoryIso14443(parameter,0x7F);
881}
882
883void ReadSTMemoryIso14443(DWORD parameter,DWORD dwLast)
884{
6949aca9 885 BYTE i = 0x00;\r
fb25b483 886\r
887 // Make sure that we start from off, since the tags are stateful;\r
888 // confusing things will happen if we don't reset them between reads.\r
889 LED_D_OFF();\r
890 FpgaWriteConfWord(FPGA_MAJOR_MODE_OFF);\r
891 SpinDelay(200);\r
892\r
893 SetAdcMuxFor(GPIO_MUXSEL_HIPKD);\r
894 FpgaSetupSsc();\r
895\r
896 // Now give it time to spin up.\r
0e25ae11 897 // Signal field is on with the appropriate LED\r
898 LED_D_ON();\r
fb25b483 899 FpgaWriteConfWord(\r
900 FPGA_MAJOR_MODE_HF_READER_RX_XCORR | FPGA_HF_READER_RX_XCORR_848_KHZ);\r
901 SpinDelay(200);\r
6949aca9 902\r
fb25b483 903 // First command: wake up the tag using the INITIATE command\r
904 BYTE cmd1[] = { 0x06, 0x00, 0x97, 0x5b};\r
905 CodeIso14443bAsReader(cmd1, sizeof(cmd1));\r
906 TransmitFor14443();\r
0e25ae11 907// LED_A_ON();\r
fb25b483 908 GetSamplesFor14443Demod(TRUE, 2000,TRUE);\r
0e25ae11 909// LED_A_OFF();\r
6949aca9 910\r
911 if (Demod.len == 0) {\r
912 DbpString("No response from tag");\r
913 return;\r
914 } else {\r
915 DbpString("Randomly generated UID from tag (+ 2 byte CRC):");\r
916 DbpIntegers(Demod.output[0], Demod.output[1],Demod.output[2]);\r
917 }\r
918 // There is a response, SELECT the uid\r
919 DbpString("Now SELECT tag:");\r
920 cmd1[0] = 0x0E; // 0x0E is SELECT\r
921 cmd1[1] = Demod.output[0];\r
fb25b483 922 ComputeCrc14443(CRC_14443_B, cmd1, 2, &cmd1[2], &cmd1[3]);\r
923 CodeIso14443bAsReader(cmd1, sizeof(cmd1));\r
924 TransmitFor14443();\r
0e25ae11 925// LED_A_ON();\r
fb25b483 926 GetSamplesFor14443Demod(TRUE, 2000,TRUE);\r
0e25ae11 927// LED_A_OFF();\r
6949aca9 928 if (Demod.len != 3) {\r
929 DbpString("Expected 3 bytes from tag, got:");\r
930 DbpIntegers(Demod.len,0x0,0x0);\r
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
941 DbpString("Bad response to SELECT from Tag, aborting:");\r
942 DbpIntegers(cmd1[1],Demod.output[0],0x0);\r
943 return;\r
944 }\r
945 // Tag is now selected,\r
946 // First get the tag's UID:\r
947 cmd1[0] = 0x0B;\r
948 ComputeCrc14443(CRC_14443_B, cmd1, 1 , &cmd1[1], &cmd1[2]);\r
1a093c19 949 CodeIso14443bAsReader(cmd1, 3); // Only first three bytes for this one\r
950 TransmitFor14443();\r
0e25ae11 951// LED_A_ON();\r
1a093c19 952 GetSamplesFor14443Demod(TRUE, 2000,TRUE);\r
0e25ae11 953// LED_A_OFF();\r
6949aca9 954 if (Demod.len != 10) {\r
955 DbpString("Expected 10 bytes from tag, got:");\r
956 DbpIntegers(Demod.len,0x0,0x0);\r
957 return;\r
958 }\r
959 // The check the CRC of the answer (use cmd1 as temporary variable):\r
1a093c19 960 ComputeCrc14443(CRC_14443_B, Demod.output, 8, &cmd1[2], &cmd1[3]);\r
961 if(cmd1[2] != Demod.output[8] || cmd1[3] != Demod.output[9]) {\r
6949aca9 962 DbpString("CRC Error reading block! - Below: expected, got");\r
963 DbpIntegers( (cmd1[2]<<8)+cmd1[3], (Demod.output[8]<<8)+Demod.output[9],0);\r
964 // Do not return;, let's go on... (we should retry, maybe ?)\r
965 }\r
966 DbpString("Tag UID (64 bits):");\r
967 DbpIntegers((Demod.output[7]<<24) + (Demod.output[6]<<16) + (Demod.output[5]<<8) + Demod.output[4], (Demod.output[3]<<24) + (Demod.output[2]<<16) + (Demod.output[1]<<8) + Demod.output[0], 0);\r
968\r
969 // Now loop to read all 16 blocks, address from 0 to 15\r
970 DbpString("Tag memory dump, block 0 to 15");\r
971 cmd1[0] = 0x08;\r
972 i = 0x00;\r
c86cc308 973 dwLast++;
6949aca9 974 for (;;) {\r
c86cc308 975 if (i == dwLast) {
6949aca9 976 DbpString("System area block (0xff):");\r
977 i = 0xff;\r
978 }\r
979 cmd1[1] = i;\r
fb25b483 980 ComputeCrc14443(CRC_14443_B, cmd1, 2, &cmd1[2], &cmd1[3]);\r
981 CodeIso14443bAsReader(cmd1, sizeof(cmd1));\r
982 TransmitFor14443();\r
0e25ae11 983// LED_A_ON();\r
fb25b483 984 GetSamplesFor14443Demod(TRUE, 2000,TRUE);\r
6949aca9 985// LED_A_OFF();\r
986 if (Demod.len != 6) { // Check if we got an answer from the tag\r
987 DbpString("Expected 6 bytes from tag, got less...");\r
988 return;\r
989 }\r
990 // The check the CRC of the answer (use cmd1 as temporary variable):\r
fb25b483 991 ComputeCrc14443(CRC_14443_B, Demod.output, 4, &cmd1[2], &cmd1[3]);\r
992 if(cmd1[2] != Demod.output[4] || cmd1[3] != Demod.output[5]) {\r
6949aca9 993 DbpString("CRC Error reading block! - Below: expected, got");\r
994 DbpIntegers( (cmd1[2]<<8)+cmd1[3], (Demod.output[4]<<8)+Demod.output[5],0);\r
995 // Do not return;, let's go on... (we should retry, maybe ?)\r
996 }\r
997 // Now print out the memory location:\r
998 DbpString("Address , Contents, CRC");\r
999 DbpIntegers(i, (Demod.output[3]<<24) + (Demod.output[2]<<16) + (Demod.output[1]<<8) + Demod.output[0], (Demod.output[4]<<8)+Demod.output[5]);\r
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
1020 * 0-1023 : Demodulated samples receive (1024 bytes)\r
1021 * 1024-1535 : Last Received command, 512 bytes (reader->tag)\r
1022 * 1536-2047 : Last Received command, 512 bytes(tag->reader)\r
6949aca9 1023 * 2048-2304 : DMA Buffer, 256 bytes (samples)\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
0e25ae11 1033 BYTE *receivedCmd = (BYTE *)(BigBuf) + 1024;\r
6658905f 1034 // The response (tag -> reader) that we're working on receiving.\r
0e25ae11 1035 BYTE *receivedResponse = (BYTE *)(BigBuf) + 1536;\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
0e25ae11 1043 SBYTE *dmaBuf = (SBYTE *)(BigBuf) + 2048;\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
1054 memset(trace, 0x44, 1024);\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
1067 // And put the FPGA in the appropriate mode\r
0e25ae11 1068 // Signal field is off with the appropriate LED\r
1069 LED_D_OFF();\r
6658905f 1070 FpgaWriteConfWord(\r
1071 FPGA_MAJOR_MODE_HF_READER_RX_XCORR | FPGA_HF_READER_RX_XCORR_848_KHZ |\r
1072 FPGA_HF_READER_RX_XCORR_SNOOP);\r
1073 SetAdcMuxFor(GPIO_MUXSEL_HIPKD);\r
1074\r
1075 // Setup for the DMA.\r
1076 FpgaSetupSsc();\r
1077 upTo = dmaBuf;\r
1078 lastRxCounter = DMA_BUFFER_SIZE;\r
1079 FpgaSetupSscDma((BYTE *)dmaBuf, DMA_BUFFER_SIZE);\r
6658905f 1080 // And now we loop, receiving samples.\r
1081 for(;;) {\r
6949aca9 1082 int behindBy = (lastRxCounter - AT91C_BASE_PDC_SSC->PDC_RCR) &\r
6658905f 1083 (DMA_BUFFER_SIZE-1);\r
1084 if(behindBy > maxBehindBy) {\r
1085 maxBehindBy = behindBy;\r
0e25ae11 1086 if(behindBy > (DMA_BUFFER_SIZE-2)) { // TODO: understand whether we can increase/decrease as we want or not?\r
6658905f 1087 DbpString("blew circular buffer!");\r
0e25ae11 1088 DbpIntegers(behindBy,0,0);\r
6658905f 1089 goto done;\r
1090 }\r
1091 }\r
1092 if(behindBy < 2) continue;\r
1093\r
1094 ci = upTo[0];\r
1095 cq = upTo[1];\r
1096 upTo += 2;\r
1097 lastRxCounter -= 2;\r
1098 if(upTo - dmaBuf > DMA_BUFFER_SIZE) {\r
1099 upTo -= DMA_BUFFER_SIZE;\r
1100 lastRxCounter += DMA_BUFFER_SIZE;\r
6949aca9 1101 AT91C_BASE_PDC_SSC->PDC_RNPR = (DWORD) upTo;\r
1102 AT91C_BASE_PDC_SSC->PDC_RNCR = DMA_BUFFER_SIZE;\r
6658905f 1103 }\r
1104\r
1105 samples += 2;\r
1106\r
1107#define HANDLE_BIT_IF_BODY \\r
1108 if(triggered) { \\r
1109 trace[traceLen++] = ((samples >> 0) & 0xff); \\r
1110 trace[traceLen++] = ((samples >> 8) & 0xff); \\r
1111 trace[traceLen++] = ((samples >> 16) & 0xff); \\r
1112 trace[traceLen++] = ((samples >> 24) & 0xff); \\r
1113 trace[traceLen++] = 0; \\r
1114 trace[traceLen++] = 0; \\r
1115 trace[traceLen++] = 0; \\r
1116 trace[traceLen++] = 0; \\r
1117 trace[traceLen++] = Uart.byteCnt; \\r
1118 memcpy(trace+traceLen, receivedCmd, Uart.byteCnt); \\r
1119 traceLen += Uart.byteCnt; \\r
1120 if(traceLen > 1000) break; \\r
1121 } \\r
1122 /* And ready to receive another command. */ \\r
1123 memset(&Uart, 0, sizeof(Uart)); \\r
1124 Uart.output = receivedCmd; \\r
1125 Uart.byteCntMax = 100; \\r
1126 Uart.state = STATE_UNSYNCD; \\r
1127 /* And also reset the demod code, which might have been */ \\r
1128 /* false-triggered by the commands from the reader. */ \\r
1129 memset(&Demod, 0, sizeof(Demod)); \\r
1130 Demod.output = receivedResponse; \\r
1131 Demod.state = DEMOD_UNSYNCD; \\r
1132\r
1133 if(Handle14443UartBit(ci & 1)) {\r
1134 HANDLE_BIT_IF_BODY\r
1135 }\r
1136 if(Handle14443UartBit(cq & 1)) {\r
1137 HANDLE_BIT_IF_BODY\r
1138 }\r
1139\r
1140 if(Handle14443SamplesDemod(ci, cq)) {\r
1141 // timestamp, as a count of samples\r
1142 trace[traceLen++] = ((samples >> 0) & 0xff);\r
1143 trace[traceLen++] = ((samples >> 8) & 0xff);\r
1144 trace[traceLen++] = ((samples >> 16) & 0xff);\r
1145 trace[traceLen++] = 0x80 | ((samples >> 24) & 0xff);\r
1146 // correlation metric (~signal strength estimate)\r
1147 if(Demod.metricN != 0) {\r
1148 Demod.metric /= Demod.metricN;\r
1149 }\r
1150 trace[traceLen++] = ((Demod.metric >> 0) & 0xff);\r
1151 trace[traceLen++] = ((Demod.metric >> 8) & 0xff);\r
1152 trace[traceLen++] = ((Demod.metric >> 16) & 0xff);\r
1153 trace[traceLen++] = ((Demod.metric >> 24) & 0xff);\r
1154 // length\r
1155 trace[traceLen++] = Demod.len;\r
1156 memcpy(trace+traceLen, receivedResponse, Demod.len);\r
1157 traceLen += Demod.len;\r
1158 if(traceLen > 1000) break;\r
1159\r
1160 triggered = TRUE;\r
6658905f 1161\r
1162 // And ready to receive another response.\r
1163 memset(&Demod, 0, sizeof(Demod));\r
1164 Demod.output = receivedResponse;\r
1165 Demod.state = DEMOD_UNSYNCD;\r
1166 }\r
0e25ae11 1167 WDT_HIT();\r
6658905f 1168\r
1169 if(BUTTON_PRESS()) {\r
1170 DbpString("cancelled");\r
1171 goto done;\r
1172 }\r
1173 }\r
1174\r
1175 DbpString("in done pt");\r
1176\r
1177 DbpIntegers(maxBehindBy, Uart.state, Uart.byteCnt);\r
1178 DbpIntegers(Uart.byteCntMax, traceLen, 0x23);\r
1179\r
1180done:\r
0e25ae11 1181 LED_D_OFF();\r
6949aca9 1182 AT91C_BASE_PDC_SSC->PDC_PTCR = AT91C_PDC_RXTDIS;\r
6658905f 1183}\r
Impressum, Datenschutz