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