]> git.zerfleddert.de Git - proxmark3-svn/blame - armsrc/appmain.c
Client cleanup and restructuring. Stage 1...
[proxmark3-svn] / armsrc / appmain.c
CommitLineData
6949aca9 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
7\r
8#include <proxmark3.h>\r
9#include <stdlib.h>\r
10#include "apps.h"\r
a7247d85 11#include "legicrf.h"\r
6949aca9 12#ifdef WITH_LCD\r
13#include "fonts.h"\r
14#include "LCD.h"\r
15#endif\r
16\r
a9bc033b 17#define va_list __builtin_va_list\r
18#define va_start __builtin_va_start\r
19#define va_arg __builtin_va_arg\r
20#define va_end __builtin_va_end\r
21int kvsprintf(char const *fmt, void *arg, int radix, va_list ap);\r
22 \r
6949aca9 23//=============================================================================\r
24// A buffer where we can queue things up to be sent through the FPGA, for\r
25// any purpose (fake tag, as reader, whatever). We go MSB first, since that\r
26// is the order in which they go out on the wire.\r
27//=============================================================================\r
28\r
13a79da4 29BYTE ToSend[512];\r
6949aca9 30int ToSendMax;\r
31static int ToSendBit;\r
32struct common_area common_area __attribute__((section(".commonarea")));\r
33\r
34void BufferClear(void)\r
35{\r
36 memset(BigBuf,0,sizeof(BigBuf));\r
13a79da4 37 Dbprintf("Buffer cleared (%i bytes)",sizeof(BigBuf));\r
6949aca9 38}\r
39\r
40void ToSendReset(void)\r
41{\r
42 ToSendMax = -1;\r
43 ToSendBit = 8;\r
44}\r
45\r
46void ToSendStuffBit(int b)\r
47{\r
48 if(ToSendBit >= 8) {\r
49 ToSendMax++;\r
50 ToSend[ToSendMax] = 0;\r
51 ToSendBit = 0;\r
52 }\r
53\r
54 if(b) {\r
55 ToSend[ToSendMax] |= (1 << (7 - ToSendBit));\r
56 }\r
57\r
58 ToSendBit++;\r
59\r
60 if(ToSendBit >= sizeof(ToSend)) {\r
61 ToSendBit = 0;\r
62 DbpString("ToSendStuffBit overflowed!");\r
63 }\r
64}\r
65\r
66//=============================================================================\r
67// Debug print functions, to go out over USB, to the usual PC-side client.\r
68//=============================================================================\r
69\r
70void DbpString(char *str)\r
71{\r
72 /* this holds up stuff unless we're connected to usb */\r
73 if (!UsbConnected())\r
74 return;\r
75\r
76 UsbCommand c;\r
77 c.cmd = CMD_DEBUG_PRINT_STRING;\r
1dea88f9 78 c.arg[0] = strlen(str);\r
79 memcpy(c.d.asBytes, str, c.arg[0]);\r
6949aca9 80\r
81 UsbSendPacket((BYTE *)&c, sizeof(c));\r
82 // TODO fix USB so stupid things like this aren't req'd\r
83 SpinDelay(50);\r
84}\r
85\r
850427c8 86#if 0\r
6949aca9 87void DbpIntegers(int x1, int x2, int x3)\r
88{\r
89 /* this holds up stuff unless we're connected to usb */\r
90 if (!UsbConnected())\r
91 return;\r
92\r
93 UsbCommand c;\r
94 c.cmd = CMD_DEBUG_PRINT_INTEGERS;\r
1dea88f9 95 c.arg[0] = x1;\r
96 c.arg[1] = x2;\r
97 c.arg[2] = x3;\r
6949aca9 98\r
99 UsbSendPacket((BYTE *)&c, sizeof(c));\r
100 // XXX\r
101 SpinDelay(50);\r
102}\r
850427c8 103#endif\r
6949aca9 104\r
a9bc033b 105void Dbprintf(const char *fmt, ...) {\r
106// should probably limit size here; oh well, let's just use a big buffer\r
107 char output_string[128];\r
108 va_list ap;\r
109\r
110 va_start(ap, fmt);\r
111 kvsprintf(fmt, output_string, 10, ap);\r
112 va_end(ap);\r
113 \r
114 DbpString(output_string);\r
115}\r
116\r
6949aca9 117//-----------------------------------------------------------------------------\r
118// Read an ADC channel and block till it completes, then return the result\r
119// in ADC units (0 to 1023). Also a routine to average 32 samples and\r
120// return that.\r
121//-----------------------------------------------------------------------------\r
122static int ReadAdc(int ch)\r
123{\r
124 DWORD d;\r
125\r
126 AT91C_BASE_ADC->ADC_CR = AT91C_ADC_SWRST;\r
127 AT91C_BASE_ADC->ADC_MR =\r
128 ADC_MODE_PRESCALE(32) |\r
129 ADC_MODE_STARTUP_TIME(16) |\r
130 ADC_MODE_SAMPLE_HOLD_TIME(8);\r
131 AT91C_BASE_ADC->ADC_CHER = ADC_CHANNEL(ch);\r
132\r
133 AT91C_BASE_ADC->ADC_CR = AT91C_ADC_START;\r
134 while(!(AT91C_BASE_ADC->ADC_SR & ADC_END_OF_CONVERSION(ch)))\r
135 ;\r
136 d = AT91C_BASE_ADC->ADC_CDR[ch];\r
137\r
138 return d;\r
139}\r
140\r
141static int AvgAdc(int ch)\r
142{\r
143 int i;\r
144 int a = 0;\r
145\r
146 for(i = 0; i < 32; i++) {\r
147 a += ReadAdc(ch);\r
148 }\r
149\r
150 return (a + 15) >> 5;\r
151}\r
152\r
153void MeasureAntennaTuning(void)\r
154{\r
155 BYTE *dest = (BYTE *)BigBuf;\r
156 int i, ptr = 0, adcval = 0, peak = 0, peakv = 0, peakf = 0;;\r
157 int vLf125 = 0, vLf134 = 0, vHf = 0; // in mV\r
158\r
159 UsbCommand c;\r
160\r
161 DbpString("Measuring antenna characteristics, please wait.");\r
162 memset(BigBuf,0,sizeof(BigBuf));\r
163\r
164/*\r
165 * Sweeps the useful LF range of the proxmark from\r
166 * 46.8kHz (divisor=255) to 600kHz (divisor=19) and\r
167 * read the voltage in the antenna, the result left\r
168 * in the buffer is a graph which should clearly show\r
169 * the resonating frequency of your LF antenna\r
170 * ( hopefully around 95 if it is tuned to 125kHz!)\r
171 */\r
172 FpgaWriteConfWord(FPGA_MAJOR_MODE_LF_READER);\r
173 for (i=255; i>19; i--) {\r
174 FpgaSendCommand(FPGA_CMD_SET_DIVISOR, i);\r
175 SpinDelay(20);\r
176 // Vref = 3.3V, and a 10000:240 voltage divider on the input\r
177 // can measure voltages up to 137500 mV\r
178 adcval = ((137500 * AvgAdc(ADC_CHAN_LF)) >> 10);\r
179 if (i==95) vLf125 = adcval; // voltage at 125Khz\r
180 if (i==89) vLf134 = adcval; // voltage at 134Khz\r
181\r
182 dest[i] = adcval>>8; // scale int to fit in byte for graphing purposes\r
183 if(dest[i] > peak) {\r
184 peakv = adcval;\r
185 peak = dest[i];\r
186 peakf = i;\r
187 ptr = i;\r
188 }\r
189 }\r
190\r
191 // Let the FPGA drive the high-frequency antenna around 13.56 MHz.\r
192 FpgaWriteConfWord(FPGA_MAJOR_MODE_HF_READER_RX_XCORR);\r
193 SpinDelay(20);\r
194 // Vref = 3300mV, and an 10:1 voltage divider on the input\r
195 // can measure voltages up to 33000 mV\r
196 vHf = (33000 * AvgAdc(ADC_CHAN_HF)) >> 10;\r
197\r
198 c.cmd = CMD_MEASURED_ANTENNA_TUNING;\r
1dea88f9 199 c.arg[0] = (vLf125 << 0) | (vLf134 << 16);\r
200 c.arg[1] = vHf;\r
201 c.arg[2] = peakf | (peakv << 16);\r
6949aca9 202 UsbSendPacket((BYTE *)&c, sizeof(c));\r
203}\r
204\r
1eb7596a 205void MeasureAntennaTuningHf(void)\r
206{\r
207 int vHf = 0; // in mV\r
208\r
d7246149 209 DbpString("Measuring HF antenna, press button to exit");\r
1eb7596a 210\r
211 for (;;) {\r
212 // Let the FPGA drive the high-frequency antenna around 13.56 MHz.\r
213 FpgaWriteConfWord(FPGA_MAJOR_MODE_HF_READER_RX_XCORR);\r
214 SpinDelay(20);\r
215 // Vref = 3300mV, and an 10:1 voltage divider on the input\r
216 // can measure voltages up to 33000 mV\r
217 vHf = (33000 * AvgAdc(ADC_CHAN_HF)) >> 10;\r
218 \r
219 Dbprintf("%d mV",vHf);\r
220 if (BUTTON_PRESS()) break;\r
221 }\r
222 DbpString("cancelled");\r
223}\r
224\r
225\r
6949aca9 226void SimulateTagHfListen(void)\r
227{\r
228 BYTE *dest = (BYTE *)BigBuf;\r
229 int n = sizeof(BigBuf);\r
230 BYTE v = 0;\r
231 int i;\r
232 int p = 0;\r
233\r
234 // We're using this mode just so that I can test it out; the simulated\r
235 // tag mode would work just as well and be simpler.\r
236 FpgaWriteConfWord(FPGA_MAJOR_MODE_HF_READER_RX_XCORR | FPGA_HF_READER_RX_XCORR_848_KHZ | FPGA_HF_READER_RX_XCORR_SNOOP);\r
237\r
238 // We need to listen to the high-frequency, peak-detected path.\r
239 SetAdcMuxFor(GPIO_MUXSEL_HIPKD);\r
240\r
241 FpgaSetupSsc();\r
242\r
243 i = 0;\r
244 for(;;) {\r
245 if(AT91C_BASE_SSC->SSC_SR & (AT91C_SSC_TXRDY)) {\r
246 AT91C_BASE_SSC->SSC_THR = 0xff;\r
247 }\r
248 if(AT91C_BASE_SSC->SSC_SR & (AT91C_SSC_RXRDY)) {\r
249 BYTE r = (BYTE)AT91C_BASE_SSC->SSC_RHR;\r
250\r
251 v <<= 1;\r
252 if(r & 1) {\r
253 v |= 1;\r
254 }\r
255 p++;\r
256\r
257 if(p >= 8) {\r
258 dest[i] = v;\r
259 v = 0;\r
260 p = 0;\r
261 i++;\r
262\r
263 if(i >= n) {\r
264 break;\r
265 }\r
266 }\r
267 }\r
268 }\r
269 DbpString("simulate tag (now type bitsamples)");\r
270}\r
271\r
272void ReadMem(int addr)\r
273{\r
815f3f25 274 const BYTE *data = ((BYTE *)addr);\r
6949aca9 275\r
1e1b3030 276 Dbprintf("%x: %02x %02x %02x %02x %02x %02x %02x %02x",\r
850427c8 277 addr, data[0], data[1], data[2], data[3], data[4], data[5], data[6], data[7]);\r
6949aca9 278}\r
279\r
280/* osimage version information is linked in */\r
281extern struct version_information version_information;\r
282/* bootrom version information is pointed to from _bootphase1_version_pointer */\r
283extern char *_bootphase1_version_pointer, _flash_start, _flash_end;\r
284void SendVersion(void)\r
285{\r
286 char temp[48]; /* Limited data payload in USB packets */\r
287 DbpString("Prox/RFID mark3 RFID instrument");\r
288 \r
289 /* Try to find the bootrom version information. Expect to find a pointer at \r
290 * symbol _bootphase1_version_pointer, perform slight sanity checks on the\r
291 * pointer, then use it.\r
292 */\r
293 char *bootrom_version = *(char**)&_bootphase1_version_pointer;\r
294 if( bootrom_version < &_flash_start || bootrom_version >= &_flash_end ) {\r
295 DbpString("bootrom version information appears invalid");\r
296 } else {\r
297 FormatVersionInformation(temp, sizeof(temp), "bootrom: ", bootrom_version);\r
298 DbpString(temp);\r
299 }\r
300 \r
301 FormatVersionInformation(temp, sizeof(temp), "os: ", &version_information);\r
302 DbpString(temp);\r
303 \r
304 FpgaGatherVersion(temp, sizeof(temp));\r
305 DbpString(temp);\r
306}\r
307\r
e7014022 308#ifdef WITH_LF\r
6949aca9 309// samy's sniff and repeat routine\r
310void SamyRun()\r
311{\r
312 DbpString("Stand-alone mode! No PC necessary.");\r
313\r
314 // 3 possible options? no just 2 for now\r
315#define OPTS 2\r
316\r
317 int high[OPTS], low[OPTS];\r
318\r
319 // Oooh pretty -- notify user we're in elite samy mode now\r
320 LED(LED_RED, 200);\r
321 LED(LED_ORANGE, 200);\r
322 LED(LED_GREEN, 200);\r
323 LED(LED_ORANGE, 200);\r
324 LED(LED_RED, 200);\r
325 LED(LED_ORANGE, 200);\r
326 LED(LED_GREEN, 200);\r
327 LED(LED_ORANGE, 200);\r
328 LED(LED_RED, 200);\r
329\r
330 int selected = 0;\r
331 int playing = 0;\r
332\r
333 // Turn on selected LED\r
334 LED(selected + 1, 0);\r
335\r
336 for (;;)\r
337 {\r
338 UsbPoll(FALSE);\r
339 WDT_HIT();\r
340\r
341 // Was our button held down or pressed?\r
342 int button_pressed = BUTTON_HELD(1000);\r
343 SpinDelay(300);\r
344\r
345 // Button was held for a second, begin recording\r
346 if (button_pressed > 0)\r
347 {\r
348 LEDsoff();\r
349 LED(selected + 1, 0);\r
350 LED(LED_RED2, 0);\r
351\r
352 // record\r
353 DbpString("Starting recording");\r
354\r
355 // wait for button to be released\r
356 while(BUTTON_PRESS())\r
357 WDT_HIT();\r
358\r
359 /* need this delay to prevent catching some weird data */\r
360 SpinDelay(500);\r
361\r
362 CmdHIDdemodFSK(1, &high[selected], &low[selected], 0);\r
850427c8 363 Dbprintf("Recorded %x %x %x", selected, high[selected], low[selected]);\r
6949aca9 364\r
365 LEDsoff();\r
366 LED(selected + 1, 0);\r
367 // Finished recording\r
368\r
369 // If we were previously playing, set playing off\r
370 // so next button push begins playing what we recorded\r
371 playing = 0;\r
372 }\r
373\r
374 // Change where to record (or begin playing)\r
375 else if (button_pressed)\r
376 {\r
377 // Next option if we were previously playing\r
378 if (playing)\r
379 selected = (selected + 1) % OPTS;\r
380 playing = !playing;\r
381\r
382 LEDsoff();\r
383 LED(selected + 1, 0);\r
384\r
385 // Begin transmitting\r
386 if (playing)\r
387 {\r
388 LED(LED_GREEN, 0);\r
389 DbpString("Playing");\r
390 // wait for button to be released\r
391 while(BUTTON_PRESS())\r
392 WDT_HIT();\r
850427c8 393 Dbprintf("%x %x %x", selected, high[selected], low[selected]);\r
6949aca9 394 CmdHIDsimTAG(high[selected], low[selected], 0);\r
395 DbpString("Done playing");\r
396 if (BUTTON_HELD(1000) > 0)\r
397 {\r
398 DbpString("Exiting");\r
399 LEDsoff();\r
400 return;\r
401 }\r
402\r
403 /* We pressed a button so ignore it here with a delay */\r
404 SpinDelay(300);\r
405\r
406 // when done, we're done playing, move to next option\r
407 selected = (selected + 1) % OPTS;\r
408 playing = !playing;\r
409 LEDsoff();\r
410 LED(selected + 1, 0);\r
411 }\r
412 else\r
413 while(BUTTON_PRESS())\r
414 WDT_HIT();\r
415 }\r
416 }\r
417}\r
c0d04e95 418#endif\r
6949aca9 419\r
420/*\r
421OBJECTIVE\r
422Listen and detect an external reader. Determine the best location\r
423for the antenna.\r
424\r
425INSTRUCTIONS:\r
426Inside the ListenReaderField() function, there is two mode.\r
427By default, when you call the function, you will enter mode 1.\r
428If you press the PM3 button one time, you will enter mode 2.\r
429If you press the PM3 button a second time, you will exit the function.\r
430\r
431DESCRIPTION OF MODE 1:\r
432This mode just listens for an external reader field and lights up green\r
433for HF and/or red for LF. This is the original mode of the detectreader\r
434function.\r
435\r
436DESCRIPTION OF MODE 2:\r
437This mode will visually represent, using the LEDs, the actual strength of the\r
438current compared to the maximum current detected. Basically, once you know\r
439what kind of external reader is present, it will help you spot the best location to place\r
440your antenna. You will probably not get some good results if there is a LF and a HF reader\r
441at the same place! :-)\r
442\r
443LIGHT SCHEME USED:\r
444*/\r
445static const char LIGHT_SCHEME[] = {\r
446 0x0, /* ---- | No field detected */\r
447 0x1, /* X--- | 14% of maximum current detected */\r
448 0x2, /* -X-- | 29% of maximum current detected */\r
449 0x4, /* --X- | 43% of maximum current detected */\r
450 0x8, /* ---X | 57% of maximum current detected */\r
451 0xC, /* --XX | 71% of maximum current detected */\r
452 0xE, /* -XXX | 86% of maximum current detected */\r
453 0xF, /* XXXX | 100% of maximum current detected */\r
454};\r
455static const int LIGHT_LEN = sizeof(LIGHT_SCHEME)/sizeof(LIGHT_SCHEME[0]);\r
456\r
457void ListenReaderField(int limit)\r
458{\r
459 int lf_av, lf_av_new, lf_baseline= 0, lf_count= 0, lf_max;\r
460 int hf_av, hf_av_new, hf_baseline= 0, hf_count= 0, hf_max;\r
461 int mode=1, display_val, display_max, i;\r
462\r
463#define LF_ONLY 1\r
464#define HF_ONLY 2\r
465\r
466 LEDsoff();\r
467\r
468 lf_av=lf_max=ReadAdc(ADC_CHAN_LF);\r
469\r
470 if(limit != HF_ONLY) {\r
850427c8 471 Dbprintf("LF 125/134 Baseline: %d", lf_av);\r
472 lf_baseline = lf_av;\r
6949aca9 473 }\r
474\r
475 hf_av=hf_max=ReadAdc(ADC_CHAN_HF);\r
476\r
477 if (limit != LF_ONLY) {\r
850427c8 478 Dbprintf("HF 13.56 Baseline: %d", hf_av);\r
479 hf_baseline = hf_av;\r
6949aca9 480 }\r
481\r
482 for(;;) {\r
483 if (BUTTON_PRESS()) {\r
484 SpinDelay(500);\r
485 switch (mode) {\r
486 case 1:\r
487 mode=2;\r
488 DbpString("Signal Strength Mode");\r
489 break;\r
490 case 2:\r
491 default:\r
492 DbpString("Stopped");\r
493 LEDsoff();\r
494 return;\r
495 break;\r
496 }\r
497 }\r
498 WDT_HIT();\r
499\r
500 if (limit != HF_ONLY) {\r
501 if(mode==1) {\r
502 if (abs(lf_av - lf_baseline) > 10) LED_D_ON();\r
503 else LED_D_OFF();\r
504 }\r
505 \r
506 ++lf_count;\r
507 lf_av_new= ReadAdc(ADC_CHAN_LF);\r
508 // see if there's a significant change\r
509 if(abs(lf_av - lf_av_new) > 10) {\r
850427c8 510 Dbprintf("LF 125/134 Field Change: %x %x %x", lf_av, lf_av_new, lf_count);\r
511 lf_av = lf_av_new;\r
6949aca9 512 if (lf_av > lf_max)\r
513 lf_max = lf_av;\r
514 lf_count= 0;\r
515 }\r
516 }\r
517\r
518 if (limit != LF_ONLY) {\r
519 if (mode == 1){\r
520 if (abs(hf_av - hf_baseline) > 10) LED_B_ON();\r
521 else LED_B_OFF();\r
522 }\r
523 \r
524 ++hf_count;\r
525 hf_av_new= ReadAdc(ADC_CHAN_HF);\r
526 // see if there's a significant change\r
527 if(abs(hf_av - hf_av_new) > 10) {\r
850427c8 528 Dbprintf("HF 13.56 Field Change: %x %x %x", hf_av, hf_av_new, hf_count);\r
529 hf_av = hf_av_new;\r
6949aca9 530 if (hf_av > hf_max)\r
531 hf_max = hf_av;\r
532 hf_count= 0;\r
533 }\r
534 }\r
535 \r
536 if(mode == 2) {\r
537 if (limit == LF_ONLY) {\r
538 display_val = lf_av;\r
539 display_max = lf_max;\r
540 } else if (limit == HF_ONLY) {\r
541 display_val = hf_av;\r
542 display_max = hf_max;\r
543 } else { /* Pick one at random */\r
544 if( (hf_max - hf_baseline) > (lf_max - lf_baseline) ) {\r
545 display_val = hf_av;\r
546 display_max = hf_max;\r
547 } else {\r
548 display_val = lf_av;\r
549 display_max = lf_max;\r
550 }\r
551 }\r
552 for (i=0; i<LIGHT_LEN; i++) {\r
553 if (display_val >= ((display_max/LIGHT_LEN)*i) && display_val <= ((display_max/LIGHT_LEN)*(i+1))) {\r
554 if (LIGHT_SCHEME[i] & 0x1) LED_C_ON(); else LED_C_OFF();\r
555 if (LIGHT_SCHEME[i] & 0x2) LED_A_ON(); else LED_A_OFF();\r
556 if (LIGHT_SCHEME[i] & 0x4) LED_B_ON(); else LED_B_OFF();\r
557 if (LIGHT_SCHEME[i] & 0x8) LED_D_ON(); else LED_D_OFF();\r
558 break;\r
559 }\r
560 }\r
561 }\r
562 }\r
563}\r
564\r
565void UsbPacketReceived(BYTE *packet, int len)\r
566{\r
567 UsbCommand *c = (UsbCommand *)packet;\r
568\r
569 switch(c->cmd) {\r
e7014022 570#ifdef WITH_LF\r
6949aca9 571 case CMD_ACQUIRE_RAW_ADC_SAMPLES_125K:\r
1dea88f9 572 AcquireRawAdcSamples125k(c->arg[0]);\r
6949aca9 573 break;\r
c0d04e95 574#endif\r
6949aca9 575\r
e7014022 576#ifdef WITH_LF\r
6949aca9 577 case CMD_MOD_THEN_ACQUIRE_RAW_ADC_SAMPLES_125K:\r
1dea88f9 578 ModThenAcquireRawAdcSamples125k(c->arg[0],c->arg[1],c->arg[2],c->d.asBytes);\r
6949aca9 579 break;\r
c0d04e95 580#endif\r
6949aca9 581\r
b1083ec9 582#ifdef WITH_ISO15693\r
6949aca9 583 case CMD_ACQUIRE_RAW_ADC_SAMPLES_ISO_15693:\r
584 AcquireRawAdcSamplesIso15693();\r
585 break;\r
b1083ec9 586#endif\r
6949aca9 587\r
588 case CMD_BUFF_CLEAR:\r
589 BufferClear();\r
590 break;\r
591\r
b1083ec9 592#ifdef WITH_ISO15693\r
6949aca9 593 case CMD_READER_ISO_15693:\r
1dea88f9 594 ReaderIso15693(c->arg[0]);\r
6949aca9 595 break;\r
b1083ec9 596#endif\r
6949aca9 597\r
dcc10e5e 598 case CMD_READER_LEGIC_RF:\r
599 LegicRfReader();\r
600 break;\r
601\r
b1083ec9 602#ifdef WITH_ISO15693\r
6949aca9 603 case CMD_SIMTAG_ISO_15693:\r
1dea88f9 604 SimTagIso15693(c->arg[0]);\r
6949aca9 605 break;\r
b1083ec9 606#endif\r
6949aca9 607\r
b1083ec9 608#ifdef WITH_ISO14443b\r
6949aca9 609 case CMD_ACQUIRE_RAW_ADC_SAMPLES_ISO_14443:\r
1dea88f9 610 AcquireRawAdcSamplesIso14443(c->arg[0]);\r
6949aca9 611 break;\r
b1083ec9 612#endif\r
6949aca9 613\r
b1083ec9 614#ifdef WITH_ISO14443b\r
6949aca9 615 case CMD_READ_SRI512_TAG:\r
1dea88f9 616 ReadSRI512Iso14443(c->arg[0]);\r
6949aca9 617 break;\r
1dea88f9 618 case CMD_READ_SRIX4K_TAG:\r
619 ReadSRIX4KIso14443(c->arg[0]);\r
620 break;\r
b1083ec9 621#endif\r
6949aca9 622\r
b1083ec9 623#ifdef WITH_ISO14443a\r
6949aca9 624 case CMD_READER_ISO_14443a:\r
1dea88f9 625 ReaderIso14443a(c->arg[0]);\r
6949aca9 626 break;\r
b1083ec9 627#endif\r
6949aca9 628\r
32cfae43 629#ifdef WITH_ISO14443a\r
630 case CMD_READER_MIFARE:\r
631 ReaderMifare(c->arg[0]);\r
632 break;\r
633#endif\r
634 \r
b1083ec9 635#ifdef WITH_ISO14443b\r
6949aca9 636 case CMD_SNOOP_ISO_14443:\r
637 SnoopIso14443();\r
638 break;\r
b1083ec9 639#endif\r
6949aca9 640\r
b1083ec9 641#ifdef WITH_ISO14443a\r
6949aca9 642 case CMD_SNOOP_ISO_14443a:\r
643 SnoopIso14443a();\r
644 break;\r
b1083ec9 645#endif\r
6949aca9 646\r
647 case CMD_SIMULATE_TAG_HF_LISTEN:\r
648 SimulateTagHfListen();\r
649 break;\r
650\r
b1083ec9 651#ifdef WITH_ISO14443b\r
6949aca9 652 case CMD_SIMULATE_TAG_ISO_14443:\r
653 SimulateIso14443Tag();\r
654 break;\r
b1083ec9 655#endif\r
a7247d85 656 \r
b1083ec9 657#ifdef WITH_ISO14443a\r
6949aca9 658 case CMD_SIMULATE_TAG_ISO_14443a:\r
1dea88f9 659 SimulateIso14443aTag(c->arg[0], c->arg[1]); // ## Simulate iso14443a tag - pass tag type & UID\r
6949aca9 660 break;\r
b1083ec9 661#endif\r
6949aca9 662\r
663 case CMD_MEASURE_ANTENNA_TUNING:\r
664 MeasureAntennaTuning();\r
665 break;\r
666\r
1eb7596a 667 case CMD_MEASURE_ANTENNA_TUNING_HF:\r
668 MeasureAntennaTuningHf();\r
669 break;\r
670\r
6949aca9 671 case CMD_LISTEN_READER_FIELD:\r
1dea88f9 672 ListenReaderField(c->arg[0]);\r
6949aca9 673 break;\r
674\r
e7014022 675#ifdef WITH_LF\r
6949aca9 676 case CMD_HID_DEMOD_FSK:\r
677 CmdHIDdemodFSK(0, 0, 0, 1); // Demodulate HID tag\r
678 break;\r
c0d04e95 679#endif\r
6949aca9 680\r
e7014022 681#ifdef WITH_LF\r
6949aca9 682 case CMD_HID_SIM_TAG:\r
1dea88f9 683 CmdHIDsimTAG(c->arg[0], c->arg[1], 1); // Simulate HID tag by ID\r
6949aca9 684 break;\r
c0d04e95 685#endif\r
6949aca9 686\r
687 case CMD_FPGA_MAJOR_MODE_OFF: // ## FPGA Control\r
688 FpgaWriteConfWord(FPGA_MAJOR_MODE_OFF);\r
689 SpinDelay(200);\r
690 LED_D_OFF(); // LED D indicates field ON or OFF\r
691 break;\r
692\r
e7014022 693#ifdef WITH_LF\r
6949aca9 694 case CMD_READ_TI_TYPE:\r
695 ReadTItag();\r
696 break;\r
c0d04e95 697#endif\r
6949aca9 698\r
e7014022 699#ifdef WITH_LF\r
6949aca9 700 case CMD_WRITE_TI_TYPE:\r
1dea88f9 701 WriteTItag(c->arg[0],c->arg[1],c->arg[2]);\r
6949aca9 702 break;\r
c0d04e95 703#endif\r
6949aca9 704\r
705 case CMD_DOWNLOAD_RAW_ADC_SAMPLES_125K: {\r
706 UsbCommand n;\r
707 if(c->cmd == CMD_DOWNLOAD_RAW_ADC_SAMPLES_125K) {\r
708 n.cmd = CMD_DOWNLOADED_RAW_ADC_SAMPLES_125K;\r
709 } else {\r
710 n.cmd = CMD_DOWNLOADED_RAW_BITS_TI_TYPE;\r
711 }\r
1dea88f9 712 n.arg[0] = c->arg[0];\r
713 memcpy(n.d.asDwords, BigBuf+c->arg[0], 12*sizeof(DWORD));\r
6949aca9 714 UsbSendPacket((BYTE *)&n, sizeof(n));\r
715 break;\r
716 }\r
c0d04e95 717\r
6949aca9 718 case CMD_DOWNLOADED_SIM_SAMPLES_125K: {\r
6982ac26 719 UsbCommand ack;\r
6949aca9 720 BYTE *b = (BYTE *)BigBuf;\r
1dea88f9 721 memcpy(b+c->arg[0], c->d.asBytes, 48);\r
13a79da4 722 //Dbprintf("copied 48 bytes to %i",b+c->arg[0]);\r
6982ac26 723 ack.cmd = CMD_ACK;\r
724 UsbSendPacket((BYTE*)&ack, sizeof(ack));\r
6949aca9 725 break;\r
726 }\r
c0d04e95 727\r
e7014022 728#ifdef WITH_LF\r
6949aca9 729 case CMD_SIMULATE_TAG_125K:\r
730 LED_A_ON();\r
13a79da4 731 SimulateTagLowFrequency(c->arg[0], c->arg[1], 1);\r
6949aca9 732 LED_A_OFF();\r
733 break;\r
c0d04e95 734#endif\r
735\r
6949aca9 736 case CMD_READ_MEM:\r
1dea88f9 737 ReadMem(c->arg[0]);\r
6949aca9 738 break;\r
c0d04e95 739\r
6949aca9 740 case CMD_SET_LF_DIVISOR:\r
1dea88f9 741 FpgaSendCommand(FPGA_CMD_SET_DIVISOR, c->arg[0]);\r
6949aca9 742 break;\r
c0d04e95 743\r
5fc8250f 744 case CMD_SET_ADC_MUX:\r
1dea88f9 745 switch(c->arg[0]) {\r
c0d04e95 746 case 0: SetAdcMuxFor(GPIO_MUXSEL_LOPKD); break;\r
747 case 1: SetAdcMuxFor(GPIO_MUXSEL_LORAW); break;\r
748 case 2: SetAdcMuxFor(GPIO_MUXSEL_HIPKD); break;\r
749 case 3: SetAdcMuxFor(GPIO_MUXSEL_HIRAW); break;\r
5fc8250f 750 }\r
751 break;\r
c0d04e95 752\r
6949aca9 753 case CMD_VERSION:\r
754 SendVersion();\r
755 break;\r
c0d04e95 756\r
e7014022 757#ifdef WITH_LF\r
6949aca9 758 case CMD_LF_SIMULATE_BIDIR:\r
1dea88f9 759 SimulateTagLowFrequencyBidir(c->arg[0], c->arg[1]);\r
6949aca9 760 break;\r
c0d04e95 761#endif\r
762\r
6949aca9 763#ifdef WITH_LCD\r
764 case CMD_LCD_RESET:\r
765 LCDReset();\r
766 break;\r
767 case CMD_LCD:\r
1dea88f9 768 LCDSend(c->arg[0]);\r
6949aca9 769 break;\r
770#endif\r
771 case CMD_SETUP_WRITE:\r
772 case CMD_FINISH_WRITE:\r
773 case CMD_HARDWARE_RESET:\r
774 USB_D_PLUS_PULLUP_OFF();\r
775 SpinDelay(1000);\r
776 SpinDelay(1000);\r
777 AT91C_BASE_RSTC->RSTC_RCR = RST_CONTROL_KEY | AT91C_RSTC_PROCRST;\r
778 for(;;) {\r
779 // We're going to reset, and the bootrom will take control.\r
780 }\r
781 break;\r
c0d04e95 782\r
6949aca9 783 case CMD_START_FLASH:\r
784 if(common_area.flags.bootrom_present) {\r
785 common_area.command = COMMON_AREA_COMMAND_ENTER_FLASH_MODE;\r
786 }\r
787 USB_D_PLUS_PULLUP_OFF();\r
788 AT91C_BASE_RSTC->RSTC_RCR = RST_CONTROL_KEY | AT91C_RSTC_PROCRST;\r
789 for(;;);\r
790 break;\r
791 \r
792 case CMD_DEVICE_INFO: {\r
793 UsbCommand c;\r
794 c.cmd = CMD_DEVICE_INFO;\r
1dea88f9 795 c.arg[0] = DEVICE_INFO_FLAG_OSIMAGE_PRESENT | DEVICE_INFO_FLAG_CURRENT_MODE_OS;\r
796 if(common_area.flags.bootrom_present) c.arg[0] |= DEVICE_INFO_FLAG_BOOTROM_PRESENT;\r
6949aca9 797 UsbSendPacket((BYTE*)&c, sizeof(c));\r
798 }\r
799 break;\r
800 default:\r
13a79da4 801 Dbprintf("%s: 0x%04x","unknown command:",c->cmd);\r
6949aca9 802 break;\r
803 }\r
804}\r
805\r
806void __attribute__((noreturn)) AppMain(void)\r
807{\r
808 SpinDelay(100);\r
809 \r
810 if(common_area.magic != COMMON_AREA_MAGIC || common_area.version != 1) {\r
811 /* Initialize common area */\r
812 memset(&common_area, 0, sizeof(common_area));\r
813 common_area.magic = COMMON_AREA_MAGIC;\r
814 common_area.version = 1;\r
815 }\r
816 common_area.flags.osimage_present = 1;\r
817\r
818 LED_D_OFF();\r
819 LED_C_OFF();\r
820 LED_B_OFF();\r
821 LED_A_OFF();\r
822\r
823 UsbStart();\r
824\r
825 // The FPGA gets its clock from us from PCK0 output, so set that up.\r
826 AT91C_BASE_PIOA->PIO_BSR = GPIO_PCK0;\r
827 AT91C_BASE_PIOA->PIO_PDR = GPIO_PCK0;\r
828 AT91C_BASE_PMC->PMC_SCER = AT91C_PMC_PCK0;\r
829 // PCK0 is PLL clock / 4 = 96Mhz / 4 = 24Mhz\r
830 AT91C_BASE_PMC->PMC_PCKR[0] = AT91C_PMC_CSS_PLL_CLK |\r
831 AT91C_PMC_PRES_CLK_4;\r
832 AT91C_BASE_PIOA->PIO_OER = GPIO_PCK0;\r
833\r
834 // Reset SPI\r
835 AT91C_BASE_SPI->SPI_CR = AT91C_SPI_SWRST;\r
836 // Reset SSC\r
837 AT91C_BASE_SSC->SSC_CR = AT91C_SSC_SWRST;\r
838\r
839 // Load the FPGA image, which we have stored in our flash.\r
840 FpgaDownloadAndGo();\r
841\r
842#ifdef WITH_LCD\r
843\r
844 LCDInit();\r
845\r
846 // test text on different colored backgrounds\r
847 LCDString(" The quick brown fox ", (char *)&FONT6x8,1,1+8*0,WHITE ,BLACK );\r
848 LCDString(" jumped over the ", (char *)&FONT6x8,1,1+8*1,BLACK ,WHITE );\r
849 LCDString(" lazy dog. ", (char *)&FONT6x8,1,1+8*2,YELLOW ,RED );\r
850 LCDString(" AaBbCcDdEeFfGgHhIiJj ", (char *)&FONT6x8,1,1+8*3,RED ,GREEN );\r
851 LCDString(" KkLlMmNnOoPpQqRrSsTt ", (char *)&FONT6x8,1,1+8*4,MAGENTA,BLUE );\r
852 LCDString("UuVvWwXxYyZz0123456789", (char *)&FONT6x8,1,1+8*5,BLUE ,YELLOW);\r
853 LCDString("`-=[]_;',./~!@#$%^&*()", (char *)&FONT6x8,1,1+8*6,BLACK ,CYAN );\r
854 LCDString(" _+{}|:\\\"<>? ",(char *)&FONT6x8,1,1+8*7,BLUE ,MAGENTA);\r
855\r
856 // color bands\r
857 LCDFill(0, 1+8* 8, 132, 8, BLACK);\r
858 LCDFill(0, 1+8* 9, 132, 8, WHITE);\r
859 LCDFill(0, 1+8*10, 132, 8, RED);\r
860 LCDFill(0, 1+8*11, 132, 8, GREEN);\r
861 LCDFill(0, 1+8*12, 132, 8, BLUE);\r
862 LCDFill(0, 1+8*13, 132, 8, YELLOW);\r
863 LCDFill(0, 1+8*14, 132, 8, CYAN);\r
864 LCDFill(0, 1+8*15, 132, 8, MAGENTA);\r
865\r
866#endif\r
867\r
868 for(;;) {\r
869 UsbPoll(FALSE);\r
870 WDT_HIT();\r
871\r
e7014022 872#ifdef WITH_LF\r
6949aca9 873 if (BUTTON_HELD(1000) > 0)\r
874 SamyRun();\r
c0d04e95 875#endif\r
6949aca9 876 }\r
877}\r
Impressum, Datenschutz