]> cvs.zerfleddert.de Git - proxmark3-svn/blame_incremental - armsrc/appmain.c
iso14a reader patches [Hagen Fritsch]
[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_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
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:
646 ReaderIso14443a(c, &ack);
647 break;
648#endif
649
650#ifdef WITH_ISO14443a
651 case CMD_READER_MIFARE:
652 ReaderMifare(c->arg[0]);
653 break;
654#endif
655
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
677
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];
734 memcpy(n.d.asDwords, BigBuf+c->arg[0], 12*sizeof(uint32_t));
735 UsbSendPacket((uint8_t *)&n, sizeof(n));
736 break;
737 }
738
739 case CMD_DOWNLOADED_SIM_SAMPLES_125K: {
740 uint8_t *b = (uint8_t *)BigBuf;
741 memcpy(b+c->arg[0], c->d.asBytes, 48);
742 //Dbprintf("copied 48 bytes to %i",b+c->arg[0]);
743 UsbSendPacket((uint8_t*)&ack, sizeof(ack));
744 break;
745 }
746
747#ifdef WITH_LF
748 case CMD_SIMULATE_TAG_125K:
749 LED_A_ON();
750 SimulateTagLowFrequency(c->arg[0], c->arg[1], 1);
751 LED_A_OFF();
752 break;
753#endif
754
755 case CMD_READ_MEM:
756 ReadMem(c->arg[0]);
757 break;
758
759 case CMD_SET_LF_DIVISOR:
760 FpgaSendCommand(FPGA_CMD_SET_DIVISOR, c->arg[0]);
761 break;
762
763 case CMD_SET_ADC_MUX:
764 switch(c->arg[0]) {
765 case 0: SetAdcMuxFor(GPIO_MUXSEL_LOPKD); break;
766 case 1: SetAdcMuxFor(GPIO_MUXSEL_LORAW); break;
767 case 2: SetAdcMuxFor(GPIO_MUXSEL_HIPKD); break;
768 case 3: SetAdcMuxFor(GPIO_MUXSEL_HIRAW); break;
769 }
770 break;
771
772 case CMD_VERSION:
773 SendVersion();
774 break;
775
776#ifdef WITH_LF
777 case CMD_LF_SIMULATE_BIDIR:
778 SimulateTagLowFrequencyBidir(c->arg[0], c->arg[1]);
779 break;
780#endif
781
782#ifdef WITH_LCD
783 case CMD_LCD_RESET:
784 LCDReset();
785 break;
786 case CMD_LCD:
787 LCDSend(c->arg[0]);
788 break;
789#endif
790 case CMD_SETUP_WRITE:
791 case CMD_FINISH_WRITE:
792 case CMD_HARDWARE_RESET:
793 USB_D_PLUS_PULLUP_OFF();
794 SpinDelay(1000);
795 SpinDelay(1000);
796 AT91C_BASE_RSTC->RSTC_RCR = RST_CONTROL_KEY | AT91C_RSTC_PROCRST;
797 for(;;) {
798 // We're going to reset, and the bootrom will take control.
799 }
800 break;
801
802 case CMD_START_FLASH:
803 if(common_area.flags.bootrom_present) {
804 common_area.command = COMMON_AREA_COMMAND_ENTER_FLASH_MODE;
805 }
806 USB_D_PLUS_PULLUP_OFF();
807 AT91C_BASE_RSTC->RSTC_RCR = RST_CONTROL_KEY | AT91C_RSTC_PROCRST;
808 for(;;);
809 break;
810
811 case CMD_DEVICE_INFO: {
812 UsbCommand c;
813 c.cmd = CMD_DEVICE_INFO;
814 c.arg[0] = DEVICE_INFO_FLAG_OSIMAGE_PRESENT | DEVICE_INFO_FLAG_CURRENT_MODE_OS;
815 if(common_area.flags.bootrom_present) c.arg[0] |= DEVICE_INFO_FLAG_BOOTROM_PRESENT;
816 UsbSendPacket((uint8_t*)&c, sizeof(c));
817 }
818 break;
819 default:
820 Dbprintf("%s: 0x%04x","unknown command:",c->cmd);
821 break;
822 }
823}
824
825void __attribute__((noreturn)) AppMain(void)
826{
827 SpinDelay(100);
828
829 if(common_area.magic != COMMON_AREA_MAGIC || common_area.version != 1) {
830 /* Initialize common area */
831 memset(&common_area, 0, sizeof(common_area));
832 common_area.magic = COMMON_AREA_MAGIC;
833 common_area.version = 1;
834 }
835 common_area.flags.osimage_present = 1;
836
837 LED_D_OFF();
838 LED_C_OFF();
839 LED_B_OFF();
840 LED_A_OFF();
841
842 UsbStart();
843
844 // The FPGA gets its clock from us from PCK0 output, so set that up.
845 AT91C_BASE_PIOA->PIO_BSR = GPIO_PCK0;
846 AT91C_BASE_PIOA->PIO_PDR = GPIO_PCK0;
847 AT91C_BASE_PMC->PMC_SCER = AT91C_PMC_PCK0;
848 // PCK0 is PLL clock / 4 = 96Mhz / 4 = 24Mhz
849 AT91C_BASE_PMC->PMC_PCKR[0] = AT91C_PMC_CSS_PLL_CLK |
850 AT91C_PMC_PRES_CLK_4;
851 AT91C_BASE_PIOA->PIO_OER = GPIO_PCK0;
852
853 // Reset SPI
854 AT91C_BASE_SPI->SPI_CR = AT91C_SPI_SWRST;
855 // Reset SSC
856 AT91C_BASE_SSC->SSC_CR = AT91C_SSC_SWRST;
857
858 // Load the FPGA image, which we have stored in our flash.
859 FpgaDownloadAndGo();
860
861#ifdef WITH_LCD
862
863 LCDInit();
864
865 // test text on different colored backgrounds
866 LCDString(" The quick brown fox ", (char *)&FONT6x8,1,1+8*0,WHITE ,BLACK );
867 LCDString(" jumped over the ", (char *)&FONT6x8,1,1+8*1,BLACK ,WHITE );
868 LCDString(" lazy dog. ", (char *)&FONT6x8,1,1+8*2,YELLOW ,RED );
869 LCDString(" AaBbCcDdEeFfGgHhIiJj ", (char *)&FONT6x8,1,1+8*3,RED ,GREEN );
870 LCDString(" KkLlMmNnOoPpQqRrSsTt ", (char *)&FONT6x8,1,1+8*4,MAGENTA,BLUE );
871 LCDString("UuVvWwXxYyZz0123456789", (char *)&FONT6x8,1,1+8*5,BLUE ,YELLOW);
872 LCDString("`-=[]_;',./~!@#$%^&*()", (char *)&FONT6x8,1,1+8*6,BLACK ,CYAN );
873 LCDString(" _+{}|:\\\"<>? ",(char *)&FONT6x8,1,1+8*7,BLUE ,MAGENTA);
874
875 // color bands
876 LCDFill(0, 1+8* 8, 132, 8, BLACK);
877 LCDFill(0, 1+8* 9, 132, 8, WHITE);
878 LCDFill(0, 1+8*10, 132, 8, RED);
879 LCDFill(0, 1+8*11, 132, 8, GREEN);
880 LCDFill(0, 1+8*12, 132, 8, BLUE);
881 LCDFill(0, 1+8*13, 132, 8, YELLOW);
882 LCDFill(0, 1+8*14, 132, 8, CYAN);
883 LCDFill(0, 1+8*15, 132, 8, MAGENTA);
884
885#endif
886
887 for(;;) {
888 UsbPoll(FALSE);
889 WDT_HIT();
890
891#ifdef WITH_LF
892 if (BUTTON_HELD(1000) > 0)
893 SamyRun();
894#endif
895 }
896}
Impressum, Datenschutz