]> git.zerfleddert.de Git - proxmark3-svn/blame - armsrc/appmain.c
Create a stamp file for download completion so that it won't have to be redone later
[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// 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
22BYTE ToSend[256];
23int ToSendMax;
24static int ToSendBit;
8fcbf652 25struct common_area common_area __attribute__((section(".commonarea")));
959baa89 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;
4271e82d 241/* bootrom version information is pointed to from _bootphase1_version_pointer */
715d74c5 242extern char *_bootphase1_version_pointer, _flash_start, _flash_end;
ba8a80b3 243void SendVersion(void)
244{
245 char temp[48]; /* Limited data payload in USB packets */
246 DbpString("Prox/RFID mark3 RFID instrument");
8a6aec16 247
4271e82d 248 /* Try to find the bootrom version information. Expect to find a pointer at
249 * symbol _bootphase1_version_pointer, perform slight sanity checks on the
250 * pointer, then use it.
8a6aec16 251 */
45dcfac2 252 char *bootrom_version = *(char**)&_bootphase1_version_pointer;
253 if( bootrom_version < &_flash_start || bootrom_version >= &_flash_end ) {
8a6aec16 254 DbpString("bootrom version information appears invalid");
255 } else {
256 FormatVersionInformation(temp, sizeof(temp), "bootrom: ", bootrom_version);
257 DbpString(temp);
258 }
259
260 FormatVersionInformation(temp, sizeof(temp), "os: ", &version_information);
261 DbpString(temp);
262
ba8a80b3 263 FpgaGatherVersion(temp, sizeof(temp));
264 DbpString(temp);
265}
266
9bea179a 267// samy's sniff and repeat routine
268void SamyRun()
959baa89 269{
9bea179a 270 DbpString("Stand-alone mode! No PC necessary.");
959baa89 271
9bea179a 272 // 3 possible options? no just 2 for now
273#define OPTS 2
959baa89 274
9bea179a 275 int high[OPTS], low[OPTS];
c701d2c2 276
9bea179a 277 // Oooh pretty -- notify user we're in elite samy mode now
278 LED(LED_RED, 200);
279 LED(LED_ORANGE, 200);
280 LED(LED_GREEN, 200);
281 LED(LED_ORANGE, 200);
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);
959baa89 287
9bea179a 288 int selected = 0;
289 int playing = 0;
959baa89 290
9bea179a 291 // Turn on selected LED
292 LED(selected + 1, 0);
959baa89 293
9bea179a 294 for (;;)
295 {
50722269 296 UsbPoll(FALSE);
9bea179a 297 WDT_HIT();
959baa89 298
9bea179a 299 // Was our button held down or pressed?
300 int button_pressed = BUTTON_HELD(1000);
301 SpinDelay(300);
959baa89 302
9bea179a 303 // Button was held for a second, begin recording
304 if (button_pressed > 0)
305 {
306 LEDsoff();
307 LED(selected + 1, 0);
308 LED(LED_RED2, 0);
959baa89 309
9bea179a 310 // record
311 DbpString("Starting recording");
959baa89 312
9bea179a 313 // wait for button to be released
314 while(BUTTON_PRESS())
315 WDT_HIT();
959baa89 316
9bea179a 317 /* need this delay to prevent catching some weird data */
318 SpinDelay(500);
959baa89 319
9bea179a 320 CmdHIDdemodFSK(1, &high[selected], &low[selected], 0);
321 DbpString("Recorded");
322 DbpIntegers(selected, high[selected], low[selected]);
959baa89 323
9bea179a 324 LEDsoff();
325 LED(selected + 1, 0);
326 // Finished recording
959baa89 327
9bea179a 328 // If we were previously playing, set playing off
329 // so next button push begins playing what we recorded
330 playing = 0;
959baa89 331 }
959baa89 332
9bea179a 333 // Change where to record (or begin playing)
334 else if (button_pressed)
335 {
336 // Next option if we were previously playing
337 if (playing)
338 selected = (selected + 1) % OPTS;
339 playing = !playing;
959baa89 340
9bea179a 341 LEDsoff();
342 LED(selected + 1, 0);
343
344 // Begin transmitting
345 if (playing)
959baa89 346 {
9bea179a 347 LED(LED_GREEN, 0);
348 DbpString("Playing");
349 // wait for button to be released
350 while(BUTTON_PRESS())
351 WDT_HIT();
352 DbpIntegers(selected, high[selected], low[selected]);
353 CmdHIDsimTAG(high[selected], low[selected], 0);
354 DbpString("Done playing");
355 if (BUTTON_HELD(1000) > 0)
955fc5e2 356 {
9bea179a 357 DbpString("Exiting");
358 LEDsoff();
359 return;
955fc5e2 360 }
9bea179a 361
362 /* We pressed a button so ignore it here with a delay */
363 SpinDelay(300);
364
365 // when done, we're done playing, move to next option
366 selected = (selected + 1) % OPTS;
367 playing = !playing;
368 LEDsoff();
369 LED(selected + 1, 0);
959baa89 370 }
9bea179a 371 else
372 while(BUTTON_PRESS())
373 WDT_HIT();
959baa89 374 }
959baa89 375 }
376}
377
9bea179a 378
379/*
380OBJECTIVE
381Listen and detect an external reader. Determine the best location
382for the antenna.
383
384INSTRUCTIONS:
385Inside the ListenReaderField() function, there is two mode.
386By default, when you call the function, you will enter mode 1.
387If you press the PM3 button one time, you will enter mode 2.
388If you press the PM3 button a second time, you will exit the function.
389
390DESCRIPTION OF MODE 1:
391This mode just listens for an external reader field and lights up green
392for HF and/or red for LF. This is the original mode of the detectreader
393function.
394
395DESCRIPTION OF MODE 2:
396This mode will visually represent, using the LEDs, the actual strength of the
397current compared to the maximum current detected. Basically, once you know
398what kind of external reader is present, it will help you spot the best location to place
399your antenna. You will probably not get some good results if there is a LF and a HF reader
400at the same place! :-)
401
402LIGHT SCHEME USED:
9bea179a 403*/
bea2a866 404static const char LIGHT_SCHEME[] = {
405 0x0, /* ---- | No field detected */
406 0x1, /* X--- | 14% of maximum current detected */
407 0x2, /* -X-- | 29% of maximum current detected */
408 0x4, /* --X- | 43% of maximum current detected */
409 0x8, /* ---X | 57% of maximum current detected */
410 0xC, /* --XX | 71% of maximum current detected */
411 0xE, /* -XXX | 86% of maximum current detected */
412 0xF, /* XXXX | 100% of maximum current detected */
413};
414static const int LIGHT_LEN = sizeof(LIGHT_SCHEME)/sizeof(LIGHT_SCHEME[0]);
415
9bea179a 416void ListenReaderField(int limit)
959baa89 417{
bea2a866 418 int lf_av, lf_av_new, lf_baseline= 0, lf_count= 0, lf_max;
9bea179a 419 int hf_av, hf_av_new, hf_baseline= 0, hf_count= 0, hf_max;
bea2a866 420 int mode=1, display_val, display_max, i;
959baa89 421
9bea179a 422#define LF_ONLY 1
423#define HF_ONLY 2
959baa89 424
bea2a866 425 LEDsoff();
959baa89 426
bea2a866 427 lf_av=lf_max=ReadAdc(ADC_CHAN_LF);
959baa89 428
bea2a866 429 if(limit != HF_ONLY) {
9bea179a 430 DbpString("LF 125/134 Baseline:");
431 DbpIntegers(lf_av,0,0);
432 lf_baseline= lf_av;
bea2a866 433 }
959baa89 434
9bea179a 435 hf_av=hf_max=ReadAdc(ADC_CHAN_HF);
959baa89 436
bea2a866 437 if (limit != LF_ONLY) {
9bea179a 438 DbpString("HF 13.56 Baseline:");
439 DbpIntegers(hf_av,0,0);
440 hf_baseline= hf_av;
bea2a866 441 }
959baa89 442
bea2a866 443 for(;;) {
9bea179a 444 if (BUTTON_PRESS()) {
445 SpinDelay(500);
446 switch (mode) {
447 case 1:
448 mode=2;
449 DbpString("Signal Strength Mode");
959baa89 450 break;
9bea179a 451 case 2:
452 default:
453 DbpString("Stopped");
bea2a866 454 LEDsoff();
9bea179a 455 return;
456 break;
457 }
458 }
459 WDT_HIT();
460
bea2a866 461 if (limit != HF_ONLY) {
462 if(mode==1) {
463 if (abs(lf_av - lf_baseline) > 10) LED_D_ON();
464 else LED_D_OFF();
465 }
466
9bea179a 467 ++lf_count;
468 lf_av_new= ReadAdc(ADC_CHAN_LF);
469 // see if there's a significant change
bea2a866 470 if(abs(lf_av - lf_av_new) > 10) {
9bea179a 471 DbpString("LF 125/134 Field Change:");
472 DbpIntegers(lf_av,lf_av_new,lf_count);
473 lf_av= lf_av_new;
bea2a866 474 if (lf_av > lf_max)
475 lf_max = lf_av;
9bea179a 476 lf_count= 0;
9bea179a 477 }
bea2a866 478 }
9bea179a 479
bea2a866 480 if (limit != LF_ONLY) {
481 if (mode == 1){
482 if (abs(hf_av - hf_baseline) > 10) LED_B_ON();
483 else LED_B_OFF();
9bea179a 484 }
bea2a866 485
9bea179a 486 ++hf_count;
487 hf_av_new= ReadAdc(ADC_CHAN_HF);
488 // see if there's a significant change
bea2a866 489 if(abs(hf_av - hf_av_new) > 10) {
9bea179a 490 DbpString("HF 13.56 Field Change:");
491 DbpIntegers(hf_av,hf_av_new,hf_count);
492 hf_av= hf_av_new;
493 if (hf_av > hf_max)
494 hf_max = hf_av;
495 hf_count= 0;
bea2a866 496 }
497 }
498
499 if(mode == 2) {
500 if (limit == LF_ONLY) {
501 display_val = lf_av;
502 display_max = lf_max;
503 } else if (limit == HF_ONLY) {
504 display_val = hf_av;
505 display_max = hf_max;
506 } else { /* Pick one at random */
507 if( (hf_max - hf_baseline) > (lf_max - lf_baseline) ) {
508 display_val = hf_av;
509 display_max = hf_max;
510 } else {
511 display_val = lf_av;
512 display_max = lf_max;
513 }
514 }
515 for (i=0; i<LIGHT_LEN; i++) {
516 if (display_val >= ((display_max/LIGHT_LEN)*i) && display_val <= ((display_max/LIGHT_LEN)*(i+1))) {
517 if (LIGHT_SCHEME[i] & 0x1) LED_C_ON(); else LED_C_OFF();
518 if (LIGHT_SCHEME[i] & 0x2) LED_A_ON(); else LED_A_OFF();
519 if (LIGHT_SCHEME[i] & 0x4) LED_B_ON(); else LED_B_OFF();
520 if (LIGHT_SCHEME[i] & 0x8) LED_D_ON(); else LED_D_OFF();
521 break;
959baa89 522 }
523 }
524 }
bea2a866 525 }
959baa89 526}
527
528void UsbPacketReceived(BYTE *packet, int len)
529{
530 UsbCommand *c = (UsbCommand *)packet;
531
532 switch(c->cmd) {
533 case CMD_ACQUIRE_RAW_ADC_SAMPLES_125K:
534 AcquireRawAdcSamples125k(c->ext1);
535 break;
536
537 case CMD_MOD_THEN_ACQUIRE_RAW_ADC_SAMPLES_125K:
538 ModThenAcquireRawAdcSamples125k(c->ext1,c->ext2,c->ext3,c->d.asBytes);
539 break;
540
541 case CMD_ACQUIRE_RAW_ADC_SAMPLES_ISO_15693:
542 AcquireRawAdcSamplesIso15693();
543 break;
f23e056d 544
545 case CMD_BUFF_CLEAR:
546 BufferClear();
547 break;
959baa89 548
549 case CMD_READER_ISO_15693:
550 ReaderIso15693(c->ext1);
551 break;
552
553 case CMD_SIMTAG_ISO_15693:
554 SimTagIso15693(c->ext1);
555 break;
556
557 case CMD_ACQUIRE_RAW_ADC_SAMPLES_ISO_14443:
558 AcquireRawAdcSamplesIso14443(c->ext1);
559 break;
fb25b483 560
561 case CMD_READ_SRI512_TAG:
562 ReadSRI512Iso14443(c->ext1);
563 break;
959baa89 564
565 case CMD_READER_ISO_14443a:
566 ReaderIso14443a(c->ext1);
567 break;
568
569 case CMD_SNOOP_ISO_14443:
570 SnoopIso14443();
571 break;
572
573 case CMD_SNOOP_ISO_14443a:
574 SnoopIso14443a();
575 break;
576
577 case CMD_SIMULATE_TAG_HF_LISTEN:
578 SimulateTagHfListen();
579 break;
580
581 case CMD_SIMULATE_TAG_ISO_14443:
582 SimulateIso14443Tag();
583 break;
584
585 case CMD_SIMULATE_TAG_ISO_14443a:
586 SimulateIso14443aTag(c->ext1, c->ext2); // ## Simulate iso14443a tag - pass tag type & UID
587 break;
588
589 case CMD_MEASURE_ANTENNA_TUNING:
590 MeasureAntennaTuning();
591 break;
592
7f348042 593 case CMD_LISTEN_READER_FIELD:
594 ListenReaderField(c->ext1);
595 break;
596
959baa89 597 case CMD_HID_DEMOD_FSK:
955fc5e2 598 CmdHIDdemodFSK(0, 0, 0, 1); // Demodulate HID tag
959baa89 599 break;
600
601 case CMD_HID_SIM_TAG:
955fc5e2 602 CmdHIDsimTAG(c->ext1, c->ext2, 1); // Simulate HID tag by ID
959baa89 603 break;
604
605 case CMD_FPGA_MAJOR_MODE_OFF: // ## FPGA Control
606 FpgaWriteConfWord(FPGA_MAJOR_MODE_OFF);
607 SpinDelay(200);
608 LED_D_OFF(); // LED D indicates field ON or OFF
609 break;
610
9bea179a 611 case CMD_READ_TI_TYPE:
612 ReadTItag();
613 break;
614
615 case CMD_WRITE_TI_TYPE:
616 WriteTItag(c->ext1,c->ext2,c->ext3);
617 break;
618
7381e8f2 619 case CMD_DOWNLOAD_RAW_ADC_SAMPLES_125K: {
959baa89 620 UsbCommand n;
621 if(c->cmd == CMD_DOWNLOAD_RAW_ADC_SAMPLES_125K) {
622 n.cmd = CMD_DOWNLOADED_RAW_ADC_SAMPLES_125K;
623 } else {
624 n.cmd = CMD_DOWNLOADED_RAW_BITS_TI_TYPE;
625 }
626 n.ext1 = c->ext1;
627 memcpy(n.d.asDwords, BigBuf+c->ext1, 12*sizeof(DWORD));
628 UsbSendPacket((BYTE *)&n, sizeof(n));
629 break;
630 }
631 case CMD_DOWNLOADED_SIM_SAMPLES_125K: {
632 BYTE *b = (BYTE *)BigBuf;
633 memcpy(b+c->ext1, c->d.asBytes, 48);
634 break;
635 }
636 case CMD_SIMULATE_TAG_125K:
637 LED_A_ON();
955fc5e2 638 SimulateTagLowFrequency(c->ext1, 1);
959baa89 639 LED_A_OFF();
640 break;
1dff8c42 641 case CMD_READ_MEM:
642 ReadMem(c->ext1);
643 break;
959baa89 644 case CMD_SET_LF_DIVISOR:
645 FpgaSendCommand(FPGA_CMD_SET_DIVISOR, c->ext1);
646 break;
ba8a80b3 647 case CMD_VERSION:
648 SendVersion();
649 break;
0fa9ca5b 650 case CMD_LF_SIMULATE_BIDIR:
651 SimulateTagLowFrequencyBidir(c->ext1, c->ext2);
652 break;
959baa89 653#ifdef WITH_LCD
7381e8f2 654 case CMD_LCD_RESET:
655 LCDReset();
656 break;
959baa89 657 case CMD_LCD:
658 LCDSend(c->ext1);
659 break;
660#endif
9bea179a 661 case CMD_SETUP_WRITE:
959baa89 662 case CMD_FINISH_WRITE:
663 case CMD_HARDWARE_RESET:
664 USB_D_PLUS_PULLUP_OFF();
665 SpinDelay(1000);
666 SpinDelay(1000);
667 RSTC_CONTROL = RST_CONTROL_KEY | RST_CONTROL_PROCESSOR_RESET;
668 for(;;) {
669 // We're going to reset, and the bootrom will take control.
670 }
671 break;
8fcbf652 672 case CMD_START_FLASH:
673 if(common_area.flags.bootrom_present) {
674 common_area.command = COMMON_AREA_COMMAND_ENTER_FLASH_MODE;
675 }
676 USB_D_PLUS_PULLUP_OFF();
677 RSTC_CONTROL = RST_CONTROL_KEY | RST_CONTROL_PROCESSOR_RESET;
678 for(;;);
679 break;
680
681 case CMD_DEVICE_INFO: {
682 UsbCommand c;
683 c.cmd = CMD_DEVICE_INFO;
684 c.ext1 = DEVICE_INFO_FLAG_OSIMAGE_PRESENT | DEVICE_INFO_FLAG_CURRENT_MODE_OS;
685 if(common_area.flags.bootrom_present) c.ext1 |= DEVICE_INFO_FLAG_BOOTROM_PRESENT;
686 UsbSendPacket((BYTE*)&c, sizeof(c));
687 }
688 break;
959baa89 689 default:
690 DbpString("unknown command");
691 break;
692 }
693}
694
1b2c8936 695void __attribute__((noreturn)) AppMain(void)
959baa89 696{
959baa89 697 SpinDelay(100);
8fcbf652 698
699 if(common_area.magic != COMMON_AREA_MAGIC || common_area.version != 1) {
700 /* Initialize common area */
701 memset(&common_area, 0, sizeof(common_area));
702 common_area.magic = COMMON_AREA_MAGIC;
703 common_area.version = 1;
704 }
705 common_area.flags.osimage_present = 1;
959baa89 706
693f7cf7 707 LED_D_OFF();
708 LED_C_OFF();
709 LED_B_OFF();
710 LED_A_OFF();
959baa89 711
712 UsbStart();
713
714 // The FPGA gets its clock from us from PCK0 output, so set that up.
715 PIO_PERIPHERAL_B_SEL = (1 << GPIO_PCK0);
716 PIO_DISABLE = (1 << GPIO_PCK0);
717 PMC_SYS_CLK_ENABLE = PMC_SYS_CLK_PROGRAMMABLE_CLK_0;
718 // PCK0 is PLL clock / 4 = 96Mhz / 4 = 24Mhz
719 PMC_PROGRAMMABLE_CLK_0 = PMC_CLK_SELECTION_PLL_CLOCK |
720 PMC_CLK_PRESCALE_DIV_4;
721 PIO_OUTPUT_ENABLE = (1 << GPIO_PCK0);
722
723 // Reset SPI
724 SPI_CONTROL = SPI_CONTROL_RESET;
725 // Reset SSC
726 SSC_CONTROL = SSC_CONTROL_RESET;
727
728 // Load the FPGA image, which we have stored in our flash.
729 FpgaDownloadAndGo();
730
731#ifdef WITH_LCD
732
733 LCDInit();
734
735 // test text on different colored backgrounds
715d74c5 736 LCDString(" The quick brown fox ", (char *)&FONT6x8,1,1+8*0,WHITE ,BLACK );
737 LCDString(" jumped over the ", (char *)&FONT6x8,1,1+8*1,BLACK ,WHITE );
738 LCDString(" lazy dog. ", (char *)&FONT6x8,1,1+8*2,YELLOW ,RED );
739 LCDString(" AaBbCcDdEeFfGgHhIiJj ", (char *)&FONT6x8,1,1+8*3,RED ,GREEN );
740 LCDString(" KkLlMmNnOoPpQqRrSsTt ", (char *)&FONT6x8,1,1+8*4,MAGENTA,BLUE );
741 LCDString("UuVvWwXxYyZz0123456789", (char *)&FONT6x8,1,1+8*5,BLUE ,YELLOW);
742 LCDString("`-=[]_;',./~!@#$%^&*()", (char *)&FONT6x8,1,1+8*6,BLACK ,CYAN );
743 LCDString(" _+{}|:\\\"<>? ",(char *)&FONT6x8,1,1+8*7,BLUE ,MAGENTA);
959baa89 744
745 // color bands
746 LCDFill(0, 1+8* 8, 132, 8, BLACK);
747 LCDFill(0, 1+8* 9, 132, 8, WHITE);
748 LCDFill(0, 1+8*10, 132, 8, RED);
749 LCDFill(0, 1+8*11, 132, 8, GREEN);
750 LCDFill(0, 1+8*12, 132, 8, BLUE);
751 LCDFill(0, 1+8*13, 132, 8, YELLOW);
752 LCDFill(0, 1+8*14, 132, 8, CYAN);
753 LCDFill(0, 1+8*15, 132, 8, MAGENTA);
754
755#endif
756
757 for(;;) {
50722269 758 UsbPoll(FALSE);
959baa89 759 WDT_HIT();
959baa89 760
955fc5e2 761 if (BUTTON_HELD(1000) > 0)
762 SamyRun();
959baa89 763 }
764}
Impressum, Datenschutz