]> git.zerfleddert.de Git - proxmark3-svn/blame - armsrc/appmain.c
Pushed standard AT91 defines into main code
[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
649 case CMD_VERSION:\r
650 SendVersion();\r
651 break;\r
652 case CMD_LF_SIMULATE_BIDIR:\r
653 SimulateTagLowFrequencyBidir(c->ext1, c->ext2);\r
654 break;\r
655#ifdef WITH_LCD\r
656 case CMD_LCD_RESET:\r
657 LCDReset();\r
658 break;\r
659 case CMD_LCD:\r
660 LCDSend(c->ext1);\r
661 break;\r
662#endif\r
663 case CMD_SETUP_WRITE:\r
664 case CMD_FINISH_WRITE:\r
665 case CMD_HARDWARE_RESET:\r
666 USB_D_PLUS_PULLUP_OFF();\r
667 SpinDelay(1000);\r
668 SpinDelay(1000);\r
669 AT91C_BASE_RSTC->RSTC_RCR = RST_CONTROL_KEY | AT91C_RSTC_PROCRST;\r
670 for(;;) {\r
671 // We're going to reset, and the bootrom will take control.\r
672 }\r
673 break;\r
674 case CMD_START_FLASH:\r
675 if(common_area.flags.bootrom_present) {\r
676 common_area.command = COMMON_AREA_COMMAND_ENTER_FLASH_MODE;\r
677 }\r
678 USB_D_PLUS_PULLUP_OFF();\r
679 AT91C_BASE_RSTC->RSTC_RCR = RST_CONTROL_KEY | AT91C_RSTC_PROCRST;\r
680 for(;;);\r
681 break;\r
682 \r
683 case CMD_DEVICE_INFO: {\r
684 UsbCommand c;\r
685 c.cmd = CMD_DEVICE_INFO;\r
686 c.ext1 = DEVICE_INFO_FLAG_OSIMAGE_PRESENT | DEVICE_INFO_FLAG_CURRENT_MODE_OS;\r
687 if(common_area.flags.bootrom_present) c.ext1 |= DEVICE_INFO_FLAG_BOOTROM_PRESENT;\r
688 UsbSendPacket((BYTE*)&c, sizeof(c));\r
689 }\r
690 break;\r
691 default:\r
692 DbpString("unknown command");\r
693 break;\r
694 }\r
695}\r
696\r
697void __attribute__((noreturn)) AppMain(void)\r
698{\r
699 SpinDelay(100);\r
700 \r
701 if(common_area.magic != COMMON_AREA_MAGIC || common_area.version != 1) {\r
702 /* Initialize common area */\r
703 memset(&common_area, 0, sizeof(common_area));\r
704 common_area.magic = COMMON_AREA_MAGIC;\r
705 common_area.version = 1;\r
706 }\r
707 common_area.flags.osimage_present = 1;\r
708\r
709 LED_D_OFF();\r
710 LED_C_OFF();\r
711 LED_B_OFF();\r
712 LED_A_OFF();\r
713\r
714 UsbStart();\r
715\r
716 // The FPGA gets its clock from us from PCK0 output, so set that up.\r
717 AT91C_BASE_PIOA->PIO_BSR = GPIO_PCK0;\r
718 AT91C_BASE_PIOA->PIO_PDR = GPIO_PCK0;\r
719 AT91C_BASE_PMC->PMC_SCER = AT91C_PMC_PCK0;\r
720 // PCK0 is PLL clock / 4 = 96Mhz / 4 = 24Mhz\r
721 AT91C_BASE_PMC->PMC_PCKR[0] = AT91C_PMC_CSS_PLL_CLK |\r
722 AT91C_PMC_PRES_CLK_4;\r
723 AT91C_BASE_PIOA->PIO_OER = GPIO_PCK0;\r
724\r
725 // Reset SPI\r
726 AT91C_BASE_SPI->SPI_CR = AT91C_SPI_SWRST;\r
727 // Reset SSC\r
728 AT91C_BASE_SSC->SSC_CR = AT91C_SSC_SWRST;\r
729\r
730 // Load the FPGA image, which we have stored in our flash.\r
731 FpgaDownloadAndGo();\r
732\r
733#ifdef WITH_LCD\r
734\r
735 LCDInit();\r
736\r
737 // test text on different colored backgrounds\r
738 LCDString(" The quick brown fox ", (char *)&FONT6x8,1,1+8*0,WHITE ,BLACK );\r
739 LCDString(" jumped over the ", (char *)&FONT6x8,1,1+8*1,BLACK ,WHITE );\r
740 LCDString(" lazy dog. ", (char *)&FONT6x8,1,1+8*2,YELLOW ,RED );\r
741 LCDString(" AaBbCcDdEeFfGgHhIiJj ", (char *)&FONT6x8,1,1+8*3,RED ,GREEN );\r
742 LCDString(" KkLlMmNnOoPpQqRrSsTt ", (char *)&FONT6x8,1,1+8*4,MAGENTA,BLUE );\r
743 LCDString("UuVvWwXxYyZz0123456789", (char *)&FONT6x8,1,1+8*5,BLUE ,YELLOW);\r
744 LCDString("`-=[]_;',./~!@#$%^&*()", (char *)&FONT6x8,1,1+8*6,BLACK ,CYAN );\r
745 LCDString(" _+{}|:\\\"<>? ",(char *)&FONT6x8,1,1+8*7,BLUE ,MAGENTA);\r
746\r
747 // color bands\r
748 LCDFill(0, 1+8* 8, 132, 8, BLACK);\r
749 LCDFill(0, 1+8* 9, 132, 8, WHITE);\r
750 LCDFill(0, 1+8*10, 132, 8, RED);\r
751 LCDFill(0, 1+8*11, 132, 8, GREEN);\r
752 LCDFill(0, 1+8*12, 132, 8, BLUE);\r
753 LCDFill(0, 1+8*13, 132, 8, YELLOW);\r
754 LCDFill(0, 1+8*14, 132, 8, CYAN);\r
755 LCDFill(0, 1+8*15, 132, 8, MAGENTA);\r
756\r
757#endif\r
758\r
759 for(;;) {\r
760 UsbPoll(FALSE);\r
761 WDT_HIT();\r
762\r
763 if (BUTTON_HELD(1000) > 0)\r
764 SamyRun();\r
765 }\r
766}\r
Impressum, Datenschutz