1 //-----------------------------------------------------------------------------
2 // The main application code. This is the first thing called after start.c
4 // Jonathan Westhues, Mar 2006
5 // Edits by Gerhard de Koning Gans, Sep 2007 (##)
6 //-----------------------------------------------------------------------------
23 #define abs(x) ( ((x)<0) ? -(x) : (x) )
25 //=============================================================================
26 // A buffer where we can queue things up to be sent through the FPGA, for
27 // any purpose (fake tag, as reader, whatever). We go MSB first, since that
28 // is the order in which they go out on the wire.
29 //=============================================================================
34 struct common_area common_area
__attribute__((section(".commonarea")));
36 void BufferClear(void)
38 memset(BigBuf
,0,sizeof(BigBuf
));
39 Dbprintf("Buffer cleared (%i bytes)",sizeof(BigBuf
));
42 void ToSendReset(void)
48 void ToSendStuffBit(int b
)
52 ToSend
[ToSendMax
] = 0;
57 ToSend
[ToSendMax
] |= (1 << (7 - ToSendBit
));
62 if(ToSendBit
>= sizeof(ToSend
)) {
64 DbpString("ToSendStuffBit overflowed!");
68 //=============================================================================
69 // Debug print functions, to go out over USB, to the usual PC-side client.
70 //=============================================================================
72 void DbpString(char *str
)
74 /* this holds up stuff unless we're connected to usb */
79 c
.cmd
= CMD_DEBUG_PRINT_STRING
;
80 c
.arg
[0] = strlen(str
);
81 if(c
.arg
[0] > sizeof(c
.d
.asBytes
)) {
82 c
.arg
[0] = sizeof(c
.d
.asBytes
);
84 memcpy(c
.d
.asBytes
, str
, c
.arg
[0]);
86 UsbSendPacket((uint8_t *)&c
, sizeof(c
));
87 // TODO fix USB so stupid things like this aren't req'd
92 void DbpIntegers(int x1
, int x2
, int x3
)
94 /* this holds up stuff unless we're connected to usb */
99 c
.cmd
= CMD_DEBUG_PRINT_INTEGERS
;
104 UsbSendPacket((uint8_t *)&c
, sizeof(c
));
110 void Dbprintf(const char *fmt
, ...) {
111 // should probably limit size here; oh well, let's just use a big buffer
112 char output_string
[128];
116 kvsprintf(fmt
, output_string
, 10, ap
);
119 DbpString(output_string
);
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 32 samples and
126 //-----------------------------------------------------------------------------
127 static int ReadAdc(int ch
)
131 AT91C_BASE_ADC
->ADC_CR
= AT91C_ADC_SWRST
;
132 AT91C_BASE_ADC
->ADC_MR
=
133 ADC_MODE_PRESCALE(32) |
134 ADC_MODE_STARTUP_TIME(16) |
135 ADC_MODE_SAMPLE_HOLD_TIME(8);
136 AT91C_BASE_ADC
->ADC_CHER
= ADC_CHANNEL(ch
);
138 AT91C_BASE_ADC
->ADC_CR
= AT91C_ADC_START
;
139 while(!(AT91C_BASE_ADC
->ADC_SR
& ADC_END_OF_CONVERSION(ch
)))
141 d
= AT91C_BASE_ADC
->ADC_CDR
[ch
];
146 static int AvgAdc(int ch
)
151 for(i
= 0; i
< 32; i
++) {
155 return (a
+ 15) >> 5;
158 void MeasureAntennaTuning(void)
160 uint8_t *dest
= (uint8_t *)BigBuf
;
161 int i
, ptr
= 0, adcval
= 0, peak
= 0, peakv
= 0, peakf
= 0;;
162 int vLf125
= 0, vLf134
= 0, vHf
= 0; // in mV
166 DbpString("Measuring antenna characteristics, please wait.");
167 memset(BigBuf
,0,sizeof(BigBuf
));
170 * Sweeps the useful LF range of the proxmark from
171 * 46.8kHz (divisor=255) to 600kHz (divisor=19) and
172 * read the voltage in the antenna, the result left
173 * in the buffer is a graph which should clearly show
174 * the resonating frequency of your LF antenna
175 * ( hopefully around 95 if it is tuned to 125kHz!)
177 FpgaWriteConfWord(FPGA_MAJOR_MODE_LF_READER
);
178 for (i
=255; i
>19; i
--) {
179 FpgaSendCommand(FPGA_CMD_SET_DIVISOR
, i
);
181 // Vref = 3.3V, and a 10000:240 voltage divider on the input
182 // can measure voltages up to 137500 mV
183 adcval
= ((137500 * AvgAdc(ADC_CHAN_LF
)) >> 10);
184 if (i
==95) vLf125
= adcval
; // voltage at 125Khz
185 if (i
==89) vLf134
= adcval
; // voltage at 134Khz
187 dest
[i
] = adcval
>>8; // scale int to fit in byte for graphing purposes
196 // Let the FPGA drive the high-frequency antenna around 13.56 MHz.
197 FpgaWriteConfWord(FPGA_MAJOR_MODE_HF_READER_RX_XCORR
);
199 // Vref = 3300mV, and an 10:1 voltage divider on the input
200 // can measure voltages up to 33000 mV
201 vHf
= (33000 * AvgAdc(ADC_CHAN_HF
)) >> 10;
203 c
.cmd
= CMD_MEASURED_ANTENNA_TUNING
;
204 c
.arg
[0] = (vLf125
<< 0) | (vLf134
<< 16);
206 c
.arg
[2] = peakf
| (peakv
<< 16);
207 UsbSendPacket((uint8_t *)&c
, sizeof(c
));
210 void MeasureAntennaTuningHf(void)
212 int vHf
= 0; // in mV
214 DbpString("Measuring HF antenna, press button to exit");
217 // Let the FPGA drive the high-frequency antenna around 13.56 MHz.
218 FpgaWriteConfWord(FPGA_MAJOR_MODE_HF_READER_RX_XCORR
);
220 // Vref = 3300mV, and an 10:1 voltage divider on the input
221 // can measure voltages up to 33000 mV
222 vHf
= (33000 * AvgAdc(ADC_CHAN_HF
)) >> 10;
224 Dbprintf("%d mV",vHf
);
225 if (BUTTON_PRESS()) break;
227 DbpString("cancelled");
231 void SimulateTagHfListen(void)
233 uint8_t *dest
= (uint8_t *)BigBuf
;
234 int n
= sizeof(BigBuf
);
239 // We're using this mode just so that I can test it out; the simulated
240 // tag mode would work just as well and be simpler.
241 FpgaWriteConfWord(FPGA_MAJOR_MODE_HF_READER_RX_XCORR
| FPGA_HF_READER_RX_XCORR_848_KHZ
| FPGA_HF_READER_RX_XCORR_SNOOP
);
243 // We need to listen to the high-frequency, peak-detected path.
244 SetAdcMuxFor(GPIO_MUXSEL_HIPKD
);
250 if(AT91C_BASE_SSC
->SSC_SR
& (AT91C_SSC_TXRDY
)) {
251 AT91C_BASE_SSC
->SSC_THR
= 0xff;
253 if(AT91C_BASE_SSC
->SSC_SR
& (AT91C_SSC_RXRDY
)) {
254 uint8_t r
= (uint8_t)AT91C_BASE_SSC
->SSC_RHR
;
274 DbpString("simulate tag (now type bitsamples)");
277 void ReadMem(int addr
)
279 const uint8_t *data
= ((uint8_t *)addr
);
281 Dbprintf("%x: %02x %02x %02x %02x %02x %02x %02x %02x",
282 addr
, data
[0], data
[1], data
[2], data
[3], data
[4], data
[5], data
[6], data
[7]);
285 /* osimage version information is linked in */
286 extern struct version_information version_information
;
287 /* bootrom version information is pointed to from _bootphase1_version_pointer */
288 extern char *_bootphase1_version_pointer
, _flash_start
, _flash_end
;
289 void SendVersion(void)
291 char temp
[48]; /* Limited data payload in USB packets */
292 DbpString("Prox/RFID mark3 RFID instrument");
294 /* Try to find the bootrom version information. Expect to find a pointer at
295 * symbol _bootphase1_version_pointer, perform slight sanity checks on the
296 * pointer, then use it.
298 char *bootrom_version
= *(char**)&_bootphase1_version_pointer
;
299 if( bootrom_version
< &_flash_start
|| bootrom_version
>= &_flash_end
) {
300 DbpString("bootrom version information appears invalid");
302 FormatVersionInformation(temp
, sizeof(temp
), "bootrom: ", bootrom_version
);
306 FormatVersionInformation(temp
, sizeof(temp
), "os: ", &version_information
);
309 FpgaGatherVersion(temp
, sizeof(temp
));
314 // samy's sniff and repeat routine
317 DbpString("Stand-alone mode! No PC necessary.");
319 // 3 possible options? no just 2 for now
322 int high
[OPTS
], low
[OPTS
];
324 // Oooh pretty -- notify user we're in elite samy mode now
326 LED(LED_ORANGE
, 200);
328 LED(LED_ORANGE
, 200);
330 LED(LED_ORANGE
, 200);
332 LED(LED_ORANGE
, 200);
338 // Turn on selected LED
339 LED(selected
+ 1, 0);
346 // Was our button held down or pressed?
347 int button_pressed
= BUTTON_HELD(1000);
350 // Button was held for a second, begin recording
351 if (button_pressed
> 0)
354 LED(selected
+ 1, 0);
358 DbpString("Starting recording");
360 // wait for button to be released
361 while(BUTTON_PRESS())
364 /* need this delay to prevent catching some weird data */
367 CmdHIDdemodFSK(1, &high
[selected
], &low
[selected
], 0);
368 Dbprintf("Recorded %x %x %x", selected
, high
[selected
], low
[selected
]);
371 LED(selected
+ 1, 0);
372 // Finished recording
374 // If we were previously playing, set playing off
375 // so next button push begins playing what we recorded
379 // Change where to record (or begin playing)
380 else if (button_pressed
)
382 // Next option if we were previously playing
384 selected
= (selected
+ 1) % OPTS
;
388 LED(selected
+ 1, 0);
390 // Begin transmitting
394 DbpString("Playing");
395 // wait for button to be released
396 while(BUTTON_PRESS())
398 Dbprintf("%x %x %x", selected
, high
[selected
], low
[selected
]);
399 CmdHIDsimTAG(high
[selected
], low
[selected
], 0);
400 DbpString("Done playing");
401 if (BUTTON_HELD(1000) > 0)
403 DbpString("Exiting");
408 /* We pressed a button so ignore it here with a delay */
411 // when done, we're done playing, move to next option
412 selected
= (selected
+ 1) % OPTS
;
415 LED(selected
+ 1, 0);
418 while(BUTTON_PRESS())
427 Listen and detect an external reader. Determine the best location
431 Inside the ListenReaderField() function, there is two mode.
432 By default, when you call the function, you will enter mode 1.
433 If you press the PM3 button one time, you will enter mode 2.
434 If you press the PM3 button a second time, you will exit the function.
436 DESCRIPTION OF MODE 1:
437 This mode just listens for an external reader field and lights up green
438 for HF and/or red for LF. This is the original mode of the detectreader
441 DESCRIPTION OF MODE 2:
442 This mode will visually represent, using the LEDs, the actual strength of the
443 current compared to the maximum current detected. Basically, once you know
444 what kind of external reader is present, it will help you spot the best location to place
445 your antenna. You will probably not get some good results if there is a LF and a HF reader
446 at the same place! :-)
450 static const char LIGHT_SCHEME
[] = {
451 0x0, /* ---- | No field detected */
452 0x1, /* X--- | 14% of maximum current detected */
453 0x2, /* -X-- | 29% of maximum current detected */
454 0x4, /* --X- | 43% of maximum current detected */
455 0x8, /* ---X | 57% of maximum current detected */
456 0xC, /* --XX | 71% of maximum current detected */
457 0xE, /* -XXX | 86% of maximum current detected */
458 0xF, /* XXXX | 100% of maximum current detected */
460 static const int LIGHT_LEN
= sizeof(LIGHT_SCHEME
)/sizeof(LIGHT_SCHEME
[0]);
462 void ListenReaderField(int limit
)
464 int lf_av
, lf_av_new
, lf_baseline
= 0, lf_count
= 0, lf_max
;
465 int hf_av
, hf_av_new
, hf_baseline
= 0, hf_count
= 0, hf_max
;
466 int mode
=1, display_val
, display_max
, i
;
473 lf_av
=lf_max
=ReadAdc(ADC_CHAN_LF
);
475 if(limit
!= HF_ONLY
) {
476 Dbprintf("LF 125/134 Baseline: %d", lf_av
);
480 hf_av
=hf_max
=ReadAdc(ADC_CHAN_HF
);
482 if (limit
!= LF_ONLY
) {
483 Dbprintf("HF 13.56 Baseline: %d", hf_av
);
488 if (BUTTON_PRESS()) {
493 DbpString("Signal Strength Mode");
497 DbpString("Stopped");
505 if (limit
!= HF_ONLY
) {
507 if (abs(lf_av
- lf_baseline
) > 10) LED_D_ON();
512 lf_av_new
= ReadAdc(ADC_CHAN_LF
);
513 // see if there's a significant change
514 if(abs(lf_av
- lf_av_new
) > 10) {
515 Dbprintf("LF 125/134 Field Change: %x %x %x", lf_av
, lf_av_new
, lf_count
);
523 if (limit
!= LF_ONLY
) {
525 if (abs(hf_av
- hf_baseline
) > 10) LED_B_ON();
530 hf_av_new
= ReadAdc(ADC_CHAN_HF
);
531 // see if there's a significant change
532 if(abs(hf_av
- hf_av_new
) > 10) {
533 Dbprintf("HF 13.56 Field Change: %x %x %x", hf_av
, hf_av_new
, hf_count
);
542 if (limit
== LF_ONLY
) {
544 display_max
= lf_max
;
545 } else if (limit
== HF_ONLY
) {
547 display_max
= hf_max
;
548 } else { /* Pick one at random */
549 if( (hf_max
- hf_baseline
) > (lf_max
- lf_baseline
) ) {
551 display_max
= hf_max
;
554 display_max
= lf_max
;
557 for (i
=0; i
<LIGHT_LEN
; i
++) {
558 if (display_val
>= ((display_max
/LIGHT_LEN
)*i
) && display_val
<= ((display_max
/LIGHT_LEN
)*(i
+1))) {
559 if (LIGHT_SCHEME
[i
] & 0x1) LED_C_ON(); else LED_C_OFF();
560 if (LIGHT_SCHEME
[i
] & 0x2) LED_A_ON(); else LED_A_OFF();
561 if (LIGHT_SCHEME
[i
] & 0x4) LED_B_ON(); else LED_B_OFF();
562 if (LIGHT_SCHEME
[i
] & 0x8) LED_D_ON(); else LED_D_OFF();
570 void UsbPacketReceived(uint8_t *packet
, int len
)
572 UsbCommand
*c
= (UsbCommand
*)packet
;
578 case CMD_ACQUIRE_RAW_ADC_SAMPLES_125K
:
579 AcquireRawAdcSamples125k(c
->arg
[0]);
580 UsbSendPacket((uint8_t*)&ack
, sizeof(ack
));
585 case CMD_MOD_THEN_ACQUIRE_RAW_ADC_SAMPLES_125K
:
586 ModThenAcquireRawAdcSamples125k(c
->arg
[0],c
->arg
[1],c
->arg
[2],c
->d
.asBytes
);
591 case CMD_ACQUIRE_RAW_ADC_SAMPLES_ISO_15693
:
592 AcquireRawAdcSamplesIso15693();
601 case CMD_READER_ISO_15693
:
602 ReaderIso15693(c
->arg
[0]);
606 case CMD_READER_LEGIC_RF
:
607 LegicRfReader(c
->arg
[0], c
->arg
[1]);
611 case CMD_SIMTAG_ISO_15693
:
612 SimTagIso15693(c
->arg
[0]);
616 #ifdef WITH_ISO14443b
617 case CMD_ACQUIRE_RAW_ADC_SAMPLES_ISO_14443
:
618 AcquireRawAdcSamplesIso14443(c
->arg
[0]);
622 #ifdef WITH_ISO14443b
623 case CMD_READ_SRI512_TAG
:
624 ReadSRI512Iso14443(c
->arg
[0]);
626 case CMD_READ_SRIX4K_TAG
:
627 ReadSRIX4KIso14443(c
->arg
[0]);
631 #ifdef WITH_ISO14443a
632 case CMD_READER_ISO_14443a
:
633 ReaderIso14443a(c
->arg
[0]);
637 #ifdef WITH_ISO14443a
638 case CMD_READER_MIFARE
:
639 ReaderMifare(c
->arg
[0]);
643 #ifdef WITH_ISO14443b
644 case CMD_SNOOP_ISO_14443
:
649 #ifdef WITH_ISO14443a
650 case CMD_SNOOP_ISO_14443a
:
655 case CMD_SIMULATE_TAG_HF_LISTEN
:
656 SimulateTagHfListen();
659 #ifdef WITH_ISO14443b
660 case CMD_SIMULATE_TAG_ISO_14443
:
661 SimulateIso14443Tag();
665 #ifdef WITH_ISO14443a
666 case CMD_SIMULATE_TAG_ISO_14443a
:
667 SimulateIso14443aTag(c
->arg
[0], c
->arg
[1]); // ## Simulate iso14443a tag - pass tag type & UID
671 case CMD_MEASURE_ANTENNA_TUNING
:
672 MeasureAntennaTuning();
675 case CMD_MEASURE_ANTENNA_TUNING_HF
:
676 MeasureAntennaTuningHf();
679 case CMD_LISTEN_READER_FIELD
:
680 ListenReaderField(c
->arg
[0]);
684 case CMD_HID_DEMOD_FSK
:
685 CmdHIDdemodFSK(0, 0, 0, 1); // Demodulate HID tag
690 case CMD_HID_SIM_TAG
:
691 CmdHIDsimTAG(c
->arg
[0], c
->arg
[1], 1); // Simulate HID tag by ID
695 case CMD_FPGA_MAJOR_MODE_OFF
: // ## FPGA Control
696 FpgaWriteConfWord(FPGA_MAJOR_MODE_OFF
);
698 LED_D_OFF(); // LED D indicates field ON or OFF
702 case CMD_READ_TI_TYPE
:
708 case CMD_WRITE_TI_TYPE
:
709 WriteTItag(c
->arg
[0],c
->arg
[1],c
->arg
[2]);
713 case CMD_DOWNLOAD_RAW_ADC_SAMPLES_125K
: {
715 if(c
->cmd
== CMD_DOWNLOAD_RAW_ADC_SAMPLES_125K
) {
716 n
.cmd
= CMD_DOWNLOADED_RAW_ADC_SAMPLES_125K
;
718 n
.cmd
= CMD_DOWNLOADED_RAW_BITS_TI_TYPE
;
720 n
.arg
[0] = c
->arg
[0];
721 memcpy(n
.d
.asDwords
, BigBuf
+c
->arg
[0], 12*sizeof(uint32_t));
722 UsbSendPacket((uint8_t *)&n
, sizeof(n
));
726 case CMD_DOWNLOADED_SIM_SAMPLES_125K
: {
727 uint8_t *b
= (uint8_t *)BigBuf
;
728 memcpy(b
+c
->arg
[0], c
->d
.asBytes
, 48);
729 //Dbprintf("copied 48 bytes to %i",b+c->arg[0]);
730 UsbSendPacket((uint8_t*)&ack
, sizeof(ack
));
735 case CMD_SIMULATE_TAG_125K
:
737 SimulateTagLowFrequency(c
->arg
[0], c
->arg
[1], 1);
746 case CMD_SET_LF_DIVISOR
:
747 FpgaSendCommand(FPGA_CMD_SET_DIVISOR
, c
->arg
[0]);
750 case CMD_SET_ADC_MUX
:
752 case 0: SetAdcMuxFor(GPIO_MUXSEL_LOPKD
); break;
753 case 1: SetAdcMuxFor(GPIO_MUXSEL_LORAW
); break;
754 case 2: SetAdcMuxFor(GPIO_MUXSEL_HIPKD
); break;
755 case 3: SetAdcMuxFor(GPIO_MUXSEL_HIRAW
); break;
764 case CMD_LF_SIMULATE_BIDIR
:
765 SimulateTagLowFrequencyBidir(c
->arg
[0], c
->arg
[1]);
777 case CMD_SETUP_WRITE
:
778 case CMD_FINISH_WRITE
:
779 case CMD_HARDWARE_RESET
:
780 USB_D_PLUS_PULLUP_OFF();
783 AT91C_BASE_RSTC
->RSTC_RCR
= RST_CONTROL_KEY
| AT91C_RSTC_PROCRST
;
785 // We're going to reset, and the bootrom will take control.
789 case CMD_START_FLASH
:
790 if(common_area
.flags
.bootrom_present
) {
791 common_area
.command
= COMMON_AREA_COMMAND_ENTER_FLASH_MODE
;
793 USB_D_PLUS_PULLUP_OFF();
794 AT91C_BASE_RSTC
->RSTC_RCR
= RST_CONTROL_KEY
| AT91C_RSTC_PROCRST
;
798 case CMD_DEVICE_INFO
: {
800 c
.cmd
= CMD_DEVICE_INFO
;
801 c
.arg
[0] = DEVICE_INFO_FLAG_OSIMAGE_PRESENT
| DEVICE_INFO_FLAG_CURRENT_MODE_OS
;
802 if(common_area
.flags
.bootrom_present
) c
.arg
[0] |= DEVICE_INFO_FLAG_BOOTROM_PRESENT
;
803 UsbSendPacket((uint8_t*)&c
, sizeof(c
));
807 Dbprintf("%s: 0x%04x","unknown command:",c
->cmd
);
812 void __attribute__((noreturn
)) AppMain(void)
816 if(common_area
.magic
!= COMMON_AREA_MAGIC
|| common_area
.version
!= 1) {
817 /* Initialize common area */
818 memset(&common_area
, 0, sizeof(common_area
));
819 common_area
.magic
= COMMON_AREA_MAGIC
;
820 common_area
.version
= 1;
822 common_area
.flags
.osimage_present
= 1;
831 // The FPGA gets its clock from us from PCK0 output, so set that up.
832 AT91C_BASE_PIOA
->PIO_BSR
= GPIO_PCK0
;
833 AT91C_BASE_PIOA
->PIO_PDR
= GPIO_PCK0
;
834 AT91C_BASE_PMC
->PMC_SCER
= AT91C_PMC_PCK0
;
835 // PCK0 is PLL clock / 4 = 96Mhz / 4 = 24Mhz
836 AT91C_BASE_PMC
->PMC_PCKR
[0] = AT91C_PMC_CSS_PLL_CLK
|
837 AT91C_PMC_PRES_CLK_4
;
838 AT91C_BASE_PIOA
->PIO_OER
= GPIO_PCK0
;
841 AT91C_BASE_SPI
->SPI_CR
= AT91C_SPI_SWRST
;
843 AT91C_BASE_SSC
->SSC_CR
= AT91C_SSC_SWRST
;
845 // Load the FPGA image, which we have stored in our flash.
852 // test text on different colored backgrounds
853 LCDString(" The quick brown fox ", (char *)&FONT6x8
,1,1+8*0,WHITE
,BLACK
);
854 LCDString(" jumped over the ", (char *)&FONT6x8
,1,1+8*1,BLACK
,WHITE
);
855 LCDString(" lazy dog. ", (char *)&FONT6x8
,1,1+8*2,YELLOW
,RED
);
856 LCDString(" AaBbCcDdEeFfGgHhIiJj ", (char *)&FONT6x8
,1,1+8*3,RED
,GREEN
);
857 LCDString(" KkLlMmNnOoPpQqRrSsTt ", (char *)&FONT6x8
,1,1+8*4,MAGENTA
,BLUE
);
858 LCDString("UuVvWwXxYyZz0123456789", (char *)&FONT6x8
,1,1+8*5,BLUE
,YELLOW
);
859 LCDString("`-=[]_;',./~!@#$%^&*()", (char *)&FONT6x8
,1,1+8*6,BLACK
,CYAN
);
860 LCDString(" _+{}|:\\\"<>? ",(char *)&FONT6x8
,1,1+8*7,BLUE
,MAGENTA
);
863 LCDFill(0, 1+8* 8, 132, 8, BLACK
);
864 LCDFill(0, 1+8* 9, 132, 8, WHITE
);
865 LCDFill(0, 1+8*10, 132, 8, RED
);
866 LCDFill(0, 1+8*11, 132, 8, GREEN
);
867 LCDFill(0, 1+8*12, 132, 8, BLUE
);
868 LCDFill(0, 1+8*13, 132, 8, YELLOW
);
869 LCDFill(0, 1+8*14, 132, 8, CYAN
);
870 LCDFill(0, 1+8*15, 132, 8, MAGENTA
);
879 if (BUTTON_HELD(1000) > 0)