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