]> git.zerfleddert.de Git - proxmark3-svn/blob - winsrc/command.cpp
add inversion option to mandemod and fix indentation
[proxmark3-svn] / winsrc / command.cpp
1 //-----------------------------------------------------------------------------
2 // The actual command interpeter for what the user types at the command line.
3 // Jonathan Westhues, Sept 2005
4 // Edits by Gerhard de Koning Gans, Sep 2007 (##)
5 //-----------------------------------------------------------------------------
6 #include <windows.h>
7 #include <stdlib.h>
8 #include <string.h>
9 #include <stdio.h>
10 #include <limits.h>
11 #include <math.h>
12
13 #include "prox.h"
14 #include "../common/iso14443_crc.c"
15
16 #define arraylen(x) (sizeof(x)/sizeof((x)[0]))
17 #define BIT(x) GraphBuffer[x * clock]
18 #define BITS (GraphTraceLen / clock)
19
20 int go = 0;
21 static int CmdHisamplest(char *str, int nrlow);
22
23 static void GetFromBigBuf(BYTE *dest, int bytes)
24 {
25 int n = bytes/4;
26
27 if(n % 48 != 0) {
28 PrintToScrollback("bad len in GetFromBigBuf");
29 return;
30 }
31
32 int i;
33 for(i = 0; i < n; i += 12) {
34 UsbCommand c;
35 c.cmd = CMD_DOWNLOAD_RAW_ADC_SAMPLES_125K;
36 c.ext1 = i;
37 SendCommand(&c, FALSE);
38 ReceiveCommand(&c);
39 if(c.cmd != CMD_DOWNLOADED_RAW_ADC_SAMPLES_125K) {
40 PrintToScrollback("bad resp");
41 return;
42 }
43
44 memcpy(dest+(i*4), c.d.asBytes, 48);
45 }
46 }
47
48 static void CmdReset(char *str)
49 {
50 UsbCommand c;
51 c.cmd = CMD_HARDWARE_RESET;
52 SendCommand(&c, FALSE);
53 }
54
55 static void CmdBuffClear(char *str)
56 {
57 UsbCommand c;
58 c.cmd = CMD_BUFF_CLEAR;
59 SendCommand(&c, FALSE);
60 CmdClearGraph(TRUE);
61 }
62
63 static void CmdQuit(char *str)
64 {
65 exit(0);
66 }
67
68 static void CmdHIDdemodFSK(char *str)
69 {
70 UsbCommand c;
71 c.cmd = CMD_HID_DEMOD_FSK;
72 SendCommand(&c, FALSE);
73 }
74
75 static void CmdTune(char *str)
76 {
77 UsbCommand c;
78 c.cmd = CMD_MEASURE_ANTENNA_TUNING;
79 SendCommand(&c, FALSE);
80 }
81
82 static void CmdHi15read(char *str)
83 {
84 UsbCommand c;
85 c.cmd = CMD_ACQUIRE_RAW_ADC_SAMPLES_ISO_15693;
86 SendCommand(&c, FALSE);
87 }
88
89 static void CmdHi14read(char *str)
90 {
91 UsbCommand c;
92 c.cmd = CMD_ACQUIRE_RAW_ADC_SAMPLES_ISO_14443;
93 c.ext1 = atoi(str);
94 SendCommand(&c, FALSE);
95 }
96
97
98 /* New command to read the contents of a SRI512 tag
99 * SRI512 tags are ISO14443-B modulated memory tags,
100 * this command just dumps the contents of the memory/
101 */
102 static void CmdSri512read(char *str)
103 {
104 UsbCommand c;
105 c.cmd = CMD_READ_SRI512_TAG;
106 c.ext1 = atoi(str);
107 SendCommand(&c, FALSE);
108 }
109
110 // ## New command
111 static void CmdHi14areader(char *str)
112 {
113 UsbCommand c;
114 c.cmd = CMD_READER_ISO_14443a;
115 c.ext1 = atoi(str);
116 SendCommand(&c, FALSE);
117 }
118
119 // ## New command
120 static void CmdHi15reader(char *str)
121 {
122 UsbCommand c;
123 c.cmd = CMD_READER_ISO_15693;
124 c.ext1 = atoi(str);
125 SendCommand(&c, FALSE);
126 }
127
128 // ## New command
129 static void CmdHi15tag(char *str)
130 {
131 UsbCommand c;
132 c.cmd = CMD_SIMTAG_ISO_15693;
133 c.ext1 = atoi(str);
134 SendCommand(&c, FALSE);
135 }
136
137 static void CmdHi14read_sim(char *str)
138 {
139 UsbCommand c;
140 c.cmd = CMD_ACQUIRE_RAW_ADC_SAMPLES_ISO_14443_SIM;
141 c.ext1 = atoi(str);
142 SendCommand(&c, FALSE);
143 }
144
145 static void CmdHi14readt(char *str)
146 {
147 UsbCommand c;
148 c.cmd = CMD_ACQUIRE_RAW_ADC_SAMPLES_ISO_14443;
149 c.ext1 = atoi(str);
150 SendCommand(&c, FALSE);
151
152 //CmdHisamplest(str);
153 while(CmdHisamplest(str,atoi(str))==0) {
154 c.cmd = CMD_ACQUIRE_RAW_ADC_SAMPLES_ISO_14443;
155 c.ext1 = atoi(str);
156 SendCommand(&c, FALSE);
157 }
158 RepaintGraphWindow();
159 }
160
161 static void CmdHisimlisten(char *str)
162 {
163 UsbCommand c;
164 c.cmd = CMD_SIMULATE_TAG_HF_LISTEN;
165 SendCommand(&c, FALSE);
166 }
167
168 static void CmdHi14sim(char *str)
169 {
170 UsbCommand c;
171 c.cmd = CMD_SIMULATE_TAG_ISO_14443;
172 SendCommand(&c, FALSE);
173 }
174
175 static void CmdHi14asim(char *str) // ## simulate iso14443a tag
176 { // ## greg - added ability to specify tag UID
177
178 unsigned int hi=0, lo=0;
179 int n=0, i=0;
180 UsbCommand c;
181
182 while (sscanf(&str[i++], "%1x", &n ) == 1) {
183 hi=(hi<<4)|(lo>>28);
184 lo=(lo<<4)|(n&0xf);
185 }
186
187 c.cmd = CMD_SIMULATE_TAG_ISO_14443a;
188 // c.ext should be set to *str or convert *str to the correct format for a uid
189 c.ext1 = hi;
190 c.ext2 = lo;
191 PrintToScrollback("Emulating 14443A TAG with UID %x%16x", hi, lo);
192 SendCommand(&c, FALSE);
193 }
194
195 static void CmdHi14snoop(char *str)
196 {
197 UsbCommand c;
198 c.cmd = CMD_SNOOP_ISO_14443;
199 SendCommand(&c, FALSE);
200 }
201
202 static void CmdHi14asnoop(char *str)
203 {
204 UsbCommand c;
205 c.cmd = CMD_SNOOP_ISO_14443a;
206 SendCommand(&c, FALSE);
207 }
208
209 static void CmdFPGAOff(char *str) // ## FPGA Control
210 {
211 UsbCommand c;
212 c.cmd = CMD_FPGA_MAJOR_MODE_OFF;
213 SendCommand(&c, FALSE);
214 }
215
216 /* clear out our graph window */
217 int CmdClearGraph(int redraw)
218 {
219 int gtl = GraphTraceLen;
220 GraphTraceLen = 0;
221
222 if (redraw)
223 RepaintGraphWindow();
224
225 return gtl;
226 }
227
228 /* write a bit to the graph */
229 static void CmdAppendGraph(int redraw, int clock, int bit)
230 {
231 int i;
232
233 for (i = 0; i < (int)(clock/2); i++)
234 GraphBuffer[GraphTraceLen++] = bit ^ 1;
235
236 for (i = (int)(clock/2); i < clock; i++)
237 GraphBuffer[GraphTraceLen++] = bit;
238
239 if (redraw)
240 RepaintGraphWindow();
241 }
242
243 /* Function is equivalent of loread + losamples + em410xread
244 * looped until an EM410x tag is detected */
245 static void CmdEM410xwatch(char *str)
246 {
247 char *zero = "";
248 char *twok = "2000";
249 go = 1;
250
251 do
252 {
253 CmdLoread(zero);
254 CmdLosamples(twok);
255 CmdEM410xread(zero);
256 } while (go);
257 }
258
259 /* Read the ID of an EM410x tag.
260 * Format:
261 * 1111 1111 1 <-- standard non-repeatable header
262 * XXXX [row parity bit] <-- 10 rows of 5 bits for our 40 bit tag ID
263 * ....
264 * CCCC <-- each bit here is parity for the 10 bits above in corresponding column
265 * 0 <-- stop bit, end of tag
266 */
267 static void CmdEM410xread(char *str)
268 {
269 int i, j, clock, header, rows, bit, hithigh, hitlow, first, bit2idx, high, low;
270 int parity[4];
271 char id[11];
272 int retested = 0;
273 int BitStream[MAX_GRAPH_TRACE_LEN];
274 high = low = 0;
275
276 /* Detect high and lows and clock */
277 for (i = 0; i < GraphTraceLen; i++)
278 {
279 if (GraphBuffer[i] > high)
280 high = GraphBuffer[i];
281 else if (GraphBuffer[i] < low)
282 low = GraphBuffer[i];
283 }
284
285 /* get clock */
286 clock = GetClock(str, high);
287
288 /* parity for our 4 columns */
289 parity[0] = parity[1] = parity[2] = parity[3] = 0;
290 header = rows = 0;
291
292 /* manchester demodulate */
293 bit = bit2idx = 0;
294 for (i = 0; i < (int)(GraphTraceLen / clock); i++)
295 {
296 hithigh = 0;
297 hitlow = 0;
298 first = 1;
299
300 /* Find out if we hit both high and low peaks */
301 for (j = 0; j < clock; j++)
302 {
303 if (GraphBuffer[(i * clock) + j] == high)
304 hithigh = 1;
305 else if (GraphBuffer[(i * clock) + j] == low)
306 hitlow = 1;
307
308 /* it doesn't count if it's the first part of our read
309 because it's really just trailing from the last sequence */
310 if (first && (hithigh || hitlow))
311 hithigh = hitlow = 0;
312 else
313 first = 0;
314
315 if (hithigh && hitlow)
316 break;
317 }
318
319 /* If we didn't hit both high and low peaks, we had a bit transition */
320 if (!hithigh || !hitlow)
321 bit ^= 1;
322
323 BitStream[bit2idx++] = bit;
324 }
325
326 retest:
327 /* We go till 5 before the graph ends because we'll get that far below */
328 for (i = 1; i < bit2idx - 5; i++)
329 {
330 /* Step 2: We have our header but need our tag ID */
331 if (header == 9 && rows < 10)
332 {
333 /* Confirm parity is correct */
334 if ((BitStream[i] ^ BitStream[i+1] ^ BitStream[i+2] ^ BitStream[i+3]) == BitStream[i+4])
335 {
336 /* Read another byte! */
337 sprintf(id+rows, "%x", (8 * BitStream[i]) + (4 * BitStream[i+1]) + (2 * BitStream[i+2]) + (1 * BitStream[i+3]));
338 rows++;
339
340 /* Keep parity info */
341 parity[0] ^= BitStream[i];
342 parity[1] ^= BitStream[i+1];
343 parity[2] ^= BitStream[i+2];
344 parity[3] ^= BitStream[i+3];
345
346 /* Move 4 bits ahead */
347 i += 4;
348 }
349
350 /* Damn, something wrong! reset */
351 else
352 {
353 PrintToScrollback("Thought we had a valid tag but failed at word %d (i=%d)", rows + 1, i);
354
355 /* Start back rows * 5 + 9 header bits, -1 to not start at same place */
356 i -= 9 + (5 * rows) - 5;
357
358 rows = header = 0;
359 }
360 }
361
362 /* Step 3: Got our 40 bits! confirm column parity */
363 else if (rows == 10)
364 {
365 /* We need to make sure our 4 bits of parity are correct and we have a stop bit */
366 if (BitStream[i] == parity[0] && BitStream[i+1] == parity[1] &&
367 BitStream[i+2] == parity[2] && BitStream[i+3] == parity[3] &&
368 BitStream[i+4] == 0)
369 {
370 /* Sweet! */
371 PrintToScrollback("EM410x Tag ID: %s", id);
372
373 /* Stop any loops */
374 go = 0;
375 return;
376 }
377
378 /* Crap! Incorrect parity or no stop bit, start all over */
379 else
380 {
381 rows = header = 0;
382
383 /* Go back 59 bits (9 header bits + 10 rows at 4+1 parity) */
384 i -= 59;
385 }
386 }
387
388 /* Step 1: get our header */
389 else if (header < 9)
390 {
391 /* Need 9 consecutive 1's */
392 if (BitStream[i] == 1)
393 header++;
394
395 /* We don't have a header, not enough consecutive 1 bits */
396 else
397 header = 0;
398 }
399 }
400
401 /* if we've already retested after flipping bits, return */
402 if (retested++)
403 return;
404
405 /* if this didn't work, try flipping bits */
406 for (i = 0; i < bit2idx; i++)
407 BitStream[i] ^= 1;
408
409 goto retest;
410 }
411
412 /* emulate an EM410X tag
413 * Format:
414 * 1111 1111 1 <-- standard non-repeatable header
415 * XXXX [row parity bit] <-- 10 rows of 5 bits for our 40 bit tag ID
416 * ....
417 * CCCC <-- each bit here is parity for the 10 bits above in corresponding column
418 * 0 <-- stop bit, end of tag
419 */
420 static void CmdEM410xsim(char *str)
421 {
422 int i, n, j, h, binary[4], parity[4];
423 char *s = "0";
424
425 /* clock is 64 in EM410x tags */
426 int clock = 64;
427
428 /* clear our graph */
429 CmdClearGraph(0);
430
431 /* write it out a few times */
432 for (h = 0; h < 4; h++)
433 {
434 /* write 9 start bits */
435 for (i = 0; i < 9; i++)
436 CmdAppendGraph(0, clock, 1);
437
438 /* for each hex char */
439 parity[0] = parity[1] = parity[2] = parity[3] = 0;
440 for (i = 0; i < 10; i++)
441 {
442 /* read each hex char */
443 sscanf(&str[i], "%1x", &n);
444 for (j = 3; j >= 0; j--, n/= 2)
445 binary[j] = n % 2;
446
447 /* append each bit */
448 CmdAppendGraph(0, clock, binary[0]);
449 CmdAppendGraph(0, clock, binary[1]);
450 CmdAppendGraph(0, clock, binary[2]);
451 CmdAppendGraph(0, clock, binary[3]);
452
453 /* append parity bit */
454 CmdAppendGraph(0, clock, binary[0] ^ binary[1] ^ binary[2] ^ binary[3]);
455
456 /* keep track of column parity */
457 parity[0] ^= binary[0];
458 parity[1] ^= binary[1];
459 parity[2] ^= binary[2];
460 parity[3] ^= binary[3];
461 }
462
463 /* parity columns */
464 CmdAppendGraph(0, clock, parity[0]);
465 CmdAppendGraph(0, clock, parity[1]);
466 CmdAppendGraph(0, clock, parity[2]);
467 CmdAppendGraph(0, clock, parity[3]);
468
469 /* stop bit */
470 CmdAppendGraph(0, clock, 0);
471 }
472
473 /* modulate that biatch */
474 Cmdmanchestermod(s);
475
476 /* booyah! */
477 RepaintGraphWindow();
478
479 CmdLosim(s);
480 }
481
482 static void ChkBitstream(char *str)
483 {
484 int i;
485
486 /* convert to bitstream if necessary */
487 for (i = 0; i < (int)(GraphTraceLen / 2); i++)
488 {
489 if (GraphBuffer[i] > 1 || GraphBuffer[i] < 0)
490 {
491 Cmdbitstream(str);
492 break;
493 }
494 }
495 }
496
497 static void CmdLosim(char *str)
498 {
499 int i;
500 char *zero = "0";
501
502 /* convert to bitstream if necessary */
503 ChkBitstream(str);
504
505 for (i = 0; i < GraphTraceLen; i += 48) {
506 UsbCommand c;
507 int j;
508 for(j = 0; j < 48; j++) {
509 c.d.asBytes[j] = GraphBuffer[i+j];
510 }
511 c.cmd = CMD_DOWNLOADED_SIM_SAMPLES_125K;
512 c.ext1 = i;
513 SendCommand(&c, FALSE);
514 }
515
516 UsbCommand c;
517 c.cmd = CMD_SIMULATE_TAG_125K;
518 c.ext1 = GraphTraceLen;
519 SendCommand(&c, FALSE);
520 }
521
522 static void CmdLoread(char *str)
523 {
524 UsbCommand c;
525 // 'h' means higher-low-frequency, 134 kHz
526 if(*str == 'h') {
527 c.ext1 = 1;
528 } else if (*str == '\0') {
529 c.ext1 = 0;
530 } else {
531 PrintToScrollback("use 'loread' or 'loread h'");
532 return;
533 }
534 c.cmd = CMD_ACQUIRE_RAW_ADC_SAMPLES_125K;
535 SendCommand(&c, FALSE);
536 }
537
538 static void CmdLosamples(char *str)
539 {
540 int cnt = 0;
541 int i;
542 int n;
543
544 n=atoi(str);
545 if (n==0) n=128;
546 if (n>16000) n=16000;
547
548 for(i = 0; i < n; i += 12) {
549 UsbCommand c;
550 c.cmd = CMD_DOWNLOAD_RAW_ADC_SAMPLES_125K;
551 c.ext1 = i;
552 SendCommand(&c, FALSE);
553 ReceiveCommand(&c);
554 if(c.cmd != CMD_DOWNLOADED_RAW_ADC_SAMPLES_125K) {
555 if (!go)
556 PrintToScrollback("bad resp");
557 return;
558 }
559 int j;
560 for(j = 0; j < 48; j++) {
561 GraphBuffer[cnt++] = ((int)c.d.asBytes[j]) - 128;
562 }
563 }
564 GraphTraceLen = n*4;
565 RepaintGraphWindow();
566 }
567
568 static void CmdBitsamples(char *str)
569 {
570 int cnt = 0;
571 int i;
572 int n;
573
574 n = 3072;
575 for(i = 0; i < n; i += 12) {
576 UsbCommand c;
577 c.cmd = CMD_DOWNLOAD_RAW_ADC_SAMPLES_125K;
578 c.ext1 = i;
579 SendCommand(&c, FALSE);
580 ReceiveCommand(&c);
581 if(c.cmd != CMD_DOWNLOADED_RAW_ADC_SAMPLES_125K) {
582 PrintToScrollback("bad resp");
583 return;
584 }
585 int j, k;
586 for(j = 0; j < 48; j++) {
587 for(k = 0; k < 8; k++) {
588 if(c.d.asBytes[j] & (1 << (7 - k))) {
589 GraphBuffer[cnt++] = 1;
590 } else {
591 GraphBuffer[cnt++] = 0;
592 }
593 }
594 }
595 }
596 GraphTraceLen = cnt;
597 RepaintGraphWindow();
598 }
599
600 static void CmdHisamples(char *str)
601 {
602 int cnt = 0;
603 int i;
604 int n;
605 n = 1000;
606 for(i = 0; i < n; i += 12) {
607 UsbCommand c;
608 c.cmd = CMD_DOWNLOAD_RAW_ADC_SAMPLES_125K;
609 c.ext1 = i;
610 SendCommand(&c, FALSE);
611 ReceiveCommand(&c);
612 if(c.cmd != CMD_DOWNLOADED_RAW_ADC_SAMPLES_125K) {
613 PrintToScrollback("bad resp");
614 return;
615 }
616 int j;
617 for(j = 0; j < 48; j++) {
618 GraphBuffer[cnt++] = (int)((BYTE)c.d.asBytes[j]);
619 }
620 }
621 GraphTraceLen = n*4;
622
623 RepaintGraphWindow();
624 }
625
626
627 static int CmdHisamplest(char *str, int nrlow)
628 {
629 int cnt = 0;
630 int t1, t2;
631 int i;
632 int n;
633 int hasbeennull;
634 int show;
635
636
637 n = 1000;
638 hasbeennull = 0;
639 for(i = 0; i < n; i += 12) {
640 UsbCommand c;
641 c.cmd = CMD_DOWNLOAD_RAW_ADC_SAMPLES_125K;
642 c.ext1 = i;
643 SendCommand(&c, FALSE);
644 ReceiveCommand(&c);
645 if(c.cmd != CMD_DOWNLOADED_RAW_ADC_SAMPLES_125K) {
646 PrintToScrollback("bad resp");
647 return 0;
648 }
649 int j;
650 for(j = 0; j < 48; j++) {
651 t2 = (int)((BYTE)c.d.asBytes[j]);
652 if((t2 ^ 0xC0) & 0xC0) { hasbeennull++; }
653
654 show = 0;
655 switch(show) {
656 case 0:
657 // combined
658 t1 = (t2 & 0x80) ^ (t2 & 0x20);
659 t2 = ((t2 << 1) & 0x80) ^ ((t2 << 1) & 0x20);
660 break;
661
662 case 1:
663 // only reader
664 t1 = (t2 & 0x80);
665 t2 = ((t2 << 1) & 0x80);
666 break;
667
668 case 2:
669 // only tag
670 t1 = (t2 & 0x20);
671 t2 = ((t2 << 1) & 0x20);
672 break;
673
674 case 3:
675 // both, but tag with other algorithm
676 t1 = (t2 & 0x80) ^ (t2 & 0x08);
677 t2 = ((t2 << 1) & 0x80) ^ ((t2 << 1) & 0x08);
678 break;
679 }
680
681 GraphBuffer[cnt++] = t1;
682 GraphBuffer[cnt++] = t2;
683 }
684 }
685 GraphTraceLen = n*4;
686 // 1130
687 if(hasbeennull>nrlow || nrlow==0) {
688 PrintToScrollback("hasbeennull=%d", hasbeennull);
689 return 1;
690 }
691 else {
692 return 0;
693 }
694 }
695
696
697 static void CmdHexsamples(char *str)
698 {
699 int i;
700 int n;
701
702 if(atoi(str) == 0) {
703 n = 12;
704 } else {
705 n = atoi(str)/4;
706 }
707
708 for(i = 0; i < n; i += 12) {
709 UsbCommand c;
710 c.cmd = CMD_DOWNLOAD_RAW_ADC_SAMPLES_125K;
711 c.ext1 = i;
712 SendCommand(&c, FALSE);
713 ReceiveCommand(&c);
714 if(c.cmd != CMD_DOWNLOADED_RAW_ADC_SAMPLES_125K) {
715 PrintToScrollback("bad resp");
716 return;
717 }
718 int j;
719 for(j = 0; j < 48; j += 8) {
720 PrintToScrollback("%02x %02x %02x %02x %02x %02x %02x %02x",
721 c.d.asBytes[j+0],
722 c.d.asBytes[j+1],
723 c.d.asBytes[j+2],
724 c.d.asBytes[j+3],
725 c.d.asBytes[j+4],
726 c.d.asBytes[j+5],
727 c.d.asBytes[j+6],
728 c.d.asBytes[j+7],
729 c.d.asBytes[j+8]
730 );
731 }
732 }
733 }
734
735 static void CmdHisampless(char *str)
736 {
737 int cnt = 0;
738 int i;
739 int n;
740
741 if(atoi(str) == 0) {
742 n = 1000;
743 } else {
744 n = atoi(str)/4;
745 }
746
747 for(i = 0; i < n; i += 12) {
748 UsbCommand c;
749 c.cmd = CMD_DOWNLOAD_RAW_ADC_SAMPLES_125K;
750 c.ext1 = i;
751 SendCommand(&c, FALSE);
752 ReceiveCommand(&c);
753 if(c.cmd != CMD_DOWNLOADED_RAW_ADC_SAMPLES_125K) {
754 PrintToScrollback("bad resp");
755 return;
756 }
757 int j;
758 for(j = 0; j < 48; j++) {
759 GraphBuffer[cnt++] = (int)((signed char)c.d.asBytes[j]);
760 }
761 }
762 GraphTraceLen = cnt;
763
764 RepaintGraphWindow();
765 }
766
767 static WORD Iso15693Crc(BYTE *v, int n)
768 {
769 DWORD reg;
770 int i, j;
771
772 reg = 0xffff;
773 for(i = 0; i < n; i++) {
774 reg = reg ^ ((DWORD)v[i]);
775 for (j = 0; j < 8; j++) {
776 if (reg & 0x0001) {
777 reg = (reg >> 1) ^ 0x8408;
778 } else {
779 reg = (reg >> 1);
780 }
781 }
782 }
783
784 return (WORD)~reg;
785 }
786
787 static void CmdHi14bdemod(char *str)
788 {
789 int i, j, iold;
790 int isum, qsum;
791 int outOfWeakAt;
792 BOOL negateI, negateQ;
793
794 BYTE data[256];
795 int dataLen=0;
796
797 // As received, the samples are pairs, correlations against I and Q
798 // square waves. So estimate angle of initial carrier (or just
799 // quadrant, actually), and then do the demod.
800
801 // First, estimate where the tag starts modulating.
802 for(i = 0; i < GraphTraceLen; i += 2) {
803 if(abs(GraphBuffer[i]) + abs(GraphBuffer[i+1]) > 40) {
804 break;
805 }
806 }
807 if(i >= GraphTraceLen) {
808 PrintToScrollback("too weak to sync");
809 return;
810 }
811 PrintToScrollback("out of weak at %d", i);
812 outOfWeakAt = i;
813
814 // Now, estimate the phase in the initial modulation of the tag
815 isum = 0;
816 qsum = 0;
817 for(; i < (outOfWeakAt + 16); i += 2) {
818 isum += GraphBuffer[i+0];
819 qsum += GraphBuffer[i+1];
820 }
821 negateI = (isum < 0);
822 negateQ = (qsum < 0);
823
824 // Turn the correlation pairs into soft decisions on the bit.
825 j = 0;
826 for(i = 0; i < GraphTraceLen/2; i++) {
827 int si = GraphBuffer[j];
828 int sq = GraphBuffer[j+1];
829 if(negateI) si = -si;
830 if(negateQ) sq = -sq;
831 GraphBuffer[i] = si + sq;
832 j += 2;
833 }
834 GraphTraceLen = i;
835
836 i = outOfWeakAt/2;
837 while(GraphBuffer[i] > 0 && i < GraphTraceLen)
838 i++;
839 if(i >= GraphTraceLen) goto demodError;
840
841 iold = i;
842 while(GraphBuffer[i] < 0 && i < GraphTraceLen)
843 i++;
844 if(i >= GraphTraceLen) goto demodError;
845 if((i - iold) > 23) goto demodError;
846
847 PrintToScrollback("make it to demod loop");
848
849 for(;;) {
850 iold = i;
851 while(GraphBuffer[i] >= 0 && i < GraphTraceLen)
852 i++;
853 if(i >= GraphTraceLen) goto demodError;
854 if((i - iold) > 6) goto demodError;
855
856 WORD shiftReg = 0;
857 if(i + 20 >= GraphTraceLen) goto demodError;
858
859 for(j = 0; j < 10; j++) {
860 int soft = GraphBuffer[i] + GraphBuffer[i+1];
861
862 if(abs(soft) < ((abs(isum) + abs(qsum))/20)) {
863 PrintToScrollback("weak bit");
864 }
865
866 shiftReg >>= 1;
867 if(GraphBuffer[i] + GraphBuffer[i+1] >= 0) {
868 shiftReg |= 0x200;
869 }
870
871 i+= 2;
872 }
873
874 if( (shiftReg & 0x200) &&
875 !(shiftReg & 0x001))
876 {
877 // valid data byte, start and stop bits okay
878 PrintToScrollback(" %02x", (shiftReg >> 1) & 0xff);
879 data[dataLen++] = (shiftReg >> 1) & 0xff;
880 if(dataLen >= sizeof(data)) {
881 return;
882 }
883 } else if(shiftReg == 0x000) {
884 // this is EOF
885 break;
886 } else {
887 goto demodError;
888 }
889 }
890
891 BYTE first, second;
892 ComputeCrc14443(CRC_14443_B, data, dataLen-2, &first, &second);
893 PrintToScrollback("CRC: %02x %02x (%s)\n", first, second,
894 (first == data[dataLen-2] && second == data[dataLen-1]) ?
895 "ok" : "****FAIL****");
896
897 RepaintGraphWindow();
898 return;
899
900 demodError:
901 PrintToScrollback("demod error");
902 RepaintGraphWindow();
903 }
904
905 static void CmdHi14list(char *str)
906 {
907 BYTE got[960];
908 GetFromBigBuf(got, sizeof(got));
909
910 PrintToScrollback("recorded activity:");
911 PrintToScrollback(" time :rssi: who bytes");
912 PrintToScrollback("---------+----+----+-----------");
913
914 int i = 0;
915 int prev = -1;
916
917 for(;;) {
918 if(i >= 900) {
919 break;
920 }
921
922 BOOL isResponse;
923 int timestamp = *((DWORD *)(got+i));
924 if(timestamp & 0x80000000) {
925 timestamp &= 0x7fffffff;
926 isResponse = 1;
927 } else {
928 isResponse = 0;
929 }
930 int metric = *((DWORD *)(got+i+4));
931
932 int len = got[i+8];
933
934 if(len > 100) {
935 break;
936 }
937 if(i + len >= 900) {
938 break;
939 }
940
941 BYTE *frame = (got+i+9);
942
943 char line[1000] = "";
944 int j;
945 for(j = 0; j < len; j++) {
946 sprintf(line+(j*3), "%02x ", frame[j]);
947 }
948
949 char *crc;
950 if(len > 2) {
951 BYTE b1, b2;
952 ComputeCrc14443(CRC_14443_B, frame, len-2, &b1, &b2);
953 if(b1 != frame[len-2] || b2 != frame[len-1]) {
954 crc = "**FAIL CRC**";
955 } else {
956 crc = "";
957 }
958 } else {
959 crc = "(SHORT)";
960 }
961
962 char metricString[100];
963 if(isResponse) {
964 sprintf(metricString, "%3d", metric);
965 } else {
966 strcpy(metricString, " ");
967 }
968
969 PrintToScrollback(" +%7d: %s: %s %s %s",
970 (prev < 0 ? 0 : timestamp - prev),
971 metricString,
972 (isResponse ? "TAG" : " "), line, crc);
973
974 prev = timestamp;
975 i += (len + 9);
976 }
977 }
978
979 static void CmdHi14alist(char *str)
980 {
981 BYTE got[1920];
982 GetFromBigBuf(got, sizeof(got));
983
984 PrintToScrollback("recorded activity:");
985 PrintToScrollback(" ETU :rssi: who bytes");
986 PrintToScrollback("---------+----+----+-----------");
987
988 int i = 0;
989 int prev = -1;
990
991 for(;;) {
992 if(i >= 1900) {
993 break;
994 }
995
996 BOOL isResponse;
997 int timestamp = *((DWORD *)(got+i));
998 if(timestamp & 0x80000000) {
999 timestamp &= 0x7fffffff;
1000 isResponse = 1;
1001 } else {
1002 isResponse = 0;
1003 }
1004
1005 int metric = 0;
1006 int parityBits = *((DWORD *)(got+i+4));
1007 // 4 bytes of additional information...
1008 // maximum of 32 additional parity bit information
1009 //
1010 // TODO:
1011 // at each quarter bit period we can send power level (16 levels)
1012 // or each half bit period in 256 levels.
1013
1014
1015 int len = got[i+8];
1016
1017 if(len > 100) {
1018 break;
1019 }
1020 if(i + len >= 1900) {
1021 break;
1022 }
1023
1024 BYTE *frame = (got+i+9);
1025
1026 // Break and stick with current result if buffer was not completely full
1027 if(frame[0] == 0x44 && frame[1] == 0x44 && frame[3] == 0x44) { break; }
1028
1029 char line[1000] = "";
1030 int j;
1031 for(j = 0; j < len; j++) {
1032 int oddparity = 0x01;
1033 int k;
1034
1035 for(k=0;k<8;k++) {
1036 oddparity ^= (((frame[j] & 0xFF) >> k) & 0x01);
1037 }
1038
1039 //if((parityBits >> (len - j - 1)) & 0x01) {
1040 if(isResponse && (oddparity != ((parityBits >> (len - j - 1)) & 0x01))) {
1041 sprintf(line+(j*4), "%02x! ", frame[j]);
1042 }
1043 else {
1044 sprintf(line+(j*4), "%02x ", frame[j]);
1045 }
1046 }
1047
1048 char *crc;
1049 crc = "";
1050 if(len > 2) {
1051 BYTE b1, b2;
1052 for(j = 0; j < (len - 1); j++) {
1053 // gives problems... search for the reason..
1054 /*if(frame[j] == 0xAA) {
1055 switch(frame[j+1]) {
1056 case 0x01:
1057 crc = "[1] Two drops close after each other";
1058 break;
1059 case 0x02:
1060 crc = "[2] Potential SOC with a drop in second half of bitperiod";
1061 break;
1062 case 0x03:
1063 crc = "[3] Segment Z after segment X is not possible";
1064 break;
1065 case 0x04:
1066 crc = "[4] Parity bit of a fully received byte was wrong";
1067 break;
1068 default:
1069 crc = "[?] Unknown error";
1070 break;
1071 }
1072 break;
1073 }*/
1074 }
1075
1076 if(strlen(crc)==0) {
1077 ComputeCrc14443(CRC_14443_A, frame, len-2, &b1, &b2);
1078 if(b1 != frame[len-2] || b2 != frame[len-1]) {
1079 crc = (isResponse & (len < 6)) ? "" : " !crc";
1080 } else {
1081 crc = "";
1082 }
1083 }
1084 } else {
1085 crc = ""; // SHORT
1086 }
1087
1088 char metricString[100];
1089 if(isResponse) {
1090 sprintf(metricString, "%3d", metric);
1091 } else {
1092 strcpy(metricString, " ");
1093 }
1094
1095 PrintToScrollback(" +%7d: %s: %s %s %s",
1096 (prev < 0 ? 0 : (timestamp - prev)),
1097 metricString,
1098 (isResponse ? "TAG" : " "), line, crc);
1099
1100 prev = timestamp;
1101 i += (len + 9);
1102 }
1103 CommandFinished = 1;
1104 }
1105
1106 static void CmdHi15demod(char *str)
1107 {
1108 // The sampling rate is 106.353 ksps/s, for T = 18.8 us
1109
1110 // SOF defined as
1111 // 1) Unmodulated time of 56.64us
1112 // 2) 24 pulses of 423.75khz
1113 // 3) logic '1' (unmodulated for 18.88us followed by 8 pulses of 423.75khz)
1114
1115 static const int FrameSOF[] = {
1116 -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
1117 -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
1118 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
1119 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
1120 -1, -1, -1, -1,
1121 -1, -1, -1, -1,
1122 1, 1, 1, 1,
1123 1, 1, 1, 1
1124 };
1125 static const int Logic0[] = {
1126 1, 1, 1, 1,
1127 1, 1, 1, 1,
1128 -1, -1, -1, -1,
1129 -1, -1, -1, -1
1130 };
1131 static const int Logic1[] = {
1132 -1, -1, -1, -1,
1133 -1, -1, -1, -1,
1134 1, 1, 1, 1,
1135 1, 1, 1, 1
1136 };
1137
1138 // EOF defined as
1139 // 1) logic '0' (8 pulses of 423.75khz followed by unmodulated for 18.88us)
1140 // 2) 24 pulses of 423.75khz
1141 // 3) Unmodulated time of 56.64us
1142
1143 static const int FrameEOF[] = {
1144 1, 1, 1, 1,
1145 1, 1, 1, 1,
1146 -1, -1, -1, -1,
1147 -1, -1, -1, -1,
1148 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
1149 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
1150 -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
1151 -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1
1152 };
1153
1154 int i, j;
1155 int max = 0, maxPos;
1156
1157 int skip = 4;
1158
1159 if(GraphTraceLen < 1000) return;
1160
1161 // First, correlate for SOF
1162 for(i = 0; i < 100; i++) {
1163 int corr = 0;
1164 for(j = 0; j < arraylen(FrameSOF); j += skip) {
1165 corr += FrameSOF[j]*GraphBuffer[i+(j/skip)];
1166 }
1167 if(corr > max) {
1168 max = corr;
1169 maxPos = i;
1170 }
1171 }
1172 PrintToScrollback("SOF at %d, correlation %d", maxPos,
1173 max/(arraylen(FrameSOF)/skip));
1174
1175 i = maxPos + arraylen(FrameSOF)/skip;
1176 int k = 0;
1177 BYTE outBuf[20];
1178 memset(outBuf, 0, sizeof(outBuf));
1179 BYTE mask = 0x01;
1180 for(;;) {
1181 int corr0 = 0, corr1 = 0, corrEOF = 0;
1182 for(j = 0; j < arraylen(Logic0); j += skip) {
1183 corr0 += Logic0[j]*GraphBuffer[i+(j/skip)];
1184 }
1185 for(j = 0; j < arraylen(Logic1); j += skip) {
1186 corr1 += Logic1[j]*GraphBuffer[i+(j/skip)];
1187 }
1188 for(j = 0; j < arraylen(FrameEOF); j += skip) {
1189 corrEOF += FrameEOF[j]*GraphBuffer[i+(j/skip)];
1190 }
1191 // Even things out by the length of the target waveform.
1192 corr0 *= 4;
1193 corr1 *= 4;
1194
1195 if(corrEOF > corr1 && corrEOF > corr0) {
1196 PrintToScrollback("EOF at %d", i);
1197 break;
1198 } else if(corr1 > corr0) {
1199 i += arraylen(Logic1)/skip;
1200 outBuf[k] |= mask;
1201 } else {
1202 i += arraylen(Logic0)/skip;
1203 }
1204 mask <<= 1;
1205 if(mask == 0) {
1206 k++;
1207 mask = 0x01;
1208 }
1209 if((i+(int)arraylen(FrameEOF)) >= GraphTraceLen) {
1210 PrintToScrollback("ran off end!");
1211 break;
1212 }
1213 }
1214 if(mask != 0x01) {
1215 PrintToScrollback("error, uneven octet! (discard extra bits!)");
1216 PrintToScrollback(" mask=%02x", mask);
1217 }
1218 PrintToScrollback("%d octets", k);
1219
1220 for(i = 0; i < k; i++) {
1221 PrintToScrollback("# %2d: %02x ", i, outBuf[i]);
1222 }
1223 PrintToScrollback("CRC=%04x", Iso15693Crc(outBuf, k-2));
1224 }
1225
1226 static void CmdTiread(char *str)
1227 {
1228 UsbCommand c;
1229 c.cmd = CMD_ACQUIRE_RAW_BITS_TI_TYPE;
1230 SendCommand(&c, FALSE);
1231 }
1232
1233 static void CmdTibits(char *str)
1234 {
1235 int cnt = 0;
1236 int i;
1237 for(i = 0; i < 1536; i += 12) {
1238 UsbCommand c;
1239 c.cmd = CMD_DOWNLOAD_RAW_BITS_TI_TYPE;
1240 c.ext1 = i;
1241 SendCommand(&c, FALSE);
1242 ReceiveCommand(&c);
1243 if(c.cmd != CMD_DOWNLOADED_RAW_BITS_TI_TYPE) {
1244 PrintToScrollback("bad resp");
1245 return;
1246 }
1247 int j;
1248 for(j = 0; j < 12; j++) {
1249 int k;
1250 for(k = 31; k >= 0; k--) {
1251 if(c.d.asDwords[j] & (1 << k)) {
1252 GraphBuffer[cnt++] = 1;
1253 } else {
1254 GraphBuffer[cnt++] = -1;
1255 }
1256 }
1257 }
1258 }
1259 GraphTraceLen = 1536*32;
1260 RepaintGraphWindow();
1261 }
1262
1263 static void CmdTidemod(char *cmdline)
1264 {
1265 /* MATLAB as follows:
1266 f_s = 2000000; % sampling frequency
1267 f_l = 123200; % low FSK tone
1268 f_h = 134200; % high FSK tone
1269
1270 T_l = 119e-6; % low bit duration
1271 T_h = 130e-6; % high bit duration
1272
1273 l = 2*pi*ones(1, floor(f_s*T_l))*(f_l/f_s);
1274 h = 2*pi*ones(1, floor(f_s*T_h))*(f_h/f_s);
1275
1276 l = sign(sin(cumsum(l)));
1277 h = sign(sin(cumsum(h)));
1278 */
1279 static const int LowTone[] = {
1280 1, 1, 1, 1, 1, 1, 1, 1, -1, -1, -1, -1, -1, -1, -1, -1, 1, 1, 1,
1281 1, 1, 1, 1, 1, -1, -1, -1, -1, -1, -1, -1, -1, 1, 1, 1, 1, 1, 1,
1282 1, 1, -1, -1, -1, -1, -1, -1, -1, -1, 1, 1, 1, 1, 1, 1, 1, 1, -1,
1283 -1, -1, -1, -1, -1, -1, -1, 1, 1, 1, 1, 1, 1, 1, 1, 1, -1, -1, -1,
1284 -1, -1, -1, -1, -1, 1, 1, 1, 1, 1, 1, 1, 1, -1, -1, -1, -1, -1, -1,
1285 -1, -1, 1, 1, 1, 1, 1, 1, 1, 1, -1, -1, -1, -1, -1, -1, -1, -1, 1,
1286 1, 1, 1, 1, 1, 1, 1, -1, -1, -1, -1, -1, -1, -1, -1, 1, 1, 1, 1,
1287 1, 1, 1, 1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 1, 1, 1, 1, 1, 1,
1288 1, 1, -1, -1, -1, -1, -1, -1, -1, -1, 1, 1, 1, 1, 1, 1, 1, 1, -1,
1289 -1, -1, -1, -1, -1, -1, -1, 1, 1, 1, 1, 1, 1, 1, 1, -1, -1, -1, -1,
1290 -1, -1, -1, -1, 1, 1, 1, 1, 1, 1, 1, 1, -1, -1, -1, -1, -1, -1, -1,
1291 -1, -1, 1, 1, 1, 1, 1, 1, 1, 1, -1, -1, -1, -1, -1, -1, -1, -1, 1,
1292 1, 1, 1, 1, 1, 1, 1, -1, -1, -1,
1293 };
1294 static const int HighTone[] = {
1295 1, 1, 1, 1, 1, 1, 1, -1, -1, -1, -1, -1, -1, -1, 1, 1, 1, 1, 1, 1,
1296 1, 1, -1, -1, -1, -1, -1, -1, -1, 1, 1, 1, 1, 1, 1, 1, 1, -1, -1,
1297 -1, -1, -1, -1, -1, 1, 1, 1, 1, 1, 1, 1, 1, -1, -1, -1, -1, -1,
1298 -1, -1, 1, 1, 1, 1, 1, 1, 1, 1, -1, -1, -1, -1, -1, -1, -1, 1, 1,
1299 1, 1, 1, 1, 1, -1, -1, -1, -1, -1, -1, -1, -1, 1, 1, 1, 1, 1, 1,
1300 1, -1, -1, -1, -1, -1, -1, -1, -1, 1, 1, 1, 1, 1, 1, 1, -1, -1,
1301 -1, -1, -1, -1, -1, -1, 1, 1, 1, 1, 1, 1, 1, -1, -1, -1, -1, -1,
1302 -1, -1, -1, 1, 1, 1, 1, 1, 1, 1, -1, -1, -1, -1, -1, -1, -1, -1,
1303 1, 1, 1, 1, 1, 1, 1, -1, -1, -1, -1, -1, -1, -1, 1, 1, 1, 1, 1, 1,
1304 1, 1, -1, -1, -1, -1, -1, -1, -1, 1, 1, 1, 1, 1, 1, 1, 1, -1, -1,
1305 -1, -1, -1, -1, -1, 1, 1, 1, 1, 1, 1, 1, 1, -1, -1, -1, -1, -1,
1306 -1, -1, 1, 1, 1, 1, 1, 1, 1, 1, -1, -1, -1, -1, -1, -1, -1, 1, 1,
1307 1, 1, 1, 1, 1, -1, -1, -1, -1, -1, -1, -1, -1, 1, 1, 1, 1, 1, 1,
1308 1, -1, -1, -1, -1, -1, -1, -1, -1, 1, 1, 1, 1, 1, 1, 1,
1309 };
1310
1311 int convLen = max(arraylen(HighTone), arraylen(LowTone));
1312
1313 int i;
1314 for(i = 0; i < GraphTraceLen - convLen; i++) {
1315 int j;
1316 int lowSum = 0, highSum = 0;;
1317 int lowLen = arraylen(LowTone);
1318 int highLen = arraylen(HighTone);
1319
1320 for(j = 0; j < lowLen; j++) {
1321 lowSum += LowTone[j]*GraphBuffer[i+j];
1322 }
1323 for(j = 0; j < highLen; j++) {
1324 highSum += HighTone[j]*GraphBuffer[i+j];
1325 }
1326 lowSum = abs((100*lowSum) / lowLen);
1327 highSum = abs((100*highSum) / highLen);
1328 GraphBuffer[i] = (highSum << 16) | lowSum;
1329 }
1330
1331 for(i = 0; i < GraphTraceLen - convLen - 16; i++) {
1332 int j;
1333 int lowTot = 0, highTot = 0;
1334 // 16 and 15 are f_s divided by f_l and f_h, rounded
1335 for(j = 0; j < 16; j++) {
1336 lowTot += (GraphBuffer[i+j] & 0xffff);
1337 }
1338 for(j = 0; j < 15; j++) {
1339 highTot += (GraphBuffer[i+j] >> 16);
1340 }
1341 GraphBuffer[i] = lowTot - highTot;
1342 }
1343
1344 GraphTraceLen -= (convLen + 16);
1345
1346 RepaintGraphWindow();
1347
1348 // Okay, so now we have unsliced soft decisions; find bit-sync, and then
1349 // get some bits.
1350
1351 int max = 0, maxPos = 0;
1352 for(i = 0; i < 6000; i++) {
1353 int j;
1354 int dec = 0;
1355 for(j = 0; j < 8*arraylen(LowTone); j++) {
1356 dec -= GraphBuffer[i+j];
1357 }
1358 for(; j < 8*arraylen(LowTone) + 8*arraylen(HighTone); j++) {
1359 dec += GraphBuffer[i+j];
1360 }
1361 if(dec > max) {
1362 max = dec;
1363 maxPos = i;
1364 }
1365 }
1366 GraphBuffer[maxPos] = 800;
1367 GraphBuffer[maxPos+1] = -800;
1368
1369 maxPos += 8*arraylen(LowTone);
1370 GraphBuffer[maxPos] = 800;
1371 GraphBuffer[maxPos+1] = -800;
1372 maxPos += 8*arraylen(HighTone);
1373
1374 GraphBuffer[maxPos] = 800;
1375 GraphBuffer[maxPos+1] = -800;
1376
1377 PrintToScrollback("actual data bits start at sample %d", maxPos);
1378
1379 PrintToScrollback("length %d/%d", arraylen(HighTone), arraylen(LowTone));
1380
1381 GraphBuffer[maxPos] = 800;
1382 GraphBuffer[maxPos+1] = -800;
1383
1384 BYTE bits[64+16+8+1];
1385 bits[sizeof(bits)-1] = '\0';
1386
1387 for(i = 0; i < arraylen(bits); i++) {
1388 int high = 0;
1389 int low = 0;
1390 int j;
1391 for(j = 0; j < arraylen(LowTone); j++) {
1392 low -= GraphBuffer[maxPos+j];
1393 }
1394 for(j = 0; j < arraylen(HighTone); j++) {
1395 high += GraphBuffer[maxPos+j];
1396 }
1397 if(high > low) {
1398 bits[i] = '1';
1399 maxPos += arraylen(HighTone);
1400 } else {
1401 bits[i] = '.';
1402 maxPos += arraylen(LowTone);
1403 }
1404 GraphBuffer[maxPos] = 800;
1405 GraphBuffer[maxPos+1] = -800;
1406 }
1407 PrintToScrollback("bits: '%s'", bits);
1408
1409 DWORD h = 0, l = 0;
1410 for(i = 0; i < 32; i++) {
1411 if(bits[i] == '1') {
1412 l |= (1<<i);
1413 }
1414 }
1415 for(i = 32; i < 64; i++) {
1416 if(bits[i] == '1') {
1417 h |= (1<<(i-32));
1418 }
1419 }
1420 PrintToScrollback("hex: %08x %08x", h, l);
1421 }
1422
1423 static void CmdNorm(char *str)
1424 {
1425 int i;
1426 int max = INT_MIN, min = INT_MAX;
1427 for(i = 10; i < GraphTraceLen; i++) {
1428 if(GraphBuffer[i] > max) {
1429 max = GraphBuffer[i];
1430 }
1431 if(GraphBuffer[i] < min) {
1432 min = GraphBuffer[i];
1433 }
1434 }
1435 if(max != min) {
1436 for(i = 0; i < GraphTraceLen; i++) {
1437 GraphBuffer[i] = (GraphBuffer[i] - ((max + min)/2))*1000/
1438 (max - min);
1439 }
1440 }
1441 RepaintGraphWindow();
1442 }
1443
1444 static void CmdDec(char *str)
1445 {
1446 int i;
1447 for(i = 0; i < (GraphTraceLen/2); i++) {
1448 GraphBuffer[i] = GraphBuffer[i*2];
1449 }
1450 GraphTraceLen /= 2;
1451 PrintToScrollback("decimated by 2");
1452 RepaintGraphWindow();
1453 }
1454
1455 static void CmdHpf(char *str)
1456 {
1457 int i;
1458 int accum = 0;
1459 for(i = 10; i < GraphTraceLen; i++) {
1460 accum += GraphBuffer[i];
1461 }
1462 accum /= (GraphTraceLen - 10);
1463 for(i = 0; i < GraphTraceLen; i++) {
1464 GraphBuffer[i] -= accum;
1465 }
1466
1467 RepaintGraphWindow();
1468 }
1469
1470 static void CmdZerocrossings(char *str)
1471 {
1472 int i;
1473 // Zero-crossings aren't meaningful unless the signal is zero-mean.
1474 CmdHpf("");
1475
1476 int sign = 1;
1477 int zc = 0;
1478 int lastZc = 0;
1479 for(i = 0; i < GraphTraceLen; i++) {
1480 if(GraphBuffer[i]*sign >= 0) {
1481 // No change in sign, reproduce the previous sample count.
1482 zc++;
1483 GraphBuffer[i] = lastZc;
1484 } else {
1485 // Change in sign, reset the sample count.
1486 sign = -sign;
1487 GraphBuffer[i] = lastZc;
1488 if(sign > 0) {
1489 lastZc = zc;
1490 zc = 0;
1491 }
1492 }
1493 }
1494
1495 RepaintGraphWindow();
1496 }
1497
1498 static void CmdLtrim(char *str)
1499 {
1500 int i;
1501 int ds = atoi(str);
1502
1503 for(i = ds; i < GraphTraceLen; i++) {
1504 GraphBuffer[i-ds] = GraphBuffer[i];
1505 }
1506 GraphTraceLen -= ds;
1507
1508 RepaintGraphWindow();
1509 }
1510
1511 static void CmdAutoCorr(char *str)
1512 {
1513 static int CorrelBuffer[MAX_GRAPH_TRACE_LEN];
1514
1515 int window = atoi(str);
1516
1517 if(window == 0) {
1518 PrintToScrollback("needs a window");
1519 return;
1520 }
1521
1522 if(window >= GraphTraceLen) {
1523 PrintToScrollback("window must be smaller than trace (%d samples)",
1524 GraphTraceLen);
1525 return;
1526 }
1527
1528 PrintToScrollback("performing %d correlations", GraphTraceLen - window);
1529
1530 int i;
1531 for(i = 0; i < GraphTraceLen - window; i++) {
1532 int sum = 0;
1533 int j;
1534 for(j = 0; j < window; j++) {
1535 sum += (GraphBuffer[j]*GraphBuffer[i+j]) / 256;
1536 }
1537 CorrelBuffer[i] = sum;
1538 }
1539 GraphTraceLen = GraphTraceLen - window;
1540 memcpy(GraphBuffer, CorrelBuffer, GraphTraceLen*sizeof(int));
1541
1542 RepaintGraphWindow();
1543 }
1544
1545 static void CmdVchdemod(char *str)
1546 {
1547 // Is this the entire sync pattern, or does this also include some
1548 // data bits that happen to be the same everywhere? That would be
1549 // lovely to know.
1550 static const int SyncPattern[] = {
1551 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
1552 1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
1553 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
1554 1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
1555 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
1556 1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
1557 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
1558 1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
1559 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
1560 1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
1561 };
1562
1563 // So first, we correlate for the sync pattern, and mark that.
1564 int bestCorrel = 0, bestPos = 0;
1565 int i;
1566 // It does us no good to find the sync pattern, with fewer than
1567 // 2048 samples after it...
1568 for(i = 0; i < (GraphTraceLen-2048); i++) {
1569 int sum = 0;
1570 int j;
1571 for(j = 0; j < arraylen(SyncPattern); j++) {
1572 sum += GraphBuffer[i+j]*SyncPattern[j];
1573 }
1574 if(sum > bestCorrel) {
1575 bestCorrel = sum;
1576 bestPos = i;
1577 }
1578 }
1579 PrintToScrollback("best sync at %d [metric %d]", bestPos, bestCorrel);
1580
1581 char bits[257];
1582 bits[256] = '\0';
1583
1584 int worst = INT_MAX;
1585 int worstPos;
1586
1587 for(i = 0; i < 2048; i += 8) {
1588 int sum = 0;
1589 int j;
1590 for(j = 0; j < 8; j++) {
1591 sum += GraphBuffer[bestPos+i+j];
1592 }
1593 if(sum < 0) {
1594 bits[i/8] = '.';
1595 } else {
1596 bits[i/8] = '1';
1597 }
1598 if(abs(sum) < worst) {
1599 worst = abs(sum);
1600 worstPos = i;
1601 }
1602 }
1603 PrintToScrollback("bits:");
1604 PrintToScrollback("%s", bits);
1605 PrintToScrollback("worst metric: %d at pos %d", worst, worstPos);
1606
1607 if(strcmp(str, "clone")==0) {
1608 GraphTraceLen = 0;
1609 char *s;
1610 for(s = bits; *s; s++) {
1611 int j;
1612 for(j = 0; j < 16; j++) {
1613 GraphBuffer[GraphTraceLen++] = (*s == '1') ? 1 : 0;
1614 }
1615 }
1616 RepaintGraphWindow();
1617 }
1618 }
1619
1620 static void CmdIndalademod(char *str)
1621 {
1622 // Usage: recover 64bit UID by default, specify "224" as arg to recover a 224bit UID
1623
1624 int state = -1;
1625 int count = 0;
1626 int i, j;
1627 // worst case with GraphTraceLen=64000 is < 4096
1628 // under normal conditions it's < 2048
1629 BYTE rawbits[4096];
1630 int rawbit = 0;
1631 int worst = 0, worstPos = 0;
1632 PrintToScrollback("Expecting a bit less than %d raw bits", GraphTraceLen/32);
1633 for(i = 0; i < GraphTraceLen-1; i += 2) {
1634 count+=1;
1635 if((GraphBuffer[i] > GraphBuffer[i + 1]) && (state != 1)) {
1636 if (state == 0) {
1637 for(j = 0; j < count - 8; j += 16) {
1638 rawbits[rawbit++] = 0;
1639 }
1640 if ((abs(count - j)) > worst) {
1641 worst = abs(count - j);
1642 worstPos = i;
1643 }
1644 }
1645 state = 1;
1646 count=0;
1647 } else if((GraphBuffer[i] < GraphBuffer[i + 1]) && (state != 0)) {
1648 if (state == 1) {
1649 for(j = 0; j < count - 8; j += 16) {
1650 rawbits[rawbit++] = 1;
1651 }
1652 if ((abs(count - j)) > worst) {
1653 worst = abs(count - j);
1654 worstPos = i;
1655 }
1656 }
1657 state = 0;
1658 count=0;
1659 }
1660 }
1661 PrintToScrollback("Recovered %d raw bits", rawbit);
1662 PrintToScrollback("worst metric (0=best..7=worst): %d at pos %d", worst, worstPos);
1663
1664 // Finding the start of a UID
1665 int uidlen, long_wait;
1666 if(strcmp(str, "224") == 0) {
1667 uidlen=224;
1668 long_wait=30;
1669 } else {
1670 uidlen=64;
1671 long_wait=29;
1672 }
1673 int start;
1674 int first = 0;
1675 for(start = 0; start <= rawbit - uidlen; start++) {
1676 first = rawbits[start];
1677 for(i = start; i < start + long_wait; i++) {
1678 if(rawbits[i] != first) {
1679 break;
1680 }
1681 }
1682 if(i == (start + long_wait)) {
1683 break;
1684 }
1685 }
1686 if(start == rawbit - uidlen + 1) {
1687 PrintToScrollback("nothing to wait for");
1688 return;
1689 }
1690
1691 // Inverting signal if needed
1692 if(first == 1) {
1693 for(i = start; i < rawbit; i++) {
1694 rawbits[i] = !rawbits[i];
1695 }
1696 }
1697
1698 // Dumping UID
1699 BYTE bits[224];
1700 char showbits[225];
1701 showbits[uidlen]='\0';
1702 int bit;
1703 i = start;
1704 int times = 0;
1705 if(uidlen > rawbit) {
1706 PrintToScrollback("Warning: not enough raw bits to get a full UID");
1707 for(bit = 0; bit < rawbit; bit++) {
1708 bits[bit] = rawbits[i++];
1709 // As we cannot know the parity, let's use "." and "/"
1710 showbits[bit] = '.' + bits[bit];
1711 }
1712 showbits[bit+1]='\0';
1713 PrintToScrollback("Partial UID=%s", showbits);
1714 return;
1715 } else {
1716 for(bit = 0; bit < uidlen; bit++) {
1717 bits[bit] = rawbits[i++];
1718 showbits[bit] = '0' + bits[bit];
1719 }
1720 times = 1;
1721 }
1722 PrintToScrollback("UID=%s", showbits);
1723
1724 // Checking UID against next occurences
1725 for(; i + uidlen <= rawbit;) {
1726 int failed = 0;
1727 for(bit = 0; bit < uidlen; bit++) {
1728 if(bits[bit] != rawbits[i++]) {
1729 failed = 1;
1730 break;
1731 }
1732 }
1733 if (failed == 1) {
1734 break;
1735 }
1736 times += 1;
1737 }
1738 PrintToScrollback("Occurences: %d (expected %d)", times, (rawbit - start) / uidlen);
1739
1740 // Remodulating for tag cloning
1741 GraphTraceLen = 32*uidlen;
1742 i = 0;
1743 int phase = 0;
1744 for(bit = 0; bit < uidlen; bit++) {
1745 if(bits[bit] == 0) {
1746 phase = 0;
1747 } else {
1748 phase = 1;
1749 }
1750 int j;
1751 for(j = 0; j < 32; j++) {
1752 GraphBuffer[i++] = phase;
1753 phase = !phase;
1754 }
1755 }
1756
1757 RepaintGraphWindow();
1758 }
1759
1760 static void CmdFlexdemod(char *str)
1761 {
1762 int i;
1763 for(i = 0; i < GraphTraceLen; i++) {
1764 if(GraphBuffer[i] < 0) {
1765 GraphBuffer[i] = -1;
1766 } else {
1767 GraphBuffer[i] = 1;
1768 }
1769 }
1770
1771 #define LONG_WAIT 100
1772 int start;
1773 for(start = 0; start < GraphTraceLen - LONG_WAIT; start++) {
1774 int first = GraphBuffer[start];
1775 for(i = start; i < start + LONG_WAIT; i++) {
1776 if(GraphBuffer[i] != first) {
1777 break;
1778 }
1779 }
1780 if(i == (start + LONG_WAIT)) {
1781 break;
1782 }
1783 }
1784 if(start == GraphTraceLen - LONG_WAIT) {
1785 PrintToScrollback("nothing to wait for");
1786 return;
1787 }
1788
1789 GraphBuffer[start] = 2;
1790 GraphBuffer[start+1] = -2;
1791
1792 BYTE bits[64];
1793
1794 int bit;
1795 i = start;
1796 for(bit = 0; bit < 64; bit++) {
1797 int j;
1798 int sum = 0;
1799 for(j = 0; j < 16; j++) {
1800 sum += GraphBuffer[i++];
1801 }
1802 if(sum > 0) {
1803 bits[bit] = 1;
1804 } else {
1805 bits[bit] = 0;
1806 }
1807 PrintToScrollback("bit %d sum %d", bit, sum);
1808 }
1809
1810 for(bit = 0; bit < 64; bit++) {
1811 int j;
1812 int sum = 0;
1813 for(j = 0; j < 16; j++) {
1814 sum += GraphBuffer[i++];
1815 }
1816 if(sum > 0 && bits[bit] != 1) {
1817 PrintToScrollback("oops1 at %d", bit);
1818 }
1819 if(sum < 0 && bits[bit] != 0) {
1820 PrintToScrollback("oops2 at %d", bit);
1821 }
1822 }
1823
1824 GraphTraceLen = 32*64;
1825 i = 0;
1826 int phase = 0;
1827 for(bit = 0; bit < 64; bit++) {
1828 if(bits[bit] == 0) {
1829 phase = 0;
1830 } else {
1831 phase = 1;
1832 }
1833 int j;
1834 for(j = 0; j < 32; j++) {
1835 GraphBuffer[i++] = phase;
1836 phase = !phase;
1837 }
1838 }
1839
1840 RepaintGraphWindow();
1841 }
1842
1843 /*
1844 * Generic command to demodulate ASK.
1845 *
1846 * Argument is convention: positive or negative (High mod means zero
1847 * or high mod means one)
1848 *
1849 * Updates the Graph trace with 0/1 values
1850 *
1851 * Arguments:
1852 * c : 0 or 1
1853 */
1854
1855 static void Cmdaskdemod(char *str) {
1856 int i;
1857 int n = 0;
1858 int c,high,low = 0;
1859
1860 // TODO: complain if we do not give 2 arguments here !
1861 sscanf(str, "%i", &c);
1862
1863 /* Detect high and lows and clock */
1864 for (i = 0; i < GraphTraceLen; i++)
1865 {
1866 if (GraphBuffer[i] > high)
1867 high = GraphBuffer[i];
1868 else if (GraphBuffer[i] < low)
1869 low = GraphBuffer[i];
1870 }
1871
1872 if (GraphBuffer[0] > 0) {
1873 GraphBuffer[0] = 1-c;
1874 } else {
1875 GraphBuffer[0] = c;
1876 }
1877 for(i=1;i<GraphTraceLen;i++) {
1878 /* Transitions are detected at each peak
1879 * Transitions are either:
1880 * - we're low: transition if we hit a high
1881 * - we're high: transition if we hit a low
1882 * (we need to do it this way because some tags keep high or
1883 * low for long periods, others just reach the peak and go
1884 * down)
1885 */
1886 if ((GraphBuffer[i]==high) && (GraphBuffer[i-1] == c)) {
1887 GraphBuffer[i]=1-c;
1888 } else if ((GraphBuffer[i]==low) && (GraphBuffer[i-1] == (1-c))){
1889 GraphBuffer[i] = c;
1890 } else {
1891 /* No transition */
1892 GraphBuffer[i] = GraphBuffer[i-1];
1893 }
1894 }
1895 RepaintGraphWindow();
1896 }
1897
1898 /* Print our clock rate */
1899 static void Cmddetectclockrate(char *str)
1900 {
1901 int clock = detectclock(0);
1902 PrintToScrollback("Auto-detected clock rate: %d", clock);
1903 }
1904
1905 /*
1906 * Detect clock rate
1907 */
1908 int detectclock(int peak)
1909 {
1910 int i;
1911 int clock = 0xFFFF;
1912 int lastpeak = 0;
1913
1914 /* Detect peak if we don't have one */
1915 if (!peak)
1916 for (i = 0; i < GraphTraceLen; i++)
1917 if (GraphBuffer[i] > peak)
1918 peak = GraphBuffer[i];
1919
1920 for (i = 1; i < GraphTraceLen; i++)
1921 {
1922 /* If this is the beginning of a peak */
1923 if (GraphBuffer[i-1] != GraphBuffer[i] && GraphBuffer[i] == peak)
1924 {
1925 /* Find lowest difference between peaks */
1926 if (lastpeak && i - lastpeak < clock)
1927 {
1928 clock = i - lastpeak;
1929 }
1930 lastpeak = i;
1931 }
1932 }
1933
1934 return clock;
1935 }
1936
1937 /* Get or auto-detect clock rate */
1938 int GetClock(char *str, int peak)
1939 {
1940 int clock;
1941
1942 sscanf(str, "%i", &clock);
1943 if (!strcmp(str, ""))
1944 clock = 0;
1945
1946 /* Auto-detect clock */
1947 if (!clock)
1948 {
1949 clock = detectclock(peak);
1950
1951 /* Only print this message if we're not looping something */
1952 if (!go)
1953 PrintToScrollback("Auto-detected clock rate: %d", clock);
1954 }
1955
1956 return clock;
1957 }
1958
1959 /*
1960 * Convert to a bitstream
1961 */
1962 static void Cmdbitstream(char *str) {
1963 int i, j;
1964 int bit;
1965 int gtl;
1966 int clock;
1967 int low = 0;
1968 int high = 0;
1969 int hithigh, hitlow, first;
1970
1971 /* Detect high and lows and clock */
1972 for (i = 0; i < GraphTraceLen; i++)
1973 {
1974 if (GraphBuffer[i] > high)
1975 high = GraphBuffer[i];
1976 else if (GraphBuffer[i] < low)
1977 low = GraphBuffer[i];
1978 }
1979
1980 /* Get our clock */
1981 clock = GetClock(str, high);
1982
1983 gtl = CmdClearGraph(0);
1984
1985 bit = 0;
1986 for (i = 0; i < (int)(gtl / clock); i++)
1987 {
1988 hithigh = 0;
1989 hitlow = 0;
1990 first = 1;
1991
1992 /* Find out if we hit both high and low peaks */
1993 for (j = 0; j < clock; j++)
1994 {
1995 if (GraphBuffer[(i * clock) + j] == high)
1996 hithigh = 1;
1997 else if (GraphBuffer[(i * clock) + j] == low)
1998 hitlow = 1;
1999
2000 /* it doesn't count if it's the first part of our read
2001 because it's really just trailing from the last sequence */
2002 if (first && (hithigh || hitlow))
2003 hithigh = hitlow = 0;
2004 else
2005 first = 0;
2006
2007 if (hithigh && hitlow)
2008 break;
2009 }
2010
2011 /* If we didn't hit both high and low peaks, we had a bit transition */
2012 if (!hithigh || !hitlow)
2013 bit ^= 1;
2014
2015 CmdAppendGraph(0, clock, bit);
2016 // for (j = 0; j < (int)(clock/2); j++)
2017 // GraphBuffer[(i * clock) + j] = bit ^ 1;
2018 // for (j = (int)(clock/2); j < clock; j++)
2019 // GraphBuffer[(i * clock) + j] = bit;
2020 }
2021
2022 RepaintGraphWindow();
2023 }
2024
2025 /* Modulate our data into manchester */
2026 static void Cmdmanchestermod(char *str)
2027 {
2028 int i, j;
2029 int clock;
2030 int bit, lastbit, wave;
2031
2032 /* Get our clock */
2033 clock = GetClock(str, 0);
2034
2035 wave = 0;
2036 lastbit = 1;
2037 for (i = 0; i < (int)(GraphTraceLen / clock); i++)
2038 {
2039 bit = GraphBuffer[i * clock] ^ 1;
2040
2041 for (j = 0; j < (int)(clock/2); j++)
2042 GraphBuffer[(i * clock) + j] = bit ^ lastbit ^ wave;
2043 for (j = (int)(clock/2); j < clock; j++)
2044 GraphBuffer[(i * clock) + j] = bit ^ lastbit ^ wave ^ 1;
2045
2046 /* Keep track of how we start our wave and if we changed or not this time */
2047 wave ^= bit ^ lastbit;
2048 lastbit = bit;
2049 }
2050
2051 RepaintGraphWindow();
2052 }
2053
2054 /*
2055 * Manchester demodulate a bitstream. The bitstream needs to be already in
2056 * the GraphBuffer as 0 and 1 values
2057 *
2058 * Give the clock rate as argument in order to help the sync - the algorithm
2059 * resyncs at each pulse anyway.
2060 *
2061 * Not optimized by any means, this is the 1st time I'm writing this type of
2062 * routine, feel free to improve...
2063 *
2064 * 1st argument: clock rate (as number of samples per clock rate)
2065 * Typical values can be 64, 32, 128...
2066 */
2067 static void Cmdmanchesterdemod(char *str) {
2068 int i, j, invert= 0;
2069 int bit;
2070 int clock;
2071 int lastval;
2072 int low = 0;
2073 int high = 0;
2074 int hithigh, hitlow, first;
2075 int lc = 0;
2076 int bitidx = 0;
2077 int bit2idx = 0;
2078 int warnings = 0;
2079
2080 /* check if we're inverting output */
2081 if(*str == 'i')
2082 {
2083 PrintToScrollback("Inverting output");
2084 invert= 1;
2085 do
2086 ++str;
2087 while(*str == ' '); // in case a 2nd argument was given
2088 }
2089
2090 /* Holds the decoded bitstream: each clock period contains 2 bits */
2091 /* later simplified to 1 bit after manchester decoding. */
2092 /* Add 10 bits to allow for noisy / uncertain traces without aborting */
2093 /* int BitStream[GraphTraceLen*2/clock+10]; */
2094
2095 /* But it does not work if compiling on WIndows: therefore we just allocate a */
2096 /* large array */
2097 int BitStream[MAX_GRAPH_TRACE_LEN];
2098
2099 /* Detect high and lows */
2100 for (i = 0; i < GraphTraceLen; i++)
2101 {
2102 if (GraphBuffer[i] > high)
2103 high = GraphBuffer[i];
2104 else if (GraphBuffer[i] < low)
2105 low = GraphBuffer[i];
2106 }
2107
2108 /* Get our clock */
2109 clock = GetClock(str, high);
2110
2111 int tolerance = clock/4;
2112
2113 /* Detect first transition */
2114 /* Lo-Hi (arbitrary) */
2115 for (i = 0; i < GraphTraceLen; i++)
2116 {
2117 if (GraphBuffer[i] == low)
2118 {
2119 lastval = i;
2120 break;
2121 }
2122 }
2123
2124 /* If we're not working with 1/0s, demod based off clock */
2125 if (high != 1)
2126 {
2127 bit = 0; /* We assume the 1st bit is zero, it may not be
2128 * the case: this routine (I think) has an init problem.
2129 * Ed.
2130 */
2131 for (; i < (int)(GraphTraceLen / clock); i++)
2132 {
2133 hithigh = 0;
2134 hitlow = 0;
2135 first = 1;
2136
2137 /* Find out if we hit both high and low peaks */
2138 for (j = 0; j < clock; j++)
2139 {
2140 if (GraphBuffer[(i * clock) + j] == high)
2141 hithigh = 1;
2142 else if (GraphBuffer[(i * clock) + j] == low)
2143 hitlow = 1;
2144
2145 /* it doesn't count if it's the first part of our read
2146 because it's really just trailing from the last sequence */
2147 if (first && (hithigh || hitlow))
2148 hithigh = hitlow = 0;
2149 else
2150 first = 0;
2151
2152 if (hithigh && hitlow)
2153 break;
2154 }
2155
2156 /* If we didn't hit both high and low peaks, we had a bit transition */
2157 if (!hithigh || !hitlow)
2158 bit ^= 1;
2159
2160 BitStream[bit2idx++] = bit ^ invert;
2161 }
2162 }
2163
2164 /* standard 1/0 bitstream */
2165 else
2166 {
2167
2168 /* Then detect duration between 2 successive transitions */
2169 for (bitidx = 1; i < GraphTraceLen; i++)
2170 {
2171 if (GraphBuffer[i-1] != GraphBuffer[i])
2172 {
2173 lc = i-lastval;
2174 lastval = i;
2175
2176 // Error check: if bitidx becomes too large, we do not
2177 // have a Manchester encoded bitstream or the clock is really
2178 // wrong!
2179 if (bitidx > (GraphTraceLen*2/clock+8) ) {
2180 PrintToScrollback("Error: the clock you gave is probably wrong, aborting.");
2181 return;
2182 }
2183 // Then switch depending on lc length:
2184 // Tolerance is 1/4 of clock rate (arbitrary)
2185 if (abs(lc-clock/2) < tolerance) {
2186 // Short pulse : either "1" or "0"
2187 BitStream[bitidx++]=GraphBuffer[i-1];
2188 } else if (abs(lc-clock) < tolerance) {
2189 // Long pulse: either "11" or "00"
2190 BitStream[bitidx++]=GraphBuffer[i-1];
2191 BitStream[bitidx++]=GraphBuffer[i-1];
2192 } else {
2193 // Error
2194 warnings++;
2195 PrintToScrollback("Warning: Manchester decode error for pulse width detection.");
2196 PrintToScrollback("(too many of those messages mean either the stream is not Manchester encoded, or clock is wrong)");
2197
2198 if (warnings > 100)
2199 {
2200 PrintToScrollback("Error: too many detection errors, aborting.");
2201 return;
2202 }
2203 }
2204 }
2205 }
2206
2207 // At this stage, we now have a bitstream of "01" ("1") or "10" ("0"), parse it into final decoded bitstream
2208 // Actually, we overwrite BitStream with the new decoded bitstream, we just need to be careful
2209 // to stop output at the final bitidx2 value, not bitidx
2210 for (i = 0; i < bitidx; i += 2) {
2211 if ((BitStream[i] == 0) && (BitStream[i+1] == 1)) {
2212 BitStream[bit2idx++] = 1 ^ invert;
2213 } else if ((BitStream[i] == 1) && (BitStream[i+1] == 0)) {
2214 BitStream[bit2idx++] = 0 ^ invert;
2215 } else {
2216 // We cannot end up in this state, this means we are unsynchronized,
2217 // move up 1 bit:
2218 i++;
2219 warnings++;
2220 PrintToScrollback("Unsynchronized, resync...");
2221 PrintToScrollback("(too many of those messages mean the stream is not Manchester encoded)");
2222
2223 if (warnings > 100)
2224 {
2225 PrintToScrollback("Error: too many decode errors, aborting.");
2226 return;
2227 }
2228 }
2229 }
2230 }
2231
2232 PrintToScrollback("Manchester decoded bitstream");
2233 // Now output the bitstream to the scrollback by line of 16 bits
2234 for (i = 0; i < (bit2idx-16); i+=16) {
2235 PrintToScrollback("%i %i %i %i %i %i %i %i %i %i %i %i %i %i %i %i",
2236 BitStream[i],
2237 BitStream[i+1],
2238 BitStream[i+2],
2239 BitStream[i+3],
2240 BitStream[i+4],
2241 BitStream[i+5],
2242 BitStream[i+6],
2243 BitStream[i+7],
2244 BitStream[i+8],
2245 BitStream[i+9],
2246 BitStream[i+10],
2247 BitStream[i+11],
2248 BitStream[i+12],
2249 BitStream[i+13],
2250 BitStream[i+14],
2251 BitStream[i+15]);
2252 }
2253 }
2254
2255
2256
2257 /*
2258 * Usage ???
2259 */
2260 static void CmdHiddemod(char *str)
2261 {
2262 if(GraphTraceLen < 4800) {
2263 PrintToScrollback("too short; need at least 4800 samples");
2264 return;
2265 }
2266
2267 GraphTraceLen = 4800;
2268 int i;
2269 for(i = 0; i < GraphTraceLen; i++) {
2270 if(GraphBuffer[i] < 0) {
2271 GraphBuffer[i] = 0;
2272 } else {
2273 GraphBuffer[i] = 1;
2274 }
2275 }
2276 RepaintGraphWindow();
2277 }
2278
2279 static void CmdPlot(char *str)
2280 {
2281 ShowGraphWindow();
2282 }
2283
2284 static void CmdHide(char *str)
2285 {
2286 HideGraphWindow();
2287 }
2288
2289 static void CmdScale(char *str)
2290 {
2291 CursorScaleFactor = atoi(str);
2292 if(CursorScaleFactor == 0) {
2293 PrintToScrollback("bad, can't have zero scale");
2294 CursorScaleFactor = 1;
2295 }
2296 RepaintGraphWindow();
2297 }
2298
2299 static void CmdSave(char *str)
2300 {
2301 FILE *f = fopen(str, "w");
2302 if(!f) {
2303 PrintToScrollback("couldn't open '%s'", str);
2304 return;
2305 }
2306 int i;
2307 for(i = 0; i < GraphTraceLen; i++) {
2308 fprintf(f, "%d\n", GraphBuffer[i]);
2309 }
2310 fclose(f);
2311 PrintToScrollback("saved to '%s'", str);
2312 }
2313
2314 static void CmdLoad(char *str)
2315 {
2316 FILE *f = fopen(str, "r");
2317 if(!f) {
2318 PrintToScrollback("couldn't open '%s'", str);
2319 return;
2320 }
2321
2322 GraphTraceLen = 0;
2323 char line[80];
2324 while(fgets(line, sizeof(line), f)) {
2325 GraphBuffer[GraphTraceLen] = atoi(line);
2326 GraphTraceLen++;
2327 }
2328 fclose(f);
2329 PrintToScrollback("loaded %d samples", GraphTraceLen);
2330 RepaintGraphWindow();
2331 }
2332
2333 static void CmdHIDsimTAG(char *str)
2334 {
2335 unsigned int hi=0, lo=0;
2336 int n=0, i=0;
2337 UsbCommand c;
2338
2339 while (sscanf(&str[i++], "%1x", &n ) == 1) {
2340 hi=(hi<<4)|(lo>>28);
2341 lo=(lo<<4)|(n&0xf);
2342 }
2343
2344 PrintToScrollback("Emulating tag with ID %x%16x", hi, lo);
2345
2346 c.cmd = CMD_HID_SIM_TAG;
2347 c.ext1 = hi;
2348 c.ext2 = lo;
2349 SendCommand(&c, FALSE);
2350 }
2351
2352 static void CmdLcdReset(char *str)
2353 {
2354 UsbCommand c;
2355 c.cmd = CMD_LCD_RESET;
2356 c.ext1 = atoi(str);
2357 SendCommand(&c, FALSE);
2358 }
2359
2360 static void CmdLcd(char *str)
2361 {
2362 int i, j;
2363 UsbCommand c;
2364 c.cmd = CMD_LCD;
2365 sscanf(str, "%x %d", &i, &j);
2366 while (j--) {
2367 c.ext1 = i&0x1ff;
2368 SendCommand(&c, FALSE);
2369 }
2370 }
2371
2372
2373
2374 static void CmdTest(char *str)
2375 {
2376 }
2377
2378 /*
2379 * Sets the divisor for LF frequency clock: lets the user choose any LF frequency below
2380 * 600kHz.
2381 */
2382 static void CmdSetDivisor(char *str)
2383 {
2384 UsbCommand c;
2385 c.cmd = CMD_SET_LF_DIVISOR;
2386 c.ext1 = atoi(str);
2387 if (( c.ext1<0) || (c.ext1>255)) {
2388 PrintToScrollback("divisor must be between 19 and 255");
2389 } else {
2390 SendCommand(&c, FALSE);
2391 PrintToScrollback("Divisor set, expected freq=%dHz", 12000000/(c.ext1+1));
2392 }
2393 }
2394
2395 static void CmdSweepLF(char *str)
2396 {
2397 UsbCommand c;
2398 c.cmd = CMD_SWEEP_LF;
2399 SendCommand(&c, FALSE);
2400 }
2401
2402
2403 typedef void HandlerFunction(char *cmdline);
2404
2405 /* in alphabetic order */
2406 static struct {
2407 char *name;
2408 HandlerFunction *handler;
2409 int offline; // 1 if the command can be used when in offline mode
2410 char *docString;
2411 } CommandTable[] = {
2412 "askdemod", Cmdaskdemod,1, "<samples per bit> <0|1> -- Attempt to demodulate simple ASK tags",
2413 "autocorr", CmdAutoCorr,1, "<window length> -- Autocorrelation over window",
2414 "bitsamples", CmdBitsamples,0, " Get raw samples as bitstring",
2415 "bitstream", Cmdbitstream,1, "[clock rate] -- Convert waveform into a bitstream",
2416 "buffclear", CmdBuffClear,0, " Clear sample buffer and graph window",
2417 "dec", CmdDec,1, " Decimate samples",
2418 "detectclock", Cmddetectclockrate,1, " Detect clock rate",
2419 "em410xsim", CmdEM410xsim,1, "<UID> -- Simulate EM410x tag",
2420 "em410xread", CmdEM410xread,1, "[clock rate] -- Extract ID from EM410x tag",
2421 "em410xwatch", CmdEM410xwatch,0, " Watches for EM410x tags",
2422 "exit", CmdQuit,1, " Exit program",
2423 "flexdemod", CmdFlexdemod,1, " Demodulate samples for FlexPass",
2424 "fpgaoff", CmdFPGAOff,0, " Set FPGA off", // ## FPGA Control
2425 "hexsamples", CmdHexsamples,0, "<blocks> -- Dump big buffer as hex bytes",
2426 "hi14alist", CmdHi14alist,0, " List ISO 14443a history", // ## New list command
2427 "hi14areader", CmdHi14areader,0, " Act like an ISO14443 Type A reader", // ## New reader command
2428 "hi14asim", CmdHi14asim,0, "<UID> -- Fake ISO 14443a tag", // ## Simulate 14443a tag
2429 "hi14asnoop", CmdHi14asnoop,0, " Eavesdrop ISO 14443 Type A", // ## New snoop command
2430 "hi14bdemod", CmdHi14bdemod,1, " Demodulate ISO14443 Type B from tag",
2431 "hi14list", CmdHi14list,0, " List ISO 14443 history",
2432 "hi14read", CmdHi14read,0, " Read HF tag (ISO 14443)",
2433 "hi14sim", CmdHi14sim,0, " Fake ISO 14443 tag",
2434 "hi14snoop", CmdHi14snoop,0, " Eavesdrop ISO 14443",
2435 "hi15demod", CmdHi15demod,1, " Demodulate ISO15693 from tag",
2436 "hi15read", CmdHi15read,0, " Read HF tag (ISO 15693)",
2437 "hi15reader", CmdHi15reader,0, " Act like an ISO15693 reader", // new command greg
2438 "hi15sim", CmdHi15tag,0, " Fake an ISO15693 tag", // new command greg
2439 "hiddemod", CmdHiddemod,1, " Demodulate HID Prox Card II (not optimal)",
2440 "hide", CmdHide,1, " Hide graph window",
2441 "hidfskdemod", CmdHIDdemodFSK,0, " Realtime HID FSK demodulator",
2442 "hidsimtag", CmdHIDsimTAG,0, "<ID> -- HID tag simulator",
2443 "higet", CmdHi14read_sim,0, "<samples> -- Get samples HF, 'analog'",
2444 "hisamples", CmdHisamples,0, " Get raw samples for HF tag",
2445 "hisampless", CmdHisampless,0, "<samples> -- Get signed raw samples, HF tag",
2446 "hisamplest", CmdHi14readt,0, " Get samples HF, for testing",
2447 "hisimlisten", CmdHisimlisten,0, " Get HF samples as fake tag",
2448 "hpf", CmdHpf,1, " Remove DC offset from trace",
2449 "indalademod", CmdIndalademod,0, "['224'] -- Demodulate samples for Indala",
2450 "lcd", CmdLcd,0, "<HEX command> <count> -- Send command/data to LCD",
2451 "lcdreset", CmdLcdReset,0, " Hardware reset LCD",
2452 "load", CmdLoad,1, "<filename> -- Load trace (to graph window",
2453 "loread", CmdLoread,0, "['h'] -- Read 125/134 kHz LF ID-only tag (option 'h' for 134)",
2454 "losamples", CmdLosamples,0, "[128 - 16000] -- Get raw samples for LF tag",
2455 "losim", CmdLosim,0, " Simulate LF tag",
2456 "ltrim", CmdLtrim,1, "<samples> -- Trim samples from left of trace",
2457 "mandemod", Cmdmanchesterdemod,1, "[i] [clock rate] -- Manchester demodulate binary stream (option 'i' to invert output)",
2458 "manmod", Cmdmanchestermod,1, "[clock rate] -- Manchester modulate a binary stream",
2459 "norm", CmdNorm,1, " Normalize max/min to +/-500",
2460 "plot", CmdPlot,1, " Show graph window",
2461 "quit", CmdQuit,1, " Quit program",
2462 "reset", CmdReset,0, " Reset the Proxmark3",
2463 "save", CmdSave,1, "<filename> -- Save trace (from graph window)",
2464 "scale", CmdScale,1, "<int> -- Set cursor display scale",
2465 "setlfdivisor", CmdSetDivisor,0, "<19 - 255> -- Drive LF antenna at 12Mhz/(divisor+1)",
2466 "sri512read", CmdSri512read,0, "<int> -- Read contents of a SRI512 tag",
2467 "sweeplf", CmdSweepLF,0, " Sweep through LF freq range and store results in buffer",
2468 "tibits", CmdTibits,0, " Get raw bits for TI-type LF tag",
2469 "tidemod", CmdTidemod,0, " Demodulate raw bits for TI-type LF tag",
2470 "tiread", CmdTiread,0, " Read a TI-type 134 kHz tag",
2471 "tune", CmdTune,0, " Measure antenna tuning",
2472 "vchdemod", CmdVchdemod,0, "['clone'] -- Demodulate samples for VeriChip",
2473 "zerocrossings", CmdZerocrossings,1, " Count time between zero-crossings",
2474 };
2475
2476
2477 //-----------------------------------------------------------------------------
2478 // Entry point into our code: called whenever the user types a command and
2479 // then presses Enter, which the full command line that they typed.
2480 //-----------------------------------------------------------------------------
2481 void CommandReceived(char *cmd)
2482 {
2483 int i;
2484
2485 PrintToScrollback("> %s", cmd);
2486
2487 if(strcmp(cmd, "help")==0) {
2488 if (offline) PrintToScrollback("Operating in OFFLINE mode (no device connected)");
2489 PrintToScrollback("\r\nAvailable commands:");
2490 for(i = 0; i < sizeof(CommandTable) / sizeof(CommandTable[0]); i++) {
2491 if (offline && (CommandTable[i].offline==0)) continue;
2492 char line[256];
2493 memset(line, ' ', sizeof(line));
2494 strcpy(line+2, CommandTable[i].name);
2495 line[strlen(line)] = ' ';
2496 sprintf(line+15, " -- %s", CommandTable[i].docString);
2497 PrintToScrollback("%s", line);
2498 }
2499 PrintToScrollback("");
2500 PrintToScrollback("and also: help, cls");
2501 return;
2502 }
2503
2504 for(i = 0; i < sizeof(CommandTable) / sizeof(CommandTable[0]); i++) {
2505 char *name = CommandTable[i].name;
2506 if(memcmp(cmd, name, strlen(name))==0 &&
2507 (cmd[strlen(name)] == ' ' || cmd[strlen(name)] == '\0'))
2508 {
2509 cmd += strlen(name);
2510 while(*cmd == ' ') {
2511 cmd++;
2512 }
2513 if (offline && (CommandTable[i].offline==0)) {
2514 PrintToScrollback("Offline mode, cannot use this command.");
2515 return;
2516 }
2517 (CommandTable[i].handler)(cmd);
2518 return;
2519 }
2520 }
2521 PrintToScrollback(">> bad command '%s'", cmd);
2522 }
2523
2524 //-----------------------------------------------------------------------------
2525 // Entry point into our code: called whenever we received a packet over USB
2526 // that we weren't necessarily expecting, for example a debug print.
2527 //-----------------------------------------------------------------------------
2528 void UsbCommandReceived(UsbCommand *c)
2529 {
2530 switch(c->cmd) {
2531 case CMD_DEBUG_PRINT_STRING: {
2532 char s[100];
2533 if(c->ext1 > 70 || c->ext1 < 0) {
2534 c->ext1 = 0;
2535 }
2536 memcpy(s, c->d.asBytes, c->ext1);
2537 s[c->ext1] = '\0';
2538 PrintToScrollback("#db# %s", s);
2539 break;
2540 }
2541
2542 case CMD_DEBUG_PRINT_INTEGERS:
2543 PrintToScrollback("#db# %08x, %08x, %08x\r\n", c->ext1, c->ext2, c->ext3);
2544 break;
2545
2546 case CMD_MEASURED_ANTENNA_TUNING: {
2547 int zLf, zHf;
2548 int vLf125, vLf134, vHf;
2549 vLf125 = c->ext1 & 0xffff;
2550 vLf134 = c->ext1 >> 16;
2551 vHf = c->ext2;
2552 zLf = c->ext3 & 0xffff;
2553 zHf = c->ext3 >> 16;
2554 PrintToScrollback("# LF antenna @ %3d mA / %5d mV [%d ohms] 125Khz",
2555 vLf125/zLf, vLf125, zLf);
2556 PrintToScrollback("# LF antenna @ %3d mA / %5d mV [%d ohms] 134Khz",
2557 vLf134/((zLf*125)/134), vLf134, (zLf*125)/134);
2558 PrintToScrollback("# HF antenna @ %3d mA / %5d mV [%d ohms] 13.56Mhz",
2559 vHf/zHf, vHf, zHf);
2560 break;
2561 }
2562 default:
2563 PrintToScrollback("unrecognized command %08x\n", c->cmd);
2564 break;
2565 }
2566 }
Impressum, Datenschutz