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