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