]> cvs.zerfleddert.de Git - proxmark3-svn/blame_incremental - armsrc/appmain.c
set svn:ignore
[proxmark3-svn] / armsrc / appmain.c
... / ...
CommitLineData
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
11#include "legicrf.h"\r
12#ifdef WITH_LCD\r
13#include "fonts.h"\r
14#include "LCD.h"\r
15#endif\r
16\r
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
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
78 c.arg[0] = strlen(str);\r
79 memcpy(c.d.asBytes, str, c.arg[0]);\r
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
86#if 0\r
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
95 c.arg[0] = x1;\r
96 c.arg[1] = x2;\r
97 c.arg[2] = x3;\r
98\r
99 UsbSendPacket((BYTE *)&c, sizeof(c));\r
100 // XXX\r
101 SpinDelay(50);\r
102}\r
103#endif\r
104\r
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
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
199 c.arg[0] = (vLf125 << 0) | (vLf134 << 16);\r
200 c.arg[1] = vHf;\r
201 c.arg[2] = peakf | (peakv << 16);\r
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
254\r
255 Dbprintf("%x: %02x %02x %02x %02x %02x %02x %02x %02x",\r
256 addr, data[0], data[1], data[2], data[3], data[4], data[5], data[6], data[7]);\r
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
287#ifdef WITH_LF\r
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
342 Dbprintf("Recorded %x %x %x", selected, high[selected], low[selected]);\r
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
372 Dbprintf("%x %x %x", selected, high[selected], low[selected]);\r
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
397#endif\r
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
450 Dbprintf("LF 125/134 Baseline: %d", lf_av);\r
451 lf_baseline = lf_av;\r
452 }\r
453\r
454 hf_av=hf_max=ReadAdc(ADC_CHAN_HF);\r
455\r
456 if (limit != LF_ONLY) {\r
457 Dbprintf("HF 13.56 Baseline: %d", hf_av);\r
458 hf_baseline = hf_av;\r
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
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
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
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
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
549#ifdef WITH_LF\r
550 case CMD_ACQUIRE_RAW_ADC_SAMPLES_125K:\r
551 AcquireRawAdcSamples125k(c->arg[0]);\r
552 break;\r
553#endif\r
554\r
555#ifdef WITH_LF\r
556 case CMD_MOD_THEN_ACQUIRE_RAW_ADC_SAMPLES_125K:\r
557 ModThenAcquireRawAdcSamples125k(c->arg[0],c->arg[1],c->arg[2],c->d.asBytes);\r
558 break;\r
559#endif\r
560\r
561#ifdef WITH_ISO15693\r
562 case CMD_ACQUIRE_RAW_ADC_SAMPLES_ISO_15693:\r
563 AcquireRawAdcSamplesIso15693();\r
564 break;\r
565#endif\r
566\r
567 case CMD_BUFF_CLEAR:\r
568 BufferClear();\r
569 break;\r
570\r
571#ifdef WITH_ISO15693\r
572 case CMD_READER_ISO_15693:\r
573 ReaderIso15693(c->arg[0]);\r
574 break;\r
575#endif\r
576\r
577 case CMD_READER_LEGIC_RF:\r
578 LegicRfReader();\r
579 break;\r
580\r
581#ifdef WITH_ISO15693\r
582 case CMD_SIMTAG_ISO_15693:\r
583 SimTagIso15693(c->arg[0]);\r
584 break;\r
585#endif\r
586\r
587#ifdef WITH_ISO14443b\r
588 case CMD_ACQUIRE_RAW_ADC_SAMPLES_ISO_14443:\r
589 AcquireRawAdcSamplesIso14443(c->arg[0]);\r
590 break;\r
591#endif\r
592\r
593#ifdef WITH_ISO14443b\r
594 case CMD_READ_SRI512_TAG:\r
595 ReadSRI512Iso14443(c->arg[0]);\r
596 break;\r
597 case CMD_READ_SRIX4K_TAG:\r
598 ReadSRIX4KIso14443(c->arg[0]);\r
599 break;\r
600#endif\r
601\r
602#ifdef WITH_ISO14443a\r
603 case CMD_READER_ISO_14443a:\r
604 ReaderIso14443a(c->arg[0]);\r
605 break;\r
606#endif\r
607\r
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
614#ifdef WITH_ISO14443b\r
615 case CMD_SNOOP_ISO_14443:\r
616 SnoopIso14443();\r
617 break;\r
618#endif\r
619\r
620#ifdef WITH_ISO14443a\r
621 case CMD_SNOOP_ISO_14443a:\r
622 SnoopIso14443a();\r
623 break;\r
624#endif\r
625\r
626 case CMD_SIMULATE_TAG_HF_LISTEN:\r
627 SimulateTagHfListen();\r
628 break;\r
629\r
630#ifdef WITH_ISO14443b\r
631 case CMD_SIMULATE_TAG_ISO_14443:\r
632 SimulateIso14443Tag();\r
633 break;\r
634#endif\r
635 \r
636#ifdef WITH_ISO14443a\r
637 case CMD_SIMULATE_TAG_ISO_14443a:\r
638 SimulateIso14443aTag(c->arg[0], c->arg[1]); // ## Simulate iso14443a tag - pass tag type & UID\r
639 break;\r
640#endif\r
641\r
642 case CMD_MEASURE_ANTENNA_TUNING:\r
643 MeasureAntennaTuning();\r
644 break;\r
645\r
646 case CMD_LISTEN_READER_FIELD:\r
647 ListenReaderField(c->arg[0]);\r
648 break;\r
649\r
650#ifdef WITH_LF\r
651 case CMD_HID_DEMOD_FSK:\r
652 CmdHIDdemodFSK(0, 0, 0, 1); // Demodulate HID tag\r
653 break;\r
654#endif\r
655\r
656#ifdef WITH_LF\r
657 case CMD_HID_SIM_TAG:\r
658 CmdHIDsimTAG(c->arg[0], c->arg[1], 1); // Simulate HID tag by ID\r
659 break;\r
660#endif\r
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
668#ifdef WITH_LF\r
669 case CMD_READ_TI_TYPE:\r
670 ReadTItag();\r
671 break;\r
672#endif\r
673\r
674#ifdef WITH_LF\r
675 case CMD_WRITE_TI_TYPE:\r
676 WriteTItag(c->arg[0],c->arg[1],c->arg[2]);\r
677 break;\r
678#endif\r
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
687 n.arg[0] = c->arg[0];\r
688 memcpy(n.d.asDwords, BigBuf+c->arg[0], 12*sizeof(DWORD));\r
689 UsbSendPacket((BYTE *)&n, sizeof(n));\r
690 break;\r
691 }\r
692\r
693 case CMD_DOWNLOADED_SIM_SAMPLES_125K: {\r
694 BYTE *b = (BYTE *)BigBuf;\r
695 memcpy(b+c->arg[0], c->d.asBytes, 48);\r
696 break;\r
697 }\r
698\r
699#ifdef WITH_LF\r
700 case CMD_SIMULATE_TAG_125K:\r
701 LED_A_ON();\r
702 SimulateTagLowFrequency(c->arg[0], 1);\r
703 LED_A_OFF();\r
704 break;\r
705#endif\r
706\r
707 case CMD_READ_MEM:\r
708 ReadMem(c->arg[0]);\r
709 break;\r
710\r
711 case CMD_SET_LF_DIVISOR:\r
712 FpgaSendCommand(FPGA_CMD_SET_DIVISOR, c->arg[0]);\r
713 break;\r
714\r
715 case CMD_SET_ADC_MUX:\r
716 switch(c->arg[0]) {\r
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
721 }\r
722 break;\r
723\r
724 case CMD_VERSION:\r
725 SendVersion();\r
726 break;\r
727\r
728#ifdef WITH_LF\r
729 case CMD_LF_SIMULATE_BIDIR:\r
730 SimulateTagLowFrequencyBidir(c->arg[0], c->arg[1]);\r
731 break;\r
732#endif\r
733\r
734#ifdef WITH_LCD\r
735 case CMD_LCD_RESET:\r
736 LCDReset();\r
737 break;\r
738 case CMD_LCD:\r
739 LCDSend(c->arg[0]);\r
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
753\r
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
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
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
843#ifdef WITH_LF\r
844 if (BUTTON_HELD(1000) > 0)\r
845 SamyRun();\r
846#endif\r
847 }\r
848}\r
Impressum, Datenschutz