]> cvs.zerfleddert.de Git - proxmark3-svn/blob - armsrc/appmain.c
7dba687fc80ca37270ffb48ba70cba2d83a20fab
[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 #include <proxmark3.h>
9 #include <stdlib.h>
10 #include "apps.h"
11 #ifdef WITH_LCD
12 #include "fonts.h"
13 #include "LCD.h"
14 #endif
15
16 int usbattached = 0;
17
18 //=============================================================================
19 // A buffer where we can queue things up to be sent through the FPGA, for
20 // any purpose (fake tag, as reader, whatever). We go MSB first, since that
21 // is the order in which they go out on the wire.
22 //=============================================================================
23
24 BYTE ToSend[256];
25 int ToSendMax;
26 static int ToSendBit;
27
28 void BufferClear(void)
29 {
30 memset(BigBuf,0,sizeof(BigBuf));
31 DbpString("Buffer cleared");
32 }
33
34 void ToSendReset(void)
35 {
36 ToSendMax = -1;
37 ToSendBit = 8;
38 }
39
40 void ToSendStuffBit(int b)
41 {
42 if(ToSendBit >= 8) {
43 ToSendMax++;
44 ToSend[ToSendMax] = 0;
45 ToSendBit = 0;
46 }
47
48 if(b) {
49 ToSend[ToSendMax] |= (1 << (7 - ToSendBit));
50 }
51
52 ToSendBit++;
53
54 if(ToSendBit >= sizeof(ToSend)) {
55 ToSendBit = 0;
56 DbpString("ToSendStuffBit overflowed!");
57 }
58 }
59
60 //=============================================================================
61 // Debug print functions, to go out over USB, to the usual PC-side client.
62 //=============================================================================
63
64 void DbpString(char *str)
65 {
66 /* this holds up stuff unless we're connected to usb */
67 // if (!usbattached)
68 // return;
69
70 UsbCommand c;
71 c.cmd = CMD_DEBUG_PRINT_STRING;
72 c.ext1 = strlen(str);
73 memcpy(c.d.asBytes, str, c.ext1);
74
75 UsbSendPacket((BYTE *)&c, sizeof(c));
76 // TODO fix USB so stupid things like this aren't req'd
77 SpinDelay(50);
78 }
79
80 void DbpIntegers(int x1, int x2, int x3)
81 {
82 /* this holds up stuff unless we're connected to usb */
83 // if (!usbattached)
84 // return;
85
86 UsbCommand c;
87 c.cmd = CMD_DEBUG_PRINT_INTEGERS;
88 c.ext1 = x1;
89 c.ext2 = x2;
90 c.ext3 = x3;
91
92 UsbSendPacket((BYTE *)&c, sizeof(c));
93 // XXX
94 SpinDelay(50);
95 }
96
97 //-----------------------------------------------------------------------------
98 // Read an ADC channel and block till it completes, then return the result
99 // in ADC units (0 to 1023). Also a routine to average 32 samples and
100 // return that.
101 //-----------------------------------------------------------------------------
102 static int ReadAdc(int ch)
103 {
104 DWORD d;
105
106 ADC_CONTROL = ADC_CONTROL_RESET;
107 ADC_MODE = ADC_MODE_PRESCALE(32) | ADC_MODE_STARTUP_TIME(16) |
108 ADC_MODE_SAMPLE_HOLD_TIME(8);
109 ADC_CHANNEL_ENABLE = ADC_CHANNEL(ch);
110
111 ADC_CONTROL = ADC_CONTROL_START;
112 while(!(ADC_STATUS & ADC_END_OF_CONVERSION(ch)))
113 ;
114 d = ADC_CHANNEL_DATA(ch);
115
116 return d;
117 }
118
119 static int AvgAdc(int ch)
120 {
121 int i;
122 int a = 0;
123
124 for(i = 0; i < 32; i++) {
125 a += ReadAdc(ch);
126 }
127
128 return (a + 15) >> 5;
129 }
130
131 void MeasureAntennaTuning(void)
132 {
133 BYTE *dest = (BYTE *)BigBuf;
134 int i, ptr = 0, adcval = 0, peak = 0, peakv = 0, peakf = 0;;
135 int vLf125 = 0, vLf134 = 0, vHf = 0; // in mV
136
137 UsbCommand c;
138
139 DbpString("Measuring antenna characteristics, please wait.");
140 memset(BigBuf,0,sizeof(BigBuf));
141
142 /*
143 * Sweeps the useful LF range of the proxmark from
144 * 46.8kHz (divisor=255) to 600kHz (divisor=19) and
145 * read the voltage in the antenna, the result left
146 * in the buffer is a graph which should clearly show
147 * the resonating frequency of your LF antenna
148 * ( hopefully around 95 if it is tuned to 125kHz!)
149 */
150 FpgaWriteConfWord(FPGA_MAJOR_MODE_LF_READER);
151 for (i=255; i>19; i--) {
152 FpgaSendCommand(FPGA_CMD_SET_DIVISOR, i);
153 SpinDelay(20);
154 // Vref = 3.3V, and a 10000:240 voltage divider on the input
155 // can measure voltages up to 137500 mV
156 adcval = ((137500 * AvgAdc(ADC_CHAN_LF)) >> 10);
157 if (i==95) vLf125 = adcval; // voltage at 125Khz
158 if (i==89) vLf134 = adcval; // voltage at 134Khz
159
160 dest[i] = adcval>>8; // scale int to fit in byte for graphing purposes
161 if(dest[i] > peak) {
162 peakv = adcval;
163 peak = dest[i];
164 peakf = i;
165 ptr = i;
166 }
167 }
168
169 // Let the FPGA drive the high-frequency antenna around 13.56 MHz.
170 FpgaWriteConfWord(FPGA_MAJOR_MODE_HF_READER_RX_XCORR);
171 SpinDelay(20);
172 // Vref = 3300mV, and an 10:1 voltage divider on the input
173 // can measure voltages up to 33000 mV
174 vHf = (33000 * AvgAdc(ADC_CHAN_HF)) >> 10;
175
176 c.cmd = CMD_MEASURED_ANTENNA_TUNING;
177 c.ext1 = (vLf125 << 0) | (vLf134 << 16);
178 c.ext2 = vHf;
179 c.ext3 = peakf | (peakv << 16);
180 UsbSendPacket((BYTE *)&c, sizeof(c));
181 }
182
183 void SimulateTagHfListen(void)
184 {
185 BYTE *dest = (BYTE *)BigBuf;
186 int n = sizeof(BigBuf);
187 BYTE v = 0;
188 int i;
189 int p = 0;
190
191 // We're using this mode just so that I can test it out; the simulated
192 // tag mode would work just as well and be simpler.
193 FpgaWriteConfWord(FPGA_MAJOR_MODE_HF_READER_RX_XCORR | FPGA_HF_READER_RX_XCORR_848_KHZ | FPGA_HF_READER_RX_XCORR_SNOOP);
194
195 // We need to listen to the high-frequency, peak-detected path.
196 SetAdcMuxFor(GPIO_MUXSEL_HIPKD);
197
198 FpgaSetupSsc();
199
200 i = 0;
201 for(;;) {
202 if(SSC_STATUS & (SSC_STATUS_TX_READY)) {
203 SSC_TRANSMIT_HOLDING = 0xff;
204 }
205 if(SSC_STATUS & (SSC_STATUS_RX_READY)) {
206 BYTE r = (BYTE)SSC_RECEIVE_HOLDING;
207
208 v <<= 1;
209 if(r & 1) {
210 v |= 1;
211 }
212 p++;
213
214 if(p >= 8) {
215 dest[i] = v;
216 v = 0;
217 p = 0;
218 i++;
219
220 if(i >= n) {
221 break;
222 }
223 }
224 }
225 }
226 DbpString("simulate tag (now type bitsamples)");
227 }
228
229 void ReadMem(int addr)
230 {
231 const DWORD *data = ((DWORD *)addr);
232 int i;
233
234 DbpString("Reading memory at address");
235 DbpIntegers(0, 0, addr);
236 for (i = 0; i < 8; i+= 2)
237 DbpIntegers(0, data[i], data[i+1]);
238 }
239
240 // samy's sniff and repeat routine
241 void SamyRun()
242 {
243 DbpString("Stand-alone mode! No PC necessary.");
244
245 // 3 possible options? no just 2 for now
246 #define OPTS 2
247
248 int high[OPTS], low[OPTS];
249
250 // Oooh pretty -- notify user we're in elite samy mode now
251 LED(LED_RED, 200);
252 LED(LED_ORANGE, 200);
253 LED(LED_GREEN, 200);
254 LED(LED_ORANGE, 200);
255 LED(LED_RED, 200);
256 LED(LED_ORANGE, 200);
257 LED(LED_GREEN, 200);
258 LED(LED_ORANGE, 200);
259 LED(LED_RED, 200);
260
261 int selected = 0;
262 int playing = 0;
263
264 // Turn on selected LED
265 LED(selected + 1, 0);
266
267 for (;;)
268 {
269 usbattached = UsbPoll(FALSE);
270 WDT_HIT();
271
272 // Was our button held down or pressed?
273 int button_pressed = BUTTON_HELD(1000);
274 SpinDelay(300);
275
276 // Button was held for a second, begin recording
277 if (button_pressed > 0)
278 {
279 LEDsoff();
280 LED(selected + 1, 0);
281 LED(LED_RED2, 0);
282
283 // record
284 DbpString("Starting recording");
285
286 // wait for button to be released
287 while(BUTTON_PRESS())
288 WDT_HIT();
289
290 /* need this delay to prevent catching some weird data */
291 SpinDelay(500);
292
293 CmdHIDdemodFSK(1, &high[selected], &low[selected], 0);
294 DbpString("Recorded");
295 DbpIntegers(selected, high[selected], low[selected]);
296
297 LEDsoff();
298 LED(selected + 1, 0);
299 // Finished recording
300
301 // If we were previously playing, set playing off
302 // so next button push begins playing what we recorded
303 playing = 0;
304 }
305
306 // Change where to record (or begin playing)
307 else if (button_pressed)
308 {
309 // Next option if we were previously playing
310 if (playing)
311 selected = (selected + 1) % OPTS;
312 playing = !playing;
313
314 LEDsoff();
315 LED(selected + 1, 0);
316
317 // Begin transmitting
318 if (playing)
319 {
320 LED(LED_GREEN, 0);
321 DbpString("Playing");
322 // wait for button to be released
323 while(BUTTON_PRESS())
324 WDT_HIT();
325 DbpIntegers(selected, high[selected], low[selected]);
326 CmdHIDsimTAG(high[selected], low[selected], 0);
327 DbpString("Done playing");
328 if (BUTTON_HELD(1000) > 0)
329 {
330 DbpString("Exiting");
331 LEDsoff();
332 return;
333 }
334
335 /* We pressed a button so ignore it here with a delay */
336 SpinDelay(300);
337
338 // when done, we're done playing, move to next option
339 selected = (selected + 1) % OPTS;
340 playing = !playing;
341 LEDsoff();
342 LED(selected + 1, 0);
343 }
344 else
345 while(BUTTON_PRESS())
346 WDT_HIT();
347 }
348 }
349 }
350
351
352 /*
353 OBJECTIVE
354 Listen and detect an external reader. Determine the best location
355 for the antenna.
356
357 INSTRUCTIONS:
358 Inside the ListenReaderField() function, there is two mode.
359 By default, when you call the function, you will enter mode 1.
360 If you press the PM3 button one time, you will enter mode 2.
361 If you press the PM3 button a second time, you will exit the function.
362
363 DESCRIPTION OF MODE 1:
364 This mode just listens for an external reader field and lights up green
365 for HF and/or red for LF. This is the original mode of the detectreader
366 function.
367
368 DESCRIPTION OF MODE 2:
369 This mode will visually represent, using the LEDs, the actual strength of the
370 current compared to the maximum current detected. Basically, once you know
371 what kind of external reader is present, it will help you spot the best location to place
372 your antenna. You will probably not get some good results if there is a LF and a HF reader
373 at the same place! :-)
374
375 LIGHT SCHEME USED:
376
377 Light scheme | Descriptiong
378 ----------------------------------------------------
379 ---- | No field detected
380 X--- | 14% of maximum current detected
381 -X-- | 29% of maximum current detected
382 --X- | 43% of maximum current detected
383 ---X | 57% of maximum current detected
384 --XX | 71% of maximum current detected
385 -XXX | 86% of maximum current detected
386 XXXX | 100% of maximum current detected
387
388 TODO:
389 Add the LF part for MODE 2
390
391 */
392 void ListenReaderField(int limit)
393 {
394 int lf_av, lf_av_new, lf_baseline= 0, lf_count= 0;
395 int hf_av, hf_av_new, hf_baseline= 0, hf_count= 0, hf_max;
396 int mode=1;
397
398 #define LF_ONLY 1
399 #define HF_ONLY 2
400
401 LED_A_OFF();
402 LED_B_OFF();
403 LED_C_OFF();
404 LED_D_OFF();
405
406 lf_av= ReadAdc(ADC_CHAN_LF);
407
408 if(limit != HF_ONLY)
409 {
410 DbpString("LF 125/134 Baseline:");
411 DbpIntegers(lf_av,0,0);
412 lf_baseline= lf_av;
413 }
414
415 hf_av=hf_max=ReadAdc(ADC_CHAN_HF);
416
417 if (limit != LF_ONLY)
418 {
419 DbpString("HF 13.56 Baseline:");
420 DbpIntegers(hf_av,0,0);
421 hf_baseline= hf_av;
422 }
423
424 for(;;)
425 {
426 if (BUTTON_PRESS()) {
427 SpinDelay(500);
428 switch (mode) {
429 case 1:
430 mode=2;
431 DbpString("Signal Strength Mode");
432 break;
433 case 2:
434 default:
435 DbpString("Stopped");
436 LED_A_OFF();
437 LED_B_OFF();
438 LED_C_OFF();
439 LED_D_OFF();
440 return;
441 break;
442 }
443 }
444 WDT_HIT();
445
446 if (limit != HF_ONLY)
447 {
448 if (abs(lf_av - lf_baseline) > 10)
449 LED_D_ON();
450 else
451 LED_D_OFF();
452 ++lf_count;
453 lf_av_new= ReadAdc(ADC_CHAN_LF);
454 // see if there's a significant change
455 if(abs(lf_av - lf_av_new) > 10)
456 {
457 DbpString("LF 125/134 Field Change:");
458 DbpIntegers(lf_av,lf_av_new,lf_count);
459 lf_av= lf_av_new;
460 lf_count= 0;
461 }
462 }
463
464 if (limit != LF_ONLY)
465 {
466 if (abs(hf_av - hf_baseline) > 10) {
467 if (mode == 1)
468 LED_B_ON();
469 if (mode == 2) {
470 if ( hf_av>(hf_max/7)*6) {
471 LED_A_ON(); LED_B_ON(); LED_C_ON(); LED_D_ON();
472 }
473 if ( (hf_av>(hf_max/7)*5) && (hf_av<=(hf_max/7)*6) ) {
474 LED_A_ON(); LED_B_ON(); LED_C_OFF(); LED_D_ON();
475 }
476 if ( (hf_av>(hf_max/7)*4) && (hf_av<=(hf_max/7)*5) ) {
477 LED_A_OFF(); LED_B_ON(); LED_C_OFF(); LED_D_ON();
478 }
479 if ( (hf_av>(hf_max/7)*3) && (hf_av<=(hf_max/7)*4) ) {
480 LED_A_OFF(); LED_B_OFF(); LED_C_OFF(); LED_D_ON();
481 }
482 if ( (hf_av>(hf_max/7)*2) && (hf_av<=(hf_max/7)*3) ) {
483 LED_A_OFF(); LED_B_ON(); LED_C_OFF(); LED_D_OFF();
484 }
485 if ( (hf_av>(hf_max/7)*1) && (hf_av<=(hf_max/7)*2) ) {
486 LED_A_ON(); LED_B_OFF(); LED_C_OFF(); LED_D_OFF();
487 }
488 if ( (hf_av>(hf_max/7)*0) && (hf_av<=(hf_max/7)*1) ) {
489 LED_A_OFF(); LED_B_OFF(); LED_C_ON(); LED_D_OFF();
490 }
491 }
492 } else {
493 if (mode == 1) {
494 LED_B_OFF();
495 }
496 if (mode == 2) {
497 LED_A_OFF(); LED_B_OFF(); LED_C_OFF(); LED_D_OFF();
498 }
499 }
500
501 ++hf_count;
502 hf_av_new= ReadAdc(ADC_CHAN_HF);
503 // see if there's a significant change
504 if(abs(hf_av - hf_av_new) > 10)
505 {
506 DbpString("HF 13.56 Field Change:");
507 DbpIntegers(hf_av,hf_av_new,hf_count);
508 hf_av= hf_av_new;
509 if (hf_av > hf_max)
510 hf_max = hf_av;
511 hf_count= 0;
512 }
513 }
514 }
515 }
516
517 void UsbPacketReceived(BYTE *packet, int len)
518 {
519 UsbCommand *c = (UsbCommand *)packet;
520
521 switch(c->cmd) {
522 case CMD_ACQUIRE_RAW_ADC_SAMPLES_125K:
523 AcquireRawAdcSamples125k(c->ext1);
524 break;
525
526 case CMD_MOD_THEN_ACQUIRE_RAW_ADC_SAMPLES_125K:
527 ModThenAcquireRawAdcSamples125k(c->ext1,c->ext2,c->ext3,c->d.asBytes);
528 break;
529
530 case CMD_ACQUIRE_RAW_ADC_SAMPLES_ISO_15693:
531 AcquireRawAdcSamplesIso15693();
532 break;
533
534 case CMD_BUFF_CLEAR:
535 BufferClear();
536 break;
537
538 case CMD_READER_ISO_15693:
539 ReaderIso15693(c->ext1);
540 break;
541
542 case CMD_SIMTAG_ISO_15693:
543 SimTagIso15693(c->ext1);
544 break;
545
546 case CMD_ACQUIRE_RAW_ADC_SAMPLES_ISO_14443:
547 AcquireRawAdcSamplesIso14443(c->ext1);
548 break;
549
550 case CMD_READ_SRI512_TAG:
551 ReadSRI512Iso14443(c->ext1);
552 break;
553
554 case CMD_READER_ISO_14443a:
555 ReaderIso14443a(c->ext1);
556 break;
557
558 case CMD_SNOOP_ISO_14443:
559 SnoopIso14443();
560 break;
561
562 case CMD_SNOOP_ISO_14443a:
563 SnoopIso14443a();
564 break;
565
566 case CMD_SIMULATE_TAG_HF_LISTEN:
567 SimulateTagHfListen();
568 break;
569
570 case CMD_SIMULATE_TAG_ISO_14443:
571 SimulateIso14443Tag();
572 break;
573
574 case CMD_SIMULATE_TAG_ISO_14443a:
575 SimulateIso14443aTag(c->ext1, c->ext2); // ## Simulate iso14443a tag - pass tag type & UID
576 break;
577
578 case CMD_MEASURE_ANTENNA_TUNING:
579 MeasureAntennaTuning();
580 break;
581
582 case CMD_LISTEN_READER_FIELD:
583 ListenReaderField(c->ext1);
584 break;
585
586 case CMD_HID_DEMOD_FSK:
587 CmdHIDdemodFSK(0, 0, 0, 1); // Demodulate HID tag
588 break;
589
590 case CMD_HID_SIM_TAG:
591 CmdHIDsimTAG(c->ext1, c->ext2, 1); // Simulate HID tag by ID
592 break;
593
594 case CMD_FPGA_MAJOR_MODE_OFF: // ## FPGA Control
595 FpgaWriteConfWord(FPGA_MAJOR_MODE_OFF);
596 SpinDelay(200);
597 LED_D_OFF(); // LED D indicates field ON or OFF
598 break;
599
600 case CMD_ACQUIRE_RAW_BITS_TI_TYPE:
601 AcquireRawBitsTI();
602 break;
603
604 case CMD_READ_TI_TYPE:
605 ReadTItag();
606 break;
607
608 case CMD_WRITE_TI_TYPE:
609 WriteTItag(c->ext1,c->ext2,c->ext3);
610 break;
611
612 case CMD_DOWNLOAD_RAW_ADC_SAMPLES_125K:
613 case CMD_DOWNLOAD_RAW_BITS_TI_TYPE: {
614 UsbCommand n;
615 if(c->cmd == CMD_DOWNLOAD_RAW_ADC_SAMPLES_125K) {
616 n.cmd = CMD_DOWNLOADED_RAW_ADC_SAMPLES_125K;
617 } else {
618 n.cmd = CMD_DOWNLOADED_RAW_BITS_TI_TYPE;
619 }
620 n.ext1 = c->ext1;
621 memcpy(n.d.asDwords, BigBuf+c->ext1, 12*sizeof(DWORD));
622 UsbSendPacket((BYTE *)&n, sizeof(n));
623 break;
624 }
625 case CMD_DOWNLOADED_SIM_SAMPLES_125K: {
626 BYTE *b = (BYTE *)BigBuf;
627 memcpy(b+c->ext1, c->d.asBytes, 48);
628 break;
629 }
630 case CMD_SIMULATE_TAG_125K:
631 LED_A_ON();
632 SimulateTagLowFrequency(c->ext1, 1);
633 LED_A_OFF();
634 break;
635 #ifdef WITH_LCD
636 case CMD_LCD_RESET:
637 LCDReset();
638 break;
639 #endif
640 case CMD_READ_MEM:
641 ReadMem(c->ext1);
642 break;
643 case CMD_SET_LF_DIVISOR:
644 FpgaSendCommand(FPGA_CMD_SET_DIVISOR, c->ext1);
645 break;
646 #ifdef WITH_LCD
647 case CMD_LCD:
648 LCDSend(c->ext1);
649 break;
650 #endif
651 case CMD_SETUP_WRITE:
652 case CMD_FINISH_WRITE:
653 case CMD_HARDWARE_RESET:
654 USB_D_PLUS_PULLUP_OFF();
655 SpinDelay(1000);
656 SpinDelay(1000);
657 RSTC_CONTROL = RST_CONTROL_KEY | RST_CONTROL_PROCESSOR_RESET;
658 for(;;) {
659 // We're going to reset, and the bootrom will take control.
660 }
661 break;
662
663
664 default:
665 DbpString("unknown command");
666 break;
667 }
668 }
669
670 void AppMain(void)
671 {
672 memset(BigBuf,0,sizeof(BigBuf));
673 SpinDelay(100);
674
675 LED_D_OFF();
676 LED_C_OFF();
677 LED_B_OFF();
678 LED_A_OFF();
679
680 UsbStart();
681
682 // The FPGA gets its clock from us from PCK0 output, so set that up.
683 PIO_PERIPHERAL_B_SEL = (1 << GPIO_PCK0);
684 PIO_DISABLE = (1 << GPIO_PCK0);
685 PMC_SYS_CLK_ENABLE = PMC_SYS_CLK_PROGRAMMABLE_CLK_0;
686 // PCK0 is PLL clock / 4 = 96Mhz / 4 = 24Mhz
687 PMC_PROGRAMMABLE_CLK_0 = PMC_CLK_SELECTION_PLL_CLOCK |
688 PMC_CLK_PRESCALE_DIV_4;
689 PIO_OUTPUT_ENABLE = (1 << GPIO_PCK0);
690
691 // Reset SPI
692 SPI_CONTROL = SPI_CONTROL_RESET;
693 // Reset SSC
694 SSC_CONTROL = SSC_CONTROL_RESET;
695
696 // Load the FPGA image, which we have stored in our flash.
697 FpgaDownloadAndGo();
698
699 #ifdef WITH_LCD
700
701 LCDInit();
702
703 // test text on different colored backgrounds
704 LCDString(" The quick brown fox ", &FONT6x8,1,1+8*0,WHITE ,BLACK );
705 LCDString(" jumped over the ", &FONT6x8,1,1+8*1,BLACK ,WHITE );
706 LCDString(" lazy dog. ", &FONT6x8,1,1+8*2,YELLOW ,RED );
707 LCDString(" AaBbCcDdEeFfGgHhIiJj ", &FONT6x8,1,1+8*3,RED ,GREEN );
708 LCDString(" KkLlMmNnOoPpQqRrSsTt ", &FONT6x8,1,1+8*4,MAGENTA,BLUE );
709 LCDString("UuVvWwXxYyZz0123456789", &FONT6x8,1,1+8*5,BLUE ,YELLOW);
710 LCDString("`-=[]_;',./~!@#$%^&*()", &FONT6x8,1,1+8*6,BLACK ,CYAN );
711 LCDString(" _+{}|:\\\"<>? ",&FONT6x8,1,1+8*7,BLUE ,MAGENTA);
712
713 // color bands
714 LCDFill(0, 1+8* 8, 132, 8, BLACK);
715 LCDFill(0, 1+8* 9, 132, 8, WHITE);
716 LCDFill(0, 1+8*10, 132, 8, RED);
717 LCDFill(0, 1+8*11, 132, 8, GREEN);
718 LCDFill(0, 1+8*12, 132, 8, BLUE);
719 LCDFill(0, 1+8*13, 132, 8, YELLOW);
720 LCDFill(0, 1+8*14, 132, 8, CYAN);
721 LCDFill(0, 1+8*15, 132, 8, MAGENTA);
722
723 #endif
724
725 for(;;) {
726 usbattached = UsbPoll(FALSE);
727 WDT_HIT();
728
729 if (BUTTON_HELD(1000) > 0)
730 SamyRun();
731 }
732 }
Impressum, Datenschutz