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