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