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