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