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