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