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