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 //-----------------------------------------------------------------------------
14 #include "../common/iso14443_crc.c"
16 #define arraylen(x) (sizeof(x)/sizeof((x)[0]))
17 #define BIT(x) GraphBuffer[x * clock]
18 #define BITS (GraphTraceLen / clock)
21 static int CmdHisamplest(char *str
, int nrlow
);
23 static void GetFromBigBuf(BYTE
*dest
, int bytes
)
28 PrintToScrollback("bad len in GetFromBigBuf");
33 for(i
= 0; i
< n
; i
+= 12) {
35 c
.cmd
= CMD_DOWNLOAD_RAW_ADC_SAMPLES_125K
;
37 SendCommand(&c
, FALSE
);
39 if(c
.cmd
!= CMD_DOWNLOADED_RAW_ADC_SAMPLES_125K
) {
40 PrintToScrollback("bad resp");
44 memcpy(dest
+(i
*4), c
.d
.asBytes
, 48);
48 static void CmdReset(char *str
)
51 c
.cmd
= CMD_HARDWARE_RESET
;
52 SendCommand(&c
, FALSE
);
55 static void CmdBuffClear(char *str
)
58 c
.cmd
= CMD_BUFF_CLEAR
;
59 SendCommand(&c
, FALSE
);
63 static void CmdQuit(char *str
)
68 static void CmdHIDdemodFSK(char *str
)
71 c
.cmd
= CMD_HID_DEMOD_FSK
;
72 SendCommand(&c
, FALSE
);
75 static void CmdTune(char *str
)
78 c
.cmd
= CMD_MEASURE_ANTENNA_TUNING
;
79 SendCommand(&c
, FALSE
);
82 static void CmdHi15read(char *str
)
85 c
.cmd
= CMD_ACQUIRE_RAW_ADC_SAMPLES_ISO_15693
;
86 SendCommand(&c
, FALSE
);
89 static void CmdHi14read(char *str
)
92 c
.cmd
= CMD_ACQUIRE_RAW_ADC_SAMPLES_ISO_14443
;
94 SendCommand(&c
, FALSE
);
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/
102 static void CmdSri512read(char *str
)
105 c
.cmd
= CMD_READ_SRI512_TAG
;
107 SendCommand(&c
, FALSE
);
111 static void CmdHi14areader(char *str
)
114 c
.cmd
= CMD_READER_ISO_14443a
;
116 SendCommand(&c
, FALSE
);
120 static void CmdHi15reader(char *str
)
123 c
.cmd
= CMD_READER_ISO_15693
;
125 SendCommand(&c
, FALSE
);
129 static void CmdHi15tag(char *str
)
132 c
.cmd
= CMD_SIMTAG_ISO_15693
;
134 SendCommand(&c
, FALSE
);
137 static void CmdHi14read_sim(char *str
)
140 c
.cmd
= CMD_ACQUIRE_RAW_ADC_SAMPLES_ISO_14443_SIM
;
142 SendCommand(&c
, FALSE
);
145 static void CmdHi14readt(char *str
)
148 c
.cmd
= CMD_ACQUIRE_RAW_ADC_SAMPLES_ISO_14443
;
150 SendCommand(&c
, FALSE
);
152 //CmdHisamplest(str);
153 while(CmdHisamplest(str
,atoi(str
))==0) {
154 c
.cmd
= CMD_ACQUIRE_RAW_ADC_SAMPLES_ISO_14443
;
156 SendCommand(&c
, FALSE
);
158 RepaintGraphWindow();
161 static void CmdHisimlisten(char *str
)
164 c
.cmd
= CMD_SIMULATE_TAG_HF_LISTEN
;
165 SendCommand(&c
, FALSE
);
168 static void CmdHi14sim(char *str
)
171 c
.cmd
= CMD_SIMULATE_TAG_ISO_14443
;
172 SendCommand(&c
, FALSE
);
175 static void CmdHi14asim(char *str
) // ## simulate iso14443a tag
176 { // ## greg - added ability to specify tag UID
178 unsigned int hi
=0, lo
=0;
182 while (sscanf(&str
[i
++], "%1x", &n
) == 1) {
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
191 PrintToScrollback("Emulating 14443A TAG with UID %x%16x", hi
, lo
);
192 SendCommand(&c
, FALSE
);
195 static void CmdHi14snoop(char *str
)
198 c
.cmd
= CMD_SNOOP_ISO_14443
;
199 SendCommand(&c
, FALSE
);
202 static void CmdHi14asnoop(char *str
)
205 c
.cmd
= CMD_SNOOP_ISO_14443a
;
206 SendCommand(&c
, FALSE
);
209 static void CmdFPGAOff(char *str
) // ## FPGA Control
212 c
.cmd
= CMD_FPGA_MAJOR_MODE_OFF
;
213 SendCommand(&c
, FALSE
);
216 /* clear out our graph window */
217 int CmdClearGraph(int redraw
)
219 int gtl
= GraphTraceLen
;
223 RepaintGraphWindow();
228 /* write a bit to the graph */
229 static void CmdAppendGraph(int redraw
, int clock
, int bit
)
233 for (i
= 0; i
< (int)(clock
/2); i
++)
234 GraphBuffer
[GraphTraceLen
++] = bit
^ 1;
236 for (i
= (int)(clock
/2); i
< clock
; i
++)
237 GraphBuffer
[GraphTraceLen
++] = bit
;
240 RepaintGraphWindow();
243 /* Function is equivalent of loread + losamples + em410xread
244 * looped until an EM410x tag is detected */
245 static void CmdEM410xwatch(char *str
)
259 /* Read the transmitted data of an EM4x50 tag
262 * XXXXXXXX [row parity bit (even)] <- 8 bits plus parity
263 * XXXXXXXX [row parity bit (even)] <- 8 bits plus parity
264 * XXXXXXXX [row parity bit (even)] <- 8 bits plus parity
265 * XXXXXXXX [row parity bit (even)] <- 8 bits plus parity
266 * CCCCCCCC <- column parity bits
268 * LW <- Listen Window
270 * This pattern repeats for every block of data being transmitted.
271 * Transmission starts with two Listen Windows (LW - a modulated
272 * pattern of 320 cycles each (32/32/128/64/64)).
274 * Note that this data may or may not be the UID. It is whatever data
275 * is stored in the blocks defined in the control word First and Last
276 * Word Read values. UID is stored in block 32.
278 static void CmdEM4x50read(char *str
)
280 int i
, j
, startblock
, clock
, skip
, block
, start
, end
, low
, high
;
281 BOOL complete
= FALSE
;
282 int tmpbuff
[MAX_GRAPH_TRACE_LEN
/ 64];
288 /* first get high and low values */
289 for (i
= 0; i
< GraphTraceLen
; i
++)
291 if (GraphBuffer
[i
] > high
)
292 high
= GraphBuffer
[i
];
293 else if (GraphBuffer
[i
] < low
)
294 low
= GraphBuffer
[i
];
297 /* populate a buffer with pulse lengths */
300 while(i
< GraphTraceLen
)
302 // measure from low to low
303 while(GraphBuffer
[i
] > low
)
306 while(GraphBuffer
[i
] < high
)
308 while(GraphBuffer
[i
] > low
)
310 tmpbuff
[j
++]= i
- start
;
314 /* look for data start - should be 2 pairs of LW (pulses of 192,128) */
317 for (i
= 0; i
< j
- 4 ; ++i
)
320 if (tmpbuff
[i
] >= 190 && tmpbuff
[i
] <= 194)
321 if (tmpbuff
[i
+1] >= 126 && tmpbuff
[i
+1] <= 130)
322 if (tmpbuff
[i
+2] >= 190 && tmpbuff
[i
+2] <= 194)
323 if (tmpbuff
[i
+3] >= 126 && tmpbuff
[i
+3] <= 130)
331 /* skip over the remainder of the LW */
332 skip
+= tmpbuff
[i
+1]+tmpbuff
[i
+2];
333 while(GraphBuffer
[skip
] > low
)
337 /* now do it again to find the end */
339 for (i
+= 3; i
< j
- 4 ; ++i
)
342 if (tmpbuff
[i
] >= 190 && tmpbuff
[i
] <= 194)
343 if (tmpbuff
[i
+1] >= 126 && tmpbuff
[i
+1] <= 130)
344 if (tmpbuff
[i
+2] >= 190 && tmpbuff
[i
+2] <= 194)
345 if (tmpbuff
[i
+3] >= 126 && tmpbuff
[i
+3] <= 130)
353 PrintToScrollback("Found data at sample: %i",skip
);
356 PrintToScrollback("No data found!");
357 PrintToScrollback("Try again with more samples.");
363 PrintToScrollback("*** Warning!");
364 PrintToScrollback("Partial data - no end found!");
365 PrintToScrollback("Try again with more samples.");
368 /* get rid of leading crap */
369 sprintf(tmp
,"%i",skip
);
372 /* now work through remaining buffer printing out data blocks */
377 PrintToScrollback("Block %i:", block
);
378 // mandemod routine needs to be split so we can call it for data
379 // just print for now for debugging
380 Cmdmanchesterdemod("i 64");
382 /* look for LW before start of next block */
383 for ( ; i
< j
- 4 ; ++i
)
386 if (tmpbuff
[i
] >= 190 && tmpbuff
[i
] <= 194)
387 if (tmpbuff
[i
+1] >= 126 && tmpbuff
[i
+1] <= 130)
390 while(GraphBuffer
[skip
] > low
)
393 sprintf(tmp
,"%i",skip
);
401 /* Read the ID of an EM410x tag.
403 * 1111 1111 1 <-- standard non-repeatable header
404 * XXXX [row parity bit] <-- 10 rows of 5 bits for our 40 bit tag ID
406 * CCCC <-- each bit here is parity for the 10 bits above in corresponding column
407 * 0 <-- stop bit, end of tag
409 static void CmdEM410xread(char *str
)
411 int i
, j
, clock
, header
, rows
, bit
, hithigh
, hitlow
, first
, bit2idx
, high
, low
;
415 int BitStream
[MAX_GRAPH_TRACE_LEN
];
418 /* Detect high and lows and clock */
419 for (i
= 0; i
< GraphTraceLen
; i
++)
421 if (GraphBuffer
[i
] > high
)
422 high
= GraphBuffer
[i
];
423 else if (GraphBuffer
[i
] < low
)
424 low
= GraphBuffer
[i
];
428 clock
= GetClock(str
, high
);
430 /* parity for our 4 columns */
431 parity
[0] = parity
[1] = parity
[2] = parity
[3] = 0;
434 /* manchester demodulate */
436 for (i
= 0; i
< (int)(GraphTraceLen
/ clock
); i
++)
442 /* Find out if we hit both high and low peaks */
443 for (j
= 0; j
< clock
; j
++)
445 if (GraphBuffer
[(i
* clock
) + j
] == high
)
447 else if (GraphBuffer
[(i
* clock
) + j
] == low
)
450 /* it doesn't count if it's the first part of our read
451 because it's really just trailing from the last sequence */
452 if (first
&& (hithigh
|| hitlow
))
453 hithigh
= hitlow
= 0;
457 if (hithigh
&& hitlow
)
461 /* If we didn't hit both high and low peaks, we had a bit transition */
462 if (!hithigh
|| !hitlow
)
465 BitStream
[bit2idx
++] = bit
;
469 /* We go till 5 before the graph ends because we'll get that far below */
470 for (i
= 1; i
< bit2idx
- 5; i
++)
472 /* Step 2: We have our header but need our tag ID */
473 if (header
== 9 && rows
< 10)
475 /* Confirm parity is correct */
476 if ((BitStream
[i
] ^ BitStream
[i
+1] ^ BitStream
[i
+2] ^ BitStream
[i
+3]) == BitStream
[i
+4])
478 /* Read another byte! */
479 sprintf(id
+rows
, "%x", (8 * BitStream
[i
]) + (4 * BitStream
[i
+1]) + (2 * BitStream
[i
+2]) + (1 * BitStream
[i
+3]));
482 /* Keep parity info */
483 parity
[0] ^= BitStream
[i
];
484 parity
[1] ^= BitStream
[i
+1];
485 parity
[2] ^= BitStream
[i
+2];
486 parity
[3] ^= BitStream
[i
+3];
488 /* Move 4 bits ahead */
492 /* Damn, something wrong! reset */
495 PrintToScrollback("Thought we had a valid tag but failed at word %d (i=%d)", rows
+ 1, i
);
497 /* Start back rows * 5 + 9 header bits, -1 to not start at same place */
498 i
-= 9 + (5 * rows
) - 5;
504 /* Step 3: Got our 40 bits! confirm column parity */
507 /* We need to make sure our 4 bits of parity are correct and we have a stop bit */
508 if (BitStream
[i
] == parity
[0] && BitStream
[i
+1] == parity
[1] &&
509 BitStream
[i
+2] == parity
[2] && BitStream
[i
+3] == parity
[3] &&
513 PrintToScrollback("EM410x Tag ID: %s", id
);
520 /* Crap! Incorrect parity or no stop bit, start all over */
525 /* Go back 59 bits (9 header bits + 10 rows at 4+1 parity) */
530 /* Step 1: get our header */
533 /* Need 9 consecutive 1's */
534 if (BitStream
[i
] == 1)
537 /* We don't have a header, not enough consecutive 1 bits */
543 /* if we've already retested after flipping bits, return */
547 /* if this didn't work, try flipping bits */
548 for (i
= 0; i
< bit2idx
; i
++)
554 /* emulate an EM410X tag
556 * 1111 1111 1 <-- standard non-repeatable header
557 * XXXX [row parity bit] <-- 10 rows of 5 bits for our 40 bit tag ID
559 * CCCC <-- each bit here is parity for the 10 bits above in corresponding column
560 * 0 <-- stop bit, end of tag
562 static void CmdEM410xsim(char *str
)
564 int i
, n
, j
, h
, binary
[4], parity
[4];
567 /* clock is 64 in EM410x tags */
570 /* clear our graph */
573 /* write it out a few times */
574 for (h
= 0; h
< 4; h
++)
576 /* write 9 start bits */
577 for (i
= 0; i
< 9; i
++)
578 CmdAppendGraph(0, clock
, 1);
580 /* for each hex char */
581 parity
[0] = parity
[1] = parity
[2] = parity
[3] = 0;
582 for (i
= 0; i
< 10; i
++)
584 /* read each hex char */
585 sscanf(&str
[i
], "%1x", &n
);
586 for (j
= 3; j
>= 0; j
--, n
/= 2)
589 /* append each bit */
590 CmdAppendGraph(0, clock
, binary
[0]);
591 CmdAppendGraph(0, clock
, binary
[1]);
592 CmdAppendGraph(0, clock
, binary
[2]);
593 CmdAppendGraph(0, clock
, binary
[3]);
595 /* append parity bit */
596 CmdAppendGraph(0, clock
, binary
[0] ^ binary
[1] ^ binary
[2] ^ binary
[3]);
598 /* keep track of column parity */
599 parity
[0] ^= binary
[0];
600 parity
[1] ^= binary
[1];
601 parity
[2] ^= binary
[2];
602 parity
[3] ^= binary
[3];
606 CmdAppendGraph(0, clock
, parity
[0]);
607 CmdAppendGraph(0, clock
, parity
[1]);
608 CmdAppendGraph(0, clock
, parity
[2]);
609 CmdAppendGraph(0, clock
, parity
[3]);
612 CmdAppendGraph(0, clock
, 0);
615 /* modulate that biatch */
619 RepaintGraphWindow();
624 static void ChkBitstream(char *str
)
628 /* convert to bitstream if necessary */
629 for (i
= 0; i
< (int)(GraphTraceLen
/ 2); i
++)
631 if (GraphBuffer
[i
] > 1 || GraphBuffer
[i
] < 0)
639 static void CmdLosim(char *str
)
643 /* convert to bitstream if necessary */
646 for (i
= 0; i
< GraphTraceLen
; i
+= 48) {
649 for(j
= 0; j
< 48; j
++) {
650 c
.d
.asBytes
[j
] = GraphBuffer
[i
+j
];
652 c
.cmd
= CMD_DOWNLOADED_SIM_SAMPLES_125K
;
654 SendCommand(&c
, FALSE
);
658 c
.cmd
= CMD_SIMULATE_TAG_125K
;
659 c
.ext1
= GraphTraceLen
;
660 SendCommand(&c
, FALSE
);
663 static void CmdLoread(char *str
)
666 // 'h' means higher-low-frequency, 134 kHz
669 } else if (*str
== '\0') {
672 PrintToScrollback("use 'loread' or 'loread h'");
675 c
.cmd
= CMD_ACQUIRE_RAW_ADC_SAMPLES_125K
;
676 SendCommand(&c
, FALSE
);
679 static void CmdDetectReader(char *str
)
682 // 'l' means LF - 125/134 kHz
685 } else if (*str
== 'h') {
687 } else if (*str
!= '\0') {
688 PrintToScrollback("use 'detectreader' or 'detectreader l' or 'detectreader h'");
691 c
.cmd
= CMD_LISTEN_READER_FIELD
;
692 SendCommand(&c
, FALSE
);
695 /* send a command before reading */
696 static void CmdLoCommandRead(char *str
)
698 static char dummy
[3];
703 c
.cmd
= CMD_MOD_THEN_ACQUIRE_RAW_ADC_SAMPLES_125K
;
704 sscanf(str
, "%i %i %i %s %s", &c
.ext1
, &c
.ext2
, &c
.ext3
, (char *) &c
.d
.asBytes
,(char *) &dummy
+1);
705 // in case they specified 'h'
706 strcpy((char *)&c
.d
.asBytes
+ strlen((char *)c
.d
.asBytes
), dummy
);
707 SendCommand(&c
, FALSE
);
710 static void CmdLosamples(char *str
)
718 if (n
>16000) n
=16000;
720 for(i
= 0; i
< n
; i
+= 12) {
722 c
.cmd
= CMD_DOWNLOAD_RAW_ADC_SAMPLES_125K
;
724 SendCommand(&c
, FALSE
);
726 if(c
.cmd
!= CMD_DOWNLOADED_RAW_ADC_SAMPLES_125K
) {
728 PrintToScrollback("bad resp");
732 for(j
= 0; j
< 48; j
++) {
733 GraphBuffer
[cnt
++] = ((int)c
.d
.asBytes
[j
]) - 128;
737 RepaintGraphWindow();
740 static void CmdBitsamples(char *str
)
747 for(i
= 0; i
< n
; i
+= 12) {
749 c
.cmd
= CMD_DOWNLOAD_RAW_ADC_SAMPLES_125K
;
751 SendCommand(&c
, FALSE
);
753 if(c
.cmd
!= CMD_DOWNLOADED_RAW_ADC_SAMPLES_125K
) {
754 PrintToScrollback("bad resp");
758 for(j
= 0; j
< 48; j
++) {
759 for(k
= 0; k
< 8; k
++) {
760 if(c
.d
.asBytes
[j
] & (1 << (7 - k
))) {
761 GraphBuffer
[cnt
++] = 1;
763 GraphBuffer
[cnt
++] = 0;
769 RepaintGraphWindow();
772 static void CmdHisamples(char *str
)
778 for(i
= 0; i
< n
; i
+= 12) {
780 c
.cmd
= CMD_DOWNLOAD_RAW_ADC_SAMPLES_125K
;
782 SendCommand(&c
, FALSE
);
784 if(c
.cmd
!= CMD_DOWNLOADED_RAW_ADC_SAMPLES_125K
) {
785 PrintToScrollback("bad resp");
789 for(j
= 0; j
< 48; j
++) {
790 GraphBuffer
[cnt
++] = (int)((BYTE
)c
.d
.asBytes
[j
]);
795 RepaintGraphWindow();
798 static int CmdHisamplest(char *str
, int nrlow
)
810 for(i
= 0; i
< n
; i
+= 12) {
812 c
.cmd
= CMD_DOWNLOAD_RAW_ADC_SAMPLES_125K
;
814 SendCommand(&c
, FALSE
);
816 if(c
.cmd
!= CMD_DOWNLOADED_RAW_ADC_SAMPLES_125K
) {
817 PrintToScrollback("bad resp");
821 for(j
= 0; j
< 48; j
++) {
822 t2
= (int)((BYTE
)c
.d
.asBytes
[j
]);
823 if((t2
^ 0xC0) & 0xC0) { hasbeennull
++; }
829 t1
= (t2
& 0x80) ^ (t2
& 0x20);
830 t2
= ((t2
<< 1) & 0x80) ^ ((t2
<< 1) & 0x20);
836 t2
= ((t2
<< 1) & 0x80);
842 t2
= ((t2
<< 1) & 0x20);
846 // both, but tag with other algorithm
847 t1
= (t2
& 0x80) ^ (t2
& 0x08);
848 t2
= ((t2
<< 1) & 0x80) ^ ((t2
<< 1) & 0x08);
852 GraphBuffer
[cnt
++] = t1
;
853 GraphBuffer
[cnt
++] = t2
;
858 if(hasbeennull
>nrlow
|| nrlow
==0) {
859 PrintToScrollback("hasbeennull=%d", hasbeennull
);
868 static void CmdHexsamples(char *str
)
879 for(i
= 0; i
< n
; i
+= 12) {
881 c
.cmd
= CMD_DOWNLOAD_RAW_ADC_SAMPLES_125K
;
883 SendCommand(&c
, FALSE
);
885 if(c
.cmd
!= CMD_DOWNLOADED_RAW_ADC_SAMPLES_125K
) {
886 PrintToScrollback("bad resp");
890 for(j
= 0; j
< 48; j
+= 8) {
891 PrintToScrollback("%02x %02x %02x %02x %02x %02x %02x %02x",
906 static void CmdHisampless(char *str
)
918 for(i
= 0; i
< n
; i
+= 12) {
920 c
.cmd
= CMD_DOWNLOAD_RAW_ADC_SAMPLES_125K
;
922 SendCommand(&c
, FALSE
);
924 if(c
.cmd
!= CMD_DOWNLOADED_RAW_ADC_SAMPLES_125K
) {
925 PrintToScrollback("bad resp");
929 for(j
= 0; j
< 48; j
++) {
930 GraphBuffer
[cnt
++] = (int)((signed char)c
.d
.asBytes
[j
]);
935 RepaintGraphWindow();
938 static WORD
Iso15693Crc(BYTE
*v
, int n
)
944 for(i
= 0; i
< n
; i
++) {
945 reg
= reg
^ ((DWORD
)v
[i
]);
946 for (j
= 0; j
< 8; j
++) {
948 reg
= (reg
>> 1) ^ 0x8408;
958 static void CmdHi14bdemod(char *str
)
963 BOOL negateI
, negateQ
;
968 // As received, the samples are pairs, correlations against I and Q
969 // square waves. So estimate angle of initial carrier (or just
970 // quadrant, actually), and then do the demod.
972 // First, estimate where the tag starts modulating.
973 for(i
= 0; i
< GraphTraceLen
; i
+= 2) {
974 if(abs(GraphBuffer
[i
]) + abs(GraphBuffer
[i
+1]) > 40) {
978 if(i
>= GraphTraceLen
) {
979 PrintToScrollback("too weak to sync");
982 PrintToScrollback("out of weak at %d", i
);
985 // Now, estimate the phase in the initial modulation of the tag
988 for(; i
< (outOfWeakAt
+ 16); i
+= 2) {
989 isum
+= GraphBuffer
[i
+0];
990 qsum
+= GraphBuffer
[i
+1];
992 negateI
= (isum
< 0);
993 negateQ
= (qsum
< 0);
995 // Turn the correlation pairs into soft decisions on the bit.
997 for(i
= 0; i
< GraphTraceLen
/2; i
++) {
998 int si
= GraphBuffer
[j
];
999 int sq
= GraphBuffer
[j
+1];
1000 if(negateI
) si
= -si
;
1001 if(negateQ
) sq
= -sq
;
1002 GraphBuffer
[i
] = si
+ sq
;
1008 while(GraphBuffer
[i
] > 0 && i
< GraphTraceLen
)
1010 if(i
>= GraphTraceLen
) goto demodError
;
1013 while(GraphBuffer
[i
] < 0 && i
< GraphTraceLen
)
1015 if(i
>= GraphTraceLen
) goto demodError
;
1016 if((i
- iold
) > 23) goto demodError
;
1018 PrintToScrollback("make it to demod loop");
1022 while(GraphBuffer
[i
] >= 0 && i
< GraphTraceLen
)
1024 if(i
>= GraphTraceLen
) goto demodError
;
1025 if((i
- iold
) > 6) goto demodError
;
1028 if(i
+ 20 >= GraphTraceLen
) goto demodError
;
1030 for(j
= 0; j
< 10; j
++) {
1031 int soft
= GraphBuffer
[i
] + GraphBuffer
[i
+1];
1033 if(abs(soft
) < ((abs(isum
) + abs(qsum
))/20)) {
1034 PrintToScrollback("weak bit");
1038 if(GraphBuffer
[i
] + GraphBuffer
[i
+1] >= 0) {
1045 if( (shiftReg
& 0x200) &&
1046 !(shiftReg
& 0x001))
1048 // valid data byte, start and stop bits okay
1049 PrintToScrollback(" %02x", (shiftReg
>> 1) & 0xff);
1050 data
[dataLen
++] = (shiftReg
>> 1) & 0xff;
1051 if(dataLen
>= sizeof(data
)) {
1054 } else if(shiftReg
== 0x000) {
1063 ComputeCrc14443(CRC_14443_B
, data
, dataLen
-2, &first
, &second
);
1064 PrintToScrollback("CRC: %02x %02x (%s)\n", first
, second
,
1065 (first
== data
[dataLen
-2] && second
== data
[dataLen
-1]) ?
1066 "ok" : "****FAIL****");
1068 RepaintGraphWindow();
1072 PrintToScrollback("demod error");
1073 RepaintGraphWindow();
1076 static void CmdHi14list(char *str
)
1079 GetFromBigBuf(got
, sizeof(got
));
1081 PrintToScrollback("recorded activity:");
1082 PrintToScrollback(" time :rssi: who bytes");
1083 PrintToScrollback("---------+----+----+-----------");
1094 int timestamp
= *((DWORD
*)(got
+i
));
1095 if(timestamp
& 0x80000000) {
1096 timestamp
&= 0x7fffffff;
1101 int metric
= *((DWORD
*)(got
+i
+4));
1108 if(i
+ len
>= 900) {
1112 BYTE
*frame
= (got
+i
+9);
1114 char line
[1000] = "";
1116 for(j
= 0; j
< len
; j
++) {
1117 sprintf(line
+(j
*3), "%02x ", frame
[j
]);
1123 ComputeCrc14443(CRC_14443_B
, frame
, len
-2, &b1
, &b2
);
1124 if(b1
!= frame
[len
-2] || b2
!= frame
[len
-1]) {
1125 crc
= "**FAIL CRC**";
1133 char metricString
[100];
1135 sprintf(metricString
, "%3d", metric
);
1137 strcpy(metricString
, " ");
1140 PrintToScrollback(" +%7d: %s: %s %s %s",
1141 (prev
< 0 ? 0 : timestamp
- prev
),
1143 (isResponse
? "TAG" : " "), line
, crc
);
1150 static void CmdHi14alist(char *str
)
1153 GetFromBigBuf(got
, sizeof(got
));
1155 PrintToScrollback("recorded activity:");
1156 PrintToScrollback(" ETU :rssi: who bytes");
1157 PrintToScrollback("---------+----+----+-----------");
1168 int timestamp
= *((DWORD
*)(got
+i
));
1169 if(timestamp
& 0x80000000) {
1170 timestamp
&= 0x7fffffff;
1177 int parityBits
= *((DWORD
*)(got
+i
+4));
1178 // 4 bytes of additional information...
1179 // maximum of 32 additional parity bit information
1182 // at each quarter bit period we can send power level (16 levels)
1183 // or each half bit period in 256 levels.
1191 if(i
+ len
>= 1900) {
1195 BYTE
*frame
= (got
+i
+9);
1197 // Break and stick with current result if buffer was not completely full
1198 if(frame
[0] == 0x44 && frame
[1] == 0x44 && frame
[3] == 0x44) { break; }
1200 char line
[1000] = "";
1202 for(j
= 0; j
< len
; j
++) {
1203 int oddparity
= 0x01;
1207 oddparity
^= (((frame
[j
] & 0xFF) >> k
) & 0x01);
1210 //if((parityBits >> (len - j - 1)) & 0x01) {
1211 if(isResponse
&& (oddparity
!= ((parityBits
>> (len
- j
- 1)) & 0x01))) {
1212 sprintf(line
+(j
*4), "%02x! ", frame
[j
]);
1215 sprintf(line
+(j
*4), "%02x ", frame
[j
]);
1223 for(j
= 0; j
< (len
- 1); j
++) {
1224 // gives problems... search for the reason..
1225 /*if(frame[j] == 0xAA) {
1226 switch(frame[j+1]) {
1228 crc = "[1] Two drops close after each other";
1231 crc = "[2] Potential SOC with a drop in second half of bitperiod";
1234 crc = "[3] Segment Z after segment X is not possible";
1237 crc = "[4] Parity bit of a fully received byte was wrong";
1240 crc = "[?] Unknown error";
1247 if(strlen(crc
)==0) {
1248 ComputeCrc14443(CRC_14443_A
, frame
, len
-2, &b1
, &b2
);
1249 if(b1
!= frame
[len
-2] || b2
!= frame
[len
-1]) {
1250 crc
= (isResponse
& (len
< 6)) ? "" : " !crc";
1259 char metricString
[100];
1261 sprintf(metricString
, "%3d", metric
);
1263 strcpy(metricString
, " ");
1266 PrintToScrollback(" +%7d: %s: %s %s %s",
1267 (prev
< 0 ? 0 : (timestamp
- prev
)),
1269 (isResponse
? "TAG" : " "), line
, crc
);
1274 CommandFinished
= 1;
1277 static void CmdHi15demod(char *str
)
1279 // The sampling rate is 106.353 ksps/s, for T = 18.8 us
1282 // 1) Unmodulated time of 56.64us
1283 // 2) 24 pulses of 423.75khz
1284 // 3) logic '1' (unmodulated for 18.88us followed by 8 pulses of 423.75khz)
1286 static const int FrameSOF
[] = {
1287 -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,
1289 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,
1296 static const int Logic0
[] = {
1302 static const int Logic1
[] = {
1310 // 1) logic '0' (8 pulses of 423.75khz followed by unmodulated for 18.88us)
1311 // 2) 24 pulses of 423.75khz
1312 // 3) Unmodulated time of 56.64us
1314 static const int FrameEOF
[] = {
1319 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
1320 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
1321 -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
1322 -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1
1326 int max
= 0, maxPos
;
1330 if(GraphTraceLen
< 1000) return;
1332 // First, correlate for SOF
1333 for(i
= 0; i
< 100; i
++) {
1335 for(j
= 0; j
< arraylen(FrameSOF
); j
+= skip
) {
1336 corr
+= FrameSOF
[j
]*GraphBuffer
[i
+(j
/skip
)];
1343 PrintToScrollback("SOF at %d, correlation %d", maxPos
,
1344 max
/(arraylen(FrameSOF
)/skip
));
1346 i
= maxPos
+ arraylen(FrameSOF
)/skip
;
1349 memset(outBuf
, 0, sizeof(outBuf
));
1352 int corr0
= 0, corr1
= 0, corrEOF
= 0;
1353 for(j
= 0; j
< arraylen(Logic0
); j
+= skip
) {
1354 corr0
+= Logic0
[j
]*GraphBuffer
[i
+(j
/skip
)];
1356 for(j
= 0; j
< arraylen(Logic1
); j
+= skip
) {
1357 corr1
+= Logic1
[j
]*GraphBuffer
[i
+(j
/skip
)];
1359 for(j
= 0; j
< arraylen(FrameEOF
); j
+= skip
) {
1360 corrEOF
+= FrameEOF
[j
]*GraphBuffer
[i
+(j
/skip
)];
1362 // Even things out by the length of the target waveform.
1366 if(corrEOF
> corr1
&& corrEOF
> corr0
) {
1367 PrintToScrollback("EOF at %d", i
);
1369 } else if(corr1
> corr0
) {
1370 i
+= arraylen(Logic1
)/skip
;
1373 i
+= arraylen(Logic0
)/skip
;
1380 if((i
+(int)arraylen(FrameEOF
)) >= GraphTraceLen
) {
1381 PrintToScrollback("ran off end!");
1386 PrintToScrollback("error, uneven octet! (discard extra bits!)");
1387 PrintToScrollback(" mask=%02x", mask
);
1389 PrintToScrollback("%d octets", k
);
1391 for(i
= 0; i
< k
; i
++) {
1392 PrintToScrollback("# %2d: %02x ", i
, outBuf
[i
]);
1394 PrintToScrollback("CRC=%04x", Iso15693Crc(outBuf
, k
-2));
1397 static void CmdTiread(char *str
)
1400 c
.cmd
= CMD_ACQUIRE_RAW_BITS_TI_TYPE
;
1401 SendCommand(&c
, FALSE
);
1404 static void CmdTibits(char *str
)
1408 // for(i = 0; i < 1536; i += 12) {
1409 for(i
= 0; i
< 4000; i
+= 12) {
1411 c
.cmd
= CMD_DOWNLOAD_RAW_BITS_TI_TYPE
;
1413 SendCommand(&c
, FALSE
);
1415 if(c
.cmd
!= CMD_DOWNLOADED_RAW_BITS_TI_TYPE
) {
1416 PrintToScrollback("bad resp");
1420 for(j
= 0; j
< 12; j
++) {
1422 for(k
= 31; k
>= 0; k
--) {
1423 if(c
.d
.asDwords
[j
] & (1 << k
)) {
1424 GraphBuffer
[cnt
++] = 1;
1426 GraphBuffer
[cnt
++] = -1;
1431 // GraphTraceLen = 1536*32;
1432 GraphTraceLen
= 4000*32;
1433 RepaintGraphWindow();
1436 static void CmdFSKdemod(char *cmdline
)
1438 static const int LowTone
[] = {
1439 1, 1, 1, 1, 1, -1, -1, -1, -1, -1,
1440 1, 1, 1, 1, 1, -1, -1, -1, -1, -1,
1441 1, 1, 1, 1, 1, -1, -1, -1, -1, -1,
1442 1, 1, 1, 1, 1, -1, -1, -1, -1, -1,
1443 1, 1, 1, 1, 1, -1, -1, -1, -1, -1
1445 static const int HighTone
[] = {
1446 1, 1, 1, 1, 1, -1, -1, -1, -1,
1447 1, 1, 1, 1, -1, -1, -1, -1,
1448 1, 1, 1, 1, -1, -1, -1, -1,
1449 1, 1, 1, 1, -1, -1, -1, -1,
1450 1, 1, 1, 1, -1, -1, -1, -1,
1451 1, 1, 1, 1, -1, -1, -1, -1, -1,
1454 int convLen
= max(arraylen(HighTone
), arraylen(LowTone
));
1455 DWORD hi
= 0, lo
= 0;
1458 int minMark
=0, maxMark
=0;
1459 int lowLen
= arraylen(LowTone
);
1460 int highLen
= arraylen(HighTone
);
1462 for(i
= 0; i
< GraphTraceLen
- convLen
; i
++) {
1463 int lowSum
= 0, highSum
= 0;
1465 for(j
= 0; j
< lowLen
; j
++) {
1466 lowSum
+= LowTone
[j
]*GraphBuffer
[i
+j
];
1468 for(j
= 0; j
< highLen
; j
++) {
1469 highSum
+= HighTone
[j
]*GraphBuffer
[i
+j
];
1471 lowSum
= abs((100*lowSum
) / lowLen
);
1472 highSum
= abs((100*highSum
) / highLen
);
1473 GraphBuffer
[i
] = (highSum
<< 16) | lowSum
;
1476 for(i
= 0; i
< GraphTraceLen
- convLen
- 16; i
++) {
1478 int lowTot
= 0, highTot
= 0;
1479 // 10 and 8 are f_s divided by f_l and f_h, rounded
1480 for(j
= 0; j
< 10; j
++) {
1481 lowTot
+= (GraphBuffer
[i
+j
] & 0xffff);
1483 for(j
= 0; j
< 8; j
++) {
1484 highTot
+= (GraphBuffer
[i
+j
] >> 16);
1486 GraphBuffer
[i
] = lowTot
- highTot
;
1487 if (GraphBuffer
[i
]>maxMark
) maxMark
=GraphBuffer
[i
];
1488 if (GraphBuffer
[i
]<minMark
) minMark
=GraphBuffer
[i
];
1491 GraphTraceLen
-= (convLen
+ 16);
1493 RepaintGraphWindow();
1495 // Find bit-sync (3 lo followed by 3 high)
1496 int max
= 0, maxPos
= 0;
1497 for(i
= 0; i
< 6000; i
++) {
1499 for(j
= 0; j
< 3*arraylen(LowTone
); j
++) {
1500 dec
-= GraphBuffer
[i
+j
];
1502 for(; j
< 3*(arraylen(LowTone
) + arraylen(HighTone
) ); j
++) {
1503 dec
+= GraphBuffer
[i
+j
];
1511 // place start of bit sync marker in graph
1512 GraphBuffer
[maxPos
] = maxMark
;
1513 GraphBuffer
[maxPos
+1] = minMark
;
1517 // place end of bit sync marker in graph
1518 GraphBuffer
[maxPos
] = maxMark
;
1519 GraphBuffer
[maxPos
+1] = minMark
;
1521 PrintToScrollback("actual data bits start at sample %d", maxPos
);
1522 PrintToScrollback("length %d/%d", arraylen(HighTone
), arraylen(LowTone
));
1525 bits
[sizeof(bits
)-1] = '\0';
1527 // find bit pairs and manchester decode them
1528 for(i
= 0; i
< arraylen(bits
)-1; i
++) {
1530 for(j
= 0; j
< arraylen(LowTone
); j
++) {
1531 dec
-= GraphBuffer
[maxPos
+j
];
1533 for(; j
< arraylen(LowTone
) + arraylen(HighTone
); j
++) {
1534 dec
+= GraphBuffer
[maxPos
+j
];
1537 // place inter bit marker in graph
1538 GraphBuffer
[maxPos
] = maxMark
;
1539 GraphBuffer
[maxPos
+1] = minMark
;
1541 // hi and lo form a 64 bit pair
1542 hi
= (hi
<<1)|(lo
>>31);
1544 // store decoded bit as binary (in hi/lo) and text (in bits[])
1552 PrintToScrollback("bits: '%s'", bits
);
1553 PrintToScrollback("hex: %08x %08x", hi
, lo
);
1556 static void CmdTidemod(char *cmdline
)
1558 /* MATLAB as follows:
1559 f_s = 2000000; % sampling frequency
1560 f_l = 123200; % low FSK tone
1561 f_h = 134200; % high FSK tone
1563 T_l = 119e-6; % low bit duration
1564 T_h = 130e-6; % high bit duration
1566 l = 2*pi*ones(1, floor(f_s*T_l))*(f_l/f_s);
1567 h = 2*pi*ones(1, floor(f_s*T_h))*(f_h/f_s);
1569 l = sign(sin(cumsum(l)));
1570 h = sign(sin(cumsum(h)));
1572 static const int LowTone
[] = {
1573 1, 1, 1, 1, 1, 1, 1, 1, -1, -1, -1, -1, -1, -1, -1, -1,
1574 1, 1, 1, 1, 1, 1, 1, 1, -1, -1, -1, -1, -1, -1, -1, -1,
1575 1, 1, 1, 1, 1, 1, 1, 1, -1, -1, -1, -1, -1, -1, -1, -1,
1576 1, 1, 1, 1, 1, 1, 1, 1, -1, -1, -1, -1, -1, -1, -1, -1,
1577 1, 1, 1, 1, 1, 1, 1, 1, 1, -1, -1, -1, -1, -1, -1, -1, -1,
1578 1, 1, 1, 1, 1, 1, 1, 1, -1, -1, -1, -1, -1, -1, -1, -1,
1579 1, 1, 1, 1, 1, 1, 1, 1, -1, -1, -1, -1, -1, -1, -1, -1,
1580 1, 1, 1, 1, 1, 1, 1, 1, -1, -1, -1, -1, -1, -1, -1, -1,
1581 1, 1, 1, 1, 1, 1, 1, 1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
1582 1, 1, 1, 1, 1, 1, 1, 1, -1, -1, -1, -1, -1, -1, -1, -1,
1583 1, 1, 1, 1, 1, 1, 1, 1, -1, -1, -1, -1, -1, -1, -1, -1,
1584 1, 1, 1, 1, 1, 1, 1, 1, -1, -1, -1, -1, -1, -1, -1, -1,
1585 1, 1, 1, 1, 1, 1, 1, 1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
1586 1, 1, 1, 1, 1, 1, 1, 1, -1, -1, -1, -1, -1, -1, -1, -1,
1587 1, 1, 1, 1, 1, 1, 1, 1, -1, -1, -1,
1589 static const int HighTone
[] = {
1590 1, 1, 1, 1, 1, 1, 1, -1, -1, -1, -1, -1, -1, -1,
1591 1, 1, 1, 1, 1, 1, 1, 1, -1, -1, -1, -1, -1, -1, -1,
1592 1, 1, 1, 1, 1, 1, 1, 1, -1, -1, -1, -1, -1, -1, -1,
1593 1, 1, 1, 1, 1, 1, 1, 1, -1, -1, -1, -1, -1, -1, -1,
1594 1, 1, 1, 1, 1, 1, 1, 1, -1, -1, -1, -1, -1, -1, -1,
1595 1, 1, 1, 1, 1, 1, 1, -1, -1, -1, -1, -1, -1, -1, -1,
1596 1, 1, 1, 1, 1, 1, 1, -1, -1, -1, -1, -1, -1, -1, -1,
1597 1, 1, 1, 1, 1, 1, 1, -1, -1, -1, -1, -1, -1, -1, -1,
1598 1, 1, 1, 1, 1, 1, 1, -1, -1, -1, -1, -1, -1, -1, -1,
1599 1, 1, 1, 1, 1, 1, 1, -1, -1, -1, -1, -1, -1, -1, -1,
1600 1, 1, 1, 1, 1, 1, 1, -1, -1, -1, -1, -1, -1, -1,
1601 1, 1, 1, 1, 1, 1, 1, 1, -1, -1, -1, -1, -1, -1, -1,
1602 1, 1, 1, 1, 1, 1, 1, 1, -1, -1, -1, -1, -1, -1, -1,
1603 1, 1, 1, 1, 1, 1, 1, 1, -1, -1, -1, -1, -1, -1, -1,
1604 1, 1, 1, 1, 1, 1, 1, 1, -1, -1, -1, -1, -1, -1, -1,
1605 1, 1, 1, 1, 1, 1, 1, -1, -1, -1, -1, -1, -1, -1, -1,
1606 1, 1, 1, 1, 1, 1, 1, -1, -1, -1, -1, -1, -1, -1, -1,
1607 1, 1, 1, 1, 1, 1, 1,
1610 int convLen
= max(arraylen(HighTone
), arraylen(LowTone
));
1613 for(i
= 0; i
< GraphTraceLen
- convLen
; i
++) {
1615 int lowSum
= 0, highSum
= 0;;
1616 int lowLen
= arraylen(LowTone
);
1617 int highLen
= arraylen(HighTone
);
1619 for(j
= 0; j
< lowLen
; j
++) {
1620 lowSum
+= LowTone
[j
]*GraphBuffer
[i
+j
];
1622 for(j
= 0; j
< highLen
; j
++) {
1623 highSum
+= HighTone
[j
]*GraphBuffer
[i
+j
];
1625 lowSum
= abs((100*lowSum
) / lowLen
);
1626 highSum
= abs((100*highSum
) / highLen
);
1627 GraphBuffer
[i
] = (highSum
<< 16) | lowSum
;
1630 for(i
= 0; i
< GraphTraceLen
- convLen
- 16; i
++) {
1632 int lowTot
= 0, highTot
= 0;
1633 // 16 and 15 are f_s divided by f_l and f_h, rounded
1634 for(j
= 0; j
< 16; j
++) {
1635 lowTot
+= (GraphBuffer
[i
+j
] & 0xffff);
1637 for(j
= 0; j
< 15; j
++) {
1638 highTot
+= (GraphBuffer
[i
+j
] >> 16);
1640 GraphBuffer
[i
] = lowTot
- highTot
;
1643 GraphTraceLen
-= (convLen
+ 16);
1645 RepaintGraphWindow();
1647 // Okay, so now we have unsliced soft decisions; find bit-sync, and then
1650 int max
= 0, maxPos
= 0;
1651 for(i
= 0; i
< 6000; i
++) {
1654 for(j
= 0; j
< 8*arraylen(LowTone
); j
++) {
1655 dec
-= GraphBuffer
[i
+j
];
1657 for(; j
< 8*arraylen(LowTone
) + 8*arraylen(HighTone
); j
++) {
1658 dec
+= GraphBuffer
[i
+j
];
1665 GraphBuffer
[maxPos
] = 800;
1666 GraphBuffer
[maxPos
+1] = -800;
1668 maxPos
+= 8*arraylen(LowTone
);
1669 GraphBuffer
[maxPos
] = 800;
1670 GraphBuffer
[maxPos
+1] = -800;
1671 maxPos
+= 8*arraylen(HighTone
);
1673 GraphBuffer
[maxPos
] = 800;
1674 GraphBuffer
[maxPos
+1] = -800;
1676 PrintToScrollback("actual data bits start at sample %d", maxPos
);
1678 PrintToScrollback("length %d/%d", arraylen(HighTone
), arraylen(LowTone
));
1680 BYTE bits
[64+16+8+1];
1681 bits
[sizeof(bits
)-1] = '\0';
1683 for(i
= 0; i
< arraylen(bits
); i
++) {
1687 for(j
= 0; j
< arraylen(LowTone
); j
++) {
1688 low
-= GraphBuffer
[maxPos
+j
];
1690 for(j
= 0; j
< arraylen(HighTone
); j
++) {
1691 high
+= GraphBuffer
[maxPos
+j
];
1695 maxPos
+= arraylen(HighTone
);
1698 maxPos
+= arraylen(LowTone
);
1700 GraphBuffer
[maxPos
] = 800;
1701 GraphBuffer
[maxPos
+1] = -800;
1703 PrintToScrollback("bits: '%s'", bits
);
1706 for(i
= 0; i
< 32; i
++) {
1707 if(bits
[i
] == '1') {
1711 for(i
= 32; i
< 64; i
++) {
1712 if(bits
[i
] == '1') {
1716 PrintToScrollback("hex: %08x %08x", h
, l
);
1719 static void CmdNorm(char *str
)
1722 int max
= INT_MIN
, min
= INT_MAX
;
1723 for(i
= 10; i
< GraphTraceLen
; i
++) {
1724 if(GraphBuffer
[i
] > max
) {
1725 max
= GraphBuffer
[i
];
1727 if(GraphBuffer
[i
] < min
) {
1728 min
= GraphBuffer
[i
];
1732 for(i
= 0; i
< GraphTraceLen
; i
++) {
1733 GraphBuffer
[i
] = (GraphBuffer
[i
] - ((max
+ min
)/2))*1000/
1737 RepaintGraphWindow();
1740 static void CmdDec(char *str
)
1743 for(i
= 0; i
< (GraphTraceLen
/2); i
++) {
1744 GraphBuffer
[i
] = GraphBuffer
[i
*2];
1747 PrintToScrollback("decimated by 2");
1748 RepaintGraphWindow();
1751 static void CmdHpf(char *str
)
1755 for(i
= 10; i
< GraphTraceLen
; i
++) {
1756 accum
+= GraphBuffer
[i
];
1758 accum
/= (GraphTraceLen
- 10);
1759 for(i
= 0; i
< GraphTraceLen
; i
++) {
1760 GraphBuffer
[i
] -= accum
;
1763 RepaintGraphWindow();
1766 static void CmdZerocrossings(char *str
)
1769 // Zero-crossings aren't meaningful unless the signal is zero-mean.
1775 for(i
= 0; i
< GraphTraceLen
; i
++) {
1776 if(GraphBuffer
[i
]*sign
>= 0) {
1777 // No change in sign, reproduce the previous sample count.
1779 GraphBuffer
[i
] = lastZc
;
1781 // Change in sign, reset the sample count.
1783 GraphBuffer
[i
] = lastZc
;
1791 RepaintGraphWindow();
1794 static void CmdThreshold(char *str
)
1797 int threshold
= atoi(str
);
1799 for(i
= 0; i
< GraphTraceLen
; i
++) {
1800 if(GraphBuffer
[i
]>= threshold
)
1805 RepaintGraphWindow();
1808 static void CmdLtrim(char *str
)
1813 for(i
= ds
; i
< GraphTraceLen
; i
++) {
1814 GraphBuffer
[i
-ds
] = GraphBuffer
[i
];
1816 GraphTraceLen
-= ds
;
1818 RepaintGraphWindow();
1821 static void CmdAutoCorr(char *str
)
1823 static int CorrelBuffer
[MAX_GRAPH_TRACE_LEN
];
1825 int window
= atoi(str
);
1828 PrintToScrollback("needs a window");
1832 if(window
>= GraphTraceLen
) {
1833 PrintToScrollback("window must be smaller than trace (%d samples)",
1838 PrintToScrollback("performing %d correlations", GraphTraceLen
- window
);
1841 for(i
= 0; i
< GraphTraceLen
- window
; i
++) {
1844 for(j
= 0; j
< window
; j
++) {
1845 sum
+= (GraphBuffer
[j
]*GraphBuffer
[i
+j
]) / 256;
1847 CorrelBuffer
[i
] = sum
;
1849 GraphTraceLen
= GraphTraceLen
- window
;
1850 memcpy(GraphBuffer
, CorrelBuffer
, GraphTraceLen
*sizeof(int));
1852 RepaintGraphWindow();
1855 static void CmdVchdemod(char *str
)
1857 // Is this the entire sync pattern, or does this also include some
1858 // data bits that happen to be the same everywhere? That would be
1860 static const int SyncPattern
[] = {
1861 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
1862 1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
1863 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
1864 1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
1865 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
1866 1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
1867 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
1868 1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
1869 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
1870 1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
1873 // So first, we correlate for the sync pattern, and mark that.
1874 int bestCorrel
= 0, bestPos
= 0;
1876 // It does us no good to find the sync pattern, with fewer than
1877 // 2048 samples after it...
1878 for(i
= 0; i
< (GraphTraceLen
-2048); i
++) {
1881 for(j
= 0; j
< arraylen(SyncPattern
); j
++) {
1882 sum
+= GraphBuffer
[i
+j
]*SyncPattern
[j
];
1884 if(sum
> bestCorrel
) {
1889 PrintToScrollback("best sync at %d [metric %d]", bestPos
, bestCorrel
);
1894 int worst
= INT_MAX
;
1897 for(i
= 0; i
< 2048; i
+= 8) {
1900 for(j
= 0; j
< 8; j
++) {
1901 sum
+= GraphBuffer
[bestPos
+i
+j
];
1908 if(abs(sum
) < worst
) {
1913 PrintToScrollback("bits:");
1914 PrintToScrollback("%s", bits
);
1915 PrintToScrollback("worst metric: %d at pos %d", worst
, worstPos
);
1917 if(strcmp(str
, "clone")==0) {
1920 for(s
= bits
; *s
; s
++) {
1922 for(j
= 0; j
< 16; j
++) {
1923 GraphBuffer
[GraphTraceLen
++] = (*s
== '1') ? 1 : 0;
1926 RepaintGraphWindow();
1930 static void CmdIndalademod(char *str
)
1932 // Usage: recover 64bit UID by default, specify "224" as arg to recover a 224bit UID
1937 // worst case with GraphTraceLen=64000 is < 4096
1938 // under normal conditions it's < 2048
1941 int worst
= 0, worstPos
= 0;
1942 PrintToScrollback("Expecting a bit less than %d raw bits", GraphTraceLen
/32);
1943 for(i
= 0; i
< GraphTraceLen
-1; i
+= 2) {
1945 if((GraphBuffer
[i
] > GraphBuffer
[i
+ 1]) && (state
!= 1)) {
1947 for(j
= 0; j
< count
- 8; j
+= 16) {
1948 rawbits
[rawbit
++] = 0;
1950 if ((abs(count
- j
)) > worst
) {
1951 worst
= abs(count
- j
);
1957 } else if((GraphBuffer
[i
] < GraphBuffer
[i
+ 1]) && (state
!= 0)) {
1959 for(j
= 0; j
< count
- 8; j
+= 16) {
1960 rawbits
[rawbit
++] = 1;
1962 if ((abs(count
- j
)) > worst
) {
1963 worst
= abs(count
- j
);
1971 PrintToScrollback("Recovered %d raw bits", rawbit
);
1972 PrintToScrollback("worst metric (0=best..7=worst): %d at pos %d", worst
, worstPos
);
1974 // Finding the start of a UID
1975 int uidlen
, long_wait
;
1976 if(strcmp(str
, "224") == 0) {
1985 for(start
= 0; start
<= rawbit
- uidlen
; start
++) {
1986 first
= rawbits
[start
];
1987 for(i
= start
; i
< start
+ long_wait
; i
++) {
1988 if(rawbits
[i
] != first
) {
1992 if(i
== (start
+ long_wait
)) {
1996 if(start
== rawbit
- uidlen
+ 1) {
1997 PrintToScrollback("nothing to wait for");
2001 // Inverting signal if needed
2003 for(i
= start
; i
< rawbit
; i
++) {
2004 rawbits
[i
] = !rawbits
[i
];
2011 showbits
[uidlen
]='\0';
2015 if(uidlen
> rawbit
) {
2016 PrintToScrollback("Warning: not enough raw bits to get a full UID");
2017 for(bit
= 0; bit
< rawbit
; bit
++) {
2018 bits
[bit
] = rawbits
[i
++];
2019 // As we cannot know the parity, let's use "." and "/"
2020 showbits
[bit
] = '.' + bits
[bit
];
2022 showbits
[bit
+1]='\0';
2023 PrintToScrollback("Partial UID=%s", showbits
);
2026 for(bit
= 0; bit
< uidlen
; bit
++) {
2027 bits
[bit
] = rawbits
[i
++];
2028 showbits
[bit
] = '0' + bits
[bit
];
2032 PrintToScrollback("UID=%s", showbits
);
2034 // Checking UID against next occurences
2035 for(; i
+ uidlen
<= rawbit
;) {
2037 for(bit
= 0; bit
< uidlen
; bit
++) {
2038 if(bits
[bit
] != rawbits
[i
++]) {
2048 PrintToScrollback("Occurences: %d (expected %d)", times
, (rawbit
- start
) / uidlen
);
2050 // Remodulating for tag cloning
2051 GraphTraceLen
= 32*uidlen
;
2054 for(bit
= 0; bit
< uidlen
; bit
++) {
2055 if(bits
[bit
] == 0) {
2061 for(j
= 0; j
< 32; j
++) {
2062 GraphBuffer
[i
++] = phase
;
2067 RepaintGraphWindow();
2070 static void CmdFlexdemod(char *str
)
2073 for(i
= 0; i
< GraphTraceLen
; i
++) {
2074 if(GraphBuffer
[i
] < 0) {
2075 GraphBuffer
[i
] = -1;
2081 #define LONG_WAIT 100
2083 for(start
= 0; start
< GraphTraceLen
- LONG_WAIT
; start
++) {
2084 int first
= GraphBuffer
[start
];
2085 for(i
= start
; i
< start
+ LONG_WAIT
; i
++) {
2086 if(GraphBuffer
[i
] != first
) {
2090 if(i
== (start
+ LONG_WAIT
)) {
2094 if(start
== GraphTraceLen
- LONG_WAIT
) {
2095 PrintToScrollback("nothing to wait for");
2099 GraphBuffer
[start
] = 2;
2100 GraphBuffer
[start
+1] = -2;
2106 for(bit
= 0; bit
< 64; bit
++) {
2109 for(j
= 0; j
< 16; j
++) {
2110 sum
+= GraphBuffer
[i
++];
2117 PrintToScrollback("bit %d sum %d", bit
, sum
);
2120 for(bit
= 0; bit
< 64; bit
++) {
2123 for(j
= 0; j
< 16; j
++) {
2124 sum
+= GraphBuffer
[i
++];
2126 if(sum
> 0 && bits
[bit
] != 1) {
2127 PrintToScrollback("oops1 at %d", bit
);
2129 if(sum
< 0 && bits
[bit
] != 0) {
2130 PrintToScrollback("oops2 at %d", bit
);
2134 GraphTraceLen
= 32*64;
2137 for(bit
= 0; bit
< 64; bit
++) {
2138 if(bits
[bit
] == 0) {
2144 for(j
= 0; j
< 32; j
++) {
2145 GraphBuffer
[i
++] = phase
;
2150 RepaintGraphWindow();
2154 * Generic command to demodulate ASK.
2156 * Argument is convention: positive or negative (High mod means zero
2157 * or high mod means one)
2159 * Updates the Graph trace with 0/1 values
2165 static void Cmdaskdemod(char *str
) {
2167 int c
, high
= 0, low
= 0;
2169 // TODO: complain if we do not give 2 arguments here !
2170 sscanf(str
, "%i", &c
);
2172 /* Detect high and lows and clock */
2173 for (i
= 0; i
< GraphTraceLen
; i
++)
2175 if (GraphBuffer
[i
] > high
)
2176 high
= GraphBuffer
[i
];
2177 else if (GraphBuffer
[i
] < low
)
2178 low
= GraphBuffer
[i
];
2181 if (GraphBuffer
[0] > 0) {
2182 GraphBuffer
[0] = 1-c
;
2186 for(i
=1;i
<GraphTraceLen
;i
++) {
2187 /* Transitions are detected at each peak
2188 * Transitions are either:
2189 * - we're low: transition if we hit a high
2190 * - we're high: transition if we hit a low
2191 * (we need to do it this way because some tags keep high or
2192 * low for long periods, others just reach the peak and go
2195 if ((GraphBuffer
[i
]==high
) && (GraphBuffer
[i
-1] == c
)) {
2197 } else if ((GraphBuffer
[i
]==low
) && (GraphBuffer
[i
-1] == (1-c
))){
2201 GraphBuffer
[i
] = GraphBuffer
[i
-1];
2204 RepaintGraphWindow();
2207 /* Print our clock rate */
2208 static void Cmddetectclockrate(char *str
)
2210 int clock
= detectclock(0);
2211 PrintToScrollback("Auto-detected clock rate: %d", clock
);
2217 int detectclock(int peak
)
2223 /* Detect peak if we don't have one */
2225 for (i
= 0; i
< GraphTraceLen
; i
++)
2226 if (GraphBuffer
[i
] > peak
)
2227 peak
= GraphBuffer
[i
];
2229 for (i
= 1; i
< GraphTraceLen
; i
++)
2231 /* If this is the beginning of a peak */
2232 if (GraphBuffer
[i
-1] != GraphBuffer
[i
] && GraphBuffer
[i
] == peak
)
2234 /* Find lowest difference between peaks */
2235 if (lastpeak
&& i
- lastpeak
< clock
)
2237 clock
= i
- lastpeak
;
2246 /* Get or auto-detect clock rate */
2247 int GetClock(char *str
, int peak
)
2251 sscanf(str
, "%i", &clock
);
2252 if (!strcmp(str
, ""))
2255 /* Auto-detect clock */
2258 clock
= detectclock(peak
);
2260 /* Only print this message if we're not looping something */
2262 PrintToScrollback("Auto-detected clock rate: %d", clock
);
2269 * Convert to a bitstream
2271 static void Cmdbitstream(char *str
) {
2278 int hithigh
, hitlow
, first
;
2280 /* Detect high and lows and clock */
2281 for (i
= 0; i
< GraphTraceLen
; i
++)
2283 if (GraphBuffer
[i
] > high
)
2284 high
= GraphBuffer
[i
];
2285 else if (GraphBuffer
[i
] < low
)
2286 low
= GraphBuffer
[i
];
2290 clock
= GetClock(str
, high
);
2292 gtl
= CmdClearGraph(0);
2295 for (i
= 0; i
< (int)(gtl
/ clock
); i
++)
2301 /* Find out if we hit both high and low peaks */
2302 for (j
= 0; j
< clock
; j
++)
2304 if (GraphBuffer
[(i
* clock
) + j
] == high
)
2306 else if (GraphBuffer
[(i
* clock
) + j
] == low
)
2309 /* it doesn't count if it's the first part of our read
2310 because it's really just trailing from the last sequence */
2311 if (first
&& (hithigh
|| hitlow
))
2312 hithigh
= hitlow
= 0;
2316 if (hithigh
&& hitlow
)
2320 /* If we didn't hit both high and low peaks, we had a bit transition */
2321 if (!hithigh
|| !hitlow
)
2324 CmdAppendGraph(0, clock
, bit
);
2325 // for (j = 0; j < (int)(clock/2); j++)
2326 // GraphBuffer[(i * clock) + j] = bit ^ 1;
2327 // for (j = (int)(clock/2); j < clock; j++)
2328 // GraphBuffer[(i * clock) + j] = bit;
2331 RepaintGraphWindow();
2334 /* Modulate our data into manchester */
2335 static void Cmdmanchestermod(char *str
)
2339 int bit
, lastbit
, wave
;
2342 clock
= GetClock(str
, 0);
2346 for (i
= 0; i
< (int)(GraphTraceLen
/ clock
); i
++)
2348 bit
= GraphBuffer
[i
* clock
] ^ 1;
2350 for (j
= 0; j
< (int)(clock
/2); j
++)
2351 GraphBuffer
[(i
* clock
) + j
] = bit
^ lastbit
^ wave
;
2352 for (j
= (int)(clock
/2); j
< clock
; j
++)
2353 GraphBuffer
[(i
* clock
) + j
] = bit
^ lastbit
^ wave
^ 1;
2355 /* Keep track of how we start our wave and if we changed or not this time */
2356 wave
^= bit
^ lastbit
;
2360 RepaintGraphWindow();
2364 * Manchester demodulate a bitstream. The bitstream needs to be already in
2365 * the GraphBuffer as 0 and 1 values
2367 * Give the clock rate as argument in order to help the sync - the algorithm
2368 * resyncs at each pulse anyway.
2370 * Not optimized by any means, this is the 1st time I'm writing this type of
2371 * routine, feel free to improve...
2373 * 1st argument: clock rate (as number of samples per clock rate)
2374 * Typical values can be 64, 32, 128...
2376 static void Cmdmanchesterdemod(char *str
) {
2377 int i
, j
, invert
= 0;
2383 int hithigh
, hitlow
, first
;
2389 /* check if we're inverting output */
2392 PrintToScrollback("Inverting output");
2396 while(*str
== ' '); // in case a 2nd argument was given
2399 /* Holds the decoded bitstream: each clock period contains 2 bits */
2400 /* later simplified to 1 bit after manchester decoding. */
2401 /* Add 10 bits to allow for noisy / uncertain traces without aborting */
2402 /* int BitStream[GraphTraceLen*2/clock+10]; */
2404 /* But it does not work if compiling on WIndows: therefore we just allocate a */
2406 int BitStream
[MAX_GRAPH_TRACE_LEN
];
2408 /* Detect high and lows */
2409 for (i
= 0; i
< GraphTraceLen
; i
++)
2411 if (GraphBuffer
[i
] > high
)
2412 high
= GraphBuffer
[i
];
2413 else if (GraphBuffer
[i
] < low
)
2414 low
= GraphBuffer
[i
];
2418 clock
= GetClock(str
, high
);
2420 int tolerance
= clock
/4;
2422 /* Detect first transition */
2423 /* Lo-Hi (arbitrary) */
2424 for (i
= 0; i
< GraphTraceLen
; i
++)
2426 if (GraphBuffer
[i
] == low
)
2433 /* If we're not working with 1/0s, demod based off clock */
2436 bit
= 0; /* We assume the 1st bit is zero, it may not be
2437 * the case: this routine (I think) has an init problem.
2440 for (; i
< (int)(GraphTraceLen
/ clock
); i
++)
2446 /* Find out if we hit both high and low peaks */
2447 for (j
= 0; j
< clock
; j
++)
2449 if (GraphBuffer
[(i
* clock
) + j
] == high
)
2451 else if (GraphBuffer
[(i
* clock
) + j
] == low
)
2454 /* it doesn't count if it's the first part of our read
2455 because it's really just trailing from the last sequence */
2456 if (first
&& (hithigh
|| hitlow
))
2457 hithigh
= hitlow
= 0;
2461 if (hithigh
&& hitlow
)
2465 /* If we didn't hit both high and low peaks, we had a bit transition */
2466 if (!hithigh
|| !hitlow
)
2469 BitStream
[bit2idx
++] = bit
^ invert
;
2473 /* standard 1/0 bitstream */
2477 /* Then detect duration between 2 successive transitions */
2478 for (bitidx
= 1; i
< GraphTraceLen
; i
++)
2480 if (GraphBuffer
[i
-1] != GraphBuffer
[i
])
2485 // Error check: if bitidx becomes too large, we do not
2486 // have a Manchester encoded bitstream or the clock is really
2488 if (bitidx
> (GraphTraceLen
*2/clock
+8) ) {
2489 PrintToScrollback("Error: the clock you gave is probably wrong, aborting.");
2492 // Then switch depending on lc length:
2493 // Tolerance is 1/4 of clock rate (arbitrary)
2494 if (abs(lc
-clock
/2) < tolerance
) {
2495 // Short pulse : either "1" or "0"
2496 BitStream
[bitidx
++]=GraphBuffer
[i
-1];
2497 } else if (abs(lc
-clock
) < tolerance
) {
2498 // Long pulse: either "11" or "00"
2499 BitStream
[bitidx
++]=GraphBuffer
[i
-1];
2500 BitStream
[bitidx
++]=GraphBuffer
[i
-1];
2504 PrintToScrollback("Warning: Manchester decode error for pulse width detection.");
2505 PrintToScrollback("(too many of those messages mean either the stream is not Manchester encoded, or clock is wrong)");
2509 PrintToScrollback("Error: too many detection errors, aborting.");
2516 // At this stage, we now have a bitstream of "01" ("1") or "10" ("0"), parse it into final decoded bitstream
2517 // Actually, we overwrite BitStream with the new decoded bitstream, we just need to be careful
2518 // to stop output at the final bitidx2 value, not bitidx
2519 for (i
= 0; i
< bitidx
; i
+= 2) {
2520 if ((BitStream
[i
] == 0) && (BitStream
[i
+1] == 1)) {
2521 BitStream
[bit2idx
++] = 1 ^ invert
;
2522 } else if ((BitStream
[i
] == 1) && (BitStream
[i
+1] == 0)) {
2523 BitStream
[bit2idx
++] = 0 ^ invert
;
2525 // We cannot end up in this state, this means we are unsynchronized,
2529 PrintToScrollback("Unsynchronized, resync...");
2530 PrintToScrollback("(too many of those messages mean the stream is not Manchester encoded)");
2534 PrintToScrollback("Error: too many decode errors, aborting.");
2541 PrintToScrollback("Manchester decoded bitstream");
2542 // Now output the bitstream to the scrollback by line of 16 bits
2543 for (i
= 0; i
< (bit2idx
-16); i
+=16) {
2544 PrintToScrollback("%i %i %i %i %i %i %i %i %i %i %i %i %i %i %i %i",
2567 static void CmdHiddemod(char *str
)
2569 if(GraphTraceLen
< 4800) {
2570 PrintToScrollback("too short; need at least 4800 samples");
2574 GraphTraceLen
= 4800;
2576 for(i
= 0; i
< GraphTraceLen
; i
++) {
2577 if(GraphBuffer
[i
] < 0) {
2583 RepaintGraphWindow();
2586 static void CmdPlot(char *str
)
2591 static void CmdGrid(char *str
)
2593 sscanf(str
, "%i %i", &PlotGridX
, &PlotGridY
);
2594 RepaintGraphWindow();
2597 static void CmdHide(char *str
)
2602 static void CmdScale(char *str
)
2604 CursorScaleFactor
= atoi(str
);
2605 if(CursorScaleFactor
== 0) {
2606 PrintToScrollback("bad, can't have zero scale");
2607 CursorScaleFactor
= 1;
2609 RepaintGraphWindow();
2612 static void CmdSave(char *str
)
2614 FILE *f
= fopen(str
, "w");
2616 PrintToScrollback("couldn't open '%s'", str
);
2620 for(i
= 0; i
< GraphTraceLen
; i
++) {
2621 fprintf(f
, "%d\n", GraphBuffer
[i
]);
2624 PrintToScrollback("saved to '%s'", str
);
2627 static void CmdLoad(char *str
)
2629 FILE *f
= fopen(str
, "r");
2631 PrintToScrollback("couldn't open '%s'", str
);
2637 while(fgets(line
, sizeof(line
), f
)) {
2638 GraphBuffer
[GraphTraceLen
] = atoi(line
);
2642 PrintToScrollback("loaded %d samples", GraphTraceLen
);
2643 RepaintGraphWindow();
2646 static void CmdHIDsimTAG(char *str
)
2648 unsigned int hi
=0, lo
=0;
2652 while (sscanf(&str
[i
++], "%1x", &n
) == 1) {
2653 hi
=(hi
<<4)|(lo
>>28);
2657 PrintToScrollback("Emulating tag with ID %x%16x", hi
, lo
);
2659 c
.cmd
= CMD_HID_SIM_TAG
;
2662 SendCommand(&c
, FALSE
);
2665 static void CmdReadmem(char *str
)
2668 c
.cmd
= CMD_READ_MEM
;
2670 SendCommand(&c
, FALSE
);
2673 static void CmdLcdReset(char *str
)
2676 c
.cmd
= CMD_LCD_RESET
;
2678 SendCommand(&c
, FALSE
);
2681 static void CmdLcd(char *str
)
2686 sscanf(str
, "%x %d", &i
, &j
);
2689 SendCommand(&c
, FALSE
);
2694 * Sets the divisor for LF frequency clock: lets the user choose any LF frequency below
2697 static void CmdSetDivisor(char *str
)
2700 c
.cmd
= CMD_SET_LF_DIVISOR
;
2702 if (( c
.ext1
<0) || (c
.ext1
>255)) {
2703 PrintToScrollback("divisor must be between 19 and 255");
2705 SendCommand(&c
, FALSE
);
2706 PrintToScrollback("Divisor set, expected freq=%dHz", 12000000/(c
.ext1
+1));
2710 typedef void HandlerFunction(char *cmdline
);
2712 /* in alphabetic order */
2715 HandlerFunction
*handler
;
2716 int offline
; // 1 if the command can be used when in offline mode
2718 } CommandTable
[] = {
2719 {"askdemod", Cmdaskdemod
, 1, "<samples per bit> <0|1> -- Attempt to demodulate simple ASK tags"},
2720 {"autocorr", CmdAutoCorr
, 1, "<window length> -- Autocorrelation over window"},
2721 {"bitsamples", CmdBitsamples
, 0, "Get raw samples as bitstring"},
2722 {"bitstream", Cmdbitstream
, 1, "[clock rate] -- Convert waveform into a bitstream"},
2723 {"buffclear", CmdBuffClear
, 0, "Clear sample buffer and graph window"},
2724 {"dec", CmdDec
, 1, "Decimate samples"},
2725 {"detectclock", Cmddetectclockrate
, 1, "Detect clock rate"},
2726 {"detectreader", CmdDetectReader
, 0, "['l'|'h'] -- Detect external reader field (option 'l' or 'h' to limit to LF or HF)"},
2727 {"em410xsim", CmdEM410xsim
, 1, "<UID> -- Simulate EM410x tag"},
2728 {"em410xread", CmdEM410xread
, 1, "[clock rate] -- Extract ID from EM410x tag"},
2729 {"em410xwatch", CmdEM410xwatch
, 0, "Watches for EM410x tags"},
2730 {"em4x50read", CmdEM4x50read
, 1, "Extract data from EM4x50 tag"},
2731 {"exit", CmdQuit
, 1, "Exit program"},
2732 {"flexdemod", CmdFlexdemod
, 1, "Demodulate samples for FlexPass"},
2733 {"fpgaoff", CmdFPGAOff
, 0, "Set FPGA off"},
2734 {"fskdemod", CmdFSKdemod
, 1, "Demodulate graph window as a HID FSK"},
2735 {"grid", CmdGrid
, 1, "<x> <y> -- overlay grid on graph window, use zero value to turn off either"},
2736 {"hexsamples", CmdHexsamples
, 0, "<blocks> -- Dump big buffer as hex bytes"},
2737 {"hi14alist", CmdHi14alist
, 0, "List ISO 14443a history"},
2738 {"hi14areader", CmdHi14areader
, 0, "Act like an ISO14443 Type A reader"},
2739 {"hi14asim", CmdHi14asim
, 0, "<UID> -- Fake ISO 14443a tag"},
2740 {"hi14asnoop", CmdHi14asnoop
, 0, "Eavesdrop ISO 14443 Type A"},
2741 {"hi14bdemod", CmdHi14bdemod
, 1, "Demodulate ISO14443 Type B from tag"},
2742 {"hi14list", CmdHi14list
, 0, "List ISO 14443 history"},
2743 {"hi14read", CmdHi14read
, 0, "Read HF tag (ISO 14443)"},
2744 {"hi14sim", CmdHi14sim
, 0, "Fake ISO 14443 tag"},
2745 {"hi14snoop", CmdHi14snoop
, 0, "Eavesdrop ISO 14443"},
2746 {"hi15demod", CmdHi15demod
, 1, "Demodulate ISO15693 from tag"},
2747 {"hi15read", CmdHi15read
, 0, "Read HF tag (ISO 15693)"},
2748 {"hi15reader", CmdHi15reader
, 0, "Act like an ISO15693 reader"},
2749 {"hi15sim", CmdHi15tag
, 0, "Fake an ISO15693 tag"},
2750 {"hiddemod", CmdHiddemod
, 1, "Demodulate HID Prox Card II (not optimal)"},
2751 {"hide", CmdHide
, 1, "Hide graph window"},
2752 {"hidfskdemod", CmdHIDdemodFSK
, 0, "Realtime HID FSK demodulator"},
2753 {"hidsimtag", CmdHIDsimTAG
, 0, "<ID> -- HID tag simulator"},
2754 {"higet", CmdHi14read_sim
, 0, "<samples> -- Get samples HF, 'analog'"},
2755 {"hisamples", CmdHisamples
, 0, "Get raw samples for HF tag"},
2756 {"hisampless", CmdHisampless
, 0, "<samples> -- Get signed raw samples, HF tag"},
2757 {"hisamplest", CmdHi14readt
, 0, "Get samples HF, for testing"},
2758 {"hisimlisten", CmdHisimlisten
, 0, "Get HF samples as fake tag"},
2759 {"hpf", CmdHpf
, 1, "Remove DC offset from trace"},
2760 {"indalademod", CmdIndalademod
, 0, "['224'] -- Demodulate samples for Indala 64 bit UID (option '224' for 224 bit)"},
2761 {"lcd", CmdLcd
, 0, "<HEX command> <count> -- Send command/data to LCD"},
2762 {"lcdreset", CmdLcdReset
, 0, "Hardware reset LCD"},
2763 {"load", CmdLoad
, 1, "<filename> -- Load trace (to graph window"},
2764 {"locomread", CmdLoCommandRead
, 0, "<off period> <'0' period> <'1' period> <command> ['h'] -- Modulate LF reader field to send command before read (all periods in microseconds) (option 'h' for 134)"},
2765 {"loread", CmdLoread
, 0, "['h'] -- Read 125/134 kHz LF ID-only tag (option 'h' for 134)"},
2766 {"losamples", CmdLosamples
, 0, "[128 - 16000] -- Get raw samples for LF tag"},
2767 {"losim", CmdLosim
, 0, "Simulate LF tag"},
2768 {"ltrim", CmdLtrim
, 1, "<samples> -- Trim samples from left of trace"},
2769 {"mandemod", Cmdmanchesterdemod
, 1, "[i] [clock rate] -- Manchester demodulate binary stream (option 'i' to invert output)"},
2770 {"manmod", Cmdmanchestermod
, 1, "[clock rate] -- Manchester modulate a binary stream"},
2771 {"norm", CmdNorm
, 1, "Normalize max/min to +/-500"},
2772 {"plot", CmdPlot
, 1, "Show graph window"},
2773 {"quit", CmdQuit
, 1, "Quit program"},
2774 {"readmem", CmdReadmem
, 0, "[address] -- Read memory at decimal address from flash"},
2775 {"reset", CmdReset
, 0, "Reset the Proxmark3"},
2776 {"save", CmdSave
, 1, "<filename> -- Save trace (from graph window)"},
2777 {"scale", CmdScale
, 1, "<int> -- Set cursor display scale"},
2778 {"setlfdivisor", CmdSetDivisor
, 0, "<19 - 255> -- Drive LF antenna at 12Mhz/(divisor+1)"},
2779 {"sri512read", CmdSri512read
, 0, "<int> -- Read contents of a SRI512 tag"},
2780 {"tibits", CmdTibits
, 0, "Get raw bits for TI-type LF tag"},
2781 {"tidemod", CmdTidemod
, 1, "Demodulate raw bits for TI-type LF tag"},
2782 {"tiread", CmdTiread
, 0, "Read a TI-type 134 kHz tag"},
2783 {"threshold", CmdThreshold
, 1, "Maximize/minimize every value in the graph window depending on threshold"},
2784 {"tune", CmdTune
, 0, "Measure antenna tuning"},
2785 {"vchdemod", CmdVchdemod
, 0, "['clone'] -- Demodulate samples for VeriChip"},
2786 {"zerocrossings", CmdZerocrossings
, 1, "Count time between zero-crossings"},
2794 } CommandExtendedHelp
[]= {
2795 {"detectreader","'l'|'h'","'l' specifies LF antenna scan only, 'h' specifies HF antenna scan only.","Monitor antenna for changes in voltage. Output is in three fields: CHANGED, CURRENT, PERIOD,\nwhere CHANGED is the value just changed from, CURRENT is the current value and PERIOD is the\nnumber of program loops since the last change.\n\nThe RED LED indicates LF field detected, and the GREEN LED indicates HF field detected."},
2796 {"tune","","","Drive LF antenna at all divisor range values (19 - 255) and store the results in the output\nbuffer. Issuing 'losamples' and then 'plot' commands will display the resulting peak. 12MHz\ndivided by the peak's position plus one gives the antenna's resonant frequency. For convenience,\nthis value is also printed out by the command."},
2799 //-----------------------------------------------------------------------------
2800 // Entry point into our code: called whenever the user types a command and
2801 // then presses Enter, which the full command line that they typed.
2802 //-----------------------------------------------------------------------------
2803 void CommandReceived(char *cmd
)
2808 PrintToScrollback("> %s", cmd
);
2810 if(strcmp(cmd
, "help") == 0 || strncmp(cmd
,"help ",strlen("help ")) == 0) {
2811 // check if we're doing extended help
2812 if(strlen(cmd
) > strlen("help ")) {
2813 cmd
+= strlen("help ");
2814 for(i
= 0; i
< sizeof(CommandExtendedHelp
) / sizeof(CommandExtendedHelp
[0]); i
++) {
2815 if(strcmp(CommandExtendedHelp
[i
].name
,cmd
) == 0) {
2816 PrintToScrollback("\nExtended help for '%s':\n", cmd
);
2817 PrintToScrollback("Args: %s\t- %s\n",CommandExtendedHelp
[i
].args
,CommandExtendedHelp
[i
].argshelp
);
2818 PrintToScrollback(CommandExtendedHelp
[i
].description
);
2819 PrintToScrollback("");
2823 PrintToScrollback("No extended help available for '%s'", cmd
);
2826 if (offline
) PrintToScrollback("Operating in OFFLINE mode (no device connected)");
2827 PrintToScrollback("\r\nAvailable commands:");
2828 for(i
= 0; i
< sizeof(CommandTable
) / sizeof(CommandTable
[0]); i
++) {
2829 if (offline
&& (CommandTable
[i
].offline
==0)) continue;
2830 memset(line
, ' ', sizeof(line
));
2831 strcpy(line
+2, CommandTable
[i
].name
);
2832 line
[strlen(line
)] = ' ';
2833 sprintf(line
+15, " -- %s", CommandTable
[i
].docString
);
2834 PrintToScrollback("%s", line
);
2836 PrintToScrollback("");
2837 PrintToScrollback("'help <command>' for extended help on that command\n");
2841 for(i
= 0; i
< sizeof(CommandTable
) / sizeof(CommandTable
[0]); i
++) {
2842 char *name
= CommandTable
[i
].name
;
2843 if(memcmp(cmd
, name
, strlen(name
))==0 &&
2844 (cmd
[strlen(name
)] == ' ' || cmd
[strlen(name
)] == '\0'))
2846 cmd
+= strlen(name
);
2847 while(*cmd
== ' ') {
2850 if (offline
&& (CommandTable
[i
].offline
==0)) {
2851 PrintToScrollback("Offline mode, cannot use this command.");
2854 (CommandTable
[i
].handler
)(cmd
);
2858 PrintToScrollback(">> bad command '%s'", cmd
);
2861 //-----------------------------------------------------------------------------
2862 // Entry point into our code: called whenever we received a packet over USB
2863 // that we weren't necessarily expecting, for example a debug print.
2864 //-----------------------------------------------------------------------------
2865 void UsbCommandReceived(UsbCommand
*c
)
2868 case CMD_DEBUG_PRINT_STRING
: {
2870 if(c
->ext1
> 70 || c
->ext1
< 0) {
2873 memcpy(s
, c
->d
.asBytes
, c
->ext1
);
2875 PrintToScrollback("#db# %s", s
);
2879 case CMD_DEBUG_PRINT_INTEGERS
:
2880 PrintToScrollback("#db# %08x, %08x, %08x\r\n", c
->ext1
, c
->ext2
, c
->ext3
);
2883 case CMD_MEASURED_ANTENNA_TUNING
: {
2885 int vLf125
, vLf134
, vHf
;
2886 vLf125
= c
->ext1
& 0xffff;
2887 vLf134
= c
->ext1
>> 16;
2888 vHf
= c
->ext2
& 0xffff;;
2889 peakf
= c
->ext3
& 0xffff;
2890 peakv
= c
->ext3
>> 16;
2891 PrintToScrollback("");
2892 PrintToScrollback("");
2893 PrintToScrollback("# LF antenna: %5.2f V @ 125.00 kHz", vLf125
/1000.0);
2894 PrintToScrollback("# LF antenna: %5.2f V @ 134.00 kHz", vLf134
/1000.0);
2895 PrintToScrollback("# LF optimal: %5.2f V @%9.2f kHz", peakv
/1000.0, 12000.0/(peakf
+1));
2896 PrintToScrollback("# HF antenna: %5.2f V @ 13.56 MHz", vHf
/1000.0);
2898 PrintToScrollback("# Your LF antenna is unusable.");
2899 else if (peakv
<10000)
2900 PrintToScrollback("# Your LF antenna is marginal.");
2902 PrintToScrollback("# Your HF antenna is unusable.");
2904 PrintToScrollback("# Your HF antenna is marginal.");
2908 PrintToScrollback("unrecognized command %08x\n", c
->cmd
);