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