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