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