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