]> git.zerfleddert.de Git - proxmark3-svn/blame - armsrc/appmain.c
Add a ramfunc section in the data segment, which will be copied to ram on startup.
[proxmark3-svn] / armsrc / appmain.c
CommitLineData
15c4dc5a 1//-----------------------------------------------------------------------------
15c4dc5a 2// Jonathan Westhues, Mar 2006
3// Edits by Gerhard de Koning Gans, Sep 2007 (##)
bd20f8f4 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.
15c4dc5a 11//-----------------------------------------------------------------------------
12
e30c654b 13#include "proxmark3.h"
15c4dc5a 14#include "apps.h"
f7e3ed82 15#include "util.h"
9ab7a6c7 16#include "printf.h"
17#include "string.h"
18
19#include <stdarg.h>
f7e3ed82 20
15c4dc5a 21#include "legicrf.h"
f7e3ed82 22
15c4dc5a 23#ifdef WITH_LCD
f7e3ed82 24# include "fonts.h"
25# include "LCD.h"
15c4dc5a 26#endif
27
15c4dc5a 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
f7e3ed82 36uint8_t ToSend[512];
15c4dc5a 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
f7e3ed82 91 UsbSendPacket((uint8_t *)&c, sizeof(c));
15c4dc5a 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
f7e3ed82 109 UsbSendPacket((uint8_t *)&c, sizeof(c));
15c4dc5a 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);
e30c654b 123
15c4dc5a 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{
f7e3ed82 134 uint32_t d;
15c4dc5a 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{
f7e3ed82 165 uint8_t *dest = (uint8_t *)BigBuf;
15c4dc5a 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);
f7e3ed82 212 UsbSendPacket((uint8_t *)&c, sizeof(c));
15c4dc5a 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;
e30c654b 228
15c4dc5a 229 Dbprintf("%d mV",vHf);
230 if (BUTTON_PRESS()) break;
231 }
232 DbpString("cancelled");
233}
234
235
236void SimulateTagHfListen(void)
237{
f7e3ed82 238 uint8_t *dest = (uint8_t *)BigBuf;
15c4dc5a 239 int n = sizeof(BigBuf);
f7e3ed82 240 uint8_t v = 0;
15c4dc5a 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)) {
f7e3ed82 259 uint8_t r = (uint8_t)AT91C_BASE_SSC->SSC_RHR;
15c4dc5a 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{
f7e3ed82 284 const uint8_t *data = ((uint8_t *)addr);
15c4dc5a 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");
e30c654b 298
299 /* Try to find the bootrom version information. Expect to find a pointer at
15c4dc5a 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 }
e30c654b 310
15c4dc5a 311 FormatVersionInformation(temp, sizeof(temp), "os: ", &version_information);
312 DbpString(temp);
e30c654b 313
15c4dc5a 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 }
e30c654b 515
15c4dc5a 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 }
e30c654b 533
15c4dc5a 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 }
e30c654b 545
15c4dc5a 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
f7e3ed82 575void UsbPacketReceived(uint8_t *packet, int len)
15c4dc5a 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]);
f7e3ed82 585 UsbSendPacket((uint8_t*)&ack, sizeof(ack));
15c4dc5a 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
3612a8a8 611 case CMD_SIMULATE_TAG_LEGIC_RF:
612 LegicRfSimulate(c->arg[0], c->arg[1], c->arg[2]);
613 break;
614
615 case CMD_WRITER_LEGIC_RF:
616 LegicRfWriter(c->arg[1], c->arg[0]);
617 break;
618
15c4dc5a 619 case CMD_READER_LEGIC_RF:
620 LegicRfReader(c->arg[0], c->arg[1]);
621 break;
622
623#ifdef WITH_ISO15693
624 case CMD_SIMTAG_ISO_15693:
625 SimTagIso15693(c->arg[0]);
626 break;
627#endif
628
629#ifdef WITH_ISO14443b
630 case CMD_ACQUIRE_RAW_ADC_SAMPLES_ISO_14443:
631 AcquireRawAdcSamplesIso14443(c->arg[0]);
632 break;
633#endif
634
635#ifdef WITH_ISO14443b
636 case CMD_READ_SRI512_TAG:
637 ReadSRI512Iso14443(c->arg[0]);
638 break;
639 case CMD_READ_SRIX4K_TAG:
640 ReadSRIX4KIso14443(c->arg[0]);
641 break;
642#endif
643
644#ifdef WITH_ISO14443a
645 case CMD_READER_ISO_14443a:
534983d7 646 ReaderIso14443a(c, &ack);
15c4dc5a 647 break;
648#endif
649
650#ifdef WITH_ISO14443a
651 case CMD_READER_MIFARE:
652 ReaderMifare(c->arg[0]);
653 break;
654#endif
e30c654b 655
15c4dc5a 656#ifdef WITH_ISO14443b
657 case CMD_SNOOP_ISO_14443:
658 SnoopIso14443();
659 break;
660#endif
661
662#ifdef WITH_ISO14443a
663 case CMD_SNOOP_ISO_14443a:
664 SnoopIso14443a();
665 break;
666#endif
667
668 case CMD_SIMULATE_TAG_HF_LISTEN:
669 SimulateTagHfListen();
670 break;
671
672#ifdef WITH_ISO14443b
673 case CMD_SIMULATE_TAG_ISO_14443:
674 SimulateIso14443Tag();
675 break;
676#endif
e30c654b 677
15c4dc5a 678#ifdef WITH_ISO14443a
679 case CMD_SIMULATE_TAG_ISO_14443a:
680 SimulateIso14443aTag(c->arg[0], c->arg[1]); // ## Simulate iso14443a tag - pass tag type & UID
681 break;
682#endif
683
684 case CMD_MEASURE_ANTENNA_TUNING:
685 MeasureAntennaTuning();
686 break;
687
688 case CMD_MEASURE_ANTENNA_TUNING_HF:
689 MeasureAntennaTuningHf();
690 break;
691
692 case CMD_LISTEN_READER_FIELD:
693 ListenReaderField(c->arg[0]);
694 break;
695
696#ifdef WITH_LF
697 case CMD_HID_DEMOD_FSK:
698 CmdHIDdemodFSK(0, 0, 0, 1); // Demodulate HID tag
699 break;
700#endif
701
702#ifdef WITH_LF
703 case CMD_HID_SIM_TAG:
704 CmdHIDsimTAG(c->arg[0], c->arg[1], 1); // Simulate HID tag by ID
705 break;
706#endif
707
708 case CMD_FPGA_MAJOR_MODE_OFF: // ## FPGA Control
709 FpgaWriteConfWord(FPGA_MAJOR_MODE_OFF);
710 SpinDelay(200);
711 LED_D_OFF(); // LED D indicates field ON or OFF
712 break;
713
714#ifdef WITH_LF
715 case CMD_READ_TI_TYPE:
716 ReadTItag();
717 break;
718#endif
719
720#ifdef WITH_LF
721 case CMD_WRITE_TI_TYPE:
722 WriteTItag(c->arg[0],c->arg[1],c->arg[2]);
723 break;
724#endif
725
726 case CMD_DOWNLOAD_RAW_ADC_SAMPLES_125K: {
727 UsbCommand n;
728 if(c->cmd == CMD_DOWNLOAD_RAW_ADC_SAMPLES_125K) {
729 n.cmd = CMD_DOWNLOADED_RAW_ADC_SAMPLES_125K;
730 } else {
731 n.cmd = CMD_DOWNLOADED_RAW_BITS_TI_TYPE;
732 }
733 n.arg[0] = c->arg[0];
f7e3ed82 734 memcpy(n.d.asDwords, BigBuf+c->arg[0], 12*sizeof(uint32_t));
d3b1f4e4 735 LED_B_ON();
f7e3ed82 736 UsbSendPacket((uint8_t *)&n, sizeof(n));
d3b1f4e4 737 LED_B_OFF();
15c4dc5a 738 break;
739 }
740
741 case CMD_DOWNLOADED_SIM_SAMPLES_125K: {
f7e3ed82 742 uint8_t *b = (uint8_t *)BigBuf;
15c4dc5a 743 memcpy(b+c->arg[0], c->d.asBytes, 48);
744 //Dbprintf("copied 48 bytes to %i",b+c->arg[0]);
f7e3ed82 745 UsbSendPacket((uint8_t*)&ack, sizeof(ack));
15c4dc5a 746 break;
747 }
748
749#ifdef WITH_LF
750 case CMD_SIMULATE_TAG_125K:
751 LED_A_ON();
752 SimulateTagLowFrequency(c->arg[0], c->arg[1], 1);
753 LED_A_OFF();
754 break;
755#endif
756
757 case CMD_READ_MEM:
758 ReadMem(c->arg[0]);
759 break;
760
761 case CMD_SET_LF_DIVISOR:
762 FpgaSendCommand(FPGA_CMD_SET_DIVISOR, c->arg[0]);
763 break;
764
765 case CMD_SET_ADC_MUX:
766 switch(c->arg[0]) {
767 case 0: SetAdcMuxFor(GPIO_MUXSEL_LOPKD); break;
768 case 1: SetAdcMuxFor(GPIO_MUXSEL_LORAW); break;
769 case 2: SetAdcMuxFor(GPIO_MUXSEL_HIPKD); break;
770 case 3: SetAdcMuxFor(GPIO_MUXSEL_HIRAW); break;
771 }
772 break;
773
774 case CMD_VERSION:
775 SendVersion();
776 break;
777
778#ifdef WITH_LF
779 case CMD_LF_SIMULATE_BIDIR:
780 SimulateTagLowFrequencyBidir(c->arg[0], c->arg[1]);
781 break;
782#endif
783
784#ifdef WITH_LCD
785 case CMD_LCD_RESET:
786 LCDReset();
787 break;
788 case CMD_LCD:
789 LCDSend(c->arg[0]);
790 break;
791#endif
792 case CMD_SETUP_WRITE:
793 case CMD_FINISH_WRITE:
794 case CMD_HARDWARE_RESET:
795 USB_D_PLUS_PULLUP_OFF();
796 SpinDelay(1000);
797 SpinDelay(1000);
798 AT91C_BASE_RSTC->RSTC_RCR = RST_CONTROL_KEY | AT91C_RSTC_PROCRST;
799 for(;;) {
800 // We're going to reset, and the bootrom will take control.
801 }
802 break;
803
804 case CMD_START_FLASH:
805 if(common_area.flags.bootrom_present) {
806 common_area.command = COMMON_AREA_COMMAND_ENTER_FLASH_MODE;
807 }
808 USB_D_PLUS_PULLUP_OFF();
809 AT91C_BASE_RSTC->RSTC_RCR = RST_CONTROL_KEY | AT91C_RSTC_PROCRST;
810 for(;;);
811 break;
e30c654b 812
15c4dc5a 813 case CMD_DEVICE_INFO: {
814 UsbCommand c;
815 c.cmd = CMD_DEVICE_INFO;
816 c.arg[0] = DEVICE_INFO_FLAG_OSIMAGE_PRESENT | DEVICE_INFO_FLAG_CURRENT_MODE_OS;
817 if(common_area.flags.bootrom_present) c.arg[0] |= DEVICE_INFO_FLAG_BOOTROM_PRESENT;
f7e3ed82 818 UsbSendPacket((uint8_t*)&c, sizeof(c));
15c4dc5a 819 }
820 break;
821 default:
822 Dbprintf("%s: 0x%04x","unknown command:",c->cmd);
823 break;
824 }
825}
826
827void __attribute__((noreturn)) AppMain(void)
828{
829 SpinDelay(100);
e30c654b 830
15c4dc5a 831 if(common_area.magic != COMMON_AREA_MAGIC || common_area.version != 1) {
832 /* Initialize common area */
833 memset(&common_area, 0, sizeof(common_area));
834 common_area.magic = COMMON_AREA_MAGIC;
835 common_area.version = 1;
836 }
837 common_area.flags.osimage_present = 1;
838
839 LED_D_OFF();
840 LED_C_OFF();
841 LED_B_OFF();
842 LED_A_OFF();
843
844 UsbStart();
845
846 // The FPGA gets its clock from us from PCK0 output, so set that up.
847 AT91C_BASE_PIOA->PIO_BSR = GPIO_PCK0;
848 AT91C_BASE_PIOA->PIO_PDR = GPIO_PCK0;
849 AT91C_BASE_PMC->PMC_SCER = AT91C_PMC_PCK0;
850 // PCK0 is PLL clock / 4 = 96Mhz / 4 = 24Mhz
851 AT91C_BASE_PMC->PMC_PCKR[0] = AT91C_PMC_CSS_PLL_CLK |
852 AT91C_PMC_PRES_CLK_4;
853 AT91C_BASE_PIOA->PIO_OER = GPIO_PCK0;
854
855 // Reset SPI
856 AT91C_BASE_SPI->SPI_CR = AT91C_SPI_SWRST;
857 // Reset SSC
858 AT91C_BASE_SSC->SSC_CR = AT91C_SSC_SWRST;
859
860 // Load the FPGA image, which we have stored in our flash.
861 FpgaDownloadAndGo();
862
863#ifdef WITH_LCD
864
865 LCDInit();
866
867 // test text on different colored backgrounds
868 LCDString(" The quick brown fox ", (char *)&FONT6x8,1,1+8*0,WHITE ,BLACK );
869 LCDString(" jumped over the ", (char *)&FONT6x8,1,1+8*1,BLACK ,WHITE );
870 LCDString(" lazy dog. ", (char *)&FONT6x8,1,1+8*2,YELLOW ,RED );
871 LCDString(" AaBbCcDdEeFfGgHhIiJj ", (char *)&FONT6x8,1,1+8*3,RED ,GREEN );
872 LCDString(" KkLlMmNnOoPpQqRrSsTt ", (char *)&FONT6x8,1,1+8*4,MAGENTA,BLUE );
873 LCDString("UuVvWwXxYyZz0123456789", (char *)&FONT6x8,1,1+8*5,BLUE ,YELLOW);
874 LCDString("`-=[]_;',./~!@#$%^&*()", (char *)&FONT6x8,1,1+8*6,BLACK ,CYAN );
875 LCDString(" _+{}|:\\\"<>? ",(char *)&FONT6x8,1,1+8*7,BLUE ,MAGENTA);
876
877 // color bands
878 LCDFill(0, 1+8* 8, 132, 8, BLACK);
879 LCDFill(0, 1+8* 9, 132, 8, WHITE);
880 LCDFill(0, 1+8*10, 132, 8, RED);
881 LCDFill(0, 1+8*11, 132, 8, GREEN);
882 LCDFill(0, 1+8*12, 132, 8, BLUE);
883 LCDFill(0, 1+8*13, 132, 8, YELLOW);
884 LCDFill(0, 1+8*14, 132, 8, CYAN);
885 LCDFill(0, 1+8*15, 132, 8, MAGENTA);
886
887#endif
888
889 for(;;) {
890 UsbPoll(FALSE);
891 WDT_HIT();
892
893#ifdef WITH_LF
894 if (BUTTON_HELD(1000) > 0)
895 SamyRun();
896#endif
897 }
898}
Impressum, Datenschutz