]> cvs.zerfleddert.de Git - proxmark3-svn/blame_incremental - armsrc/appmain.c
- Added new Makefile.linux in bootrom directory
[proxmark3-svn] / armsrc / appmain.c
... / ...
CommitLineData
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\r
9#include <proxmark3.h>\r
10#include "apps.h"\r
11#include "fonts.h"\r
12#ifdef WITH_LCD\r
13#include "LCD.h"\r
14#endif\r
15\r
16// The large multi-purpose buffer, typically used to hold A/D samples,\r
17// maybe pre-processed in some way.\r
18DWORD BigBuf[16000];\r
19\r
20//=============================================================================\r
21// A buffer where we can queue things up to be sent through the FPGA, for\r
22// any purpose (fake tag, as reader, whatever). We go MSB first, since that\r
23// is the order in which they go out on the wire.\r
24//=============================================================================\r
25\r
26BYTE ToSend[256];\r
27int ToSendMax;\r
28static int ToSendBit;\r
29\r
30void ToSendReset(void)\r
31{\r
32 ToSendMax = -1;\r
33 ToSendBit = 8;\r
34}\r
35\r
36void ToSendStuffBit(int b)\r
37{\r
38 if(ToSendBit >= 8) {\r
39 ToSendMax++;\r
40 ToSend[ToSendMax] = 0;\r
41 ToSendBit = 0;\r
42 }\r
43\r
44 if(b) {\r
45 ToSend[ToSendMax] |= (1 << (7 - ToSendBit));\r
46 }\r
47\r
48 ToSendBit++;\r
49\r
50 if(ToSendBit >= sizeof(ToSend)) {\r
51 ToSendBit = 0;\r
52 DbpString("ToSendStuffBit overflowed!");\r
53 }\r
54}\r
55\r
56//=============================================================================\r
57// Debug print functions, to go out over USB, to the usual PC-side client.\r
58//=============================================================================\r
59\r
60void DbpString(char *str)\r
61{\r
62 UsbCommand c;\r
63 c.cmd = CMD_DEBUG_PRINT_STRING;\r
64 c.ext1 = strlen(str);\r
65 memcpy(c.d.asBytes, str, c.ext1);\r
66\r
67 UsbSendPacket((BYTE *)&c, sizeof(c));\r
68 // TODO fix USB so stupid things like this aren't req'd\r
69 SpinDelay(50);\r
70}\r
71\r
72void DbpIntegers(int x1, int x2, int x3)\r
73{\r
74 UsbCommand c;\r
75 c.cmd = CMD_DEBUG_PRINT_INTEGERS;\r
76 c.ext1 = x1;\r
77 c.ext2 = x2;\r
78 c.ext3 = x3;\r
79\r
80 UsbSendPacket((BYTE *)&c, sizeof(c));\r
81 // XXX\r
82 SpinDelay(50);\r
83}\r
84\r
85void AcquireRawAdcSamples125k(BOOL at134khz)\r
86{\r
87 BYTE *dest = (BYTE *)BigBuf;\r
88 int n = sizeof(BigBuf);\r
89 int i;\r
90\r
91 memset(dest,0,n);\r
92\r
93 if(at134khz) {\r
94 FpgaSendCommand(FPGA_CMD_SET_DIVISOR, 88); //134.8Khz\r
95 FpgaWriteConfWord(FPGA_MAJOR_MODE_LF_READER | FPGA_LF_READER_USE_134_KHZ);\r
96 } else {\r
97 FpgaSendCommand(FPGA_CMD_SET_DIVISOR, 95); //125Khz\r
98 FpgaWriteConfWord(FPGA_MAJOR_MODE_LF_READER | FPGA_LF_READER_USE_125_KHZ);\r
99 }\r
100\r
101 // Connect the A/D to the peak-detected low-frequency path.\r
102 SetAdcMuxFor(GPIO_MUXSEL_LOPKD);\r
103\r
104 // Give it a bit of time for the resonant antenna to settle.\r
105 SpinDelay(50);\r
106\r
107 // Now set up the SSC to get the ADC samples that are now streaming at us.\r
108 FpgaSetupSsc();\r
109\r
110 i = 0;\r
111 for(;;) {\r
112 if(SSC_STATUS & (SSC_STATUS_TX_READY)) {\r
113 SSC_TRANSMIT_HOLDING = 0x43;\r
114 LED_D_ON();\r
115 }\r
116 if(SSC_STATUS & (SSC_STATUS_RX_READY)) {\r
117 dest[i] = (BYTE)SSC_RECEIVE_HOLDING;\r
118 i++;\r
119 LED_D_OFF();\r
120 if(i >= n) {\r
121 break;\r
122 }\r
123 }\r
124 }\r
125 DbpIntegers(dest[0], dest[1], at134khz);\r
126}\r
127\r
128//-----------------------------------------------------------------------------\r
129// Read an ADC channel and block till it completes, then return the result\r
130// in ADC units (0 to 1023). Also a routine to average 32 samples and\r
131// return that.\r
132//-----------------------------------------------------------------------------\r
133static int ReadAdc(int ch)\r
134{\r
135 DWORD d;\r
136\r
137 ADC_CONTROL = ADC_CONTROL_RESET;\r
138 ADC_MODE = ADC_MODE_PRESCALE(32) | ADC_MODE_STARTUP_TIME(16) |\r
139 ADC_MODE_SAMPLE_HOLD_TIME(8);\r
140 ADC_CHANNEL_ENABLE = ADC_CHANNEL(ch);\r
141\r
142 ADC_CONTROL = ADC_CONTROL_START;\r
143 while(!(ADC_STATUS & ADC_END_OF_CONVERSION(ch)))\r
144 ;\r
145 d = ADC_CHANNEL_DATA(ch);\r
146\r
147 return d;\r
148}\r
149\r
150static int AvgAdc(int ch)\r
151{\r
152 int i;\r
153 int a = 0;\r
154\r
155 for(i = 0; i < 32; i++) {\r
156 a += ReadAdc(ch);\r
157 }\r
158\r
159 return (a + 15) >> 5;\r
160}\r
161
162/*
163 * Sweeps the useful LF range of the proxmark from
164 * 46.8kHz (divisor=255) to 600kHz (divisor=19) and
165 * reads the voltage in the antenna: the result is a graph
166 * which should clearly show the resonating frequency of your
167 * LF antenna ( hopefully around 90 if it is tuned to 125kHz!)
168 */\r
169void SweepLFrange()\r
170{\r
171 BYTE *dest = (BYTE *)BigBuf;\r
172 int i;\r
173\r
174 // clear buffer\r
175 memset(BigBuf,0,sizeof(BigBuf));\r
176\r
177 FpgaWriteConfWord(FPGA_MAJOR_MODE_LF_READER);\r
178 for (i=255; i>19; i--) {\r
179 FpgaSendCommand(FPGA_CMD_SET_DIVISOR, i);\r
180 SpinDelay(20);\r
181 dest[i] = (137500 * AvgAdc(4)) >> 18;\r
182 }\r
183}\r
184\r
185void MeasureAntennaTuning(void)\r
186{\r
187// Impedances are Zc = 1/(j*omega*C), in ohms\r
188#define LF_TUNING_CAP_Z 1273 // 1 nF @ 125 kHz\r
189#define HF_TUNING_CAP_Z 235 // 50 pF @ 13.56 MHz\r
190\r
191 int vLf125, vLf134, vHf; // in mV\r
192\r
193 UsbCommand c;\r
194\r
195 // Let the FPGA drive the low-frequency antenna around 125 kHz.\r
196 FpgaSendCommand(FPGA_CMD_SET_DIVISOR, 95); //125Khz\r
197 FpgaWriteConfWord(FPGA_MAJOR_MODE_LF_READER | FPGA_LF_READER_USE_125_KHZ);\r
198 SpinDelay(20);\r
199 vLf125 = AvgAdc(4);\r
200 // Vref = 3.3V, and a 10000:240 voltage divider on the input\r
201 // can measure voltages up to 137500 mV\r
202 vLf125 = (137500 * vLf125) >> 10;\r
203\r
204 // Let the FPGA drive the low-frequency antenna around 134 kHz.\r
205 FpgaSendCommand(FPGA_CMD_SET_DIVISOR, 88); //134.8Khz\r
206 FpgaWriteConfWord(FPGA_MAJOR_MODE_LF_READER | FPGA_LF_READER_USE_134_KHZ);\r
207 SpinDelay(20);\r
208 vLf134 = AvgAdc(4);\r
209 // Vref = 3.3V, and a 10000:240 voltage divider on the input\r
210 // can measure voltages up to 137500 mV\r
211 vLf134 = (137500 * vLf134) >> 10;\r
212\r
213 // Let the FPGA drive the high-frequency antenna around 13.56 MHz.\r
214 FpgaWriteConfWord(FPGA_MAJOR_MODE_HF_READER_RX_XCORR);\r
215 SpinDelay(20);\r
216 vHf = AvgAdc(5);\r
217 // Vref = 3300mV, and an 10:1 voltage divider on the input\r
218 // can measure voltages up to 33000 mV\r
219 vHf = (33000 * vHf) >> 10;\r
220\r
221 c.cmd = CMD_MEASURED_ANTENNA_TUNING;\r
222 c.ext1 = (vLf125 << 0) | (vLf134 << 16);\r
223 c.ext2 = vHf;\r
224 c.ext3 = (LF_TUNING_CAP_Z << 0) | (HF_TUNING_CAP_Z << 16);\r
225 UsbSendPacket((BYTE *)&c, sizeof(c));\r
226}\r
227\r
228void SimulateTagLowFrequency(int period)\r
229{\r
230 int i;\r
231 BYTE *tab = (BYTE *)BigBuf;\r
232\r
233 FpgaWriteConfWord(FPGA_MAJOR_MODE_LF_SIMULATOR);\r
234\r
235 PIO_ENABLE = (1 << GPIO_SSC_DOUT) | (1 << GPIO_SSC_CLK);\r
236\r
237 PIO_OUTPUT_ENABLE = (1 << GPIO_SSC_DOUT);\r
238 PIO_OUTPUT_DISABLE = (1 << GPIO_SSC_CLK);\r
239\r
240#define SHORT_COIL() LOW(GPIO_SSC_DOUT)\r
241#define OPEN_COIL() HIGH(GPIO_SSC_DOUT)\r
242\r
243 i = 0;\r
244 for(;;) {\r
245 while(!(PIO_PIN_DATA_STATUS & (1<<GPIO_SSC_CLK))) {\r
246 if(BUTTON_PRESS()) {\r
247 return;\r
248 }\r
249 WDT_HIT();\r
250 }\r
251\r
252 LED_D_ON();\r
253 if(tab[i]) {\r
254 OPEN_COIL();\r
255 } else {\r
256 SHORT_COIL();\r
257 }\r
258 LED_D_OFF();\r
259\r
260 while(PIO_PIN_DATA_STATUS & (1<<GPIO_SSC_CLK)) {\r
261 if(BUTTON_PRESS()) {\r
262 return;\r
263 }\r
264 WDT_HIT();\r
265 }\r
266\r
267 i++;\r
268 if(i == period) i = 0;\r
269 }\r
270}\r
271\r
272// compose fc/8 fc/10 waveform\r
273static void fc(int c, int *n) {\r
274 BYTE *dest = (BYTE *)BigBuf;\r
275 int idx;\r
276\r
277 // for when we want an fc8 pattern every 4 logical bits\r
278 if(c==0) {\r
279 dest[((*n)++)]=1;\r
280 dest[((*n)++)]=1;\r
281 dest[((*n)++)]=0;\r
282 dest[((*n)++)]=0;\r
283 dest[((*n)++)]=0;\r
284 dest[((*n)++)]=0;\r
285 dest[((*n)++)]=0;\r
286 dest[((*n)++)]=0;\r
287 }\r
288 // an fc/8 encoded bit is a bit pattern of 11000000 x6 = 48 samples\r
289 if(c==8) {\r
290 for (idx=0; idx<6; idx++) {\r
291 dest[((*n)++)]=1;\r
292 dest[((*n)++)]=1;\r
293 dest[((*n)++)]=0;\r
294 dest[((*n)++)]=0;\r
295 dest[((*n)++)]=0;\r
296 dest[((*n)++)]=0;\r
297 dest[((*n)++)]=0;\r
298 dest[((*n)++)]=0;\r
299 }\r
300 }\r
301\r
302 // an fc/10 encoded bit is a bit pattern of 1110000000 x5 = 50 samples\r
303 if(c==10) {\r
304 for (idx=0; idx<5; idx++) {\r
305 dest[((*n)++)]=1;\r
306 dest[((*n)++)]=1;\r
307 dest[((*n)++)]=1;\r
308 dest[((*n)++)]=0;\r
309 dest[((*n)++)]=0;\r
310 dest[((*n)++)]=0;\r
311 dest[((*n)++)]=0;\r
312 dest[((*n)++)]=0;\r
313 dest[((*n)++)]=0;\r
314 dest[((*n)++)]=0;\r
315 }\r
316 }\r
317}\r
318\r
319// prepare a waveform pattern in the buffer based on the ID given then\r
320// simulate a HID tag until the button is pressed\r
321static void CmdHIDsimTAG(int hi, int lo)\r
322{\r
323 int n=0, i=0;\r
324 /*\r
325 HID tag bitstream format\r
326 The tag contains a 44bit unique code. This is sent out MSB first in sets of 4 bits\r
327 A 1 bit is represented as 6 fc8 and 5 fc10 patterns\r
328 A 0 bit is represented as 5 fc10 and 6 fc8 patterns\r
329 A fc8 is inserted before every 4 bits\r
330 A special start of frame pattern is used consisting a0b0 where a and b are neither 0\r
331 nor 1 bits, they are special patterns (a = set of 12 fc8 and b = set of 10 fc10)\r
332 */\r
333\r
334 if (hi>0xFFF) {\r
335 DbpString("Tags can only have 44 bits.");\r
336 return;\r
337 }\r
338 fc(0,&n);\r
339 // special start of frame marker containing invalid bit sequences\r
340 fc(8, &n); fc(8, &n); // invalid\r
341 fc(8, &n); fc(10, &n); // logical 0\r
342 fc(10, &n); fc(10, &n); // invalid\r
343 fc(8, &n); fc(10, &n); // logical 0\r
344\r
345 WDT_HIT();\r
346 // manchester encode bits 43 to 32\r
347 for (i=11; i>=0; i--) {\r
348 if ((i%4)==3) fc(0,&n);\r
349 if ((hi>>i)&1) {\r
350 fc(10, &n); fc(8, &n); // low-high transition\r
351 } else {\r
352 fc(8, &n); fc(10, &n); // high-low transition\r
353 }\r
354 }\r
355\r
356 WDT_HIT();\r
357 // manchester encode bits 31 to 0\r
358 for (i=31; i>=0; i--) {\r
359 if ((i%4)==3) fc(0,&n);\r
360 if ((lo>>i)&1) {\r
361 fc(10, &n); fc(8, &n); // low-high transition\r
362 } else {\r
363 fc(8, &n); fc(10, &n); // high-low transition\r
364 }\r
365 }\r
366\r
367 LED_A_ON();\r
368 SimulateTagLowFrequency(n);\r
369 LED_A_OFF();\r
370}\r
371\r
372// loop to capture raw HID waveform then FSK demodulate the TAG ID from it\r
373static void CmdHIDdemodFSK(void)\r
374{\r
375 BYTE *dest = (BYTE *)BigBuf;\r
376 int m=0, n=0, i=0, idx=0, found=0, lastval=0;\r
377 DWORD hi=0, lo=0;\r
378\r
379 FpgaSendCommand(FPGA_CMD_SET_DIVISOR, 95); //125Khz\r
380 FpgaWriteConfWord(FPGA_MAJOR_MODE_LF_READER | FPGA_LF_READER_USE_125_KHZ);\r
381\r
382 // Connect the A/D to the peak-detected low-frequency path.\r
383 SetAdcMuxFor(GPIO_MUXSEL_LOPKD);\r
384\r
385 // Give it a bit of time for the resonant antenna to settle.\r
386 SpinDelay(50);\r
387\r
388 // Now set up the SSC to get the ADC samples that are now streaming at us.\r
389 FpgaSetupSsc();\r
390\r
391 for(;;) {\r
392 WDT_HIT();\r
393 LED_A_ON();\r
394 if(BUTTON_PRESS()) {\r
395 LED_A_OFF();\r
396 return;\r
397 }\r
398\r
399 i = 0;\r
400 m = sizeof(BigBuf);\r
401 memset(dest,128,m);\r
402 for(;;) {\r
403 if(SSC_STATUS & (SSC_STATUS_TX_READY)) {\r
404 SSC_TRANSMIT_HOLDING = 0x43;\r
405 LED_D_ON();\r
406 }\r
407 if(SSC_STATUS & (SSC_STATUS_RX_READY)) {\r
408 dest[i] = (BYTE)SSC_RECEIVE_HOLDING;\r
409 // we don't care about actual value, only if it's more or less than a\r
410 // threshold essentially we capture zero crossings for later analysis\r
411 if(dest[i] < 127) dest[i] = 0; else dest[i] = 1;\r
412 i++;\r
413 LED_D_OFF();\r
414 if(i >= m) {\r
415 break;\r
416 }\r
417 }\r
418 }\r
419\r
420 // FSK demodulator\r
421\r
422 // sync to first lo-hi transition\r
423 for( idx=1; idx<m; idx++) {\r
424 if (dest[idx-1]<dest[idx])\r
425 lastval=idx;\r
426 break;\r
427 }\r
428 WDT_HIT();\r
429\r
430 // count cycles between consecutive lo-hi transitions, there should be either 8 (fc/8)\r
431 // or 10 (fc/10) cycles but in practice due to noise etc we may end up with with anywhere\r
432 // between 7 to 11 cycles so fuzz it by treat anything <9 as 8 and anything else as 10\r
433 for( i=0; idx<m; idx++) {\r
434 if (dest[idx-1]<dest[idx]) {\r
435 dest[i]=idx-lastval;\r
436 if (dest[i] <= 8) {\r
437 dest[i]=1;\r
438 } else {\r
439 dest[i]=0;\r
440 }\r
441\r
442 lastval=idx;\r
443 i++;\r
444 }\r
445 }\r
446 m=i;\r
447 WDT_HIT();\r
448\r
449 // we now have a set of cycle counts, loop over previous results and aggregate data into bit patterns\r
450 lastval=dest[0];\r
451 idx=0;\r
452 i=0;\r
453 n=0;\r
454 for( idx=0; idx<m; idx++) {\r
455 if (dest[idx]==lastval) {\r
456 n++;\r
457 } else {\r
458 // a bit time is five fc/10 or six fc/8 cycles so figure out how many bits a pattern width represents,\r
459 // an extra fc/8 pattern preceeds every 4 bits (about 200 cycles) just to complicate things but it gets\r
460 // swallowed up by rounding\r
461 // expected results are 1 or 2 bits, any more and it's an invalid manchester encoding\r
462 // special start of frame markers use invalid manchester states (no transitions) by using sequences\r
463 // like 111000\r
464 if (dest[idx-1]) {\r
465 n=(n+1)/6; // fc/8 in sets of 6\r
466 } else {\r
467 n=(n+1)/5; // fc/10 in sets of 5\r
468 }\r
469 switch (n) { // stuff appropriate bits in buffer\r
470 case 0:\r
471 case 1: // one bit\r
472 dest[i++]=dest[idx-1];\r
473 break;\r
474 case 2: // two bits\r
475 dest[i++]=dest[idx-1];\r
476 dest[i++]=dest[idx-1];\r
477 break;\r
478 case 3: // 3 bit start of frame markers\r
479 dest[i++]=dest[idx-1];\r
480 dest[i++]=dest[idx-1];\r
481 dest[i++]=dest[idx-1];\r
482 break;\r
483 // When a logic 0 is immediately followed by the start of the next transmisson\r
484 // (special pattern) a pattern of 4 bit duration lengths is created.\r
485 case 4:\r
486 dest[i++]=dest[idx-1];\r
487 dest[i++]=dest[idx-1];\r
488 dest[i++]=dest[idx-1];\r
489 dest[i++]=dest[idx-1];\r
490 break;\r
491 default: // this shouldn't happen, don't stuff any bits\r
492 break;\r
493 }\r
494 n=0;\r
495 lastval=dest[idx];\r
496 }\r
497 }\r
498 m=i;\r
499 WDT_HIT();\r
500\r
501 // final loop, go over previously decoded manchester data and decode into usable tag ID\r
502 // 111000 bit pattern represent start of frame, 01 pattern represents a 1 and 10 represents a 0\r
503 for( idx=0; idx<m-6; idx++) {\r
504 // search for a start of frame marker\r
505 if ( dest[idx] && dest[idx+1] && dest[idx+2] && (!dest[idx+3]) && (!dest[idx+4]) && (!dest[idx+5]) )\r
506 {\r
507 found=1;\r
508 idx+=6;\r
509 if (found && (hi|lo)) {\r
510 DbpString("TAG ID");\r
511 DbpIntegers(hi, lo, (lo>>1)&0xffff);\r
512 hi=0;\r
513 lo=0;\r
514 found=0;\r
515 }\r
516 }\r
517 if (found) {\r
518 if (dest[idx] && (!dest[idx+1]) ) {\r
519 hi=(hi<<1)|(lo>>31);\r
520 lo=(lo<<1)|0;\r
521 } else if ( (!dest[idx]) && dest[idx+1]) {\r
522 hi=(hi<<1)|(lo>>31);\r
523 lo=(lo<<1)|1;\r
524 } else {\r
525 found=0;\r
526 hi=0;\r
527 lo=0;\r
528 }\r
529 idx++;\r
530 }\r
531 if ( dest[idx] && dest[idx+1] && dest[idx+2] && (!dest[idx+3]) && (!dest[idx+4]) && (!dest[idx+5]) )\r
532 {\r
533 found=1;\r
534 idx+=6;\r
535 if (found && (hi|lo)) {\r
536 DbpString("TAG ID");\r
537 DbpIntegers(hi, lo, (lo>>1)&0xffff);\r
538 hi=0;\r
539 lo=0;\r
540 found=0;\r
541 }\r
542 }\r
543 }\r
544 WDT_HIT();\r
545 }\r
546}\r
547\r
548void SimulateTagHfListen(void)\r
549{\r
550 BYTE *dest = (BYTE *)BigBuf;\r
551 int n = sizeof(BigBuf);\r
552 BYTE v = 0;\r
553 int i;\r
554 int p = 0;\r
555\r
556 // We're using this mode just so that I can test it out; the simulated\r
557 // tag mode would work just as well and be simpler.\r
558 FpgaWriteConfWord(FPGA_MAJOR_MODE_HF_READER_RX_XCORR | FPGA_HF_READER_RX_XCORR_848_KHZ | FPGA_HF_READER_RX_XCORR_SNOOP);\r
559\r
560 // We need to listen to the high-frequency, peak-detected path.\r
561 SetAdcMuxFor(GPIO_MUXSEL_HIPKD);\r
562\r
563 FpgaSetupSsc();\r
564\r
565 i = 0;\r
566 for(;;) {\r
567 if(SSC_STATUS & (SSC_STATUS_TX_READY)) {\r
568 SSC_TRANSMIT_HOLDING = 0xff;\r
569 }\r
570 if(SSC_STATUS & (SSC_STATUS_RX_READY)) {\r
571 BYTE r = (BYTE)SSC_RECEIVE_HOLDING;\r
572\r
573 v <<= 1;\r
574 if(r & 1) {\r
575 v |= 1;\r
576 }\r
577 p++;\r
578\r
579 if(p >= 8) {\r
580 dest[i] = v;\r
581 v = 0;\r
582 p = 0;\r
583 i++;\r
584\r
585 if(i >= n) {\r
586 break;\r
587 }\r
588 }\r
589 }\r
590 }\r
591 DbpString("simulate tag (now type bitsamples)");\r
592}\r
593\r
594void UsbPacketReceived(BYTE *packet, int len)\r
595{\r
596 UsbCommand *c = (UsbCommand *)packet;\r
597\r
598 switch(c->cmd) {\r
599 case CMD_ACQUIRE_RAW_ADC_SAMPLES_125K:\r
600 AcquireRawAdcSamples125k(c->ext1);\r
601 break;\r
602\r
603 case CMD_ACQUIRE_RAW_ADC_SAMPLES_ISO_15693:\r
604 AcquireRawAdcSamplesIso15693();\r
605 break;\r
606\r
607 case CMD_READER_ISO_15693:\r
608 ReaderIso15693(c->ext1);\r
609 break;\r
610\r
611 case CMD_SIMTAG_ISO_15693:\r
612 SimTagIso15693(c->ext1);\r
613 break;\r
614\r
615 case CMD_ACQUIRE_RAW_ADC_SAMPLES_ISO_14443:\r
616 AcquireRawAdcSamplesIso14443(c->ext1);\r
617 break;\r
618
619 case CMD_READ_SRI512_TAG:
620 ReadSRI512Iso14443(c->ext1);
621 break;
622\r
623 case CMD_READER_ISO_14443a:\r
624 ReaderIso14443a(c->ext1);\r
625 break;\r
626\r
627 case CMD_SNOOP_ISO_14443:\r
628 SnoopIso14443();\r
629 break;\r
630\r
631 case CMD_SNOOP_ISO_14443a:\r
632 SnoopIso14443a();\r
633 break;\r
634\r
635 case CMD_SIMULATE_TAG_HF_LISTEN:\r
636 SimulateTagHfListen();\r
637 break;\r
638\r
639 case CMD_SIMULATE_TAG_ISO_14443:\r
640 SimulateIso14443Tag();\r
641 break;\r
642\r
643 case CMD_SIMULATE_TAG_ISO_14443a:\r
644 SimulateIso14443aTag(c->ext1, c->ext2); // ## Simulate iso14443a tag - pass tag type & UID\r
645 break;\r
646\r
647 case CMD_MEASURE_ANTENNA_TUNING:\r
648 MeasureAntennaTuning();\r
649 break;\r
650\r
651 case CMD_HID_DEMOD_FSK:\r
652 CmdHIDdemodFSK(); // Demodulate HID tag\r
653 break;\r
654\r
655 case CMD_HID_SIM_TAG:\r
656 CmdHIDsimTAG(c->ext1, c->ext2); // Simulate HID tag by ID\r
657 break;\r
658\r
659 case CMD_FPGA_MAJOR_MODE_OFF: // ## FPGA Control\r
660 LED_C_ON();\r
661 FpgaWriteConfWord(FPGA_MAJOR_MODE_OFF);\r
662 SpinDelay(200);\r
663 LED_C_OFF();\r
664 break;\r
665\r
666 case CMD_DOWNLOAD_RAW_ADC_SAMPLES_125K:\r
667 case CMD_DOWNLOAD_RAW_BITS_TI_TYPE: {\r
668 UsbCommand n;\r
669 if(c->cmd == CMD_DOWNLOAD_RAW_ADC_SAMPLES_125K) {\r
670 n.cmd = CMD_DOWNLOADED_RAW_ADC_SAMPLES_125K;\r
671 } else {\r
672 n.cmd = CMD_DOWNLOADED_RAW_BITS_TI_TYPE;\r
673 }\r
674 n.ext1 = c->ext1;\r
675 memcpy(n.d.asDwords, BigBuf+c->ext1, 12*sizeof(DWORD));\r
676 UsbSendPacket((BYTE *)&n, sizeof(n));\r
677 break;\r
678 }\r
679 case CMD_DOWNLOADED_SIM_SAMPLES_125K: {\r
680 BYTE *b = (BYTE *)BigBuf;\r
681 memcpy(b+c->ext1, c->d.asBytes, 48);\r
682 break;\r
683 }\r
684 case CMD_SIMULATE_TAG_125K:\r
685 LED_A_ON();\r
686 SimulateTagLowFrequency(c->ext1);\r
687 LED_A_OFF();\r
688 break;\r
689#ifdef WITH_LCD\r
690 case CMD_LCD_RESET:\r
691 LCDReset();\r
692 break;\r
693#endif\r
694 case CMD_SWEEP_LF:\r
695 SweepLFrange();\r
696 break;\r
697\r
698 case CMD_SET_LF_DIVISOR:\r
699 FpgaSendCommand(FPGA_CMD_SET_DIVISOR, c->ext1);\r
700 break;\r
701#ifdef WITH_LCD\r
702 case CMD_LCD:\r
703 LCDSend(c->ext1);\r
704 break;\r
705#endif\r
706 case CMD_SETUP_WRITE:\r
707 case CMD_FINISH_WRITE:\r
708 USB_D_PLUS_PULLUP_OFF();\r
709 SpinDelay(1000);\r
710 SpinDelay(1000);\r
711 RSTC_CONTROL = RST_CONTROL_KEY | RST_CONTROL_PROCESSOR_RESET;\r
712 for(;;) {\r
713 // We're going to reset, and the bootrom will take control.\r
714 }\r
715 break;\r
716\r
717 default:\r
718 DbpString("unknown command");\r
719 break;\r
720 }\r
721}\r
722\r
723void AppMain(void)\r
724{\r
725 memset(BigBuf,0,sizeof(BigBuf));\r
726 SpinDelay(100);\r
727\r
728 LED_D_OFF();\r
729 LED_C_OFF();\r
730 LED_B_OFF();\r
731 LED_A_OFF();\r
732\r
733 UsbStart();\r
734\r
735 // The FPGA gets its clock from us from PCK0 output, so set that up.\r
736 PIO_PERIPHERAL_B_SEL = (1 << GPIO_PCK0);\r
737 PIO_DISABLE = (1 << GPIO_PCK0);\r
738 PMC_SYS_CLK_ENABLE = PMC_SYS_CLK_PROGRAMMABLE_CLK_0;\r
739 // PCK0 is PLL clock / 4 = 96Mhz / 4 = 24Mhz\r
740 PMC_PROGRAMMABLE_CLK_0 = PMC_CLK_SELECTION_PLL_CLOCK |\r
741 PMC_CLK_PRESCALE_DIV_4;\r
742 PIO_OUTPUT_ENABLE = (1 << GPIO_PCK0);\r
743\r
744 // Reset SPI\r
745 SPI_CONTROL = SPI_CONTROL_RESET;\r
746 // Reset SSC\r
747 SSC_CONTROL = SSC_CONTROL_RESET;\r
748\r
749 // Load the FPGA image, which we have stored in our flash.\r
750 FpgaDownloadAndGo();\r
751\r
752#ifdef WITH_LCD\r
753\r
754 LCDInit();\r
755\r
756 // test text on different colored backgrounds\r
757 LCDString(" The quick brown fox ", &FONT6x8,1,1+8*0,WHITE ,BLACK );\r
758 LCDString(" jumped over the ", &FONT6x8,1,1+8*1,BLACK ,WHITE );\r
759 LCDString(" lazy dog. ", &FONT6x8,1,1+8*2,YELLOW ,RED );\r
760 LCDString(" AaBbCcDdEeFfGgHhIiJj ", &FONT6x8,1,1+8*3,RED ,GREEN );\r
761 LCDString(" KkLlMmNnOoPpQqRrSsTt ", &FONT6x8,1,1+8*4,MAGENTA,BLUE );\r
762 LCDString("UuVvWwXxYyZz0123456789", &FONT6x8,1,1+8*5,BLUE ,YELLOW);\r
763 LCDString("`-=[]_;',./~!@#$%^&*()", &FONT6x8,1,1+8*6,BLACK ,CYAN );\r
764 LCDString(" _+{}|:\\\"<>? ",&FONT6x8,1,1+8*7,BLUE ,MAGENTA);\r
765\r
766 // color bands\r
767 LCDFill(0, 1+8* 8, 132, 8, BLACK);\r
768 LCDFill(0, 1+8* 9, 132, 8, WHITE);\r
769 LCDFill(0, 1+8*10, 132, 8, RED);\r
770 LCDFill(0, 1+8*11, 132, 8, GREEN);\r
771 LCDFill(0, 1+8*12, 132, 8, BLUE);\r
772 LCDFill(0, 1+8*13, 132, 8, YELLOW);\r
773 LCDFill(0, 1+8*14, 132, 8, CYAN);\r
774 LCDFill(0, 1+8*15, 132, 8, MAGENTA);\r
775\r
776#endif\r
777\r
778 for(;;) {\r
779 UsbPoll(FALSE);\r
780 WDT_HIT();\r
781 }\r
782}\r
783\r
784void SpinDelay(int ms)\r
785{\r
786 int ticks = (48000*ms) >> 10;\r
787\r
788 // Borrow a PWM unit for my real-time clock\r
789 PWM_ENABLE = PWM_CHANNEL(0);\r
790 // 48 MHz / 1024 gives 46.875 kHz\r
791 PWM_CH_MODE(0) = PWM_CH_MODE_PRESCALER(10);\r
792 PWM_CH_DUTY_CYCLE(0) = 0;\r
793 PWM_CH_PERIOD(0) = 0xffff;\r
794\r
795 WORD start = (WORD)PWM_CH_COUNTER(0);\r
796\r
797 for(;;) {\r
798 WORD now = (WORD)PWM_CH_COUNTER(0);\r
799 if(now == (WORD)(start + ticks)) {\r
800 return;\r
801 }\r
802 WDT_HIT();\r
803 }\r
804}\r
Impressum, Datenschutz