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