]> git.zerfleddert.de Git - proxmark3-svn/blame - armsrc/appmain.c
[rleroy] add signal strength meter to 'detectreader' command (HF only)
[proxmark3-svn] / armsrc / appmain.c
CommitLineData
959baa89 1//-----------------------------------------------------------------------------
2// The main application code. This is the first thing called after start.c
3// executes.
4// Jonathan Westhues, Mar 2006
5// Edits by Gerhard de Koning Gans, Sep 2007 (##)
6//-----------------------------------------------------------------------------
7
8
9#include <proxmark3.h>
7f348042 10#include <stdlib.h>
959baa89 11#include "apps.h"
12#ifdef WITH_LCD
13#include "fonts.h"
14#include "LCD.h"
15#endif
16
17// The large multi-purpose buffer, typically used to hold A/D samples,
18// maybe pre-processed in some way.
19DWORD BigBuf[16000];
955fc5e2 20int usbattached = 0;
959baa89 21
22//=============================================================================
23// A buffer where we can queue things up to be sent through the FPGA, for
24// any purpose (fake tag, as reader, whatever). We go MSB first, since that
25// is the order in which they go out on the wire.
26//=============================================================================
27
28BYTE ToSend[256];
29int ToSendMax;
30static int ToSendBit;
31
f23e056d 32
33void BufferClear(void)
34{
35 memset(BigBuf,0,sizeof(BigBuf));
36 DbpString("Buffer cleared");
37}
38
959baa89 39void ToSendReset(void)
40{
41 ToSendMax = -1;
42 ToSendBit = 8;
43}
44
45void ToSendStuffBit(int b)
46{
47 if(ToSendBit >= 8) {
48 ToSendMax++;
49 ToSend[ToSendMax] = 0;
50 ToSendBit = 0;
51 }
52
53 if(b) {
54 ToSend[ToSendMax] |= (1 << (7 - ToSendBit));
55 }
56
57 ToSendBit++;
58
59 if(ToSendBit >= sizeof(ToSend)) {
60 ToSendBit = 0;
61 DbpString("ToSendStuffBit overflowed!");
62 }
63}
64
65//=============================================================================
66// Debug print functions, to go out over USB, to the usual PC-side client.
67//=============================================================================
68
69void DbpString(char *str)
70{
955fc5e2 71 /* this holds up stuff unless we're connected to usb */
1dff8c42 72// if (!usbattached)
73// return;
c701d2c2 74
959baa89 75 UsbCommand c;
76 c.cmd = CMD_DEBUG_PRINT_STRING;
77 c.ext1 = strlen(str);
78 memcpy(c.d.asBytes, str, c.ext1);
79
80 UsbSendPacket((BYTE *)&c, sizeof(c));
81 // TODO fix USB so stupid things like this aren't req'd
82 SpinDelay(50);
83}
84
85void DbpIntegers(int x1, int x2, int x3)
86{
955fc5e2 87 /* this holds up stuff unless we're connected to usb */
1dff8c42 88// if (!usbattached)
89// return;
955fc5e2 90
959baa89 91 UsbCommand c;
92 c.cmd = CMD_DEBUG_PRINT_INTEGERS;
93 c.ext1 = x1;
94 c.ext2 = x2;
95 c.ext3 = x3;
96
97 UsbSendPacket((BYTE *)&c, sizeof(c));
98 // XXX
99 SpinDelay(50);
100}
101
102void AcquireRawAdcSamples125k(BOOL at134khz)
103{
104 if(at134khz) {
105 FpgaSendCommand(FPGA_CMD_SET_DIVISOR, 88); //134.8Khz
c701d2c2 106 FpgaWriteConfWord(FPGA_MAJOR_MODE_LF_READER);
959baa89 107 } else {
108 FpgaSendCommand(FPGA_CMD_SET_DIVISOR, 95); //125Khz
c701d2c2 109 FpgaWriteConfWord(FPGA_MAJOR_MODE_LF_READER);
959baa89 110 }
111
112 // Connect the A/D to the peak-detected low-frequency path.
113 SetAdcMuxFor(GPIO_MUXSEL_LOPKD);
114
115 // Give it a bit of time for the resonant antenna to settle.
116 SpinDelay(50);
117
118 // Now set up the SSC to get the ADC samples that are now streaming at us.
119 FpgaSetupSsc();
120
121 // Now call the acquisition routine
122 DoAcquisition125k(at134khz);
123}
124
125// split into two routines so we can avoid timing issues after sending commands //
126void DoAcquisition125k(BOOL at134khz)
127{
128 BYTE *dest = (BYTE *)BigBuf;
129 int n = sizeof(BigBuf);
130 int i;
131
132 memset(dest,0,n);
133 i = 0;
134 for(;;) {
135 if(SSC_STATUS & (SSC_STATUS_TX_READY)) {
136 SSC_TRANSMIT_HOLDING = 0x43;
137 LED_D_ON();
138 }
139 if(SSC_STATUS & (SSC_STATUS_RX_READY)) {
140 dest[i] = (BYTE)SSC_RECEIVE_HOLDING;
141 i++;
142 LED_D_OFF();
143 if(i >= n) {
144 break;
145 }
146 }
147 }
148 DbpIntegers(dest[0], dest[1], at134khz);
149}
150
151void ModThenAcquireRawAdcSamples125k(int delay_off,int period_0,int period_1,BYTE *command)
152{
153 BOOL at134khz;
154
155 // see if 'h' was specified
1dd23352 156 if(command[strlen((char *) command) - 1] == 'h')
959baa89 157 at134khz= TRUE;
158 else
159 at134khz= FALSE;
c701d2c2 160
959baa89 161 if(at134khz) {
162 FpgaSendCommand(FPGA_CMD_SET_DIVISOR, 88); //134.8Khz
c701d2c2 163 FpgaWriteConfWord(FPGA_MAJOR_MODE_LF_READER);
959baa89 164 } else {
165 FpgaSendCommand(FPGA_CMD_SET_DIVISOR, 95); //125Khz
c701d2c2 166 FpgaWriteConfWord(FPGA_MAJOR_MODE_LF_READER);
959baa89 167 }
168
169 // Give it a bit of time for the resonant antenna to settle.
170 SpinDelay(50);
171
172 // Now set up the SSC to get the ADC samples that are now streaming at us.
173 FpgaSetupSsc();
174
175 // now modulate the reader field
176 while(*command != '\0' && *command != ' ')
177 {
178 FpgaWriteConfWord(FPGA_MAJOR_MODE_OFF);
179 LED_D_OFF();
180 SpinDelayUs(delay_off);
181 if(at134khz) {
182 FpgaSendCommand(FPGA_CMD_SET_DIVISOR, 88); //134.8Khz
c701d2c2 183 FpgaWriteConfWord(FPGA_MAJOR_MODE_LF_READER);
959baa89 184 } else {
185 FpgaSendCommand(FPGA_CMD_SET_DIVISOR, 95); //125Khz
c701d2c2 186 FpgaWriteConfWord(FPGA_MAJOR_MODE_LF_READER);
959baa89 187 }
188 LED_D_ON();
189 if(*(command++) == '0')
190 SpinDelayUs(period_0);
191 else
192 SpinDelayUs(period_1);
193 }
194 FpgaWriteConfWord(FPGA_MAJOR_MODE_OFF);
195 LED_D_OFF();
196 SpinDelayUs(delay_off);
197 if(at134khz) {
198 FpgaSendCommand(FPGA_CMD_SET_DIVISOR, 88); //134.8Khz
c701d2c2 199 FpgaWriteConfWord(FPGA_MAJOR_MODE_LF_READER);
959baa89 200 } else {
201 FpgaSendCommand(FPGA_CMD_SET_DIVISOR, 95); //125Khz
c701d2c2 202 FpgaWriteConfWord(FPGA_MAJOR_MODE_LF_READER);
959baa89 203 }
204
205 // now do the read
206 DoAcquisition125k(at134khz);
207}
208
c701d2c2 209void AcquireTiType(void)
210{
211 int i;
8e7a6ce4 212 int n = 5000;
c701d2c2 213
214 // clear buffer
215 memset(BigBuf,0,sizeof(BigBuf));
216
8e7a6ce4 217 // Set up the synchronous serial port
c701d2c2 218 PIO_DISABLE = (1<<GPIO_SSC_DIN);
219 PIO_PERIPHERAL_A_SEL = (1<<GPIO_SSC_DIN);
220
8e7a6ce4 221 // steal this pin from the SSP and use it to control the modulation
222 PIO_ENABLE = (1<<GPIO_SSC_DOUT);
223 PIO_OUTPUT_ENABLE = (1<<GPIO_SSC_DOUT);
224
c701d2c2 225 SSC_CONTROL = SSC_CONTROL_RESET;
226 SSC_CONTROL = SSC_CONTROL_RX_ENABLE | SSC_CONTROL_TX_ENABLE;
227
228 // Sample at 2 Mbit/s, so TI tags are 16.2 vs. 14.9 clocks long
229 // 48/2 = 24 MHz clock must be divided by 12
230 SSC_CLOCK_DIVISOR = 12;
231
232 SSC_RECEIVE_CLOCK_MODE = SSC_CLOCK_MODE_SELECT(0);
8e7a6ce4 233 SSC_RECEIVE_FRAME_MODE = SSC_FRAME_MODE_BITS_IN_WORD(32) | SSC_FRAME_MODE_MSB_FIRST;
234 SSC_TRANSMIT_CLOCK_MODE = 0;
235 SSC_TRANSMIT_FRAME_MODE = 0;
c701d2c2 236
c701d2c2 237 LED_D_ON();
8e7a6ce4 238
239 // modulate antenna
240 PIO_OUTPUT_DATA_SET = (1<<GPIO_SSC_DOUT);
c701d2c2 241
242 // Charge TI tag for 50ms.
243 SpinDelay(50);
8e7a6ce4 244
245 // stop modulating antenna and listen
246 PIO_OUTPUT_DATA_CLEAR = (1<<GPIO_SSC_DOUT);
247
c701d2c2 248 LED_D_OFF();
249
8e7a6ce4 250 i = 0;
251 for(;;) {
252 if(SSC_STATUS & SSC_STATUS_RX_READY) {
253 BigBuf[i] = SSC_RECEIVE_HOLDING; // store 32 bit values in buffer
254 i++; if(i >= n) return;
255 }
256 WDT_HIT();
257 }
258
259 // return stolen pin ro SSP
260 PIO_DISABLE = (1<<GPIO_SSC_DOUT);
261 PIO_PERIPHERAL_A_SEL = (1<<GPIO_SSC_DIN) | (1<<GPIO_SSC_DOUT);
262}
263
264void AcquireRawBitsTI(void)
265{
266 LED_D_ON();
267 // TI tags charge at 134.2Khz
268 FpgaSendCommand(FPGA_CMD_SET_DIVISOR, 88); //134.8Khz
269 // Place FPGA in passthrough mode, in this mode the CROSS_LO line
270 // connects to SSP_DIN and the SSP_DOUT logic level controls
271 // whether we're modulating the antenna (high)
272 // or listening to the antenna (low)
c701d2c2 273 FpgaWriteConfWord(FPGA_MAJOR_MODE_LF_PASSTHRU);
274
275 // get TI tag data into the buffer
276 AcquireTiType();
277
278 FpgaWriteConfWord(FPGA_MAJOR_MODE_OFF);
c701d2c2 279}
280
959baa89 281//-----------------------------------------------------------------------------
282// Read an ADC channel and block till it completes, then return the result
283// in ADC units (0 to 1023). Also a routine to average 32 samples and
284// return that.
285//-----------------------------------------------------------------------------
286static int ReadAdc(int ch)
287{
288 DWORD d;
289
290 ADC_CONTROL = ADC_CONTROL_RESET;
291 ADC_MODE = ADC_MODE_PRESCALE(32) | ADC_MODE_STARTUP_TIME(16) |
292 ADC_MODE_SAMPLE_HOLD_TIME(8);
293 ADC_CHANNEL_ENABLE = ADC_CHANNEL(ch);
294
295 ADC_CONTROL = ADC_CONTROL_START;
296 while(!(ADC_STATUS & ADC_END_OF_CONVERSION(ch)))
297 ;
298 d = ADC_CHANNEL_DATA(ch);
299
300 return d;
301}
302
303static int AvgAdc(int ch)
304{
305 int i;
306 int a = 0;
307
308 for(i = 0; i < 32; i++) {
309 a += ReadAdc(ch);
310 }
311
312 return (a + 15) >> 5;
313}
30f2a7d3 314
e7aee94e 315void MeasureAntennaTuning(void)
959baa89 316{
317 BYTE *dest = (BYTE *)BigBuf;
e7aee94e 318 int i, ptr = 0, adcval = 0, peak = 0, peakv = 0, peakf = 0;;
319 int vLf125 = 0, vLf134 = 0, vHf = 0; // in mV
320
321 UsbCommand c;
959baa89 322
e7aee94e 323 DbpString("Measuring antenna characteristics, please wait.");
959baa89 324 memset(BigBuf,0,sizeof(BigBuf));
325
e7aee94e 326/*
327 * Sweeps the useful LF range of the proxmark from
328 * 46.8kHz (divisor=255) to 600kHz (divisor=19) and
329 * read the voltage in the antenna, the result left
330 * in the buffer is a graph which should clearly show
331 * the resonating frequency of your LF antenna
332 * ( hopefully around 95 if it is tuned to 125kHz!)
333 */
959baa89 334 FpgaWriteConfWord(FPGA_MAJOR_MODE_LF_READER);
335 for (i=255; i>19; i--) {
336 FpgaSendCommand(FPGA_CMD_SET_DIVISOR, i);
337 SpinDelay(20);
e7aee94e 338 // Vref = 3.3V, and a 10000:240 voltage divider on the input
339 // can measure voltages up to 137500 mV
340 adcval = ((137500 * AvgAdc(ADC_CHAN_LF)) >> 10);
341 if (i==95) vLf125 = adcval; // voltage at 125Khz
342 if (i==89) vLf134 = adcval; // voltage at 134Khz
343
344 dest[i] = adcval>>8; // scale int to fit in byte for graphing purposes
38b65694 345 if(dest[i] > peak) {
e7aee94e 346 peakv = adcval;
347 peak = dest[i];
348 peakf = i;
349 ptr = i;
38b65694 350 }
e7aee94e 351 }
959baa89 352
353 // Let the FPGA drive the high-frequency antenna around 13.56 MHz.
354 FpgaWriteConfWord(FPGA_MAJOR_MODE_HF_READER_RX_XCORR);
355 SpinDelay(20);
959baa89 356 // Vref = 3300mV, and an 10:1 voltage divider on the input
357 // can measure voltages up to 33000 mV
e7aee94e 358 vHf = (33000 * AvgAdc(ADC_CHAN_HF)) >> 10;
959baa89 359
360 c.cmd = CMD_MEASURED_ANTENNA_TUNING;
361 c.ext1 = (vLf125 << 0) | (vLf134 << 16);
362 c.ext2 = vHf;
c701d2c2 363 c.ext3 = peakf | (peakv << 16);
959baa89 364 UsbSendPacket((BYTE *)&c, sizeof(c));
365}
366
955fc5e2 367void SimulateTagLowFrequency(int period, int ledcontrol)
959baa89 368{
369 int i;
370 BYTE *tab = (BYTE *)BigBuf;
371
372 FpgaWriteConfWord(FPGA_MAJOR_MODE_LF_SIMULATOR);
373
374 PIO_ENABLE = (1 << GPIO_SSC_DOUT) | (1 << GPIO_SSC_CLK);
375
376 PIO_OUTPUT_ENABLE = (1 << GPIO_SSC_DOUT);
377 PIO_OUTPUT_DISABLE = (1 << GPIO_SSC_CLK);
378
379#define SHORT_COIL() LOW(GPIO_SSC_DOUT)
380#define OPEN_COIL() HIGH(GPIO_SSC_DOUT)
381
382 i = 0;
383 for(;;) {
384 while(!(PIO_PIN_DATA_STATUS & (1<<GPIO_SSC_CLK))) {
385 if(BUTTON_PRESS()) {
6bd86cb2 386 DbpString("Stopped");
959baa89 387 return;
388 }
389 WDT_HIT();
390 }
391
955fc5e2 392 if (ledcontrol)
393 LED_D_ON();
394
395 if(tab[i])
959baa89 396 OPEN_COIL();
955fc5e2 397 else
959baa89 398 SHORT_COIL();
c701d2c2 399
955fc5e2 400 if (ledcontrol)
401 LED_D_OFF();
959baa89 402
403 while(PIO_PIN_DATA_STATUS & (1<<GPIO_SSC_CLK)) {
404 if(BUTTON_PRESS()) {
6bd86cb2 405 DbpString("Stopped");
959baa89 406 return;
407 }
408 WDT_HIT();
409 }
410
411 i++;
412 if(i == period) i = 0;
413 }
414}
415
416// compose fc/8 fc/10 waveform
417static void fc(int c, int *n) {
418 BYTE *dest = (BYTE *)BigBuf;
419 int idx;
420
421 // for when we want an fc8 pattern every 4 logical bits
422 if(c==0) {
423 dest[((*n)++)]=1;
424 dest[((*n)++)]=1;
425 dest[((*n)++)]=0;
426 dest[((*n)++)]=0;
427 dest[((*n)++)]=0;
428 dest[((*n)++)]=0;
429 dest[((*n)++)]=0;
430 dest[((*n)++)]=0;
431 }
432 // an fc/8 encoded bit is a bit pattern of 11000000 x6 = 48 samples
433 if(c==8) {
434 for (idx=0; idx<6; idx++) {
435 dest[((*n)++)]=1;
436 dest[((*n)++)]=1;
437 dest[((*n)++)]=0;
438 dest[((*n)++)]=0;
439 dest[((*n)++)]=0;
440 dest[((*n)++)]=0;
441 dest[((*n)++)]=0;
442 dest[((*n)++)]=0;
443 }
444 }
445
446 // an fc/10 encoded bit is a bit pattern of 1110000000 x5 = 50 samples
447 if(c==10) {
448 for (idx=0; idx<5; idx++) {
449 dest[((*n)++)]=1;
450 dest[((*n)++)]=1;
451 dest[((*n)++)]=1;
452 dest[((*n)++)]=0;
453 dest[((*n)++)]=0;
454 dest[((*n)++)]=0;
455 dest[((*n)++)]=0;
456 dest[((*n)++)]=0;
457 dest[((*n)++)]=0;
458 dest[((*n)++)]=0;
459 }
460 }
461}
462
463// prepare a waveform pattern in the buffer based on the ID given then
464// simulate a HID tag until the button is pressed
955fc5e2 465static void CmdHIDsimTAG(int hi, int lo, int ledcontrol)
959baa89 466{
467 int n=0, i=0;
468 /*
469 HID tag bitstream format
470 The tag contains a 44bit unique code. This is sent out MSB first in sets of 4 bits
471 A 1 bit is represented as 6 fc8 and 5 fc10 patterns
472 A 0 bit is represented as 5 fc10 and 6 fc8 patterns
473 A fc8 is inserted before every 4 bits
474 A special start of frame pattern is used consisting a0b0 where a and b are neither 0
475 nor 1 bits, they are special patterns (a = set of 12 fc8 and b = set of 10 fc10)
476 */
477
478 if (hi>0xFFF) {
479 DbpString("Tags can only have 44 bits.");
480 return;
481 }
482 fc(0,&n);
483 // special start of frame marker containing invalid bit sequences
484 fc(8, &n); fc(8, &n); // invalid
485 fc(8, &n); fc(10, &n); // logical 0
486 fc(10, &n); fc(10, &n); // invalid
487 fc(8, &n); fc(10, &n); // logical 0
488
489 WDT_HIT();
490 // manchester encode bits 43 to 32
491 for (i=11; i>=0; i--) {
492 if ((i%4)==3) fc(0,&n);
493 if ((hi>>i)&1) {
494 fc(10, &n); fc(8, &n); // low-high transition
495 } else {
496 fc(8, &n); fc(10, &n); // high-low transition
497 }
498 }
499
500 WDT_HIT();
501 // manchester encode bits 31 to 0
502 for (i=31; i>=0; i--) {
503 if ((i%4)==3) fc(0,&n);
504 if ((lo>>i)&1) {
505 fc(10, &n); fc(8, &n); // low-high transition
506 } else {
507 fc(8, &n); fc(10, &n); // high-low transition
508 }
509 }
510
955fc5e2 511 if (ledcontrol)
512 LED_A_ON();
513 SimulateTagLowFrequency(n, ledcontrol);
c701d2c2 514
955fc5e2 515 if (ledcontrol)
516 LED_A_OFF();
959baa89 517}
518
519// loop to capture raw HID waveform then FSK demodulate the TAG ID from it
955fc5e2 520static void CmdHIDdemodFSK(int findone, int *high, int *low, int ledcontrol)
959baa89 521{
522 BYTE *dest = (BYTE *)BigBuf;
523 int m=0, n=0, i=0, idx=0, found=0, lastval=0;
524 DWORD hi=0, lo=0;
525
526 FpgaSendCommand(FPGA_CMD_SET_DIVISOR, 95); //125Khz
c701d2c2 527 FpgaWriteConfWord(FPGA_MAJOR_MODE_LF_READER);
959baa89 528
529 // Connect the A/D to the peak-detected low-frequency path.
530 SetAdcMuxFor(GPIO_MUXSEL_LOPKD);
531
532 // Give it a bit of time for the resonant antenna to settle.
533 SpinDelay(50);
534
535 // Now set up the SSC to get the ADC samples that are now streaming at us.
536 FpgaSetupSsc();
537
538 for(;;) {
539 WDT_HIT();
955fc5e2 540 if (ledcontrol)
541 LED_A_ON();
959baa89 542 if(BUTTON_PRESS()) {
6bd86cb2 543 DbpString("Stopped");
955fc5e2 544 if (ledcontrol)
545 LED_A_OFF();
959baa89 546 return;
547 }
548
549 i = 0;
550 m = sizeof(BigBuf);
551 memset(dest,128,m);
552 for(;;) {
553 if(SSC_STATUS & (SSC_STATUS_TX_READY)) {
554 SSC_TRANSMIT_HOLDING = 0x43;
955fc5e2 555 if (ledcontrol)
556 LED_D_ON();
959baa89 557 }
558 if(SSC_STATUS & (SSC_STATUS_RX_READY)) {
559 dest[i] = (BYTE)SSC_RECEIVE_HOLDING;
560 // we don't care about actual value, only if it's more or less than a
561 // threshold essentially we capture zero crossings for later analysis
562 if(dest[i] < 127) dest[i] = 0; else dest[i] = 1;
563 i++;
955fc5e2 564 if (ledcontrol)
565 LED_D_OFF();
959baa89 566 if(i >= m) {
567 break;
568 }
569 }
570 }
571
572 // FSK demodulator
573
574 // sync to first lo-hi transition
575 for( idx=1; idx<m; idx++) {
576 if (dest[idx-1]<dest[idx])
577 lastval=idx;
578 break;
579 }
580 WDT_HIT();
581
582 // count cycles between consecutive lo-hi transitions, there should be either 8 (fc/8)
583 // or 10 (fc/10) cycles but in practice due to noise etc we may end up with with anywhere
584 // between 7 to 11 cycles so fuzz it by treat anything <9 as 8 and anything else as 10
585 for( i=0; idx<m; idx++) {
586 if (dest[idx-1]<dest[idx]) {
587 dest[i]=idx-lastval;
588 if (dest[i] <= 8) {
589 dest[i]=1;
590 } else {
591 dest[i]=0;
592 }
593
594 lastval=idx;
595 i++;
596 }
597 }
598 m=i;
599 WDT_HIT();
600
601 // we now have a set of cycle counts, loop over previous results and aggregate data into bit patterns
602 lastval=dest[0];
603 idx=0;
604 i=0;
605 n=0;
606 for( idx=0; idx<m; idx++) {
607 if (dest[idx]==lastval) {
608 n++;
609 } else {
610 // a bit time is five fc/10 or six fc/8 cycles so figure out how many bits a pattern width represents,
611 // an extra fc/8 pattern preceeds every 4 bits (about 200 cycles) just to complicate things but it gets
612 // swallowed up by rounding
613 // expected results are 1 or 2 bits, any more and it's an invalid manchester encoding
614 // special start of frame markers use invalid manchester states (no transitions) by using sequences
615 // like 111000
616 if (dest[idx-1]) {
617 n=(n+1)/6; // fc/8 in sets of 6
618 } else {
619 n=(n+1)/5; // fc/10 in sets of 5
620 }
621 switch (n) { // stuff appropriate bits in buffer
622 case 0:
623 case 1: // one bit
624 dest[i++]=dest[idx-1];
625 break;
626 case 2: // two bits
627 dest[i++]=dest[idx-1];
628 dest[i++]=dest[idx-1];
629 break;
630 case 3: // 3 bit start of frame markers
631 dest[i++]=dest[idx-1];
632 dest[i++]=dest[idx-1];
633 dest[i++]=dest[idx-1];
634 break;
635 // When a logic 0 is immediately followed by the start of the next transmisson
636 // (special pattern) a pattern of 4 bit duration lengths is created.
637 case 4:
638 dest[i++]=dest[idx-1];
639 dest[i++]=dest[idx-1];
640 dest[i++]=dest[idx-1];
641 dest[i++]=dest[idx-1];
642 break;
643 default: // this shouldn't happen, don't stuff any bits
644 break;
645 }
646 n=0;
647 lastval=dest[idx];
648 }
649 }
650 m=i;
651 WDT_HIT();
652
653 // final loop, go over previously decoded manchester data and decode into usable tag ID
654 // 111000 bit pattern represent start of frame, 01 pattern represents a 1 and 10 represents a 0
655 for( idx=0; idx<m-6; idx++) {
656 // search for a start of frame marker
657 if ( dest[idx] && dest[idx+1] && dest[idx+2] && (!dest[idx+3]) && (!dest[idx+4]) && (!dest[idx+5]) )
658 {
659 found=1;
660 idx+=6;
661 if (found && (hi|lo)) {
662 DbpString("TAG ID");
663 DbpIntegers(hi, lo, (lo>>1)&0xffff);
955fc5e2 664 /* if we're only looking for one tag */
665 if (findone)
666 {
667 *high = hi;
668 *low = lo;
669 return;
670 }
959baa89 671 hi=0;
672 lo=0;
673 found=0;
674 }
675 }
676 if (found) {
677 if (dest[idx] && (!dest[idx+1]) ) {
678 hi=(hi<<1)|(lo>>31);
679 lo=(lo<<1)|0;
680 } else if ( (!dest[idx]) && dest[idx+1]) {
681 hi=(hi<<1)|(lo>>31);
682 lo=(lo<<1)|1;
683 } else {
684 found=0;
685 hi=0;
686 lo=0;
687 }
688 idx++;
689 }
690 if ( dest[idx] && dest[idx+1] && dest[idx+2] && (!dest[idx+3]) && (!dest[idx+4]) && (!dest[idx+5]) )
691 {
692 found=1;
693 idx+=6;
694 if (found && (hi|lo)) {
695 DbpString("TAG ID");
696 DbpIntegers(hi, lo, (lo>>1)&0xffff);
955fc5e2 697 /* if we're only looking for one tag */
698 if (findone)
699 {
700 *high = hi;
701 *low = lo;
702 return;
703 }
959baa89 704 hi=0;
705 lo=0;
706 found=0;
707 }
708 }
709 }
710 WDT_HIT();
711 }
712}
713
714void SimulateTagHfListen(void)
715{
716 BYTE *dest = (BYTE *)BigBuf;
717 int n = sizeof(BigBuf);
718 BYTE v = 0;
719 int i;
720 int p = 0;
721
722 // We're using this mode just so that I can test it out; the simulated
723 // tag mode would work just as well and be simpler.
724 FpgaWriteConfWord(FPGA_MAJOR_MODE_HF_READER_RX_XCORR | FPGA_HF_READER_RX_XCORR_848_KHZ | FPGA_HF_READER_RX_XCORR_SNOOP);
725
726 // We need to listen to the high-frequency, peak-detected path.
727 SetAdcMuxFor(GPIO_MUXSEL_HIPKD);
728
729 FpgaSetupSsc();
730
731 i = 0;
732 for(;;) {
733 if(SSC_STATUS & (SSC_STATUS_TX_READY)) {
734 SSC_TRANSMIT_HOLDING = 0xff;
735 }
736 if(SSC_STATUS & (SSC_STATUS_RX_READY)) {
737 BYTE r = (BYTE)SSC_RECEIVE_HOLDING;
738
739 v <<= 1;
740 if(r & 1) {
741 v |= 1;
742 }
743 p++;
744
745 if(p >= 8) {
746 dest[i] = v;
747 v = 0;
748 p = 0;
749 i++;
750
751 if(i >= n) {
752 break;
753 }
754 }
755 }
756 }
757 DbpString("simulate tag (now type bitsamples)");
758}
759
760void UsbPacketReceived(BYTE *packet, int len)
761{
762 UsbCommand *c = (UsbCommand *)packet;
763
764 switch(c->cmd) {
765 case CMD_ACQUIRE_RAW_ADC_SAMPLES_125K:
766 AcquireRawAdcSamples125k(c->ext1);
767 break;
768
769 case CMD_MOD_THEN_ACQUIRE_RAW_ADC_SAMPLES_125K:
770 ModThenAcquireRawAdcSamples125k(c->ext1,c->ext2,c->ext3,c->d.asBytes);
771 break;
772
c701d2c2 773 case CMD_ACQUIRE_RAW_BITS_TI_TYPE:
774 AcquireRawBitsTI();
775 break;
776
959baa89 777 case CMD_ACQUIRE_RAW_ADC_SAMPLES_ISO_15693:
778 AcquireRawAdcSamplesIso15693();
779 break;
f23e056d 780
781 case CMD_BUFF_CLEAR:
782 BufferClear();
783 break;
959baa89 784
785 case CMD_READER_ISO_15693:
786 ReaderIso15693(c->ext1);
787 break;
788
789 case CMD_SIMTAG_ISO_15693:
790 SimTagIso15693(c->ext1);
791 break;
792
793 case CMD_ACQUIRE_RAW_ADC_SAMPLES_ISO_14443:
794 AcquireRawAdcSamplesIso14443(c->ext1);
795 break;
fb25b483 796
797 case CMD_READ_SRI512_TAG:
798 ReadSRI512Iso14443(c->ext1);
799 break;
959baa89 800
801 case CMD_READER_ISO_14443a:
802 ReaderIso14443a(c->ext1);
803 break;
804
805 case CMD_SNOOP_ISO_14443:
806 SnoopIso14443();
807 break;
808
809 case CMD_SNOOP_ISO_14443a:
810 SnoopIso14443a();
811 break;
812
813 case CMD_SIMULATE_TAG_HF_LISTEN:
814 SimulateTagHfListen();
815 break;
816
817 case CMD_SIMULATE_TAG_ISO_14443:
818 SimulateIso14443Tag();
819 break;
820
821 case CMD_SIMULATE_TAG_ISO_14443a:
822 SimulateIso14443aTag(c->ext1, c->ext2); // ## Simulate iso14443a tag - pass tag type & UID
823 break;
824
825 case CMD_MEASURE_ANTENNA_TUNING:
826 MeasureAntennaTuning();
827 break;
828
7f348042 829 case CMD_LISTEN_READER_FIELD:
830 ListenReaderField(c->ext1);
831 break;
832
959baa89 833 case CMD_HID_DEMOD_FSK:
955fc5e2 834 CmdHIDdemodFSK(0, 0, 0, 1); // Demodulate HID tag
959baa89 835 break;
836
837 case CMD_HID_SIM_TAG:
955fc5e2 838 CmdHIDsimTAG(c->ext1, c->ext2, 1); // Simulate HID tag by ID
959baa89 839 break;
840
841 case CMD_FPGA_MAJOR_MODE_OFF: // ## FPGA Control
842 FpgaWriteConfWord(FPGA_MAJOR_MODE_OFF);
843 SpinDelay(200);
844 LED_D_OFF(); // LED D indicates field ON or OFF
845 break;
846
847 case CMD_DOWNLOAD_RAW_ADC_SAMPLES_125K:
848 case CMD_DOWNLOAD_RAW_BITS_TI_TYPE: {
849 UsbCommand n;
850 if(c->cmd == CMD_DOWNLOAD_RAW_ADC_SAMPLES_125K) {
851 n.cmd = CMD_DOWNLOADED_RAW_ADC_SAMPLES_125K;
852 } else {
853 n.cmd = CMD_DOWNLOADED_RAW_BITS_TI_TYPE;
854 }
855 n.ext1 = c->ext1;
856 memcpy(n.d.asDwords, BigBuf+c->ext1, 12*sizeof(DWORD));
857 UsbSendPacket((BYTE *)&n, sizeof(n));
858 break;
859 }
860 case CMD_DOWNLOADED_SIM_SAMPLES_125K: {
861 BYTE *b = (BYTE *)BigBuf;
862 memcpy(b+c->ext1, c->d.asBytes, 48);
863 break;
864 }
865 case CMD_SIMULATE_TAG_125K:
866 LED_A_ON();
955fc5e2 867 SimulateTagLowFrequency(c->ext1, 1);
959baa89 868 LED_A_OFF();
869 break;
870#ifdef WITH_LCD
871 case CMD_LCD_RESET:
872 LCDReset();
873 break;
874#endif
1dff8c42 875 case CMD_READ_MEM:
876 ReadMem(c->ext1);
877 break;
959baa89 878 case CMD_SET_LF_DIVISOR:
879 FpgaSendCommand(FPGA_CMD_SET_DIVISOR, c->ext1);
880 break;
881#ifdef WITH_LCD
882 case CMD_LCD:
883 LCDSend(c->ext1);
884 break;
885#endif
886 case CMD_SETUP_WRITE:
887 case CMD_FINISH_WRITE:
888 case CMD_HARDWARE_RESET:
889 USB_D_PLUS_PULLUP_OFF();
890 SpinDelay(1000);
891 SpinDelay(1000);
892 RSTC_CONTROL = RST_CONTROL_KEY | RST_CONTROL_PROCESSOR_RESET;
893 for(;;) {
894 // We're going to reset, and the bootrom will take control.
895 }
896 break;
897
898
899 default:
900 DbpString("unknown command");
901 break;
902 }
903}
904
1dff8c42 905void ReadMem(int addr)
906{
907 const DWORD *data = ((DWORD *)addr);
908 int i;
c701d2c2 909
1dff8c42 910 DbpString("Reading memory at address");
911 DbpIntegers(0, 0, addr);
912 for (i = 0; i < 8; i+= 2)
913 DbpIntegers(0, data[i], data[i+1]);
914}
915
959baa89 916void AppMain(void)
917{
918 memset(BigBuf,0,sizeof(BigBuf));
919 SpinDelay(100);
920
693f7cf7 921 LED_D_OFF();
922 LED_C_OFF();
923 LED_B_OFF();
924 LED_A_OFF();
959baa89 925
926 UsbStart();
927
928 // The FPGA gets its clock from us from PCK0 output, so set that up.
929 PIO_PERIPHERAL_B_SEL = (1 << GPIO_PCK0);
930 PIO_DISABLE = (1 << GPIO_PCK0);
931 PMC_SYS_CLK_ENABLE = PMC_SYS_CLK_PROGRAMMABLE_CLK_0;
932 // PCK0 is PLL clock / 4 = 96Mhz / 4 = 24Mhz
933 PMC_PROGRAMMABLE_CLK_0 = PMC_CLK_SELECTION_PLL_CLOCK |
934 PMC_CLK_PRESCALE_DIV_4;
935 PIO_OUTPUT_ENABLE = (1 << GPIO_PCK0);
936
937 // Reset SPI
938 SPI_CONTROL = SPI_CONTROL_RESET;
939 // Reset SSC
940 SSC_CONTROL = SSC_CONTROL_RESET;
941
942 // Load the FPGA image, which we have stored in our flash.
943 FpgaDownloadAndGo();
944
945#ifdef WITH_LCD
946
947 LCDInit();
948
949 // test text on different colored backgrounds
693f7cf7 950 LCDString(" The quick brown fox ", &FONT6x8,1,1+8*0,WHITE ,BLACK );
951 LCDString(" jumped over the ", &FONT6x8,1,1+8*1,BLACK ,WHITE );
952 LCDString(" lazy dog. ", &FONT6x8,1,1+8*2,YELLOW ,RED );
953 LCDString(" AaBbCcDdEeFfGgHhIiJj ", &FONT6x8,1,1+8*3,RED ,GREEN );
954 LCDString(" KkLlMmNnOoPpQqRrSsTt ", &FONT6x8,1,1+8*4,MAGENTA,BLUE );
955 LCDString("UuVvWwXxYyZz0123456789", &FONT6x8,1,1+8*5,BLUE ,YELLOW);
956 LCDString("`-=[]_;',./~!@#$%^&*()", &FONT6x8,1,1+8*6,BLACK ,CYAN );
957 LCDString(" _+{}|:\\\"<>? ",&FONT6x8,1,1+8*7,BLUE ,MAGENTA);
959baa89 958
959 // color bands
960 LCDFill(0, 1+8* 8, 132, 8, BLACK);
961 LCDFill(0, 1+8* 9, 132, 8, WHITE);
962 LCDFill(0, 1+8*10, 132, 8, RED);
963 LCDFill(0, 1+8*11, 132, 8, GREEN);
964 LCDFill(0, 1+8*12, 132, 8, BLUE);
965 LCDFill(0, 1+8*13, 132, 8, YELLOW);
966 LCDFill(0, 1+8*14, 132, 8, CYAN);
967 LCDFill(0, 1+8*15, 132, 8, MAGENTA);
968
969#endif
970
971 for(;;) {
955fc5e2 972 usbattached = UsbPoll(FALSE);
959baa89 973 WDT_HIT();
959baa89 974
955fc5e2 975 if (BUTTON_HELD(1000) > 0)
976 SamyRun();
959baa89 977 }
978}
979
959baa89 980
955fc5e2 981// samy's sniff and repeat routine
982void SamyRun()
983{
984 DbpString("Stand-alone mode! No PC necessary.");
959baa89 985
955fc5e2 986 // 3 possible options? no just 2 for now
987#define OPTS 2
959baa89 988
955fc5e2 989 int high[OPTS], low[OPTS];
c701d2c2 990
955fc5e2 991 // Oooh pretty -- notify user we're in elite samy mode now
992 LED(LED_RED, 200);
993 LED(LED_ORANGE, 200);
994 LED(LED_GREEN, 200);
995 LED(LED_ORANGE, 200);
996 LED(LED_RED, 200);
997 LED(LED_ORANGE, 200);
998 LED(LED_GREEN, 200);
999 LED(LED_ORANGE, 200);
1000 LED(LED_RED, 200);
c701d2c2 1001
955fc5e2 1002 int selected = 0;
1003 int playing = 0;
c701d2c2 1004
955fc5e2 1005 // Turn on selected LED
1006 LED(selected + 1, 0);
c701d2c2 1007
955fc5e2 1008 for (;;)
1009 {
1010 usbattached = UsbPoll(FALSE);
959baa89 1011 WDT_HIT();
c701d2c2 1012
955fc5e2 1013 // Was our button held down or pressed?
1014 int button_pressed = BUTTON_HELD(1000);
1015 SpinDelay(300);
c701d2c2 1016
955fc5e2 1017 // Button was held for a second, begin recording
1018 if (button_pressed > 0)
1019 {
1020 LEDsoff();
1021 LED(selected + 1, 0);
1022 LED(LED_RED2, 0);
c701d2c2 1023
955fc5e2 1024 // record
1025 DbpString("Starting recording");
693f7cf7 1026
1027 // wait for button to be released
1028 while(BUTTON_PRESS())
1029 WDT_HIT();
1030
955fc5e2 1031 /* need this delay to prevent catching some weird data */
1032 SpinDelay(500);
693f7cf7 1033
955fc5e2 1034 CmdHIDdemodFSK(1, &high[selected], &low[selected], 0);
1035 DbpString("Recorded");
1036 DbpIntegers(selected, high[selected], low[selected]);
c701d2c2 1037
955fc5e2 1038 LEDsoff();
1039 LED(selected + 1, 0);
1040 // Finished recording
c701d2c2 1041
955fc5e2 1042 // If we were previously playing, set playing off
1043 // so next button push begins playing what we recorded
1044 playing = 0;
1045 }
c701d2c2 1046
955fc5e2 1047 // Change where to record (or begin playing)
1048 else if (button_pressed)
1049 {
1050 // Next option if we were previously playing
1051 if (playing)
1052 selected = (selected + 1) % OPTS;
1053 playing = !playing;
c701d2c2 1054
955fc5e2 1055 LEDsoff();
1056 LED(selected + 1, 0);
c701d2c2 1057
955fc5e2 1058 // Begin transmitting
1059 if (playing)
1060 {
1061 LED(LED_GREEN, 0);
1062 DbpString("Playing");
693f7cf7 1063 // wait for button to be released
1064 while(BUTTON_PRESS())
1065 WDT_HIT();
955fc5e2 1066 DbpIntegers(selected, high[selected], low[selected]);
1067 CmdHIDsimTAG(high[selected], low[selected], 0);
1068 DbpString("Done playing");
693f7cf7 1069 if (BUTTON_HELD(1000) > 0)
1070 {
1071 DbpString("Exiting");
1072 LEDsoff();
1073 return;
1074 }
c701d2c2 1075
955fc5e2 1076 /* We pressed a button so ignore it here with a delay */
1077 SpinDelay(300);
c701d2c2 1078
955fc5e2 1079 // when done, we're done playing, move to next option
1080 selected = (selected + 1) % OPTS;
1081 playing = !playing;
1082 LEDsoff();
1083 LED(selected + 1, 0);
1084 }
693f7cf7 1085 else
1086 while(BUTTON_PRESS())
1087 WDT_HIT();
955fc5e2 1088 }
959baa89 1089 }
1090}
7f348042 1091
955fc5e2 1092
ebd7aaf9 1093/* \r
1094OBJECTIVE\r
1095Listen and detect an external reader. Determine the best location\r
1096for the antenna.\r
1097\r
1098INSTRUCTIONS:\r
1099Inside the ListenReaderField() function, there is two mode. \r
1100By default, when you call the function, you will enter mode 1.\r
1101If you press the PM3 button one time, you will enter mode 2.\r
1102If you press the PM3 button a second time, you will exit the function.\r
1103\r
1104DESCRIPTION OF MODE 1:\r
1105This mode just listens for an external reader field and lights up green \r
1106for HF and/or red for LF. This is the original mode of the detectreader\r
1107function.\r
1108\r
1109DESCRIPTION OF MODE 2:\r
1110This mode will visually represent, using the LEDs, the actual strength of the\r
1111current compared to the maximum current detected. Basically, once you know \r
1112what kind of external reader is present, it will help you spot the best location to place\r
1113your antenna. You will probably not get some good results if there is a LF and a HF reader\r
1114at the same place! :-)\r
1115\r
1116LIGHT SCHEME USED:\r
1117\r
1118Light scheme | Descriptiong\r
1119----------------------------------------------------\r
1120 ---- | No field detected\r
1121 X--- | 14% of maximum current detected\r
1122 -X-- | 29% of maximum current detected\r
1123 --X- | 43% of maximum current detected\r
1124 ---X | 57% of maximum current detected\r
1125 --XX | 71% of maximum current detected\r
1126 -XXX | 86% of maximum current detected\r
1127 XXXX | 100% of maximum current detected\r
1128\r
1129TODO:\r
1130Add the LF part for MODE 2\r
1131\r
1132*/\r
1133void ListenReaderField(int limit)\r
1134{\r
1135 int lf_av, lf_av_new, lf_baseline= 0, lf_count= 0;\r
1136 int hf_av, hf_av_new, hf_baseline= 0, hf_count= 0, hf_max;\r
1137 int mode=1;\r
1138\r
1139#define LF_ONLY 1\r
1140#define HF_ONLY 2\r
1141\r
1142 LED_A_OFF();\r
1143 LED_B_OFF();\r
1144 LED_C_OFF();\r
1145 LED_D_OFF();\r
1146\r
1147 lf_av= ReadAdc(ADC_CHAN_LF);\r
1148\r
1149 if(limit != HF_ONLY) \r
1150 {\r
1151 DbpString("LF 125/134 Baseline:");\r
1152 DbpIntegers(lf_av,0,0);\r
1153 lf_baseline= lf_av;\r
1154 }\r
1155\r
1156 hf_av=hf_max=ReadAdc(ADC_CHAN_HF);\r
1157\r
1158 if (limit != LF_ONLY) \r
1159 {\r
1160 DbpString("HF 13.56 Baseline:");\r
1161 DbpIntegers(hf_av,0,0);\r
1162 hf_baseline= hf_av;\r
1163 }\r
1164\r
1165 for(;;) \r
1166 {\r
1167 if (BUTTON_PRESS()) {\r
1168 SpinDelay(500);\r
1169 switch (mode) {\r
1170 case 1:\r
1171 mode=2;\r
1172 DbpString("Signal Strength Mode");
1173 break;\r
1174 case 2:\r
1175 default:\r
1176 DbpString("Stopped");\r
1177 LED_A_OFF();\r
1178 LED_B_OFF();\r
1179 LED_C_OFF();\r
1180 LED_D_OFF();\r
1181 return;\r
1182 break;\r
1183 }\r
1184 }\r
1185 WDT_HIT();\r
1186\r
1187 if (limit != HF_ONLY) \r
1188 {\r
1189 if (abs(lf_av - lf_baseline) > 10)\r
1190 LED_D_ON();\r
1191 else\r
1192 LED_D_OFF();\r
1193 ++lf_count;\r
1194 lf_av_new= ReadAdc(ADC_CHAN_LF);\r
1195 // see if there's a significant change\r
1196 if(abs(lf_av - lf_av_new) > 10) \r
1197 {\r
1198 DbpString("LF 125/134 Field Change:");\r
1199 DbpIntegers(lf_av,lf_av_new,lf_count);\r
1200 lf_av= lf_av_new;\r
1201 lf_count= 0;\r
1202 }\r
1203 }\r
1204\r
1205 if (limit != LF_ONLY) \r
1206 {\r
1207 if (abs(hf_av - hf_baseline) > 10) {\r
1208 if (mode == 1)\r
1209 LED_B_ON();\r
1210 if (mode == 2) {\r
1211 if ( hf_av>(hf_max/7)*6) {\r
1212 LED_A_ON(); LED_B_ON(); LED_C_ON(); LED_D_ON();\r
1213 }\r
1214 if ( (hf_av>(hf_max/7)*5) && (hf_av<=(hf_max/7)*6) ) {\r
1215 LED_A_ON(); LED_B_ON(); LED_C_OFF(); LED_D_ON();\r
1216 }\r
1217 if ( (hf_av>(hf_max/7)*4) && (hf_av<=(hf_max/7)*5) ) {\r
1218 LED_A_OFF(); LED_B_ON(); LED_C_OFF(); LED_D_ON();\r
1219 }\r
1220 if ( (hf_av>(hf_max/7)*3) && (hf_av<=(hf_max/7)*4) ) {\r
1221 LED_A_OFF(); LED_B_OFF(); LED_C_OFF(); LED_D_ON();\r
1222 }\r
1223 if ( (hf_av>(hf_max/7)*2) && (hf_av<=(hf_max/7)*3) ) {\r
1224 LED_A_OFF(); LED_B_ON(); LED_C_OFF(); LED_D_OFF();\r
1225 }\r
1226 if ( (hf_av>(hf_max/7)*1) && (hf_av<=(hf_max/7)*2) ) {\r
1227 LED_A_ON(); LED_B_OFF(); LED_C_OFF(); LED_D_OFF();\r
1228 }\r
1229 if ( (hf_av>(hf_max/7)*0) && (hf_av<=(hf_max/7)*1) ) {\r
1230 LED_A_OFF(); LED_B_OFF(); LED_C_ON(); LED_D_OFF();\r
1231 }\r
1232 } \r
1233 } else {\r
1234 if (mode == 1) {\r
1235 LED_B_OFF();\r
1236 }\r
1237 if (mode == 2) {\r
1238 LED_A_OFF(); LED_B_OFF(); LED_C_OFF(); LED_D_OFF();\r
1239 }\r
1240 }\r
1241\r
1242 ++hf_count;\r
1243 hf_av_new= ReadAdc(ADC_CHAN_HF);\r
1244 // see if there's a significant change\r
1245 if(abs(hf_av - hf_av_new) > 10) \r
1246 {\r
1247 DbpString("HF 13.56 Field Change:");\r
1248 DbpIntegers(hf_av,hf_av_new,hf_count);\r
1249 hf_av= hf_av_new;\r
1250 if (hf_av > hf_max)\r
1251 hf_max = hf_av;\r
1252 hf_count= 0;\r
1253 }\r
1254 }\r
1255 }\r
1256}\r
1257\r
Impressum, Datenschutz