]> cvs.zerfleddert.de Git - proxmark3-svn/blame - armsrc/iso14443.c
Added LF frequency adjustments from d18c7db, cleaned up code,
[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
134static BOOL Handle14443UartBit(int bit)\r
135{\r
136 switch(Uart.state) {\r
137 case STATE_UNSYNCD:\r
138 if(!bit) {\r
139 // we went low, so this could be the beginning\r
140 // of an SOF\r
141 Uart.state = STATE_GOT_FALLING_EDGE_OF_SOF;\r
142 Uart.posCnt = 0;\r
143 Uart.bitCnt = 0;\r
144 }\r
145 break;\r
146\r
147 case STATE_GOT_FALLING_EDGE_OF_SOF:\r
148 Uart.posCnt++;\r
149 if(Uart.posCnt == 2) {\r
150 if(bit) {\r
151 if(Uart.bitCnt >= 10) {\r
152 // we've seen enough consecutive\r
153 // zeros that it's a valid SOF\r
154 Uart.posCnt = 0;\r
155 Uart.byteCnt = 0;\r
156 Uart.state = STATE_AWAITING_START_BIT;\r
157 } else {\r
158 // didn't stay down long enough\r
159 // before going high, error\r
160 Uart.state = STATE_ERROR_WAIT;\r
161 }\r
162 } else {\r
163 // do nothing, keep waiting\r
164 }\r
165 Uart.bitCnt++;\r
166 }\r
167 if(Uart.posCnt >= 4) Uart.posCnt = 0;\r
168 if(Uart.bitCnt > 14) {\r
169 // Give up if we see too many zeros without\r
170 // a one, too.\r
171 Uart.state = STATE_ERROR_WAIT;\r
172 }\r
173 break;\r
174\r
175 case STATE_AWAITING_START_BIT:\r
176 Uart.posCnt++;\r
177 if(bit) {\r
178 if(Uart.posCnt > 25) {\r
179 // stayed high for too long between\r
180 // characters, error\r
181 Uart.state = STATE_ERROR_WAIT;\r
182 }\r
183 } else {\r
184 // falling edge, this starts the data byte\r
185 Uart.posCnt = 0;\r
186 Uart.bitCnt = 0;\r
187 Uart.shiftReg = 0;\r
188 Uart.state = STATE_RECEIVING_DATA;\r
189 }\r
190 break;\r
191\r
192 case STATE_RECEIVING_DATA:\r
193 Uart.posCnt++;\r
194 if(Uart.posCnt == 2) {\r
195 // time to sample a bit\r
196 Uart.shiftReg >>= 1;\r
197 if(bit) {\r
198 Uart.shiftReg |= 0x200;\r
199 }\r
200 Uart.bitCnt++;\r
201 }\r
202 if(Uart.posCnt >= 4) {\r
203 Uart.posCnt = 0;\r
204 }\r
205 if(Uart.bitCnt == 10) {\r
206 if((Uart.shiftReg & 0x200) && !(Uart.shiftReg & 0x001))\r
207 {\r
208 // this is a data byte, with correct\r
209 // start and stop bits\r
210 Uart.output[Uart.byteCnt] = (Uart.shiftReg >> 1) & 0xff;\r
211 Uart.byteCnt++;\r
212\r
213 if(Uart.byteCnt >= Uart.byteCntMax) {\r
214 // Buffer overflowed, give up\r
215 Uart.posCnt = 0;\r
216 Uart.state = STATE_ERROR_WAIT;\r
217 } else {\r
218 // so get the next byte now\r
219 Uart.posCnt = 0;\r
220 Uart.state = STATE_AWAITING_START_BIT;\r
221 }\r
222 } else if(Uart.shiftReg == 0x000) {\r
223 // this is an EOF byte\r
224 return TRUE;\r
225 } else {\r
226 // this is an error\r
227 Uart.posCnt = 0;\r
228 Uart.state = STATE_ERROR_WAIT;\r
229 }\r
230 }\r
231 break;\r
232\r
233 case STATE_ERROR_WAIT:\r
234 // We're all screwed up, so wait a little while\r
235 // for whatever went wrong to finish, and then\r
236 // start over.\r
237 Uart.posCnt++;\r
238 if(Uart.posCnt > 10) {\r
239 Uart.state = STATE_UNSYNCD;\r
240 }\r
241 break;\r
242\r
243 default:\r
244 Uart.state = STATE_UNSYNCD;\r
245 break;\r
246 }\r
247\r
248 return FALSE;\r
249}\r
250\r
251//-----------------------------------------------------------------------------\r
252// Receive a command (from the reader to us, where we are the simulated tag),\r
253// and store it in the given buffer, up to the given maximum length. Keeps\r
254// spinning, waiting for a well-framed command, until either we get one\r
255// (returns TRUE) or someone presses the pushbutton on the board (FALSE).\r
256//\r
257// Assume that we're called with the SSC (to the FPGA) and ADC path set\r
258// correctly.\r
259//-----------------------------------------------------------------------------\r
260static BOOL GetIso14443CommandFromReader(BYTE *received, int *len, int maxLen)\r
261{\r
262 BYTE mask;\r
263 int i, bit;\r
264\r
265 // Set FPGA mode to "simulated ISO 14443 tag", no modulation (listen\r
266 // only, since we are receiving, not transmitting).\r
267 FpgaWriteConfWord(\r
268 FPGA_MAJOR_MODE_HF_SIMULATOR | FPGA_HF_SIMULATOR_NO_MODULATION);\r
269\r
270\r
271 // Now run a `software UART' on the stream of incoming samples.\r
272 Uart.output = received;\r
273 Uart.byteCntMax = maxLen;\r
274 Uart.state = STATE_UNSYNCD;\r
275\r
276 for(;;) {\r
277 WDT_HIT();\r
278\r
279 if(BUTTON_PRESS()) return FALSE;\r
280\r
281 if(SSC_STATUS & (SSC_STATUS_TX_READY)) {\r
282 SSC_TRANSMIT_HOLDING = 0x00;\r
283 }\r
284 if(SSC_STATUS & (SSC_STATUS_RX_READY)) {\r
285 BYTE b = (BYTE)SSC_RECEIVE_HOLDING;\r
286\r
287 mask = 0x80;\r
288 for(i = 0; i < 8; i++, mask >>= 1) {\r
289 bit = (b & mask);\r
290 if(Handle14443UartBit(bit)) {\r
291 *len = Uart.byteCnt;\r
292 return TRUE;\r
293 }\r
294 }\r
295 }\r
296 }\r
297}\r
298\r
299//-----------------------------------------------------------------------------\r
300// Main loop of simulated tag: receive commands from reader, decide what\r
301// response to send, and send it.\r
302//-----------------------------------------------------------------------------\r
303void SimulateIso14443Tag(void)\r
304{\r
305 static const BYTE cmd1[] = { 0x05, 0x00, 0x08, 0x39, 0x73 };\r
306 static const BYTE response1[] = {\r
307 0x50, 0x82, 0x0d, 0xe1, 0x74, 0x20, 0x38, 0x19, 0x22,\r
308 0x00, 0x21, 0x85, 0x5e, 0xd7\r
309 };\r
310\r
311 BYTE *resp;\r
312 int respLen;\r
313\r
314 BYTE *resp1 = (((BYTE *)BigBuf) + 800);\r
315 int resp1Len;\r
316\r
317 BYTE *receivedCmd = (BYTE *)BigBuf;\r
318 int len;\r
319\r
320 int i;\r
321\r
322 int cmdsRecvd = 0;\r
323\r
324 memset(receivedCmd, 0x44, 400);\r
325\r
326 CodeIso14443bAsTag(response1, sizeof(response1));\r
327 memcpy(resp1, ToSend, ToSendMax); resp1Len = ToSendMax;\r
328\r
329 // We need to listen to the high-frequency, peak-detected path.\r
330 SetAdcMuxFor(GPIO_MUXSEL_HIPKD);\r
331 FpgaSetupSsc();\r
332\r
333 cmdsRecvd = 0;\r
334\r
335 for(;;) {\r
336 BYTE b1, b2;\r
337\r
338 if(!GetIso14443CommandFromReader(receivedCmd, &len, 100)) {\r
339 DbpIntegers(cmdsRecvd, 0, 0);\r
340 DbpString("button press");\r
341 break;\r
342 }\r
343\r
344 // Good, look at the command now.\r
345\r
346 if(len == sizeof(cmd1) && memcmp(receivedCmd, cmd1, len)==0) {\r
347 resp = resp1; respLen = resp1Len;\r
348 } else {\r
349 DbpString("new cmd from reader:");\r
350 DbpIntegers(len, 0x1234, cmdsRecvd);\r
351 // And print whether the CRC fails, just for good measure\r
352 ComputeCrc14443(CRC_14443_B, receivedCmd, len-2, &b1, &b2);\r
353 if(b1 != receivedCmd[len-2] || b2 != receivedCmd[len-1]) {\r
354 // Not so good, try again.\r
355 DbpString("+++CRC fail");\r
356 } else {\r
357 DbpString("CRC passes");\r
358 }\r
359 break;\r
360 }\r
361\r
362 memset(receivedCmd, 0x44, 32);\r
363\r
364 cmdsRecvd++;\r
365\r
366 if(cmdsRecvd > 0x30) {\r
367 DbpString("many commands later...");\r
368 break;\r
369 }\r
370\r
371 if(respLen <= 0) continue;\r
372\r
373 // Modulate BPSK\r
374 FpgaWriteConfWord(\r
375 FPGA_MAJOR_MODE_HF_SIMULATOR | FPGA_HF_SIMULATOR_MODULATE_BPSK);\r
376 SSC_TRANSMIT_HOLDING = 0xff;\r
377 FpgaSetupSsc();\r
378\r
379 // Transmit the response.\r
380 i = 0;\r
381 for(;;) {\r
382 if(SSC_STATUS & (SSC_STATUS_TX_READY)) {\r
383 BYTE b = resp[i];\r
384\r
385 SSC_TRANSMIT_HOLDING = b;\r
386\r
387 i++;\r
388 if(i > respLen) {\r
389 break;\r
390 }\r
391 }\r
392 if(SSC_STATUS & (SSC_STATUS_RX_READY)) {\r
393 volatile BYTE b = (BYTE)SSC_RECEIVE_HOLDING;\r
394 (void)b;\r
395 }\r
396 }\r
397 }\r
398}\r
399\r
400//=============================================================================\r
401// An ISO 14443 Type B reader. We take layer two commands, code them\r
402// appropriately, and then send them to the tag. We then listen for the\r
403// tag's response, which we leave in the buffer to be demodulated on the\r
404// PC side.\r
405//=============================================================================\r
406\r
407static struct {\r
408 enum {\r
409 DEMOD_UNSYNCD,\r
410 DEMOD_PHASE_REF_TRAINING,\r
411 DEMOD_AWAITING_FALLING_EDGE_OF_SOF,\r
412 DEMOD_GOT_FALLING_EDGE_OF_SOF,\r
413 DEMOD_AWAITING_START_BIT,\r
414 DEMOD_RECEIVING_DATA,\r
415 DEMOD_ERROR_WAIT\r
416 } state;\r
417 int bitCount;\r
418 int posCount;\r
419 int thisBit;\r
420 int metric;\r
421 int metricN;\r
422 WORD shiftReg;\r
423 BYTE *output;\r
424 int len;\r
425 int sumI;\r
426 int sumQ;\r
427} Demod;\r
428\r
429static BOOL Handle14443SamplesDemod(int ci, int cq)\r
430{\r
431 int v;\r
432\r
433 // The soft decision on the bit uses an estimate of just the\r
434 // quadrant of the reference angle, not the exact angle.\r
435#define MAKE_SOFT_DECISION() { \\r
436 if(Demod.sumI > 0) { \\r
437 v = ci; \\r
438 } else { \\r
439 v = -ci; \\r
440 } \\r
441 if(Demod.sumQ > 0) { \\r
442 v += cq; \\r
443 } else { \\r
444 v -= cq; \\r
445 } \\r
446 }\r
447\r
448 switch(Demod.state) {\r
449 case DEMOD_UNSYNCD:\r
450 v = ci;\r
451 if(v < 0) v = -v;\r
452 if(cq > 0) {\r
453 v += cq;\r
454 } else {\r
455 v -= cq;\r
456 }\r
457 if(v > 40) {\r
458 Demod.posCount = 0;\r
459 Demod.state = DEMOD_PHASE_REF_TRAINING;\r
460 Demod.sumI = 0;\r
461 Demod.sumQ = 0;\r
462 }\r
463 break;\r
464\r
465 case DEMOD_PHASE_REF_TRAINING:\r
466 if(Demod.posCount < 8) {\r
467 Demod.sumI += ci;\r
468 Demod.sumQ += cq;\r
469 } else if(Demod.posCount > 100) {\r
470 // error, waited too long\r
471 Demod.state = DEMOD_UNSYNCD;\r
472 } else {\r
473 MAKE_SOFT_DECISION();\r
474 if(v < 0) {\r
475 Demod.state = DEMOD_AWAITING_FALLING_EDGE_OF_SOF;\r
476 Demod.posCount = 0;\r
477 }\r
478 }\r
479 Demod.posCount++;\r
480 break;\r
481\r
482 case DEMOD_AWAITING_FALLING_EDGE_OF_SOF:\r
483 MAKE_SOFT_DECISION();\r
484 if(v < 0) {\r
485 Demod.state = DEMOD_GOT_FALLING_EDGE_OF_SOF;\r
486 Demod.posCount = 0;\r
487 } else {\r
488 if(Demod.posCount > 100) {\r
489 Demod.state = DEMOD_UNSYNCD;\r
490 }\r
491 }\r
492 Demod.posCount++;\r
493 break;\r
494\r
495 case DEMOD_GOT_FALLING_EDGE_OF_SOF:\r
496 MAKE_SOFT_DECISION();\r
497 if(v > 0) {\r
498 if(Demod.posCount < 12) {\r
499 Demod.state = DEMOD_UNSYNCD;\r
500 } else {\r
501 Demod.state = DEMOD_AWAITING_START_BIT;\r
502 Demod.posCount = 0;\r
503 Demod.len = 0;\r
504 Demod.metricN = 0;\r
505 Demod.metric = 0;\r
506 }\r
507 } else {\r
508 if(Demod.posCount > 100) {\r
509 Demod.state = DEMOD_UNSYNCD;\r
510 }\r
511 }\r
512 Demod.posCount++;\r
513 break;\r
514\r
515 case DEMOD_AWAITING_START_BIT:\r
516 MAKE_SOFT_DECISION();\r
517 if(v > 0) {\r
518 if(Demod.posCount > 10) {\r
519 Demod.state = DEMOD_UNSYNCD;\r
520 }\r
521 } else {\r
522 Demod.bitCount = 0;\r
523 Demod.posCount = 1;\r
524 Demod.thisBit = v;\r
525 Demod.shiftReg = 0;\r
526 Demod.state = DEMOD_RECEIVING_DATA;\r
527 }\r
528 break;\r
529\r
530 case DEMOD_RECEIVING_DATA:\r
531 MAKE_SOFT_DECISION();\r
532 if(Demod.posCount == 0) {\r
533 Demod.thisBit = v;\r
534 Demod.posCount = 1;\r
535 } else {\r
536 Demod.thisBit += v;\r
537\r
538 if(Demod.thisBit > 0) {\r
539 Demod.metric += Demod.thisBit;\r
540 } else {\r
541 Demod.metric -= Demod.thisBit;\r
542 }\r
543 (Demod.metricN)++;\r
544\r
545 Demod.shiftReg >>= 1;\r
546 if(Demod.thisBit > 0) {\r
547 Demod.shiftReg |= 0x200;\r
548 }\r
549\r
550 Demod.bitCount++;\r
551 if(Demod.bitCount == 10) {\r
552 WORD s = Demod.shiftReg;\r
553 if((s & 0x200) && !(s & 0x001)) {\r
554 BYTE b = (s >> 1);\r
555 Demod.output[Demod.len] = b;\r
556 Demod.len++;\r
557 Demod.state = DEMOD_AWAITING_START_BIT;\r
558 } else if(s == 0x000) {\r
559 // This is EOF\r
560 return TRUE;\r
561 Demod.state = DEMOD_UNSYNCD;\r
562 } else {\r
563 Demod.state = DEMOD_UNSYNCD;\r
564 }\r
565 }\r
566 Demod.posCount = 0;\r
567 }\r
568 break;\r
569\r
570 default:\r
571 Demod.state = DEMOD_UNSYNCD;\r
572 break;\r
573 }\r
574\r
575 return FALSE;\r
576}\r
577\r
578static void GetSamplesFor14443Demod(BOOL weTx, int n)\r
579{\r
580 int max = 0;\r
581 BOOL gotFrame = FALSE;\r
582\r
583//# define DMA_BUFFER_SIZE 8\r
584 SBYTE *dmaBuf;\r
585\r
586 int lastRxCounter;\r
587 SBYTE *upTo;\r
588\r
589 int ci, cq;\r
590\r
591 int samples = 0;\r
592\r
593 // Clear out the state of the "UART" that receives from the tag.\r
594 memset(BigBuf, 0x44, 400);\r
595 Demod.output = (BYTE *)BigBuf;\r
596 Demod.len = 0;\r
597 Demod.state = DEMOD_UNSYNCD;\r
598\r
599 // And the UART that receives from the reader\r
600 Uart.output = (((BYTE *)BigBuf) + 1024);\r
601 Uart.byteCntMax = 100;\r
602 Uart.state = STATE_UNSYNCD;\r
603\r
604 // Setup for the DMA.\r
605 dmaBuf = (SBYTE *)(BigBuf + 32);\r
606 upTo = dmaBuf;\r
607 lastRxCounter = DMA_BUFFER_SIZE;\r
608 FpgaSetupSscDma((BYTE *)dmaBuf, DMA_BUFFER_SIZE);\r
609\r
610 // And put the FPGA in the appropriate mode\r
611 FpgaWriteConfWord(\r
612 FPGA_MAJOR_MODE_HF_READER_RX_XCORR | FPGA_HF_READER_RX_XCORR_848_KHZ |\r
613 (weTx ? 0 : FPGA_HF_READER_RX_XCORR_SNOOP));\r
614\r
615 for(;;) {\r
616 int behindBy = lastRxCounter - PDC_RX_COUNTER(SSC_BASE);\r
617 if(behindBy > max) max = behindBy;\r
618\r
619 LED_D_ON();\r
620 while(((lastRxCounter-PDC_RX_COUNTER(SSC_BASE)) & (DMA_BUFFER_SIZE-1))\r
621 > 2)\r
622 {\r
623 ci = upTo[0];\r
624 cq = upTo[1];\r
625 upTo += 2;\r
626 if(upTo - dmaBuf > DMA_BUFFER_SIZE) {\r
627 upTo -= DMA_BUFFER_SIZE;\r
628 PDC_RX_NEXT_POINTER(SSC_BASE) = (DWORD)upTo;\r
629 PDC_RX_NEXT_COUNTER(SSC_BASE) = DMA_BUFFER_SIZE;\r
630 }\r
631 lastRxCounter -= 2;\r
632 if(lastRxCounter <= 0) {\r
633 lastRxCounter += DMA_BUFFER_SIZE;\r
634 }\r
635\r
636 samples += 2;\r
637\r
638 Handle14443UartBit(1);\r
639 Handle14443UartBit(1);\r
640\r
641 if(Handle14443SamplesDemod(ci, cq)) {\r
642 gotFrame = 1;\r
643 }\r
644 }\r
645 LED_D_OFF();\r
646\r
647 if(samples > 2000) {\r
648 break;\r
649 }\r
650 }\r
651 PDC_CONTROL(SSC_BASE) = PDC_RX_DISABLE;\r
652 DbpIntegers(max, gotFrame, -1);\r
653}\r
654\r
655//-----------------------------------------------------------------------------\r
656// Read the tag's response. We just receive a stream of slightly-processed\r
657// samples from the FPGA, which we will later do some signal processing on,\r
658// to get the bits.\r
659//-----------------------------------------------------------------------------\r
660/*static void GetSamplesFor14443(BOOL weTx, int n)\r
661{\r
662 BYTE *dest = (BYTE *)BigBuf;\r
663 int c;\r
664\r
665 FpgaWriteConfWord(\r
666 FPGA_MAJOR_MODE_HF_READER_RX_XCORR | FPGA_HF_READER_RX_XCORR_848_KHZ |\r
667 (weTx ? 0 : FPGA_HF_READER_RX_XCORR_SNOOP));\r
668\r
669 c = 0;\r
670 for(;;) {\r
671 if(SSC_STATUS & (SSC_STATUS_TX_READY)) {\r
672 SSC_TRANSMIT_HOLDING = 0x43;\r
673 }\r
674 if(SSC_STATUS & (SSC_STATUS_RX_READY)) {\r
675 SBYTE b;\r
676 b = (SBYTE)SSC_RECEIVE_HOLDING;\r
677\r
678 dest[c++] = (BYTE)b;\r
679\r
680 if(c >= n) {\r
681 break;\r
682 }\r
683 }\r
684 }\r
685}*/\r
686\r
687//-----------------------------------------------------------------------------\r
688// Transmit the command (to the tag) that was placed in ToSend[].\r
689//-----------------------------------------------------------------------------\r
690static void TransmitFor14443(void)\r
691{\r
692 int c;\r
693\r
694 FpgaSetupSsc();\r
695\r
696 while(SSC_STATUS & (SSC_STATUS_TX_READY)) {\r
697 SSC_TRANSMIT_HOLDING = 0xff;\r
698 }\r
699\r
700 FpgaWriteConfWord(\r
701 FPGA_MAJOR_MODE_HF_READER_TX | FPGA_HF_READER_TX_SHALLOW_MOD);\r
702\r
703 for(c = 0; c < 10;) {\r
704 if(SSC_STATUS & (SSC_STATUS_TX_READY)) {\r
705 SSC_TRANSMIT_HOLDING = 0xff;\r
706 c++;\r
707 }\r
708 if(SSC_STATUS & (SSC_STATUS_RX_READY)) {\r
709 volatile DWORD r = SSC_RECEIVE_HOLDING;\r
710 (void)r;\r
711 }\r
712 WDT_HIT();\r
713 }\r
714\r
715 c = 0;\r
716 for(;;) {\r
717 if(SSC_STATUS & (SSC_STATUS_TX_READY)) {\r
718 SSC_TRANSMIT_HOLDING = ToSend[c];\r
719 c++;\r
720 if(c >= ToSendMax) {\r
721 break;\r
722 }\r
723 }\r
724 if(SSC_STATUS & (SSC_STATUS_RX_READY)) {\r
725 volatile DWORD r = SSC_RECEIVE_HOLDING;\r
726 (void)r;\r
727 }\r
728 WDT_HIT();\r
729 }\r
730}\r
731\r
732//-----------------------------------------------------------------------------\r
733// Code a layer 2 command (string of octets, including CRC) into ToSend[],\r
734// so that it is ready to transmit to the tag using TransmitFor14443().\r
735//-----------------------------------------------------------------------------\r
736void CodeIso14443bAsReader(const BYTE *cmd, int len)\r
737{\r
738 int i, j;\r
739 BYTE b;\r
740\r
741 ToSendReset();\r
742\r
743 // Establish initial reference level\r
744 for(i = 0; i < 40; i++) {\r
745 ToSendStuffBit(1);\r
746 }\r
747 // Send SOF\r
748 for(i = 0; i < 10; i++) {\r
749 ToSendStuffBit(0);\r
750 }\r
751\r
752 for(i = 0; i < len; i++) {\r
753 // Stop bits/EGT\r
754 ToSendStuffBit(1);\r
755 ToSendStuffBit(1);\r
756 // Start bit\r
757 ToSendStuffBit(0);\r
758 // Data bits\r
759 b = cmd[i];\r
760 for(j = 0; j < 8; j++) {\r
761 if(b & 1) {\r
762 ToSendStuffBit(1);\r
763 } else {\r
764 ToSendStuffBit(0);\r
765 }\r
766 b >>= 1;\r
767 }\r
768 }\r
769 // Send EOF\r
770 ToSendStuffBit(1);\r
771 for(i = 0; i < 10; i++) {\r
772 ToSendStuffBit(0);\r
773 }\r
774 for(i = 0; i < 8; i++) {\r
775 ToSendStuffBit(1);\r
776 }\r
777\r
778 // And then a little more, to make sure that the last character makes\r
779 // it out before we switch to rx mode.\r
780 for(i = 0; i < 24; i++) {\r
781 ToSendStuffBit(1);\r
782 }\r
783\r
784 // Convert from last character reference to length\r
785 ToSendMax++;\r
786}\r
787\r
788//-----------------------------------------------------------------------------\r
789// Read an ISO 14443 tag. We send it some set of commands, and record the\r
790// responses.\r
791//-----------------------------------------------------------------------------\r
792void AcquireRawAdcSamplesIso14443(DWORD parameter)\r
793{\r
794// BYTE cmd1[] = { 0x05, 0x00, 0x00, 0x71, 0xff };\r
795 BYTE cmd1[] = { 0x05, 0x00, 0x08, 0x39, 0x73 };\r
796\r
797 // Make sure that we start from off, since the tags are stateful;\r
798 // confusing things will happen if we don't reset them between reads.\r
799 LED_D_OFF();\r
800 FpgaWriteConfWord(FPGA_MAJOR_MODE_OFF);\r
801 SpinDelay(200);\r
802\r
803 SetAdcMuxFor(GPIO_MUXSEL_HIPKD);\r
804 FpgaSetupSsc();\r
805\r
806 // Now give it time to spin up.\r
807 FpgaWriteConfWord(\r
808 FPGA_MAJOR_MODE_HF_READER_RX_XCORR | FPGA_HF_READER_RX_XCORR_848_KHZ);\r
809 SpinDelay(200);\r
810\r
811 CodeIso14443bAsReader(cmd1, sizeof(cmd1));\r
812 TransmitFor14443();\r
813 LED_A_ON();\r
814 GetSamplesFor14443Demod(TRUE, 2000);\r
815 LED_A_OFF();\r
816}\r
817\r
818//=============================================================================\r
819// Finally, the `sniffer' combines elements from both the reader and\r
820// simulated tag, to show both sides of the conversation.\r
821//=============================================================================\r
822\r
823//-----------------------------------------------------------------------------\r
824// Record the sequence of commands sent by the reader to the tag, with\r
825// triggering so that we start recording at the point that the tag is moved\r
826// near the reader.\r
827//-----------------------------------------------------------------------------\r
828void SnoopIso14443(void)\r
829{\r
830 // We won't start recording the frames that we acquire until we trigger;\r
831 // a good trigger condition to get started is probably when we see a\r
832 // response from the tag.\r
833 BOOL triggered = FALSE;\r
834\r
835 // The command (reader -> tag) that we're working on receiving.\r
836 BYTE *receivedCmd = (((BYTE *)BigBuf) + 1024);\r
837 // The response (tag -> reader) that we're working on receiving.\r
838 BYTE *receivedResponse = (((BYTE *)BigBuf) + 1536);\r
839\r
840 // As we receive stuff, we copy it from receivedCmd or receivedResponse\r
841 // into trace, along with its length and other annotations.\r
842 BYTE *trace = (BYTE *)BigBuf;\r
843 int traceLen = 0;\r
844\r
845 // The DMA buffer, used to stream samples from the FPGA.\r
846//# define DMA_BUFFER_SIZE 256\r
847 SBYTE *dmaBuf = ((SBYTE *)BigBuf) + 2048;\r
848 int lastRxCounter;\r
849 SBYTE *upTo;\r
850 int ci, cq;\r
851 int maxBehindBy = 0;\r
852\r
853 // Count of samples received so far, so that we can include timing\r
854 // information in the trace buffer.\r
855 int samples = 0;\r
856\r
857 memset(trace, 0x44, 1000);\r
858\r
859 // Set up the demodulator for tag -> reader responses.\r
860 Demod.output = receivedResponse;\r
861 Demod.len = 0;\r
862 Demod.state = DEMOD_UNSYNCD;\r
863\r
864 // And the reader -> tag commands\r
865 memset(&Uart, 0, sizeof(Uart));\r
866 Uart.output = receivedCmd;\r
867 Uart.byteCntMax = 100;\r
868 Uart.state = STATE_UNSYNCD;\r
869\r
870 // And put the FPGA in the appropriate mode\r
871 FpgaWriteConfWord(\r
872 FPGA_MAJOR_MODE_HF_READER_RX_XCORR | FPGA_HF_READER_RX_XCORR_848_KHZ |\r
873 FPGA_HF_READER_RX_XCORR_SNOOP);\r
874 SetAdcMuxFor(GPIO_MUXSEL_HIPKD);\r
875\r
876 // Setup for the DMA.\r
877 FpgaSetupSsc();\r
878 upTo = dmaBuf;\r
879 lastRxCounter = DMA_BUFFER_SIZE;\r
880 FpgaSetupSscDma((BYTE *)dmaBuf, DMA_BUFFER_SIZE);\r
881\r
882 LED_A_ON();\r
883\r
884 // And now we loop, receiving samples.\r
885 for(;;) {\r
886 int behindBy = (lastRxCounter - PDC_RX_COUNTER(SSC_BASE)) &\r
887 (DMA_BUFFER_SIZE-1);\r
888 if(behindBy > maxBehindBy) {\r
889 maxBehindBy = behindBy;\r
890 if(behindBy > 100) {\r
891 DbpString("blew circular buffer!");\r
892 goto done;\r
893 }\r
894 }\r
895 if(behindBy < 2) continue;\r
896\r
897 ci = upTo[0];\r
898 cq = upTo[1];\r
899 upTo += 2;\r
900 lastRxCounter -= 2;\r
901 if(upTo - dmaBuf > DMA_BUFFER_SIZE) {\r
902 upTo -= DMA_BUFFER_SIZE;\r
903 lastRxCounter += DMA_BUFFER_SIZE;\r
904 PDC_RX_NEXT_POINTER(SSC_BASE) = (DWORD)upTo;\r
905 PDC_RX_NEXT_COUNTER(SSC_BASE) = DMA_BUFFER_SIZE;\r
906 }\r
907\r
908 samples += 2;\r
909\r
910#define HANDLE_BIT_IF_BODY \\r
911 if(triggered) { \\r
912 trace[traceLen++] = ((samples >> 0) & 0xff); \\r
913 trace[traceLen++] = ((samples >> 8) & 0xff); \\r
914 trace[traceLen++] = ((samples >> 16) & 0xff); \\r
915 trace[traceLen++] = ((samples >> 24) & 0xff); \\r
916 trace[traceLen++] = 0; \\r
917 trace[traceLen++] = 0; \\r
918 trace[traceLen++] = 0; \\r
919 trace[traceLen++] = 0; \\r
920 trace[traceLen++] = Uart.byteCnt; \\r
921 memcpy(trace+traceLen, receivedCmd, Uart.byteCnt); \\r
922 traceLen += Uart.byteCnt; \\r
923 if(traceLen > 1000) break; \\r
924 } \\r
925 /* And ready to receive another command. */ \\r
926 memset(&Uart, 0, sizeof(Uart)); \\r
927 Uart.output = receivedCmd; \\r
928 Uart.byteCntMax = 100; \\r
929 Uart.state = STATE_UNSYNCD; \\r
930 /* And also reset the demod code, which might have been */ \\r
931 /* false-triggered by the commands from the reader. */ \\r
932 memset(&Demod, 0, sizeof(Demod)); \\r
933 Demod.output = receivedResponse; \\r
934 Demod.state = DEMOD_UNSYNCD; \\r
935\r
936 if(Handle14443UartBit(ci & 1)) {\r
937 HANDLE_BIT_IF_BODY\r
938 }\r
939 if(Handle14443UartBit(cq & 1)) {\r
940 HANDLE_BIT_IF_BODY\r
941 }\r
942\r
943 if(Handle14443SamplesDemod(ci, cq)) {\r
944 // timestamp, as a count of samples\r
945 trace[traceLen++] = ((samples >> 0) & 0xff);\r
946 trace[traceLen++] = ((samples >> 8) & 0xff);\r
947 trace[traceLen++] = ((samples >> 16) & 0xff);\r
948 trace[traceLen++] = 0x80 | ((samples >> 24) & 0xff);\r
949 // correlation metric (~signal strength estimate)\r
950 if(Demod.metricN != 0) {\r
951 Demod.metric /= Demod.metricN;\r
952 }\r
953 trace[traceLen++] = ((Demod.metric >> 0) & 0xff);\r
954 trace[traceLen++] = ((Demod.metric >> 8) & 0xff);\r
955 trace[traceLen++] = ((Demod.metric >> 16) & 0xff);\r
956 trace[traceLen++] = ((Demod.metric >> 24) & 0xff);\r
957 // length\r
958 trace[traceLen++] = Demod.len;\r
959 memcpy(trace+traceLen, receivedResponse, Demod.len);\r
960 traceLen += Demod.len;\r
961 if(traceLen > 1000) break;\r
962\r
963 triggered = TRUE;\r
964 LED_A_OFF();\r
965 LED_B_ON();\r
966\r
967 // And ready to receive another response.\r
968 memset(&Demod, 0, sizeof(Demod));\r
969 Demod.output = receivedResponse;\r
970 Demod.state = DEMOD_UNSYNCD;\r
971 }\r
972\r
973 if(BUTTON_PRESS()) {\r
974 DbpString("cancelled");\r
975 goto done;\r
976 }\r
977 }\r
978\r
979 DbpString("in done pt");\r
980\r
981 DbpIntegers(maxBehindBy, Uart.state, Uart.byteCnt);\r
982 DbpIntegers(Uart.byteCntMax, traceLen, 0x23);\r
983\r
984done:\r
985 PDC_CONTROL(SSC_BASE) = PDC_RX_DISABLE;\r
986 LED_A_OFF();\r
987 LED_B_OFF();\r
988}\r
Impressum, Datenschutz