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