- Added new Makefile.linux in bootrom directory
[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
9 #include <proxmark3.h>
10 #include "apps.h"
11 #include "fonts.h"
12 #ifdef WITH_LCD
13 #include "LCD.h"
14 #endif
15
16 // The large multi-purpose buffer, typically used to hold A/D samples,
17 // maybe pre-processed in some way.
18 DWORD BigBuf[16000];
19
20 //=============================================================================
21 // A buffer where we can queue things up to be sent through the FPGA, for
22 // any purpose (fake tag, as reader, whatever). We go MSB first, since that
23 // is the order in which they go out on the wire.
24 //=============================================================================
25
26 BYTE ToSend[256];
27 int ToSendMax;
28 static int ToSendBit;
29
30 void ToSendReset(void)
31 {
32 ToSendMax = -1;
33 ToSendBit = 8;
34 }
35
36 void ToSendStuffBit(int b)
37 {
38 if(ToSendBit >= 8) {
39 ToSendMax++;
40 ToSend[ToSendMax] = 0;
41 ToSendBit = 0;
42 }
43
44 if(b) {
45 ToSend[ToSendMax] |= (1 << (7 - ToSendBit));
46 }
47
48 ToSendBit++;
49
50 if(ToSendBit >= sizeof(ToSend)) {
51 ToSendBit = 0;
52 DbpString("ToSendStuffBit overflowed!");
53 }
54 }
55
56 //=============================================================================
57 // Debug print functions, to go out over USB, to the usual PC-side client.
58 //=============================================================================
59
60 void DbpString(char *str)
61 {
62 UsbCommand c;
63 c.cmd = CMD_DEBUG_PRINT_STRING;
64 c.ext1 = strlen(str);
65 memcpy(c.d.asBytes, str, c.ext1);
66
67 UsbSendPacket((BYTE *)&c, sizeof(c));
68 // TODO fix USB so stupid things like this aren't req'd
69 SpinDelay(50);
70 }
71
72 void DbpIntegers(int x1, int x2, int x3)
73 {
74 UsbCommand c;
75 c.cmd = CMD_DEBUG_PRINT_INTEGERS;
76 c.ext1 = x1;
77 c.ext2 = x2;
78 c.ext3 = x3;
79
80 UsbSendPacket((BYTE *)&c, sizeof(c));
81 // XXX
82 SpinDelay(50);
83 }
84
85 void AcquireRawAdcSamples125k(BOOL at134khz)
86 {
87 BYTE *dest = (BYTE *)BigBuf;
88 int n = sizeof(BigBuf);
89 int i;
90
91 memset(dest,0,n);
92
93 if(at134khz) {
94 FpgaSendCommand(FPGA_CMD_SET_DIVISOR, 88); //134.8Khz
95 FpgaWriteConfWord(FPGA_MAJOR_MODE_LF_READER | FPGA_LF_READER_USE_134_KHZ);
96 } else {
97 FpgaSendCommand(FPGA_CMD_SET_DIVISOR, 95); //125Khz
98 FpgaWriteConfWord(FPGA_MAJOR_MODE_LF_READER | FPGA_LF_READER_USE_125_KHZ);
99 }
100
101 // Connect the A/D to the peak-detected low-frequency path.
102 SetAdcMuxFor(GPIO_MUXSEL_LOPKD);
103
104 // Give it a bit of time for the resonant antenna to settle.
105 SpinDelay(50);
106
107 // Now set up the SSC to get the ADC samples that are now streaming at us.
108 FpgaSetupSsc();
109
110 i = 0;
111 for(;;) {
112 if(SSC_STATUS & (SSC_STATUS_TX_READY)) {
113 SSC_TRANSMIT_HOLDING = 0x43;
114 LED_D_ON();
115 }
116 if(SSC_STATUS & (SSC_STATUS_RX_READY)) {
117 dest[i] = (BYTE)SSC_RECEIVE_HOLDING;
118 i++;
119 LED_D_OFF();
120 if(i >= n) {
121 break;
122 }
123 }
124 }
125 DbpIntegers(dest[0], dest[1], at134khz);
126 }
127
128 //-----------------------------------------------------------------------------
129 // Read an ADC channel and block till it completes, then return the result
130 // in ADC units (0 to 1023). Also a routine to average 32 samples and
131 // return that.
132 //-----------------------------------------------------------------------------
133 static int ReadAdc(int ch)
134 {
135 DWORD d;
136
137 ADC_CONTROL = ADC_CONTROL_RESET;
138 ADC_MODE = ADC_MODE_PRESCALE(32) | ADC_MODE_STARTUP_TIME(16) |
139 ADC_MODE_SAMPLE_HOLD_TIME(8);
140 ADC_CHANNEL_ENABLE = ADC_CHANNEL(ch);
141
142 ADC_CONTROL = ADC_CONTROL_START;
143 while(!(ADC_STATUS & ADC_END_OF_CONVERSION(ch)))
144 ;
145 d = ADC_CHANNEL_DATA(ch);
146
147 return d;
148 }
149
150 static int AvgAdc(int ch)
151 {
152 int i;
153 int a = 0;
154
155 for(i = 0; i < 32; i++) {
156 a += ReadAdc(ch);
157 }
158
159 return (a + 15) >> 5;
160 }
161
162 /*
163 * Sweeps the useful LF range of the proxmark from
164 * 46.8kHz (divisor=255) to 600kHz (divisor=19) and
165 * reads the voltage in the antenna: the result is a graph
166 * which should clearly show the resonating frequency of your
167 * LF antenna ( hopefully around 90 if it is tuned to 125kHz!)
168 */
169 void SweepLFrange()
170 {
171 BYTE *dest = (BYTE *)BigBuf;
172 int i;
173
174 // clear buffer
175 memset(BigBuf,0,sizeof(BigBuf));
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 dest[i] = (137500 * AvgAdc(4)) >> 18;
182 }
183 }
184
185 void MeasureAntennaTuning(void)
186 {
187 // Impedances are Zc = 1/(j*omega*C), in ohms
188 #define LF_TUNING_CAP_Z 1273 // 1 nF @ 125 kHz
189 #define HF_TUNING_CAP_Z 235 // 50 pF @ 13.56 MHz
190
191 int vLf125, vLf134, vHf; // in mV
192
193 UsbCommand c;
194
195 // Let the FPGA drive the low-frequency antenna around 125 kHz.
196 FpgaSendCommand(FPGA_CMD_SET_DIVISOR, 95); //125Khz
197 FpgaWriteConfWord(FPGA_MAJOR_MODE_LF_READER | FPGA_LF_READER_USE_125_KHZ);
198 SpinDelay(20);
199 vLf125 = AvgAdc(4);
200 // Vref = 3.3V, and a 10000:240 voltage divider on the input
201 // can measure voltages up to 137500 mV
202 vLf125 = (137500 * vLf125) >> 10;
203
204 // Let the FPGA drive the low-frequency antenna around 134 kHz.
205 FpgaSendCommand(FPGA_CMD_SET_DIVISOR, 88); //134.8Khz
206 FpgaWriteConfWord(FPGA_MAJOR_MODE_LF_READER | FPGA_LF_READER_USE_134_KHZ);
207 SpinDelay(20);
208 vLf134 = AvgAdc(4);
209 // Vref = 3.3V, and a 10000:240 voltage divider on the input
210 // can measure voltages up to 137500 mV
211 vLf134 = (137500 * vLf134) >> 10;
212
213 // Let the FPGA drive the high-frequency antenna around 13.56 MHz.
214 FpgaWriteConfWord(FPGA_MAJOR_MODE_HF_READER_RX_XCORR);
215 SpinDelay(20);
216 vHf = AvgAdc(5);
217 // Vref = 3300mV, and an 10:1 voltage divider on the input
218 // can measure voltages up to 33000 mV
219 vHf = (33000 * vHf) >> 10;
220
221 c.cmd = CMD_MEASURED_ANTENNA_TUNING;
222 c.ext1 = (vLf125 << 0) | (vLf134 << 16);
223 c.ext2 = vHf;
224 c.ext3 = (LF_TUNING_CAP_Z << 0) | (HF_TUNING_CAP_Z << 16);
225 UsbSendPacket((BYTE *)&c, sizeof(c));
226 }
227
228 void SimulateTagLowFrequency(int period)
229 {
230 int i;
231 BYTE *tab = (BYTE *)BigBuf;
232
233 FpgaWriteConfWord(FPGA_MAJOR_MODE_LF_SIMULATOR);
234
235 PIO_ENABLE = (1 << GPIO_SSC_DOUT) | (1 << GPIO_SSC_CLK);
236
237 PIO_OUTPUT_ENABLE = (1 << GPIO_SSC_DOUT);
238 PIO_OUTPUT_DISABLE = (1 << GPIO_SSC_CLK);
239
240 #define SHORT_COIL() LOW(GPIO_SSC_DOUT)
241 #define OPEN_COIL() HIGH(GPIO_SSC_DOUT)
242
243 i = 0;
244 for(;;) {
245 while(!(PIO_PIN_DATA_STATUS & (1<<GPIO_SSC_CLK))) {
246 if(BUTTON_PRESS()) {
247 return;
248 }
249 WDT_HIT();
250 }
251
252 LED_D_ON();
253 if(tab[i]) {
254 OPEN_COIL();
255 } else {
256 SHORT_COIL();
257 }
258 LED_D_OFF();
259
260 while(PIO_PIN_DATA_STATUS & (1<<GPIO_SSC_CLK)) {
261 if(BUTTON_PRESS()) {
262 return;
263 }
264 WDT_HIT();
265 }
266
267 i++;
268 if(i == period) i = 0;
269 }
270 }
271
272 // compose fc/8 fc/10 waveform
273 static void fc(int c, int *n) {
274 BYTE *dest = (BYTE *)BigBuf;
275 int idx;
276
277 // for when we want an fc8 pattern every 4 logical bits
278 if(c==0) {
279 dest[((*n)++)]=1;
280 dest[((*n)++)]=1;
281 dest[((*n)++)]=0;
282 dest[((*n)++)]=0;
283 dest[((*n)++)]=0;
284 dest[((*n)++)]=0;
285 dest[((*n)++)]=0;
286 dest[((*n)++)]=0;
287 }
288 // an fc/8 encoded bit is a bit pattern of 11000000 x6 = 48 samples
289 if(c==8) {
290 for (idx=0; idx<6; idx++) {
291 dest[((*n)++)]=1;
292 dest[((*n)++)]=1;
293 dest[((*n)++)]=0;
294 dest[((*n)++)]=0;
295 dest[((*n)++)]=0;
296 dest[((*n)++)]=0;
297 dest[((*n)++)]=0;
298 dest[((*n)++)]=0;
299 }
300 }
301
302 // an fc/10 encoded bit is a bit pattern of 1110000000 x5 = 50 samples
303 if(c==10) {
304 for (idx=0; idx<5; idx++) {
305 dest[((*n)++)]=1;
306 dest[((*n)++)]=1;
307 dest[((*n)++)]=1;
308 dest[((*n)++)]=0;
309 dest[((*n)++)]=0;
310 dest[((*n)++)]=0;
311 dest[((*n)++)]=0;
312 dest[((*n)++)]=0;
313 dest[((*n)++)]=0;
314 dest[((*n)++)]=0;
315 }
316 }
317 }
318
319 // prepare a waveform pattern in the buffer based on the ID given then
320 // simulate a HID tag until the button is pressed
321 static void CmdHIDsimTAG(int hi, int lo)
322 {
323 int n=0, i=0;
324 /*
325 HID tag bitstream format
326 The tag contains a 44bit unique code. This is sent out MSB first in sets of 4 bits
327 A 1 bit is represented as 6 fc8 and 5 fc10 patterns
328 A 0 bit is represented as 5 fc10 and 6 fc8 patterns
329 A fc8 is inserted before every 4 bits
330 A special start of frame pattern is used consisting a0b0 where a and b are neither 0
331 nor 1 bits, they are special patterns (a = set of 12 fc8 and b = set of 10 fc10)
332 */
333
334 if (hi>0xFFF) {
335 DbpString("Tags can only have 44 bits.");
336 return;
337 }
338 fc(0,&n);
339 // special start of frame marker containing invalid bit sequences
340 fc(8, &n); fc(8, &n); // invalid
341 fc(8, &n); fc(10, &n); // logical 0
342 fc(10, &n); fc(10, &n); // invalid
343 fc(8, &n); fc(10, &n); // logical 0
344
345 WDT_HIT();
346 // manchester encode bits 43 to 32
347 for (i=11; i>=0; i--) {
348 if ((i%4)==3) fc(0,&n);
349 if ((hi>>i)&1) {
350 fc(10, &n); fc(8, &n); // low-high transition
351 } else {
352 fc(8, &n); fc(10, &n); // high-low transition
353 }
354 }
355
356 WDT_HIT();
357 // manchester encode bits 31 to 0
358 for (i=31; i>=0; i--) {
359 if ((i%4)==3) fc(0,&n);
360 if ((lo>>i)&1) {
361 fc(10, &n); fc(8, &n); // low-high transition
362 } else {
363 fc(8, &n); fc(10, &n); // high-low transition
364 }
365 }
366
367 LED_A_ON();
368 SimulateTagLowFrequency(n);
369 LED_A_OFF();
370 }
371
372 // loop to capture raw HID waveform then FSK demodulate the TAG ID from it
373 static void CmdHIDdemodFSK(void)
374 {
375 BYTE *dest = (BYTE *)BigBuf;
376 int m=0, n=0, i=0, idx=0, found=0, lastval=0;
377 DWORD hi=0, lo=0;
378
379 FpgaSendCommand(FPGA_CMD_SET_DIVISOR, 95); //125Khz
380 FpgaWriteConfWord(FPGA_MAJOR_MODE_LF_READER | FPGA_LF_READER_USE_125_KHZ);
381
382 // Connect the A/D to the peak-detected low-frequency path.
383 SetAdcMuxFor(GPIO_MUXSEL_LOPKD);
384
385 // Give it a bit of time for the resonant antenna to settle.
386 SpinDelay(50);
387
388 // Now set up the SSC to get the ADC samples that are now streaming at us.
389 FpgaSetupSsc();
390
391 for(;;) {
392 WDT_HIT();
393 LED_A_ON();
394 if(BUTTON_PRESS()) {
395 LED_A_OFF();
396 return;
397 }
398
399 i = 0;
400 m = sizeof(BigBuf);
401 memset(dest,128,m);
402 for(;;) {
403 if(SSC_STATUS & (SSC_STATUS_TX_READY)) {
404 SSC_TRANSMIT_HOLDING = 0x43;
405 LED_D_ON();
406 }
407 if(SSC_STATUS & (SSC_STATUS_RX_READY)) {
408 dest[i] = (BYTE)SSC_RECEIVE_HOLDING;
409 // we don't care about actual value, only if it's more or less than a
410 // threshold essentially we capture zero crossings for later analysis
411 if(dest[i] < 127) dest[i] = 0; else dest[i] = 1;
412 i++;
413 LED_D_OFF();
414 if(i >= m) {
415 break;
416 }
417 }
418 }
419
420 // FSK demodulator
421
422 // sync to first lo-hi transition
423 for( idx=1; idx<m; idx++) {
424 if (dest[idx-1]<dest[idx])
425 lastval=idx;
426 break;
427 }
428 WDT_HIT();
429
430 // count cycles between consecutive lo-hi transitions, there should be either 8 (fc/8)
431 // or 10 (fc/10) cycles but in practice due to noise etc we may end up with with anywhere
432 // between 7 to 11 cycles so fuzz it by treat anything <9 as 8 and anything else as 10
433 for( i=0; idx<m; idx++) {
434 if (dest[idx-1]<dest[idx]) {
435 dest[i]=idx-lastval;
436 if (dest[i] <= 8) {
437 dest[i]=1;
438 } else {
439 dest[i]=0;
440 }
441
442 lastval=idx;
443 i++;
444 }
445 }
446 m=i;
447 WDT_HIT();
448
449 // we now have a set of cycle counts, loop over previous results and aggregate data into bit patterns
450 lastval=dest[0];
451 idx=0;
452 i=0;
453 n=0;
454 for( idx=0; idx<m; idx++) {
455 if (dest[idx]==lastval) {
456 n++;
457 } else {
458 // a bit time is five fc/10 or six fc/8 cycles so figure out how many bits a pattern width represents,
459 // an extra fc/8 pattern preceeds every 4 bits (about 200 cycles) just to complicate things but it gets
460 // swallowed up by rounding
461 // expected results are 1 or 2 bits, any more and it's an invalid manchester encoding
462 // special start of frame markers use invalid manchester states (no transitions) by using sequences
463 // like 111000
464 if (dest[idx-1]) {
465 n=(n+1)/6; // fc/8 in sets of 6
466 } else {
467 n=(n+1)/5; // fc/10 in sets of 5
468 }
469 switch (n) { // stuff appropriate bits in buffer
470 case 0:
471 case 1: // one bit
472 dest[i++]=dest[idx-1];
473 break;
474 case 2: // two bits
475 dest[i++]=dest[idx-1];
476 dest[i++]=dest[idx-1];
477 break;
478 case 3: // 3 bit start of frame markers
479 dest[i++]=dest[idx-1];
480 dest[i++]=dest[idx-1];
481 dest[i++]=dest[idx-1];
482 break;
483 // When a logic 0 is immediately followed by the start of the next transmisson
484 // (special pattern) a pattern of 4 bit duration lengths is created.
485 case 4:
486 dest[i++]=dest[idx-1];
487 dest[i++]=dest[idx-1];
488 dest[i++]=dest[idx-1];
489 dest[i++]=dest[idx-1];
490 break;
491 default: // this shouldn't happen, don't stuff any bits
492 break;
493 }
494 n=0;
495 lastval=dest[idx];
496 }
497 }
498 m=i;
499 WDT_HIT();
500
501 // final loop, go over previously decoded manchester data and decode into usable tag ID
502 // 111000 bit pattern represent start of frame, 01 pattern represents a 1 and 10 represents a 0
503 for( idx=0; idx<m-6; idx++) {
504 // search for a start of frame marker
505 if ( dest[idx] && dest[idx+1] && dest[idx+2] && (!dest[idx+3]) && (!dest[idx+4]) && (!dest[idx+5]) )
506 {
507 found=1;
508 idx+=6;
509 if (found && (hi|lo)) {
510 DbpString("TAG ID");
511 DbpIntegers(hi, lo, (lo>>1)&0xffff);
512 hi=0;
513 lo=0;
514 found=0;
515 }
516 }
517 if (found) {
518 if (dest[idx] && (!dest[idx+1]) ) {
519 hi=(hi<<1)|(lo>>31);
520 lo=(lo<<1)|0;
521 } else if ( (!dest[idx]) && dest[idx+1]) {
522 hi=(hi<<1)|(lo>>31);
523 lo=(lo<<1)|1;
524 } else {
525 found=0;
526 hi=0;
527 lo=0;
528 }
529 idx++;
530 }
531 if ( dest[idx] && dest[idx+1] && dest[idx+2] && (!dest[idx+3]) && (!dest[idx+4]) && (!dest[idx+5]) )
532 {
533 found=1;
534 idx+=6;
535 if (found && (hi|lo)) {
536 DbpString("TAG ID");
537 DbpIntegers(hi, lo, (lo>>1)&0xffff);
538 hi=0;
539 lo=0;
540 found=0;
541 }
542 }
543 }
544 WDT_HIT();
545 }
546 }
547
548 void SimulateTagHfListen(void)
549 {
550 BYTE *dest = (BYTE *)BigBuf;
551 int n = sizeof(BigBuf);
552 BYTE v = 0;
553 int i;
554 int p = 0;
555
556 // We're using this mode just so that I can test it out; the simulated
557 // tag mode would work just as well and be simpler.
558 FpgaWriteConfWord(FPGA_MAJOR_MODE_HF_READER_RX_XCORR | FPGA_HF_READER_RX_XCORR_848_KHZ | FPGA_HF_READER_RX_XCORR_SNOOP);
559
560 // We need to listen to the high-frequency, peak-detected path.
561 SetAdcMuxFor(GPIO_MUXSEL_HIPKD);
562
563 FpgaSetupSsc();
564
565 i = 0;
566 for(;;) {
567 if(SSC_STATUS & (SSC_STATUS_TX_READY)) {
568 SSC_TRANSMIT_HOLDING = 0xff;
569 }
570 if(SSC_STATUS & (SSC_STATUS_RX_READY)) {
571 BYTE r = (BYTE)SSC_RECEIVE_HOLDING;
572
573 v <<= 1;
574 if(r & 1) {
575 v |= 1;
576 }
577 p++;
578
579 if(p >= 8) {
580 dest[i] = v;
581 v = 0;
582 p = 0;
583 i++;
584
585 if(i >= n) {
586 break;
587 }
588 }
589 }
590 }
591 DbpString("simulate tag (now type bitsamples)");
592 }
593
594 void UsbPacketReceived(BYTE *packet, int len)
595 {
596 UsbCommand *c = (UsbCommand *)packet;
597
598 switch(c->cmd) {
599 case CMD_ACQUIRE_RAW_ADC_SAMPLES_125K:
600 AcquireRawAdcSamples125k(c->ext1);
601 break;
602
603 case CMD_ACQUIRE_RAW_ADC_SAMPLES_ISO_15693:
604 AcquireRawAdcSamplesIso15693();
605 break;
606
607 case CMD_READER_ISO_15693:
608 ReaderIso15693(c->ext1);
609 break;
610
611 case CMD_SIMTAG_ISO_15693:
612 SimTagIso15693(c->ext1);
613 break;
614
615 case CMD_ACQUIRE_RAW_ADC_SAMPLES_ISO_14443:
616 AcquireRawAdcSamplesIso14443(c->ext1);
617 break;
618
619 case CMD_READ_SRI512_TAG:
620 ReadSRI512Iso14443(c->ext1);
621 break;
622
623 case CMD_READER_ISO_14443a:
624 ReaderIso14443a(c->ext1);
625 break;
626
627 case CMD_SNOOP_ISO_14443:
628 SnoopIso14443();
629 break;
630
631 case CMD_SNOOP_ISO_14443a:
632 SnoopIso14443a();
633 break;
634
635 case CMD_SIMULATE_TAG_HF_LISTEN:
636 SimulateTagHfListen();
637 break;
638
639 case CMD_SIMULATE_TAG_ISO_14443:
640 SimulateIso14443Tag();
641 break;
642
643 case CMD_SIMULATE_TAG_ISO_14443a:
644 SimulateIso14443aTag(c->ext1, c->ext2); // ## Simulate iso14443a tag - pass tag type & UID
645 break;
646
647 case CMD_MEASURE_ANTENNA_TUNING:
648 MeasureAntennaTuning();
649 break;
650
651 case CMD_HID_DEMOD_FSK:
652 CmdHIDdemodFSK(); // Demodulate HID tag
653 break;
654
655 case CMD_HID_SIM_TAG:
656 CmdHIDsimTAG(c->ext1, c->ext2); // Simulate HID tag by ID
657 break;
658
659 case CMD_FPGA_MAJOR_MODE_OFF: // ## FPGA Control
660 LED_C_ON();
661 FpgaWriteConfWord(FPGA_MAJOR_MODE_OFF);
662 SpinDelay(200);
663 LED_C_OFF();
664 break;
665
666 case CMD_DOWNLOAD_RAW_ADC_SAMPLES_125K:
667 case CMD_DOWNLOAD_RAW_BITS_TI_TYPE: {
668 UsbCommand n;
669 if(c->cmd == CMD_DOWNLOAD_RAW_ADC_SAMPLES_125K) {
670 n.cmd = CMD_DOWNLOADED_RAW_ADC_SAMPLES_125K;
671 } else {
672 n.cmd = CMD_DOWNLOADED_RAW_BITS_TI_TYPE;
673 }
674 n.ext1 = c->ext1;
675 memcpy(n.d.asDwords, BigBuf+c->ext1, 12*sizeof(DWORD));
676 UsbSendPacket((BYTE *)&n, sizeof(n));
677 break;
678 }
679 case CMD_DOWNLOADED_SIM_SAMPLES_125K: {
680 BYTE *b = (BYTE *)BigBuf;
681 memcpy(b+c->ext1, c->d.asBytes, 48);
682 break;
683 }
684 case CMD_SIMULATE_TAG_125K:
685 LED_A_ON();
686 SimulateTagLowFrequency(c->ext1);
687 LED_A_OFF();
688 break;
689 #ifdef WITH_LCD
690 case CMD_LCD_RESET:
691 LCDReset();
692 break;
693 #endif
694 case CMD_SWEEP_LF:
695 SweepLFrange();
696 break;
697
698 case CMD_SET_LF_DIVISOR:
699 FpgaSendCommand(FPGA_CMD_SET_DIVISOR, c->ext1);
700 break;
701 #ifdef WITH_LCD
702 case CMD_LCD:
703 LCDSend(c->ext1);
704 break;
705 #endif
706 case CMD_SETUP_WRITE:
707 case CMD_FINISH_WRITE:
708 USB_D_PLUS_PULLUP_OFF();
709 SpinDelay(1000);
710 SpinDelay(1000);
711 RSTC_CONTROL = RST_CONTROL_KEY | RST_CONTROL_PROCESSOR_RESET;
712 for(;;) {
713 // We're going to reset, and the bootrom will take control.
714 }
715 break;
716
717 default:
718 DbpString("unknown command");
719 break;
720 }
721 }
722
723 void AppMain(void)
724 {
725 memset(BigBuf,0,sizeof(BigBuf));
726 SpinDelay(100);
727
728 LED_D_OFF();
729 LED_C_OFF();
730 LED_B_OFF();
731 LED_A_OFF();
732
733 UsbStart();
734
735 // The FPGA gets its clock from us from PCK0 output, so set that up.
736 PIO_PERIPHERAL_B_SEL = (1 << GPIO_PCK0);
737 PIO_DISABLE = (1 << GPIO_PCK0);
738 PMC_SYS_CLK_ENABLE = PMC_SYS_CLK_PROGRAMMABLE_CLK_0;
739 // PCK0 is PLL clock / 4 = 96Mhz / 4 = 24Mhz
740 PMC_PROGRAMMABLE_CLK_0 = PMC_CLK_SELECTION_PLL_CLOCK |
741 PMC_CLK_PRESCALE_DIV_4;
742 PIO_OUTPUT_ENABLE = (1 << GPIO_PCK0);
743
744 // Reset SPI
745 SPI_CONTROL = SPI_CONTROL_RESET;
746 // Reset SSC
747 SSC_CONTROL = SSC_CONTROL_RESET;
748
749 // Load the FPGA image, which we have stored in our flash.
750 FpgaDownloadAndGo();
751
752 #ifdef WITH_LCD
753
754 LCDInit();
755
756 // test text on different colored backgrounds
757 LCDString(" The quick brown fox ", &FONT6x8,1,1+8*0,WHITE ,BLACK );
758 LCDString(" jumped over the ", &FONT6x8,1,1+8*1,BLACK ,WHITE );
759 LCDString(" lazy dog. ", &FONT6x8,1,1+8*2,YELLOW ,RED );
760 LCDString(" AaBbCcDdEeFfGgHhIiJj ", &FONT6x8,1,1+8*3,RED ,GREEN );
761 LCDString(" KkLlMmNnOoPpQqRrSsTt ", &FONT6x8,1,1+8*4,MAGENTA,BLUE );
762 LCDString("UuVvWwXxYyZz0123456789", &FONT6x8,1,1+8*5,BLUE ,YELLOW);
763 LCDString("`-=[]_;',./~!@#$%^&*()", &FONT6x8,1,1+8*6,BLACK ,CYAN );
764 LCDString(" _+{}|:\\\"<>? ",&FONT6x8,1,1+8*7,BLUE ,MAGENTA);
765
766 // color bands
767 LCDFill(0, 1+8* 8, 132, 8, BLACK);
768 LCDFill(0, 1+8* 9, 132, 8, WHITE);
769 LCDFill(0, 1+8*10, 132, 8, RED);
770 LCDFill(0, 1+8*11, 132, 8, GREEN);
771 LCDFill(0, 1+8*12, 132, 8, BLUE);
772 LCDFill(0, 1+8*13, 132, 8, YELLOW);
773 LCDFill(0, 1+8*14, 132, 8, CYAN);
774 LCDFill(0, 1+8*15, 132, 8, MAGENTA);
775
776 #endif
777
778 for(;;) {
779 UsbPoll(FALSE);
780 WDT_HIT();
781 }
782 }
783
784 void SpinDelay(int ms)
785 {
786 int ticks = (48000*ms) >> 10;
787
788 // Borrow a PWM unit for my real-time clock
789 PWM_ENABLE = PWM_CHANNEL(0);
790 // 48 MHz / 1024 gives 46.875 kHz
791 PWM_CH_MODE(0) = PWM_CH_MODE_PRESCALER(10);
792 PWM_CH_DUTY_CYCLE(0) = 0;
793 PWM_CH_PERIOD(0) = 0xffff;
794
795 WORD start = (WORD)PWM_CH_COUNTER(0);
796
797 for(;;) {
798 WORD now = (WORD)PWM_CH_COUNTER(0);
799 if(now == (WORD)(start + ticks)) {
800 return;
801 }
802 WDT_HIT();
803 }
804 }
Impressum, Datenschutz