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