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