]> git.zerfleddert.de Git - proxmark3-svn/blame - armsrc/appmain.c
add inversion option to mandemod and fix indentation
[proxmark3-svn] / armsrc / appmain.c
CommitLineData
6658905f 1//-----------------------------------------------------------------------------\r
2// The main application code. This is the first thing called after start.c\r
3// executes.\r
4// Jonathan Westhues, Mar 2006\r
5// Edits by Gerhard de Koning Gans, Sep 2007 (##)\r
6//-----------------------------------------------------------------------------\r
aa4d9d9b 7\r
8\r
6658905f 9#include <proxmark3.h>\r
10#include "apps.h"\r
aa4d9d9b 11#ifdef WITH_LCD\r
0e25ae11 12#include "fonts.h"\r
6658905f 13#include "LCD.h"\r
aa4d9d9b 14#endif\r
6658905f 15\r
16// The large multi-purpose buffer, typically used to hold A/D samples,\r
17// maybe pre-processed in some way.\r
18DWORD BigBuf[16000];\r
19\r
20//=============================================================================\r
21// A buffer where we can queue things up to be sent through the FPGA, for\r
22// any purpose (fake tag, as reader, whatever). We go MSB first, since that\r
23// is the order in which they go out on the wire.\r
24//=============================================================================\r
25\r
26BYTE ToSend[256];\r
27int ToSendMax;\r
28static int ToSendBit;\r
29\r
f23e056d 30
31void BufferClear(void)
32{
33 memset(BigBuf,0,sizeof(BigBuf));
34 DbpString("Buffer cleared");
35}
36
6658905f 37void ToSendReset(void)\r
38{\r
39 ToSendMax = -1;\r
40 ToSendBit = 8;\r
41}\r
42\r
43void ToSendStuffBit(int b)\r
44{\r
45 if(ToSendBit >= 8) {\r
46 ToSendMax++;\r
47 ToSend[ToSendMax] = 0;\r
48 ToSendBit = 0;\r
49 }\r
50\r
51 if(b) {\r
52 ToSend[ToSendMax] |= (1 << (7 - ToSendBit));\r
53 }\r
54\r
55 ToSendBit++;\r
56\r
57 if(ToSendBit >= sizeof(ToSend)) {\r
58 ToSendBit = 0;\r
59 DbpString("ToSendStuffBit overflowed!");\r
60 }\r
61}\r
62\r
63//=============================================================================\r
64// Debug print functions, to go out over USB, to the usual PC-side client.\r
65//=============================================================================\r
66\r
67void DbpString(char *str)\r
68{\r
69 UsbCommand c;\r
70 c.cmd = CMD_DEBUG_PRINT_STRING;\r
71 c.ext1 = strlen(str);\r
72 memcpy(c.d.asBytes, str, c.ext1);\r
73\r
74 UsbSendPacket((BYTE *)&c, sizeof(c));\r
75 // TODO fix USB so stupid things like this aren't req'd\r
76 SpinDelay(50);\r
77}\r
78\r
79void DbpIntegers(int x1, int x2, int x3)\r
80{\r
81 UsbCommand c;\r
82 c.cmd = CMD_DEBUG_PRINT_INTEGERS;\r
83 c.ext1 = x1;\r
84 c.ext2 = x2;\r
85 c.ext3 = x3;\r
86\r
87 UsbSendPacket((BYTE *)&c, sizeof(c));\r
88 // XXX\r
89 SpinDelay(50);\r
90}\r
91\r
92void AcquireRawAdcSamples125k(BOOL at134khz)\r
93{\r
94 BYTE *dest = (BYTE *)BigBuf;\r
95 int n = sizeof(BigBuf);\r
96 int i;\r
97\r
98 memset(dest,0,n);\r
99\r
100 if(at134khz) {\r
30f2a7d3 101 FpgaSendCommand(FPGA_CMD_SET_DIVISOR, 88); //134.8Khz\r
6658905f 102 FpgaWriteConfWord(FPGA_MAJOR_MODE_LF_READER | FPGA_LF_READER_USE_134_KHZ);\r
103 } else {\r
30f2a7d3 104 FpgaSendCommand(FPGA_CMD_SET_DIVISOR, 95); //125Khz\r
6658905f 105 FpgaWriteConfWord(FPGA_MAJOR_MODE_LF_READER | FPGA_LF_READER_USE_125_KHZ);\r
106 }\r
107\r
108 // Connect the A/D to the peak-detected low-frequency path.\r
109 SetAdcMuxFor(GPIO_MUXSEL_LOPKD);\r
110\r
111 // Give it a bit of time for the resonant antenna to settle.\r
112 SpinDelay(50);\r
113\r
114 // Now set up the SSC to get the ADC samples that are now streaming at us.\r
115 FpgaSetupSsc();\r
116\r
117 i = 0;\r
118 for(;;) {\r
119 if(SSC_STATUS & (SSC_STATUS_TX_READY)) {\r
120 SSC_TRANSMIT_HOLDING = 0x43;\r
121 LED_D_ON();\r
122 }\r
123 if(SSC_STATUS & (SSC_STATUS_RX_READY)) {\r
124 dest[i] = (BYTE)SSC_RECEIVE_HOLDING;\r
125 i++;\r
126 LED_D_OFF();\r
127 if(i >= n) {\r
128 break;\r
129 }\r
130 }\r
131 }\r
132 DbpIntegers(dest[0], dest[1], at134khz);\r
133}\r
134\r
135//-----------------------------------------------------------------------------\r
136// Read an ADC channel and block till it completes, then return the result\r
30f2a7d3 137// in ADC units (0 to 1023). Also a routine to average 32 samples and\r
6658905f 138// return that.\r
139//-----------------------------------------------------------------------------\r
140static int ReadAdc(int ch)\r
141{\r
142 DWORD d;\r
143\r
144 ADC_CONTROL = ADC_CONTROL_RESET;\r
145 ADC_MODE = ADC_MODE_PRESCALE(32) | ADC_MODE_STARTUP_TIME(16) |\r
146 ADC_MODE_SAMPLE_HOLD_TIME(8);\r
147 ADC_CHANNEL_ENABLE = ADC_CHANNEL(ch);\r
148\r
149 ADC_CONTROL = ADC_CONTROL_START;\r
150 while(!(ADC_STATUS & ADC_END_OF_CONVERSION(ch)))\r
151 ;\r
152 d = ADC_CHANNEL_DATA(ch);\r
153\r
154 return d;\r
155}\r
156\r
157static int AvgAdc(int ch)\r
158{\r
159 int i;\r
160 int a = 0;\r
161\r
162 for(i = 0; i < 32; i++) {\r
163 a += ReadAdc(ch);\r
164 }\r
165\r
166 return (a + 15) >> 5;\r
167}\r
30f2a7d3 168
169/*
170 * Sweeps the useful LF range of the proxmark from
171 * 46.8kHz (divisor=255) to 600kHz (divisor=19) and
172 * reads the voltage in the antenna: the result is a graph
173 * which should clearly show the resonating frequency of your
174 * LF antenna ( hopefully around 90 if it is tuned to 125kHz!)
175 */\r
176void SweepLFrange()\r
177{\r
178 BYTE *dest = (BYTE *)BigBuf;\r
179 int i;\r
180\r
181 // clear buffer\r
182 memset(BigBuf,0,sizeof(BigBuf));\r
183\r
184 FpgaWriteConfWord(FPGA_MAJOR_MODE_LF_READER);\r
185 for (i=255; i>19; i--) {\r
186 FpgaSendCommand(FPGA_CMD_SET_DIVISOR, i);\r
187 SpinDelay(20);\r
188 dest[i] = (137500 * AvgAdc(4)) >> 18;\r
189 }\r
190}\r
6658905f 191\r
192void MeasureAntennaTuning(void)\r
193{\r
194// Impedances are Zc = 1/(j*omega*C), in ohms\r
195#define LF_TUNING_CAP_Z 1273 // 1 nF @ 125 kHz\r
196#define HF_TUNING_CAP_Z 235 // 50 pF @ 13.56 MHz\r
197\r
198 int vLf125, vLf134, vHf; // in mV\r
199\r
200 UsbCommand c;\r
201\r
202 // Let the FPGA drive the low-frequency antenna around 125 kHz.\r
30f2a7d3 203 FpgaSendCommand(FPGA_CMD_SET_DIVISOR, 95); //125Khz\r
6658905f 204 FpgaWriteConfWord(FPGA_MAJOR_MODE_LF_READER | FPGA_LF_READER_USE_125_KHZ);\r
205 SpinDelay(20);\r
206 vLf125 = AvgAdc(4);\r
207 // Vref = 3.3V, and a 10000:240 voltage divider on the input\r
208 // can measure voltages up to 137500 mV\r
209 vLf125 = (137500 * vLf125) >> 10;\r
210\r
211 // Let the FPGA drive the low-frequency antenna around 134 kHz.\r
30f2a7d3 212 FpgaSendCommand(FPGA_CMD_SET_DIVISOR, 88); //134.8Khz\r
6658905f 213 FpgaWriteConfWord(FPGA_MAJOR_MODE_LF_READER | FPGA_LF_READER_USE_134_KHZ);\r
214 SpinDelay(20);\r
215 vLf134 = AvgAdc(4);\r
216 // Vref = 3.3V, and a 10000:240 voltage divider on the input\r
217 // can measure voltages up to 137500 mV\r
218 vLf134 = (137500 * vLf134) >> 10;\r
219\r
220 // Let the FPGA drive the high-frequency antenna around 13.56 MHz.\r
221 FpgaWriteConfWord(FPGA_MAJOR_MODE_HF_READER_RX_XCORR);\r
222 SpinDelay(20);\r
223 vHf = AvgAdc(5);\r
224 // Vref = 3300mV, and an 10:1 voltage divider on the input\r
225 // can measure voltages up to 33000 mV\r
226 vHf = (33000 * vHf) >> 10;\r
227\r
228 c.cmd = CMD_MEASURED_ANTENNA_TUNING;\r
229 c.ext1 = (vLf125 << 0) | (vLf134 << 16);\r
230 c.ext2 = vHf;\r
231 c.ext3 = (LF_TUNING_CAP_Z << 0) | (HF_TUNING_CAP_Z << 16);\r
232 UsbSendPacket((BYTE *)&c, sizeof(c));\r
233}\r
234\r
235void SimulateTagLowFrequency(int period)\r
236{\r
237 int i;\r
238 BYTE *tab = (BYTE *)BigBuf;\r
239\r
240 FpgaWriteConfWord(FPGA_MAJOR_MODE_LF_SIMULATOR);\r
241\r
242 PIO_ENABLE = (1 << GPIO_SSC_DOUT) | (1 << GPIO_SSC_CLK);\r
243\r
244 PIO_OUTPUT_ENABLE = (1 << GPIO_SSC_DOUT);\r
245 PIO_OUTPUT_DISABLE = (1 << GPIO_SSC_CLK);\r
246\r
247#define SHORT_COIL() LOW(GPIO_SSC_DOUT)\r
30f2a7d3 248#define OPEN_COIL() HIGH(GPIO_SSC_DOUT)\r
6658905f 249\r
250 i = 0;\r
251 for(;;) {\r
252 while(!(PIO_PIN_DATA_STATUS & (1<<GPIO_SSC_CLK))) {\r
253 if(BUTTON_PRESS()) {\r
254 return;\r
255 }\r
256 WDT_HIT();\r
257 }\r
258\r
259 LED_D_ON();\r
260 if(tab[i]) {\r
261 OPEN_COIL();\r
262 } else {\r
263 SHORT_COIL();\r
264 }\r
265 LED_D_OFF();\r
266\r
267 while(PIO_PIN_DATA_STATUS & (1<<GPIO_SSC_CLK)) {\r
268 if(BUTTON_PRESS()) {\r
269 return;\r
270 }\r
271 WDT_HIT();\r
272 }\r
273\r
274 i++;\r
275 if(i == period) i = 0;\r
276 }\r
277}\r
278\r
279// compose fc/8 fc/10 waveform\r
280static void fc(int c, int *n) {\r
281 BYTE *dest = (BYTE *)BigBuf;\r
282 int idx;\r
283\r
284 // for when we want an fc8 pattern every 4 logical bits\r
285 if(c==0) {\r
286 dest[((*n)++)]=1;\r
287 dest[((*n)++)]=1;\r
288 dest[((*n)++)]=0;\r
289 dest[((*n)++)]=0;\r
290 dest[((*n)++)]=0;\r
291 dest[((*n)++)]=0;\r
292 dest[((*n)++)]=0;\r
293 dest[((*n)++)]=0;\r
294 }\r
295 // an fc/8 encoded bit is a bit pattern of 11000000 x6 = 48 samples\r
296 if(c==8) {\r
297 for (idx=0; idx<6; idx++) {\r
298 dest[((*n)++)]=1;\r
299 dest[((*n)++)]=1;\r
300 dest[((*n)++)]=0;\r
301 dest[((*n)++)]=0;\r
302 dest[((*n)++)]=0;\r
303 dest[((*n)++)]=0;\r
304 dest[((*n)++)]=0;\r
305 dest[((*n)++)]=0;\r
306 }\r
307 }\r
308\r
309 // an fc/10 encoded bit is a bit pattern of 1110000000 x5 = 50 samples\r
310 if(c==10) {\r
311 for (idx=0; idx<5; idx++) {\r
312 dest[((*n)++)]=1;\r
313 dest[((*n)++)]=1;\r
314 dest[((*n)++)]=1;\r
315 dest[((*n)++)]=0;\r
316 dest[((*n)++)]=0;\r
317 dest[((*n)++)]=0;\r
318 dest[((*n)++)]=0;\r
319 dest[((*n)++)]=0;\r
320 dest[((*n)++)]=0;\r
321 dest[((*n)++)]=0;\r
322 }\r
323 }\r
324}\r
325\r
326// prepare a waveform pattern in the buffer based on the ID given then\r
327// simulate a HID tag until the button is pressed\r
328static void CmdHIDsimTAG(int hi, int lo)\r
329{\r
330 int n=0, i=0;\r
331 /*\r
332 HID tag bitstream format\r
333 The tag contains a 44bit unique code. This is sent out MSB first in sets of 4 bits\r
334 A 1 bit is represented as 6 fc8 and 5 fc10 patterns\r
335 A 0 bit is represented as 5 fc10 and 6 fc8 patterns\r
336 A fc8 is inserted before every 4 bits\r
337 A special start of frame pattern is used consisting a0b0 where a and b are neither 0\r
338 nor 1 bits, they are special patterns (a = set of 12 fc8 and b = set of 10 fc10)\r
339 */\r
340\r
341 if (hi>0xFFF) {\r
342 DbpString("Tags can only have 44 bits.");\r
343 return;\r
344 }\r
345 fc(0,&n);\r
346 // special start of frame marker containing invalid bit sequences\r
347 fc(8, &n); fc(8, &n); // invalid\r
348 fc(8, &n); fc(10, &n); // logical 0\r
349 fc(10, &n); fc(10, &n); // invalid\r
350 fc(8, &n); fc(10, &n); // logical 0\r
351\r
352 WDT_HIT();\r
353 // manchester encode bits 43 to 32\r
354 for (i=11; i>=0; i--) {\r
355 if ((i%4)==3) fc(0,&n);\r
356 if ((hi>>i)&1) {\r
357 fc(10, &n); fc(8, &n); // low-high transition\r
358 } else {\r
359 fc(8, &n); fc(10, &n); // high-low transition\r
360 }\r
361 }\r
362\r
363 WDT_HIT();\r
364 // manchester encode bits 31 to 0\r
365 for (i=31; i>=0; i--) {\r
366 if ((i%4)==3) fc(0,&n);\r
367 if ((lo>>i)&1) {\r
368 fc(10, &n); fc(8, &n); // low-high transition\r
369 } else {\r
370 fc(8, &n); fc(10, &n); // high-low transition\r
371 }\r
372 }\r
373\r
374 LED_A_ON();\r
375 SimulateTagLowFrequency(n);\r
376 LED_A_OFF();\r
377}\r
378\r
379// loop to capture raw HID waveform then FSK demodulate the TAG ID from it\r
380static void CmdHIDdemodFSK(void)\r
381{\r
382 BYTE *dest = (BYTE *)BigBuf;\r
383 int m=0, n=0, i=0, idx=0, found=0, lastval=0;\r
384 DWORD hi=0, lo=0;\r
385\r
30f2a7d3 386 FpgaSendCommand(FPGA_CMD_SET_DIVISOR, 95); //125Khz\r
6658905f 387 FpgaWriteConfWord(FPGA_MAJOR_MODE_LF_READER | FPGA_LF_READER_USE_125_KHZ);\r
388\r
389 // Connect the A/D to the peak-detected low-frequency path.\r
390 SetAdcMuxFor(GPIO_MUXSEL_LOPKD);\r
391\r
392 // Give it a bit of time for the resonant antenna to settle.\r
393 SpinDelay(50);\r
394\r
395 // Now set up the SSC to get the ADC samples that are now streaming at us.\r
396 FpgaSetupSsc();\r
397\r
398 for(;;) {\r
399 WDT_HIT();\r
400 LED_A_ON();\r
401 if(BUTTON_PRESS()) {\r
402 LED_A_OFF();\r
403 return;\r
404 }\r
405\r
406 i = 0;\r
407 m = sizeof(BigBuf);\r
408 memset(dest,128,m);\r
409 for(;;) {\r
410 if(SSC_STATUS & (SSC_STATUS_TX_READY)) {\r
411 SSC_TRANSMIT_HOLDING = 0x43;\r
412 LED_D_ON();\r
413 }\r
414 if(SSC_STATUS & (SSC_STATUS_RX_READY)) {\r
415 dest[i] = (BYTE)SSC_RECEIVE_HOLDING;\r
416 // we don't care about actual value, only if it's more or less than a\r
417 // threshold essentially we capture zero crossings for later analysis\r
418 if(dest[i] < 127) dest[i] = 0; else dest[i] = 1;\r
419 i++;\r
420 LED_D_OFF();\r
421 if(i >= m) {\r
422 break;\r
423 }\r
424 }\r
425 }\r
426\r
427 // FSK demodulator\r
428\r
429 // sync to first lo-hi transition\r
430 for( idx=1; idx<m; idx++) {\r
431 if (dest[idx-1]<dest[idx])\r
432 lastval=idx;\r
433 break;\r
434 }\r
435 WDT_HIT();\r
436\r
437 // count cycles between consecutive lo-hi transitions, there should be either 8 (fc/8)\r
438 // or 10 (fc/10) cycles but in practice due to noise etc we may end up with with anywhere\r
439 // between 7 to 11 cycles so fuzz it by treat anything <9 as 8 and anything else as 10\r
440 for( i=0; idx<m; idx++) {\r
441 if (dest[idx-1]<dest[idx]) {\r
442 dest[i]=idx-lastval;\r
443 if (dest[i] <= 8) {\r
444 dest[i]=1;\r
445 } else {\r
446 dest[i]=0;\r
447 }\r
448\r
449 lastval=idx;\r
450 i++;\r
451 }\r
452 }\r
453 m=i;\r
454 WDT_HIT();\r
455\r
456 // we now have a set of cycle counts, loop over previous results and aggregate data into bit patterns\r
457 lastval=dest[0];\r
458 idx=0;\r
459 i=0;\r
460 n=0;\r
461 for( idx=0; idx<m; idx++) {\r
462 if (dest[idx]==lastval) {\r
463 n++;\r
464 } else {\r
465 // a bit time is five fc/10 or six fc/8 cycles so figure out how many bits a pattern width represents,\r
466 // an extra fc/8 pattern preceeds every 4 bits (about 200 cycles) just to complicate things but it gets\r
467 // swallowed up by rounding\r
468 // expected results are 1 or 2 bits, any more and it's an invalid manchester encoding\r
469 // special start of frame markers use invalid manchester states (no transitions) by using sequences\r
470 // like 111000\r
471 if (dest[idx-1]) {\r
472 n=(n+1)/6; // fc/8 in sets of 6\r
473 } else {\r
474 n=(n+1)/5; // fc/10 in sets of 5\r
475 }\r
476 switch (n) { // stuff appropriate bits in buffer\r
477 case 0:\r
478 case 1: // one bit\r
479 dest[i++]=dest[idx-1];\r
480 break;\r
481 case 2: // two bits\r
482 dest[i++]=dest[idx-1];\r
483 dest[i++]=dest[idx-1];\r
484 break;\r
485 case 3: // 3 bit start of frame markers\r
486 dest[i++]=dest[idx-1];\r
487 dest[i++]=dest[idx-1];\r
488 dest[i++]=dest[idx-1];\r
489 break;\r
30f2a7d3 490 // When a logic 0 is immediately followed by the start of the next transmisson\r
6658905f 491 // (special pattern) a pattern of 4 bit duration lengths is created.\r
492 case 4:\r
493 dest[i++]=dest[idx-1];\r
494 dest[i++]=dest[idx-1];\r
495 dest[i++]=dest[idx-1];\r
496 dest[i++]=dest[idx-1];\r
497 break;\r
498 default: // this shouldn't happen, don't stuff any bits\r
499 break;\r
500 }\r
501 n=0;\r
502 lastval=dest[idx];\r
503 }\r
504 }\r
505 m=i;\r
506 WDT_HIT();\r
507\r
508 // final loop, go over previously decoded manchester data and decode into usable tag ID\r
509 // 111000 bit pattern represent start of frame, 01 pattern represents a 1 and 10 represents a 0\r
510 for( idx=0; idx<m-6; idx++) {\r
511 // search for a start of frame marker\r
512 if ( dest[idx] && dest[idx+1] && dest[idx+2] && (!dest[idx+3]) && (!dest[idx+4]) && (!dest[idx+5]) )\r
513 {\r
514 found=1;\r
515 idx+=6;\r
516 if (found && (hi|lo)) {\r
517 DbpString("TAG ID");\r
518 DbpIntegers(hi, lo, (lo>>1)&0xffff);\r
519 hi=0;\r
520 lo=0;\r
521 found=0;\r
522 }\r
523 }\r
524 if (found) {\r
525 if (dest[idx] && (!dest[idx+1]) ) {\r
526 hi=(hi<<1)|(lo>>31);\r
527 lo=(lo<<1)|0;\r
528 } else if ( (!dest[idx]) && dest[idx+1]) {\r
529 hi=(hi<<1)|(lo>>31);\r
530 lo=(lo<<1)|1;\r
531 } else {\r
532 found=0;\r
533 hi=0;\r
534 lo=0;\r
535 }\r
536 idx++;\r
537 }\r
538 if ( dest[idx] && dest[idx+1] && dest[idx+2] && (!dest[idx+3]) && (!dest[idx+4]) && (!dest[idx+5]) )\r
539 {\r
540 found=1;\r
541 idx+=6;\r
542 if (found && (hi|lo)) {\r
543 DbpString("TAG ID");\r
544 DbpIntegers(hi, lo, (lo>>1)&0xffff);\r
545 hi=0;\r
546 lo=0;\r
547 found=0;\r
548 }\r
549 }\r
550 }\r
551 WDT_HIT();\r
552 }\r
553}\r
554\r
555void SimulateTagHfListen(void)\r
556{\r
557 BYTE *dest = (BYTE *)BigBuf;\r
558 int n = sizeof(BigBuf);\r
559 BYTE v = 0;\r
560 int i;\r
561 int p = 0;\r
562\r
563 // We're using this mode just so that I can test it out; the simulated\r
564 // tag mode would work just as well and be simpler.\r
565 FpgaWriteConfWord(FPGA_MAJOR_MODE_HF_READER_RX_XCORR | FPGA_HF_READER_RX_XCORR_848_KHZ | FPGA_HF_READER_RX_XCORR_SNOOP);\r
566\r
567 // We need to listen to the high-frequency, peak-detected path.\r
568 SetAdcMuxFor(GPIO_MUXSEL_HIPKD);\r
569\r
570 FpgaSetupSsc();\r
571\r
572 i = 0;\r
573 for(;;) {\r
574 if(SSC_STATUS & (SSC_STATUS_TX_READY)) {\r
575 SSC_TRANSMIT_HOLDING = 0xff;\r
576 }\r
577 if(SSC_STATUS & (SSC_STATUS_RX_READY)) {\r
578 BYTE r = (BYTE)SSC_RECEIVE_HOLDING;\r
579\r
580 v <<= 1;\r
581 if(r & 1) {\r
582 v |= 1;\r
583 }\r
584 p++;\r
585\r
586 if(p >= 8) {\r
587 dest[i] = v;\r
588 v = 0;\r
589 p = 0;\r
590 i++;\r
591\r
592 if(i >= n) {\r
593 break;\r
594 }\r
595 }\r
596 }\r
597 }\r
598 DbpString("simulate tag (now type bitsamples)");\r
599}\r
600\r
601void UsbPacketReceived(BYTE *packet, int len)\r
602{\r
603 UsbCommand *c = (UsbCommand *)packet;\r
604\r
605 switch(c->cmd) {\r
606 case CMD_ACQUIRE_RAW_ADC_SAMPLES_125K:\r
607 AcquireRawAdcSamples125k(c->ext1);\r
608 break;\r
609\r
610 case CMD_ACQUIRE_RAW_ADC_SAMPLES_ISO_15693:\r
611 AcquireRawAdcSamplesIso15693();\r
612 break;\r
f23e056d 613
614 case CMD_BUFF_CLEAR:
615 BufferClear();
616 break;
6658905f 617\r
618 case CMD_READER_ISO_15693:\r
30f2a7d3 619 ReaderIso15693(c->ext1);\r
6658905f 620 break;\r
621\r
622 case CMD_SIMTAG_ISO_15693:\r
30f2a7d3 623 SimTagIso15693(c->ext1);\r
6658905f 624 break;\r
625\r
6658905f 626 case CMD_ACQUIRE_RAW_ADC_SAMPLES_ISO_14443:\r
627 AcquireRawAdcSamplesIso14443(c->ext1);\r
628 break;\r
fb25b483 629
630 case CMD_READ_SRI512_TAG:
631 ReadSRI512Iso14443(c->ext1);
632 break;
6658905f 633\r
634 case CMD_READER_ISO_14443a:\r
30f2a7d3 635 ReaderIso14443a(c->ext1);\r
6658905f 636 break;\r
637\r
638 case CMD_SNOOP_ISO_14443:\r
639 SnoopIso14443();\r
640 break;\r
641\r
642 case CMD_SNOOP_ISO_14443a:\r
643 SnoopIso14443a();\r
644 break;\r
645\r
646 case CMD_SIMULATE_TAG_HF_LISTEN:\r
647 SimulateTagHfListen();\r
648 break;\r
649\r
650 case CMD_SIMULATE_TAG_ISO_14443:\r
651 SimulateIso14443Tag();\r
652 break;\r
653\r
654 case CMD_SIMULATE_TAG_ISO_14443a:\r
655 SimulateIso14443aTag(c->ext1, c->ext2); // ## Simulate iso14443a tag - pass tag type & UID\r
656 break;\r
657\r
658 case CMD_MEASURE_ANTENNA_TUNING:\r
659 MeasureAntennaTuning();\r
660 break;\r
661\r
662 case CMD_HID_DEMOD_FSK:\r
663 CmdHIDdemodFSK(); // Demodulate HID tag\r
664 break;\r
665\r
666 case CMD_HID_SIM_TAG:\r
667 CmdHIDsimTAG(c->ext1, c->ext2); // Simulate HID tag by ID\r
668 break;\r
669\r
670 case CMD_FPGA_MAJOR_MODE_OFF: // ## FPGA Control\r
6658905f 671 FpgaWriteConfWord(FPGA_MAJOR_MODE_OFF);\r
672 SpinDelay(200);\r
0e25ae11 673 LED_D_OFF(); // LED D indicates field ON or OFF\r
6658905f 674 break;\r
675\r
676 case CMD_DOWNLOAD_RAW_ADC_SAMPLES_125K:\r
677 case CMD_DOWNLOAD_RAW_BITS_TI_TYPE: {\r
678 UsbCommand n;\r
679 if(c->cmd == CMD_DOWNLOAD_RAW_ADC_SAMPLES_125K) {\r
680 n.cmd = CMD_DOWNLOADED_RAW_ADC_SAMPLES_125K;\r
681 } else {\r
682 n.cmd = CMD_DOWNLOADED_RAW_BITS_TI_TYPE;\r
683 }\r
684 n.ext1 = c->ext1;\r
685 memcpy(n.d.asDwords, BigBuf+c->ext1, 12*sizeof(DWORD));\r
686 UsbSendPacket((BYTE *)&n, sizeof(n));\r
687 break;\r
688 }\r
689 case CMD_DOWNLOADED_SIM_SAMPLES_125K: {\r
690 BYTE *b = (BYTE *)BigBuf;\r
691 memcpy(b+c->ext1, c->d.asBytes, 48);\r
692 break;\r
693 }\r
694 case CMD_SIMULATE_TAG_125K:\r
695 LED_A_ON();\r
696 SimulateTagLowFrequency(c->ext1);\r
697 LED_A_OFF();\r
698 break;\r
aa4d9d9b 699#ifdef WITH_LCD\r
6658905f 700 case CMD_LCD_RESET:\r
701 LCDReset();\r
702 break;\r
aa4d9d9b 703#endif\r
30f2a7d3 704 case CMD_SWEEP_LF:\r
705 SweepLFrange();\r
706 break;\r
707\r
708 case CMD_SET_LF_DIVISOR:\r
709 FpgaSendCommand(FPGA_CMD_SET_DIVISOR, c->ext1);\r
710 break;\r
aa4d9d9b 711#ifdef WITH_LCD\r
6658905f 712 case CMD_LCD:\r
713 LCDSend(c->ext1);\r
714 break;\r
aa4d9d9b 715#endif\r
6658905f 716 case CMD_SETUP_WRITE:\r
717 case CMD_FINISH_WRITE:\r
d722c4ce 718 case CMD_HARDWARE_RESET:\r
6658905f 719 USB_D_PLUS_PULLUP_OFF();\r
720 SpinDelay(1000);\r
721 SpinDelay(1000);\r
722 RSTC_CONTROL = RST_CONTROL_KEY | RST_CONTROL_PROCESSOR_RESET;\r
723 for(;;) {\r
724 // We're going to reset, and the bootrom will take control.\r
725 }\r
726 break;\r
727\r
d722c4ce 728\r
6658905f 729 default:\r
730 DbpString("unknown command");\r
731 break;\r
732 }\r
733}\r
734\r
735void AppMain(void)\r
736{\r
737 memset(BigBuf,0,sizeof(BigBuf));\r
738 SpinDelay(100);\r
739\r
740 LED_D_OFF();\r
741 LED_C_OFF();\r
742 LED_B_OFF();\r
743 LED_A_OFF();\r
744\r
745 UsbStart();\r
746\r
747 // The FPGA gets its clock from us from PCK0 output, so set that up.\r
748 PIO_PERIPHERAL_B_SEL = (1 << GPIO_PCK0);\r
749 PIO_DISABLE = (1 << GPIO_PCK0);\r
750 PMC_SYS_CLK_ENABLE = PMC_SYS_CLK_PROGRAMMABLE_CLK_0;\r
751 // PCK0 is PLL clock / 4 = 96Mhz / 4 = 24Mhz\r
752 PMC_PROGRAMMABLE_CLK_0 = PMC_CLK_SELECTION_PLL_CLOCK |\r
753 PMC_CLK_PRESCALE_DIV_4;\r
754 PIO_OUTPUT_ENABLE = (1 << GPIO_PCK0);\r
755\r
756 // Reset SPI\r
757 SPI_CONTROL = SPI_CONTROL_RESET;\r
758 // Reset SSC\r
759 SSC_CONTROL = SSC_CONTROL_RESET;\r
760\r
761 // Load the FPGA image, which we have stored in our flash.\r
762 FpgaDownloadAndGo();\r
763\r
aa4d9d9b 764#ifdef WITH_LCD\r
765\r
6658905f 766 LCDInit();\r
767\r
768 // test text on different colored backgrounds\r
769 LCDString(" The quick brown fox ", &FONT6x8,1,1+8*0,WHITE ,BLACK );\r
770 LCDString(" jumped over the ", &FONT6x8,1,1+8*1,BLACK ,WHITE );\r
771 LCDString(" lazy dog. ", &FONT6x8,1,1+8*2,YELLOW ,RED );\r
772 LCDString(" AaBbCcDdEeFfGgHhIiJj ", &FONT6x8,1,1+8*3,RED ,GREEN );\r
773 LCDString(" KkLlMmNnOoPpQqRrSsTt ", &FONT6x8,1,1+8*4,MAGENTA,BLUE );\r
774 LCDString("UuVvWwXxYyZz0123456789", &FONT6x8,1,1+8*5,BLUE ,YELLOW);\r
775 LCDString("`-=[]_;',./~!@#$%^&*()", &FONT6x8,1,1+8*6,BLACK ,CYAN );\r
776 LCDString(" _+{}|:\\\"<>? ",&FONT6x8,1,1+8*7,BLUE ,MAGENTA);\r
777\r
778 // color bands\r
779 LCDFill(0, 1+8* 8, 132, 8, BLACK);\r
780 LCDFill(0, 1+8* 9, 132, 8, WHITE);\r
781 LCDFill(0, 1+8*10, 132, 8, RED);\r
782 LCDFill(0, 1+8*11, 132, 8, GREEN);\r
783 LCDFill(0, 1+8*12, 132, 8, BLUE);\r
784 LCDFill(0, 1+8*13, 132, 8, YELLOW);\r
785 LCDFill(0, 1+8*14, 132, 8, CYAN);\r
786 LCDFill(0, 1+8*15, 132, 8, MAGENTA);\r
787\r
aa4d9d9b 788#endif\r
789\r
6658905f 790 for(;;) {\r
791 UsbPoll(FALSE);\r
792 WDT_HIT();\r
793 }\r
794}\r
795\r
796void SpinDelay(int ms)\r
797{\r
798 int ticks = (48000*ms) >> 10;\r
799\r
800 // Borrow a PWM unit for my real-time clock\r
801 PWM_ENABLE = PWM_CHANNEL(0);\r
802 // 48 MHz / 1024 gives 46.875 kHz\r
803 PWM_CH_MODE(0) = PWM_CH_MODE_PRESCALER(10);\r
804 PWM_CH_DUTY_CYCLE(0) = 0;\r
805 PWM_CH_PERIOD(0) = 0xffff;\r
806\r
807 WORD start = (WORD)PWM_CH_COUNTER(0);\r
808\r
809 for(;;) {\r
810 WORD now = (WORD)PWM_CH_COUNTER(0);\r
811 if(now == (WORD)(start + ticks)) {\r
812 return;\r
813 }\r
814 WDT_HIT();\r
815 }\r
816}\r
Impressum, Datenschutz