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