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 //-----------------------------------------------------------------------------
15 #include "../common/iso14443_crc.c"
17 #define arraylen(x) (sizeof(x)/sizeof((x)[0]))
18 #define BIT(x) GraphBuffer[x * clock]
19 #define BITS (GraphTraceLen / clock)
22 static int CmdHisamplest(char *str
, int nrlow
);
24 static void GetFromBigBuf(BYTE
*dest
, int bytes
)
29 PrintToScrollback("bad len in GetFromBigBuf");
34 for(i
= 0; i
< n
; i
+= 12) {
36 c
.cmd
= CMD_DOWNLOAD_RAW_ADC_SAMPLES_125K
;
38 SendCommand(&c
, FALSE
);
40 if(c
.cmd
!= CMD_DOWNLOADED_RAW_ADC_SAMPLES_125K
) {
41 PrintToScrollback("bad resp");
45 memcpy(dest
+(i
*4), c
.d
.asBytes
, 48);
49 static void CmdReset(char *str
)
52 c
.cmd
= CMD_HARDWARE_RESET
;
53 SendCommand(&c
, FALSE
);
56 static void CmdBuffClear(char *str
)
59 c
.cmd
= CMD_BUFF_CLEAR
;
60 SendCommand(&c
, FALSE
);
64 static void CmdQuit(char *str
)
69 static void CmdHIDdemodFSK(char *str
)
72 c
.cmd
= CMD_HID_DEMOD_FSK
;
73 SendCommand(&c
, FALSE
);
76 static void CmdTune(char *str
)
79 c
.cmd
= CMD_MEASURE_ANTENNA_TUNING
;
80 SendCommand(&c
, FALSE
);
83 static void CmdHi15read(char *str
)
86 c
.cmd
= CMD_ACQUIRE_RAW_ADC_SAMPLES_ISO_15693
;
87 SendCommand(&c
, FALSE
);
90 static void CmdHi14read(char *str
)
93 c
.cmd
= CMD_ACQUIRE_RAW_ADC_SAMPLES_ISO_14443
;
95 SendCommand(&c
, FALSE
);
99 /* New command to read the contents of a SRI512 tag
100 * SRI512 tags are ISO14443-B modulated memory tags,
101 * this command just dumps the contents of the memory/
103 static void CmdSri512read(char *str
)
106 c
.cmd
= CMD_READ_SRI512_TAG
;
108 SendCommand(&c
, FALSE
);
112 static void CmdHi14areader(char *str
)
115 c
.cmd
= CMD_READER_ISO_14443a
;
117 SendCommand(&c
, FALSE
);
121 static void CmdHi15reader(char *str
)
124 c
.cmd
= CMD_READER_ISO_15693
;
126 SendCommand(&c
, FALSE
);
130 static void CmdHi15tag(char *str
)
133 c
.cmd
= CMD_SIMTAG_ISO_15693
;
135 SendCommand(&c
, FALSE
);
138 static void CmdHi14read_sim(char *str
)
141 c
.cmd
= CMD_ACQUIRE_RAW_ADC_SAMPLES_ISO_14443_SIM
;
143 SendCommand(&c
, FALSE
);
146 static void CmdHi14readt(char *str
)
149 c
.cmd
= CMD_ACQUIRE_RAW_ADC_SAMPLES_ISO_14443
;
151 SendCommand(&c
, FALSE
);
153 //CmdHisamplest(str);
154 while(CmdHisamplest(str
,atoi(str
))==0) {
155 c
.cmd
= CMD_ACQUIRE_RAW_ADC_SAMPLES_ISO_14443
;
157 SendCommand(&c
, FALSE
);
159 RepaintGraphWindow();
162 static void CmdHisimlisten(char *str
)
165 c
.cmd
= CMD_SIMULATE_TAG_HF_LISTEN
;
166 SendCommand(&c
, FALSE
);
169 static void CmdHi14sim(char *str
)
172 c
.cmd
= CMD_SIMULATE_TAG_ISO_14443
;
173 SendCommand(&c
, FALSE
);
176 static void CmdHi14asim(char *str
) // ## simulate iso14443a tag
177 { // ## greg - added ability to specify tag UID
179 unsigned int hi
=0, lo
=0;
183 while (sscanf(&str
[i
++], "%1x", &n
) == 1) {
188 c
.cmd
= CMD_SIMULATE_TAG_ISO_14443a
;
189 // c.ext should be set to *str or convert *str to the correct format for a uid
192 PrintToScrollback("Emulating 14443A TAG with UID %x%16x", hi
, lo
);
193 SendCommand(&c
, FALSE
);
196 static void CmdHi14snoop(char *str
)
199 c
.cmd
= CMD_SNOOP_ISO_14443
;
200 SendCommand(&c
, FALSE
);
203 static void CmdHi14asnoop(char *str
)
206 c
.cmd
= CMD_SNOOP_ISO_14443a
;
207 SendCommand(&c
, FALSE
);
210 static void CmdFPGAOff(char *str
) // ## FPGA Control
213 c
.cmd
= CMD_FPGA_MAJOR_MODE_OFF
;
214 SendCommand(&c
, FALSE
);
217 /* clear out our graph window */
218 int CmdClearGraph(int redraw
)
220 int gtl
= GraphTraceLen
;
224 RepaintGraphWindow();
229 /* write a bit to the graph */
230 static void CmdAppendGraph(int redraw
, int clock
, int bit
)
234 for (i
= 0; i
< (int)(clock
/2); i
++)
235 GraphBuffer
[GraphTraceLen
++] = bit
^ 1;
237 for (i
= (int)(clock
/2); i
< clock
; i
++)
238 GraphBuffer
[GraphTraceLen
++] = bit
;
241 RepaintGraphWindow();
244 /* Function is equivalent of loread + losamples + em410xread
245 * looped until an EM410x tag is detected */
246 static void CmdEM410xwatch(char *str
)
260 /* Read the ID of an EM410x tag.
262 * 1111 1111 1 <-- standard non-repeatable header
263 * XXXX [row parity bit] <-- 10 rows of 5 bits for our 40 bit tag ID
265 * CCCC <-- each bit here is parity for the 10 bits above in corresponding column
266 * 0 <-- stop bit, end of tag
268 static void CmdEM410xread(char *str
)
270 int i
, j
, clock
, header
, rows
, bit
, hithigh
, hitlow
, first
, bit2idx
, high
, low
;
274 int BitStream
[MAX_GRAPH_TRACE_LEN
];
277 /* Detect high and lows and clock */
278 for (i
= 0; i
< GraphTraceLen
; i
++)
280 if (GraphBuffer
[i
] > high
)
281 high
= GraphBuffer
[i
];
282 else if (GraphBuffer
[i
] < low
)
283 low
= GraphBuffer
[i
];
287 clock
= GetClock(str
, high
);
289 /* parity for our 4 columns */
290 parity
[0] = parity
[1] = parity
[2] = parity
[3] = 0;
293 /* manchester demodulate */
295 for (i
= 0; i
< (int)(GraphTraceLen
/ clock
); i
++)
301 /* Find out if we hit both high and low peaks */
302 for (j
= 0; j
< clock
; j
++)
304 if (GraphBuffer
[(i
* clock
) + j
] == high
)
306 else if (GraphBuffer
[(i
* clock
) + j
] == low
)
309 /* it doesn't count if it's the first part of our read
310 because it's really just trailing from the last sequence */
311 if (first
&& (hithigh
|| hitlow
))
312 hithigh
= hitlow
= 0;
316 if (hithigh
&& hitlow
)
320 /* If we didn't hit both high and low peaks, we had a bit transition */
321 if (!hithigh
|| !hitlow
)
324 BitStream
[bit2idx
++] = bit
;
328 /* We go till 5 before the graph ends because we'll get that far below */
329 for (i
= 1; i
< bit2idx
- 5; i
++)
331 /* Step 2: We have our header but need our tag ID */
332 if (header
== 9 && rows
< 10)
334 /* Confirm parity is correct */
335 if ((BitStream
[i
] ^ BitStream
[i
+1] ^ BitStream
[i
+2] ^ BitStream
[i
+3]) == BitStream
[i
+4])
337 /* Read another byte! */
338 sprintf(id
+rows
, "%x", (8 * BitStream
[i
]) + (4 * BitStream
[i
+1]) + (2 * BitStream
[i
+2]) + (1 * BitStream
[i
+3]));
341 /* Keep parity info */
342 parity
[0] ^= BitStream
[i
];
343 parity
[1] ^= BitStream
[i
+1];
344 parity
[2] ^= BitStream
[i
+2];
345 parity
[3] ^= BitStream
[i
+3];
347 /* Move 4 bits ahead */
351 /* Damn, something wrong! reset */
354 PrintToScrollback("Thought we had a valid tag but failed at word %d (i=%d)", rows
+ 1, i
);
356 /* Start back rows * 5 + 9 header bits, -1 to not start at same place */
357 i
-= 9 + (5 * rows
) - 5;
363 /* Step 3: Got our 40 bits! confirm column parity */
366 /* We need to make sure our 4 bits of parity are correct and we have a stop bit */
367 if (BitStream
[i
] == parity
[0] && BitStream
[i
+1] == parity
[1] &&
368 BitStream
[i
+2] == parity
[2] && BitStream
[i
+3] == parity
[3] &&
372 PrintToScrollback("EM410x Tag ID: %s", id
);
379 /* Crap! Incorrect parity or no stop bit, start all over */
384 /* Go back 59 bits (9 header bits + 10 rows at 4+1 parity) */
389 /* Step 1: get our header */
392 /* Need 9 consecutive 1's */
393 if (BitStream
[i
] == 1)
396 /* We don't have a header, not enough consecutive 1 bits */
402 /* if we've already retested after flipping bits, return */
406 /* if this didn't work, try flipping bits */
407 for (i
= 0; i
< bit2idx
; i
++)
413 /* emulate an EM410X tag
415 * 1111 1111 1 <-- standard non-repeatable header
416 * XXXX [row parity bit] <-- 10 rows of 5 bits for our 40 bit tag ID
418 * CCCC <-- each bit here is parity for the 10 bits above in corresponding column
419 * 0 <-- stop bit, end of tag
421 static void CmdEM410xsim(char *str
)
423 int i
, n
, j
, h
, binary
[4], parity
[4];
426 /* clock is 64 in EM410x tags */
429 /* clear our graph */
432 /* write it out a few times */
433 for (h
= 0; h
< 4; h
++)
435 /* write 9 start bits */
436 for (i
= 0; i
< 9; i
++)
437 CmdAppendGraph(0, clock
, 1);
439 /* for each hex char */
440 parity
[0] = parity
[1] = parity
[2] = parity
[3] = 0;
441 for (i
= 0; i
< 10; i
++)
443 /* read each hex char */
444 sscanf(&str
[i
], "%1x", &n
);
445 for (j
= 3; j
>= 0; j
--, n
/= 2)
448 /* append each bit */
449 CmdAppendGraph(0, clock
, binary
[0]);
450 CmdAppendGraph(0, clock
, binary
[1]);
451 CmdAppendGraph(0, clock
, binary
[2]);
452 CmdAppendGraph(0, clock
, binary
[3]);
454 /* append parity bit */
455 CmdAppendGraph(0, clock
, binary
[0] ^ binary
[1] ^ binary
[2] ^ binary
[3]);
457 /* keep track of column parity */
458 parity
[0] ^= binary
[0];
459 parity
[1] ^= binary
[1];
460 parity
[2] ^= binary
[2];
461 parity
[3] ^= binary
[3];
465 CmdAppendGraph(0, clock
, parity
[0]);
466 CmdAppendGraph(0, clock
, parity
[1]);
467 CmdAppendGraph(0, clock
, parity
[2]);
468 CmdAppendGraph(0, clock
, parity
[3]);
471 CmdAppendGraph(0, clock
, 0);
474 /* modulate that biatch */
478 RepaintGraphWindow();
483 static void ChkBitstream(char *str
)
487 /* convert to bitstream if necessary */
488 for (i
= 0; i
< (int)(GraphTraceLen
/ 2); i
++)
490 if (GraphBuffer
[i
] > 1 || GraphBuffer
[i
] < 0)
498 static void CmdLosim(char *str
)
503 /* convert to bitstream if necessary */
506 for (i
= 0; i
< GraphTraceLen
; i
+= 48) {
509 for(j
= 0; j
< 48; j
++) {
510 c
.d
.asBytes
[j
] = GraphBuffer
[i
+j
];
512 c
.cmd
= CMD_DOWNLOADED_SIM_SAMPLES_125K
;
514 SendCommand(&c
, FALSE
);
518 c
.cmd
= CMD_SIMULATE_TAG_125K
;
519 c
.ext1
= GraphTraceLen
;
520 SendCommand(&c
, FALSE
);
523 static void CmdLoread(char *str
)
526 // 'h' means higher-low-frequency, 134 kHz
529 } else if (*str
== '\0') {
532 PrintToScrollback("use 'loread' or 'loread h'");
535 c
.cmd
= CMD_ACQUIRE_RAW_ADC_SAMPLES_125K
;
536 SendCommand(&c
, FALSE
);
539 /* send a command before reading */
540 static void CmdLoCommandRead(char *str
)
542 static char dummy
[3];
547 c
.cmd
= CMD_MOD_THEN_ACQUIRE_RAW_ADC_SAMPLES_125K
;
548 sscanf(str
, "%i %i %i %s %s", &c
.ext1
, &c
.ext2
, &c
.ext3
, &c
.d
.asBytes
,&dummy
+1);
549 // in case they specified 'h'
550 strcpy(&c
.d
.asBytes
+ strlen(c
.d
.asBytes
),dummy
);
551 SendCommand(&c
, FALSE
);
554 static void CmdLosamples(char *str
)
562 if (n
>16000) n
=16000;
564 for(i
= 0; i
< n
; i
+= 12) {
566 c
.cmd
= CMD_DOWNLOAD_RAW_ADC_SAMPLES_125K
;
568 SendCommand(&c
, FALSE
);
570 if(c
.cmd
!= CMD_DOWNLOADED_RAW_ADC_SAMPLES_125K
) {
572 PrintToScrollback("bad resp");
576 for(j
= 0; j
< 48; j
++) {
577 GraphBuffer
[cnt
++] = ((int)c
.d
.asBytes
[j
]) - 128;
581 RepaintGraphWindow();
584 static void CmdBitsamples(char *str
)
591 for(i
= 0; i
< n
; i
+= 12) {
593 c
.cmd
= CMD_DOWNLOAD_RAW_ADC_SAMPLES_125K
;
595 SendCommand(&c
, FALSE
);
597 if(c
.cmd
!= CMD_DOWNLOADED_RAW_ADC_SAMPLES_125K
) {
598 PrintToScrollback("bad resp");
602 for(j
= 0; j
< 48; j
++) {
603 for(k
= 0; k
< 8; k
++) {
604 if(c
.d
.asBytes
[j
] & (1 << (7 - k
))) {
605 GraphBuffer
[cnt
++] = 1;
607 GraphBuffer
[cnt
++] = 0;
613 RepaintGraphWindow();
616 static void CmdHisamples(char *str
)
622 for(i
= 0; i
< n
; i
+= 12) {
624 c
.cmd
= CMD_DOWNLOAD_RAW_ADC_SAMPLES_125K
;
626 SendCommand(&c
, FALSE
);
628 if(c
.cmd
!= CMD_DOWNLOADED_RAW_ADC_SAMPLES_125K
) {
629 PrintToScrollback("bad resp");
633 for(j
= 0; j
< 48; j
++) {
634 GraphBuffer
[cnt
++] = (int)((BYTE
)c
.d
.asBytes
[j
]);
639 RepaintGraphWindow();
643 static int CmdHisamplest(char *str
, int nrlow
)
655 for(i
= 0; i
< n
; i
+= 12) {
657 c
.cmd
= CMD_DOWNLOAD_RAW_ADC_SAMPLES_125K
;
659 SendCommand(&c
, FALSE
);
661 if(c
.cmd
!= CMD_DOWNLOADED_RAW_ADC_SAMPLES_125K
) {
662 PrintToScrollback("bad resp");
666 for(j
= 0; j
< 48; j
++) {
667 t2
= (int)((BYTE
)c
.d
.asBytes
[j
]);
668 if((t2
^ 0xC0) & 0xC0) { hasbeennull
++; }
674 t1
= (t2
& 0x80) ^ (t2
& 0x20);
675 t2
= ((t2
<< 1) & 0x80) ^ ((t2
<< 1) & 0x20);
681 t2
= ((t2
<< 1) & 0x80);
687 t2
= ((t2
<< 1) & 0x20);
691 // both, but tag with other algorithm
692 t1
= (t2
& 0x80) ^ (t2
& 0x08);
693 t2
= ((t2
<< 1) & 0x80) ^ ((t2
<< 1) & 0x08);
697 GraphBuffer
[cnt
++] = t1
;
698 GraphBuffer
[cnt
++] = t2
;
703 if(hasbeennull
>nrlow
|| nrlow
==0) {
704 PrintToScrollback("hasbeennull=%d", hasbeennull
);
713 static void CmdHexsamples(char *str
)
724 for(i
= 0; i
< n
; i
+= 12) {
726 c
.cmd
= CMD_DOWNLOAD_RAW_ADC_SAMPLES_125K
;
728 SendCommand(&c
, FALSE
);
730 if(c
.cmd
!= CMD_DOWNLOADED_RAW_ADC_SAMPLES_125K
) {
731 PrintToScrollback("bad resp");
735 for(j
= 0; j
< 48; j
+= 8) {
736 PrintToScrollback("%02x %02x %02x %02x %02x %02x %02x %02x",
751 static void CmdHisampless(char *str
)
763 for(i
= 0; i
< n
; i
+= 12) {
765 c
.cmd
= CMD_DOWNLOAD_RAW_ADC_SAMPLES_125K
;
767 SendCommand(&c
, FALSE
);
769 if(c
.cmd
!= CMD_DOWNLOADED_RAW_ADC_SAMPLES_125K
) {
770 PrintToScrollback("bad resp");
774 for(j
= 0; j
< 48; j
++) {
775 GraphBuffer
[cnt
++] = (int)((signed char)c
.d
.asBytes
[j
]);
780 RepaintGraphWindow();
783 static WORD
Iso15693Crc(BYTE
*v
, int n
)
789 for(i
= 0; i
< n
; i
++) {
790 reg
= reg
^ ((DWORD
)v
[i
]);
791 for (j
= 0; j
< 8; j
++) {
793 reg
= (reg
>> 1) ^ 0x8408;
803 static void CmdHi14bdemod(char *str
)
808 BOOL negateI
, negateQ
;
813 // As received, the samples are pairs, correlations against I and Q
814 // square waves. So estimate angle of initial carrier (or just
815 // quadrant, actually), and then do the demod.
817 // First, estimate where the tag starts modulating.
818 for(i
= 0; i
< GraphTraceLen
; i
+= 2) {
819 if(abs(GraphBuffer
[i
]) + abs(GraphBuffer
[i
+1]) > 40) {
823 if(i
>= GraphTraceLen
) {
824 PrintToScrollback("too weak to sync");
827 PrintToScrollback("out of weak at %d", i
);
830 // Now, estimate the phase in the initial modulation of the tag
833 for(; i
< (outOfWeakAt
+ 16); i
+= 2) {
834 isum
+= GraphBuffer
[i
+0];
835 qsum
+= GraphBuffer
[i
+1];
837 negateI
= (isum
< 0);
838 negateQ
= (qsum
< 0);
840 // Turn the correlation pairs into soft decisions on the bit.
842 for(i
= 0; i
< GraphTraceLen
/2; i
++) {
843 int si
= GraphBuffer
[j
];
844 int sq
= GraphBuffer
[j
+1];
845 if(negateI
) si
= -si
;
846 if(negateQ
) sq
= -sq
;
847 GraphBuffer
[i
] = si
+ sq
;
853 while(GraphBuffer
[i
] > 0 && i
< GraphTraceLen
)
855 if(i
>= GraphTraceLen
) goto demodError
;
858 while(GraphBuffer
[i
] < 0 && i
< GraphTraceLen
)
860 if(i
>= GraphTraceLen
) goto demodError
;
861 if((i
- iold
) > 23) goto demodError
;
863 PrintToScrollback("make it to demod loop");
867 while(GraphBuffer
[i
] >= 0 && i
< GraphTraceLen
)
869 if(i
>= GraphTraceLen
) goto demodError
;
870 if((i
- iold
) > 6) goto demodError
;
873 if(i
+ 20 >= GraphTraceLen
) goto demodError
;
875 for(j
= 0; j
< 10; j
++) {
876 int soft
= GraphBuffer
[i
] + GraphBuffer
[i
+1];
878 if(abs(soft
) < ((abs(isum
) + abs(qsum
))/20)) {
879 PrintToScrollback("weak bit");
883 if(GraphBuffer
[i
] + GraphBuffer
[i
+1] >= 0) {
890 if( (shiftReg
& 0x200) &&
893 // valid data byte, start and stop bits okay
894 PrintToScrollback(" %02x", (shiftReg
>> 1) & 0xff);
895 data
[dataLen
++] = (shiftReg
>> 1) & 0xff;
896 if(dataLen
>= sizeof(data
)) {
899 } else if(shiftReg
== 0x000) {
908 ComputeCrc14443(CRC_14443_B
, data
, dataLen
-2, &first
, &second
);
909 PrintToScrollback("CRC: %02x %02x (%s)\n", first
, second
,
910 (first
== data
[dataLen
-2] && second
== data
[dataLen
-1]) ?
911 "ok" : "****FAIL****");
913 RepaintGraphWindow();
917 PrintToScrollback("demod error");
918 RepaintGraphWindow();
921 static void CmdHi14list(char *str
)
924 GetFromBigBuf(got
, sizeof(got
));
926 PrintToScrollback("recorded activity:");
927 PrintToScrollback(" time :rssi: who bytes");
928 PrintToScrollback("---------+----+----+-----------");
939 int timestamp
= *((DWORD
*)(got
+i
));
940 if(timestamp
& 0x80000000) {
941 timestamp
&= 0x7fffffff;
946 int metric
= *((DWORD
*)(got
+i
+4));
957 BYTE
*frame
= (got
+i
+9);
959 char line
[1000] = "";
961 for(j
= 0; j
< len
; j
++) {
962 sprintf(line
+(j
*3), "%02x ", frame
[j
]);
968 ComputeCrc14443(CRC_14443_B
, frame
, len
-2, &b1
, &b2
);
969 if(b1
!= frame
[len
-2] || b2
!= frame
[len
-1]) {
970 crc
= "**FAIL CRC**";
978 char metricString
[100];
980 sprintf(metricString
, "%3d", metric
);
982 strcpy(metricString
, " ");
985 PrintToScrollback(" +%7d: %s: %s %s %s",
986 (prev
< 0 ? 0 : timestamp
- prev
),
988 (isResponse
? "TAG" : " "), line
, crc
);
995 static void CmdHi14alist(char *str
)
998 GetFromBigBuf(got
, sizeof(got
));
1000 PrintToScrollback("recorded activity:");
1001 PrintToScrollback(" ETU :rssi: who bytes");
1002 PrintToScrollback("---------+----+----+-----------");
1013 int timestamp
= *((DWORD
*)(got
+i
));
1014 if(timestamp
& 0x80000000) {
1015 timestamp
&= 0x7fffffff;
1022 int parityBits
= *((DWORD
*)(got
+i
+4));
1023 // 4 bytes of additional information...
1024 // maximum of 32 additional parity bit information
1027 // at each quarter bit period we can send power level (16 levels)
1028 // or each half bit period in 256 levels.
1036 if(i
+ len
>= 1900) {
1040 BYTE
*frame
= (got
+i
+9);
1042 // Break and stick with current result if buffer was not completely full
1043 if(frame
[0] == 0x44 && frame
[1] == 0x44 && frame
[3] == 0x44) { break; }
1045 char line
[1000] = "";
1047 for(j
= 0; j
< len
; j
++) {
1048 int oddparity
= 0x01;
1052 oddparity
^= (((frame
[j
] & 0xFF) >> k
) & 0x01);
1055 //if((parityBits >> (len - j - 1)) & 0x01) {
1056 if(isResponse
&& (oddparity
!= ((parityBits
>> (len
- j
- 1)) & 0x01))) {
1057 sprintf(line
+(j
*4), "%02x! ", frame
[j
]);
1060 sprintf(line
+(j
*4), "%02x ", frame
[j
]);
1068 for(j
= 0; j
< (len
- 1); j
++) {
1069 // gives problems... search for the reason..
1070 /*if(frame[j] == 0xAA) {
1071 switch(frame[j+1]) {
1073 crc = "[1] Two drops close after each other";
1076 crc = "[2] Potential SOC with a drop in second half of bitperiod";
1079 crc = "[3] Segment Z after segment X is not possible";
1082 crc = "[4] Parity bit of a fully received byte was wrong";
1085 crc = "[?] Unknown error";
1092 if(strlen(crc
)==0) {
1093 ComputeCrc14443(CRC_14443_A
, frame
, len
-2, &b1
, &b2
);
1094 if(b1
!= frame
[len
-2] || b2
!= frame
[len
-1]) {
1095 crc
= (isResponse
& (len
< 6)) ? "" : " !crc";
1104 char metricString
[100];
1106 sprintf(metricString
, "%3d", metric
);
1108 strcpy(metricString
, " ");
1111 PrintToScrollback(" +%7d: %s: %s %s %s",
1112 (prev
< 0 ? 0 : (timestamp
- prev
)),
1114 (isResponse
? "TAG" : " "), line
, crc
);
1119 CommandFinished
= 1;
1122 static void CmdHi15demod(char *str
)
1124 // The sampling rate is 106.353 ksps/s, for T = 18.8 us
1127 // 1) Unmodulated time of 56.64us
1128 // 2) 24 pulses of 423.75khz
1129 // 3) logic '1' (unmodulated for 18.88us followed by 8 pulses of 423.75khz)
1131 static const int FrameSOF
[] = {
1132 -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
1133 -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
1134 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
1135 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
1141 static const int Logic0
[] = {
1147 static const int Logic1
[] = {
1155 // 1) logic '0' (8 pulses of 423.75khz followed by unmodulated for 18.88us)
1156 // 2) 24 pulses of 423.75khz
1157 // 3) Unmodulated time of 56.64us
1159 static const int FrameEOF
[] = {
1164 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
1165 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
1166 -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
1167 -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1
1171 int max
= 0, maxPos
;
1175 if(GraphTraceLen
< 1000) return;
1177 // First, correlate for SOF
1178 for(i
= 0; i
< 100; i
++) {
1180 for(j
= 0; j
< arraylen(FrameSOF
); j
+= skip
) {
1181 corr
+= FrameSOF
[j
]*GraphBuffer
[i
+(j
/skip
)];
1188 PrintToScrollback("SOF at %d, correlation %d", maxPos
,
1189 max
/(arraylen(FrameSOF
)/skip
));
1191 i
= maxPos
+ arraylen(FrameSOF
)/skip
;
1194 memset(outBuf
, 0, sizeof(outBuf
));
1197 int corr0
= 0, corr1
= 0, corrEOF
= 0;
1198 for(j
= 0; j
< arraylen(Logic0
); j
+= skip
) {
1199 corr0
+= Logic0
[j
]*GraphBuffer
[i
+(j
/skip
)];
1201 for(j
= 0; j
< arraylen(Logic1
); j
+= skip
) {
1202 corr1
+= Logic1
[j
]*GraphBuffer
[i
+(j
/skip
)];
1204 for(j
= 0; j
< arraylen(FrameEOF
); j
+= skip
) {
1205 corrEOF
+= FrameEOF
[j
]*GraphBuffer
[i
+(j
/skip
)];
1207 // Even things out by the length of the target waveform.
1211 if(corrEOF
> corr1
&& corrEOF
> corr0
) {
1212 PrintToScrollback("EOF at %d", i
);
1214 } else if(corr1
> corr0
) {
1215 i
+= arraylen(Logic1
)/skip
;
1218 i
+= arraylen(Logic0
)/skip
;
1225 if((i
+(int)arraylen(FrameEOF
)) >= GraphTraceLen
) {
1226 PrintToScrollback("ran off end!");
1231 PrintToScrollback("error, uneven octet! (discard extra bits!)");
1232 PrintToScrollback(" mask=%02x", mask
);
1234 PrintToScrollback("%d octets", k
);
1236 for(i
= 0; i
< k
; i
++) {
1237 PrintToScrollback("# %2d: %02x ", i
, outBuf
[i
]);
1239 PrintToScrollback("CRC=%04x", Iso15693Crc(outBuf
, k
-2));
1242 static void CmdTiread(char *str
)
1245 c
.cmd
= CMD_ACQUIRE_RAW_BITS_TI_TYPE
;
1246 SendCommand(&c
, FALSE
);
1249 static void CmdTibits(char *str
)
1253 for(i
= 0; i
< 1536; i
+= 12) {
1255 c
.cmd
= CMD_DOWNLOAD_RAW_BITS_TI_TYPE
;
1257 SendCommand(&c
, FALSE
);
1259 if(c
.cmd
!= CMD_DOWNLOADED_RAW_BITS_TI_TYPE
) {
1260 PrintToScrollback("bad resp");
1264 for(j
= 0; j
< 12; j
++) {
1266 for(k
= 31; k
>= 0; k
--) {
1267 if(c
.d
.asDwords
[j
] & (1 << k
)) {
1268 GraphBuffer
[cnt
++] = 1;
1270 GraphBuffer
[cnt
++] = -1;
1275 GraphTraceLen
= 1536*32;
1276 RepaintGraphWindow();
1279 static void CmdTidemod(char *cmdline
)
1281 /* MATLAB as follows:
1282 f_s = 2000000; % sampling frequency
1283 f_l = 123200; % low FSK tone
1284 f_h = 134200; % high FSK tone
1286 T_l = 119e-6; % low bit duration
1287 T_h = 130e-6; % high bit duration
1289 l = 2*pi*ones(1, floor(f_s*T_l))*(f_l/f_s);
1290 h = 2*pi*ones(1, floor(f_s*T_h))*(f_h/f_s);
1292 l = sign(sin(cumsum(l)));
1293 h = sign(sin(cumsum(h)));
1295 static const int LowTone
[] = {
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, 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, -1,
1301 -1, -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, 1,
1303 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, -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,
1310 static const int HighTone
[] = {
1311 1, 1, 1, 1, 1, 1, 1, -1, -1, -1, -1, -1, -1, -1, 1, 1, 1, 1, 1, 1,
1312 1, 1, -1, -1, -1, -1, -1, -1, -1, 1, 1, 1, 1, 1, 1, 1, 1, -1, -1,
1313 -1, -1, -1, -1, -1, 1, 1, 1, 1, 1, 1, 1, 1, -1, -1, -1, -1, -1,
1314 -1, -1, 1, 1, 1, 1, 1, 1, 1, 1, -1, -1, -1, -1, -1, -1, -1, 1, 1,
1315 1, 1, 1, 1, 1, -1, -1, -1, -1, -1, -1, -1, -1, 1, 1, 1, 1, 1, 1,
1316 1, -1, -1, -1, -1, -1, -1, -1, -1, 1, 1, 1, 1, 1, 1, 1, -1, -1,
1317 -1, -1, -1, -1, -1, -1, 1, 1, 1, 1, 1, 1, 1, -1, -1, -1, -1, -1,
1318 -1, -1, -1, 1, 1, 1, 1, 1, 1, 1, -1, -1, -1, -1, -1, -1, -1, -1,
1319 1, 1, 1, 1, 1, 1, 1, -1, -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, 1, 1, 1, 1, 1, -1, -1,
1321 -1, -1, -1, -1, -1, 1, 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, -1, -1, -1, -1, -1, 1, 1,
1323 1, 1, 1, 1, 1, -1, -1, -1, -1, -1, -1, -1, -1, 1, 1, 1, 1, 1, 1,
1324 1, -1, -1, -1, -1, -1, -1, -1, -1, 1, 1, 1, 1, 1, 1, 1,
1327 int convLen
= max(arraylen(HighTone
), arraylen(LowTone
));
1330 for(i
= 0; i
< GraphTraceLen
- convLen
; i
++) {
1332 int lowSum
= 0, highSum
= 0;;
1333 int lowLen
= arraylen(LowTone
);
1334 int highLen
= arraylen(HighTone
);
1336 for(j
= 0; j
< lowLen
; j
++) {
1337 lowSum
+= LowTone
[j
]*GraphBuffer
[i
+j
];
1339 for(j
= 0; j
< highLen
; j
++) {
1340 highSum
+= HighTone
[j
]*GraphBuffer
[i
+j
];
1342 lowSum
= abs((100*lowSum
) / lowLen
);
1343 highSum
= abs((100*highSum
) / highLen
);
1344 GraphBuffer
[i
] = (highSum
<< 16) | lowSum
;
1347 for(i
= 0; i
< GraphTraceLen
- convLen
- 16; i
++) {
1349 int lowTot
= 0, highTot
= 0;
1350 // 16 and 15 are f_s divided by f_l and f_h, rounded
1351 for(j
= 0; j
< 16; j
++) {
1352 lowTot
+= (GraphBuffer
[i
+j
] & 0xffff);
1354 for(j
= 0; j
< 15; j
++) {
1355 highTot
+= (GraphBuffer
[i
+j
] >> 16);
1357 GraphBuffer
[i
] = lowTot
- highTot
;
1360 GraphTraceLen
-= (convLen
+ 16);
1362 RepaintGraphWindow();
1364 // Okay, so now we have unsliced soft decisions; find bit-sync, and then
1367 int max
= 0, maxPos
= 0;
1368 for(i
= 0; i
< 6000; i
++) {
1371 for(j
= 0; j
< 8*arraylen(LowTone
); j
++) {
1372 dec
-= GraphBuffer
[i
+j
];
1374 for(; j
< 8*arraylen(LowTone
) + 8*arraylen(HighTone
); j
++) {
1375 dec
+= GraphBuffer
[i
+j
];
1382 GraphBuffer
[maxPos
] = 800;
1383 GraphBuffer
[maxPos
+1] = -800;
1385 maxPos
+= 8*arraylen(LowTone
);
1386 GraphBuffer
[maxPos
] = 800;
1387 GraphBuffer
[maxPos
+1] = -800;
1388 maxPos
+= 8*arraylen(HighTone
);
1390 GraphBuffer
[maxPos
] = 800;
1391 GraphBuffer
[maxPos
+1] = -800;
1393 PrintToScrollback("actual data bits start at sample %d", maxPos
);
1395 PrintToScrollback("length %d/%d", arraylen(HighTone
), arraylen(LowTone
));
1397 GraphBuffer
[maxPos
] = 800;
1398 GraphBuffer
[maxPos
+1] = -800;
1400 BYTE bits
[64+16+8+1];
1401 bits
[sizeof(bits
)-1] = '\0';
1403 for(i
= 0; i
< arraylen(bits
); i
++) {
1407 for(j
= 0; j
< arraylen(LowTone
); j
++) {
1408 low
-= GraphBuffer
[maxPos
+j
];
1410 for(j
= 0; j
< arraylen(HighTone
); j
++) {
1411 high
+= GraphBuffer
[maxPos
+j
];
1415 maxPos
+= arraylen(HighTone
);
1418 maxPos
+= arraylen(LowTone
);
1420 GraphBuffer
[maxPos
] = 800;
1421 GraphBuffer
[maxPos
+1] = -800;
1423 PrintToScrollback("bits: '%s'", bits
);
1426 for(i
= 0; i
< 32; i
++) {
1427 if(bits
[i
] == '1') {
1431 for(i
= 32; i
< 64; i
++) {
1432 if(bits
[i
] == '1') {
1436 PrintToScrollback("hex: %08x %08x", h
, l
);
1439 static void CmdNorm(char *str
)
1442 int max
= INT_MIN
, min
= INT_MAX
;
1443 for(i
= 10; i
< GraphTraceLen
; i
++) {
1444 if(GraphBuffer
[i
] > max
) {
1445 max
= GraphBuffer
[i
];
1447 if(GraphBuffer
[i
] < min
) {
1448 min
= GraphBuffer
[i
];
1452 for(i
= 0; i
< GraphTraceLen
; i
++) {
1453 GraphBuffer
[i
] = (GraphBuffer
[i
] - ((max
+ min
)/2))*1000/
1457 RepaintGraphWindow();
1460 static void CmdDec(char *str
)
1463 for(i
= 0; i
< (GraphTraceLen
/2); i
++) {
1464 GraphBuffer
[i
] = GraphBuffer
[i
*2];
1467 PrintToScrollback("decimated by 2");
1468 RepaintGraphWindow();
1471 static void CmdHpf(char *str
)
1475 for(i
= 10; i
< GraphTraceLen
; i
++) {
1476 accum
+= GraphBuffer
[i
];
1478 accum
/= (GraphTraceLen
- 10);
1479 for(i
= 0; i
< GraphTraceLen
; i
++) {
1480 GraphBuffer
[i
] -= accum
;
1483 RepaintGraphWindow();
1486 static void CmdZerocrossings(char *str
)
1489 // Zero-crossings aren't meaningful unless the signal is zero-mean.
1495 for(i
= 0; i
< GraphTraceLen
; i
++) {
1496 if(GraphBuffer
[i
]*sign
>= 0) {
1497 // No change in sign, reproduce the previous sample count.
1499 GraphBuffer
[i
] = lastZc
;
1501 // Change in sign, reset the sample count.
1503 GraphBuffer
[i
] = lastZc
;
1511 RepaintGraphWindow();
1514 static void CmdLtrim(char *str
)
1519 for(i
= ds
; i
< GraphTraceLen
; i
++) {
1520 GraphBuffer
[i
-ds
] = GraphBuffer
[i
];
1522 GraphTraceLen
-= ds
;
1524 RepaintGraphWindow();
1527 static void CmdAutoCorr(char *str
)
1529 static int CorrelBuffer
[MAX_GRAPH_TRACE_LEN
];
1531 int window
= atoi(str
);
1534 PrintToScrollback("needs a window");
1538 if(window
>= GraphTraceLen
) {
1539 PrintToScrollback("window must be smaller than trace (%d samples)",
1544 PrintToScrollback("performing %d correlations", GraphTraceLen
- window
);
1547 for(i
= 0; i
< GraphTraceLen
- window
; i
++) {
1550 for(j
= 0; j
< window
; j
++) {
1551 sum
+= (GraphBuffer
[j
]*GraphBuffer
[i
+j
]) / 256;
1553 CorrelBuffer
[i
] = sum
;
1555 GraphTraceLen
= GraphTraceLen
- window
;
1556 memcpy(GraphBuffer
, CorrelBuffer
, GraphTraceLen
*sizeof(int));
1558 RepaintGraphWindow();
1561 static void CmdVchdemod(char *str
)
1563 // Is this the entire sync pattern, or does this also include some
1564 // data bits that happen to be the same everywhere? That would be
1566 static const int SyncPattern
[] = {
1567 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
1568 1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
1569 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
1570 1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
1571 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
1572 1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
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,
1579 // So first, we correlate for the sync pattern, and mark that.
1580 int bestCorrel
= 0, bestPos
= 0;
1582 // It does us no good to find the sync pattern, with fewer than
1583 // 2048 samples after it...
1584 for(i
= 0; i
< (GraphTraceLen
-2048); i
++) {
1587 for(j
= 0; j
< arraylen(SyncPattern
); j
++) {
1588 sum
+= GraphBuffer
[i
+j
]*SyncPattern
[j
];
1590 if(sum
> bestCorrel
) {
1595 PrintToScrollback("best sync at %d [metric %d]", bestPos
, bestCorrel
);
1600 int worst
= INT_MAX
;
1603 for(i
= 0; i
< 2048; i
+= 8) {
1606 for(j
= 0; j
< 8; j
++) {
1607 sum
+= GraphBuffer
[bestPos
+i
+j
];
1614 if(abs(sum
) < worst
) {
1619 PrintToScrollback("bits:");
1620 PrintToScrollback("%s", bits
);
1621 PrintToScrollback("worst metric: %d at pos %d", worst
, worstPos
);
1623 if(strcmp(str
, "clone")==0) {
1626 for(s
= bits
; *s
; s
++) {
1628 for(j
= 0; j
< 16; j
++) {
1629 GraphBuffer
[GraphTraceLen
++] = (*s
== '1') ? 1 : 0;
1632 RepaintGraphWindow();
1636 static void CmdIndalademod(char *str
)
1638 // Usage: recover 64bit UID by default, specify "224" as arg to recover a 224bit UID
1643 // worst case with GraphTraceLen=64000 is < 4096
1644 // under normal conditions it's < 2048
1647 int worst
= 0, worstPos
= 0;
1648 PrintToScrollback("Expecting a bit less than %d raw bits", GraphTraceLen
/32);
1649 for(i
= 0; i
< GraphTraceLen
-1; i
+= 2) {
1651 if((GraphBuffer
[i
] > GraphBuffer
[i
+ 1]) && (state
!= 1)) {
1653 for(j
= 0; j
< count
- 8; j
+= 16) {
1654 rawbits
[rawbit
++] = 0;
1656 if ((abs(count
- j
)) > worst
) {
1657 worst
= abs(count
- j
);
1663 } else if((GraphBuffer
[i
] < GraphBuffer
[i
+ 1]) && (state
!= 0)) {
1665 for(j
= 0; j
< count
- 8; j
+= 16) {
1666 rawbits
[rawbit
++] = 1;
1668 if ((abs(count
- j
)) > worst
) {
1669 worst
= abs(count
- j
);
1677 PrintToScrollback("Recovered %d raw bits", rawbit
);
1678 PrintToScrollback("worst metric (0=best..7=worst): %d at pos %d", worst
, worstPos
);
1680 // Finding the start of a UID
1681 int uidlen
, long_wait
;
1682 if(strcmp(str
, "224") == 0) {
1691 for(start
= 0; start
<= rawbit
- uidlen
; start
++) {
1692 first
= rawbits
[start
];
1693 for(i
= start
; i
< start
+ long_wait
; i
++) {
1694 if(rawbits
[i
] != first
) {
1698 if(i
== (start
+ long_wait
)) {
1702 if(start
== rawbit
- uidlen
+ 1) {
1703 PrintToScrollback("nothing to wait for");
1707 // Inverting signal if needed
1709 for(i
= start
; i
< rawbit
; i
++) {
1710 rawbits
[i
] = !rawbits
[i
];
1717 showbits
[uidlen
]='\0';
1721 if(uidlen
> rawbit
) {
1722 PrintToScrollback("Warning: not enough raw bits to get a full UID");
1723 for(bit
= 0; bit
< rawbit
; bit
++) {
1724 bits
[bit
] = rawbits
[i
++];
1725 // As we cannot know the parity, let's use "." and "/"
1726 showbits
[bit
] = '.' + bits
[bit
];
1728 showbits
[bit
+1]='\0';
1729 PrintToScrollback("Partial UID=%s", showbits
);
1732 for(bit
= 0; bit
< uidlen
; bit
++) {
1733 bits
[bit
] = rawbits
[i
++];
1734 showbits
[bit
] = '0' + bits
[bit
];
1738 PrintToScrollback("UID=%s", showbits
);
1740 // Checking UID against next occurences
1741 for(; i
+ uidlen
<= rawbit
;) {
1743 for(bit
= 0; bit
< uidlen
; bit
++) {
1744 if(bits
[bit
] != rawbits
[i
++]) {
1754 PrintToScrollback("Occurences: %d (expected %d)", times
, (rawbit
- start
) / uidlen
);
1756 // Remodulating for tag cloning
1757 GraphTraceLen
= 32*uidlen
;
1760 for(bit
= 0; bit
< uidlen
; bit
++) {
1761 if(bits
[bit
] == 0) {
1767 for(j
= 0; j
< 32; j
++) {
1768 GraphBuffer
[i
++] = phase
;
1773 RepaintGraphWindow();
1776 static void CmdFlexdemod(char *str
)
1779 for(i
= 0; i
< GraphTraceLen
; i
++) {
1780 if(GraphBuffer
[i
] < 0) {
1781 GraphBuffer
[i
] = -1;
1787 #define LONG_WAIT 100
1789 for(start
= 0; start
< GraphTraceLen
- LONG_WAIT
; start
++) {
1790 int first
= GraphBuffer
[start
];
1791 for(i
= start
; i
< start
+ LONG_WAIT
; i
++) {
1792 if(GraphBuffer
[i
] != first
) {
1796 if(i
== (start
+ LONG_WAIT
)) {
1800 if(start
== GraphTraceLen
- LONG_WAIT
) {
1801 PrintToScrollback("nothing to wait for");
1805 GraphBuffer
[start
] = 2;
1806 GraphBuffer
[start
+1] = -2;
1812 for(bit
= 0; bit
< 64; bit
++) {
1815 for(j
= 0; j
< 16; j
++) {
1816 sum
+= GraphBuffer
[i
++];
1823 PrintToScrollback("bit %d sum %d", bit
, sum
);
1826 for(bit
= 0; bit
< 64; bit
++) {
1829 for(j
= 0; j
< 16; j
++) {
1830 sum
+= GraphBuffer
[i
++];
1832 if(sum
> 0 && bits
[bit
] != 1) {
1833 PrintToScrollback("oops1 at %d", bit
);
1835 if(sum
< 0 && bits
[bit
] != 0) {
1836 PrintToScrollback("oops2 at %d", bit
);
1840 GraphTraceLen
= 32*64;
1843 for(bit
= 0; bit
< 64; bit
++) {
1844 if(bits
[bit
] == 0) {
1850 for(j
= 0; j
< 32; j
++) {
1851 GraphBuffer
[i
++] = phase
;
1856 RepaintGraphWindow();
1860 * Generic command to demodulate ASK.
1862 * Argument is convention: positive or negative (High mod means zero
1863 * or high mod means one)
1865 * Updates the Graph trace with 0/1 values
1871 static void Cmdaskdemod(char *str
) {
1876 // TODO: complain if we do not give 2 arguments here !
1877 sscanf(str
, "%i", &c
);
1879 /* Detect high and lows and clock */
1880 for (i
= 0; i
< GraphTraceLen
; i
++)
1882 if (GraphBuffer
[i
] > high
)
1883 high
= GraphBuffer
[i
];
1884 else if (GraphBuffer
[i
] < low
)
1885 low
= GraphBuffer
[i
];
1888 if (GraphBuffer
[0] > 0) {
1889 GraphBuffer
[0] = 1-c
;
1893 for(i
=1;i
<GraphTraceLen
;i
++) {
1894 /* Transitions are detected at each peak
1895 * Transitions are either:
1896 * - we're low: transition if we hit a high
1897 * - we're high: transition if we hit a low
1898 * (we need to do it this way because some tags keep high or
1899 * low for long periods, others just reach the peak and go
1902 if ((GraphBuffer
[i
]==high
) && (GraphBuffer
[i
-1] == c
)) {
1904 } else if ((GraphBuffer
[i
]==low
) && (GraphBuffer
[i
-1] == (1-c
))){
1908 GraphBuffer
[i
] = GraphBuffer
[i
-1];
1911 RepaintGraphWindow();
1914 /* Print our clock rate */
1915 static void Cmddetectclockrate(char *str
)
1917 int clock
= detectclock(0);
1918 PrintToScrollback("Auto-detected clock rate: %d", clock
);
1924 int detectclock(int peak
)
1930 /* Detect peak if we don't have one */
1932 for (i
= 0; i
< GraphTraceLen
; i
++)
1933 if (GraphBuffer
[i
] > peak
)
1934 peak
= GraphBuffer
[i
];
1936 for (i
= 1; i
< GraphTraceLen
; i
++)
1938 /* If this is the beginning of a peak */
1939 if (GraphBuffer
[i
-1] != GraphBuffer
[i
] && GraphBuffer
[i
] == peak
)
1941 /* Find lowest difference between peaks */
1942 if (lastpeak
&& i
- lastpeak
< clock
)
1944 clock
= i
- lastpeak
;
1953 /* Get or auto-detect clock rate */
1954 int GetClock(char *str
, int peak
)
1958 sscanf(str
, "%i", &clock
);
1959 if (!strcmp(str
, ""))
1962 /* Auto-detect clock */
1965 clock
= detectclock(peak
);
1967 /* Only print this message if we're not looping something */
1969 PrintToScrollback("Auto-detected clock rate: %d", clock
);
1976 * Convert to a bitstream
1978 static void Cmdbitstream(char *str
) {
1985 int hithigh
, hitlow
, first
;
1987 /* Detect high and lows and clock */
1988 for (i
= 0; i
< GraphTraceLen
; i
++)
1990 if (GraphBuffer
[i
] > high
)
1991 high
= GraphBuffer
[i
];
1992 else if (GraphBuffer
[i
] < low
)
1993 low
= GraphBuffer
[i
];
1997 clock
= GetClock(str
, high
);
1999 gtl
= CmdClearGraph(0);
2002 for (i
= 0; i
< (int)(gtl
/ clock
); i
++)
2008 /* Find out if we hit both high and low peaks */
2009 for (j
= 0; j
< clock
; j
++)
2011 if (GraphBuffer
[(i
* clock
) + j
] == high
)
2013 else if (GraphBuffer
[(i
* clock
) + j
] == low
)
2016 /* it doesn't count if it's the first part of our read
2017 because it's really just trailing from the last sequence */
2018 if (first
&& (hithigh
|| hitlow
))
2019 hithigh
= hitlow
= 0;
2023 if (hithigh
&& hitlow
)
2027 /* If we didn't hit both high and low peaks, we had a bit transition */
2028 if (!hithigh
|| !hitlow
)
2031 CmdAppendGraph(0, clock
, bit
);
2032 // for (j = 0; j < (int)(clock/2); j++)
2033 // GraphBuffer[(i * clock) + j] = bit ^ 1;
2034 // for (j = (int)(clock/2); j < clock; j++)
2035 // GraphBuffer[(i * clock) + j] = bit;
2038 RepaintGraphWindow();
2041 /* Modulate our data into manchester */
2042 static void Cmdmanchestermod(char *str
)
2046 int bit
, lastbit
, wave
;
2049 clock
= GetClock(str
, 0);
2053 for (i
= 0; i
< (int)(GraphTraceLen
/ clock
); i
++)
2055 bit
= GraphBuffer
[i
* clock
] ^ 1;
2057 for (j
= 0; j
< (int)(clock
/2); j
++)
2058 GraphBuffer
[(i
* clock
) + j
] = bit
^ lastbit
^ wave
;
2059 for (j
= (int)(clock
/2); j
< clock
; j
++)
2060 GraphBuffer
[(i
* clock
) + j
] = bit
^ lastbit
^ wave
^ 1;
2062 /* Keep track of how we start our wave and if we changed or not this time */
2063 wave
^= bit
^ lastbit
;
2067 RepaintGraphWindow();
2071 * Manchester demodulate a bitstream. The bitstream needs to be already in
2072 * the GraphBuffer as 0 and 1 values
2074 * Give the clock rate as argument in order to help the sync - the algorithm
2075 * resyncs at each pulse anyway.
2077 * Not optimized by any means, this is the 1st time I'm writing this type of
2078 * routine, feel free to improve...
2080 * 1st argument: clock rate (as number of samples per clock rate)
2081 * Typical values can be 64, 32, 128...
2083 static void Cmdmanchesterdemod(char *str
) {
2090 int hithigh
, hitlow
, first
;
2096 /* Holds the decoded bitstream: each clock period contains 2 bits */
2097 /* later simplified to 1 bit after manchester decoding. */
2098 /* Add 10 bits to allow for noisy / uncertain traces without aborting */
2099 /* int BitStream[GraphTraceLen*2/clock+10]; */
2101 /* But it does not work if compiling on WIndows: therefore we just allocate a */
2103 int BitStream
[MAX_GRAPH_TRACE_LEN
];
2105 /* Detect high and lows */
2106 for (i
= 0; i
< GraphTraceLen
; i
++)
2108 if (GraphBuffer
[i
] > high
)
2109 high
= GraphBuffer
[i
];
2110 else if (GraphBuffer
[i
] < low
)
2111 low
= GraphBuffer
[i
];
2115 clock
= GetClock(str
, high
);
2117 int tolerance
= clock
/4;
2119 /* Detect first transition */
2120 /* Lo-Hi (arbitrary) */
2121 for (i
= 0; i
< GraphTraceLen
; i
++)
2123 if (GraphBuffer
[i
] == low
)
2130 /* If we're not working with 1/0s, demod based off clock */
2133 bit
= 0; /* We assume the 1st bit is zero, it may not be
2134 * the case: this routine (I think) has an init problem.
2137 for (; i
< (int)(GraphTraceLen
/ clock
); i
++)
2143 /* Find out if we hit both high and low peaks */
2144 for (j
= 0; j
< clock
; j
++)
2146 if (GraphBuffer
[(i
* clock
) + j
] == high
)
2148 else if (GraphBuffer
[(i
* clock
) + j
] == low
)
2151 /* it doesn't count if it's the first part of our read
2152 because it's really just trailing from the last sequence */
2153 if (first
&& (hithigh
|| hitlow
))
2154 hithigh
= hitlow
= 0;
2158 if (hithigh
&& hitlow
)
2162 /* If we didn't hit both high and low peaks, we had a bit transition */
2163 if (!hithigh
|| !hitlow
)
2166 BitStream
[bit2idx
++] = bit
;
2170 /* standard 1/0 bitstream */
2174 /* Then detect duration between 2 successive transitions */
2175 for (bitidx
= 1; i
< GraphTraceLen
; i
++)
2177 if (GraphBuffer
[i
-1] != GraphBuffer
[i
])
2182 // Error check: if bitidx becomes too large, we do not
2183 // have a Manchester encoded bitstream or the clock is really
2185 if (bitidx
> (GraphTraceLen
*2/clock
+8) ) {
2186 PrintToScrollback("Error: the clock you gave is probably wrong, aborting.");
2189 // Then switch depending on lc length:
2190 // Tolerance is 1/4 of clock rate (arbitrary)
2191 if (abs(lc
-clock
/2) < tolerance
) {
2192 // Short pulse : either "1" or "0"
2193 BitStream
[bitidx
++]=GraphBuffer
[i
-1];
2194 } else if (abs(lc
-clock
) < tolerance
) {
2195 // Long pulse: either "11" or "00"
2196 BitStream
[bitidx
++]=GraphBuffer
[i
-1];
2197 BitStream
[bitidx
++]=GraphBuffer
[i
-1];
2201 PrintToScrollback("Warning: Manchester decode error for pulse width detection.");
2202 PrintToScrollback("(too many of those messages mean either the stream is not Manchester encoded, or clock is wrong)");
2206 PrintToScrollback("Error: too many detection errors, aborting.");
2213 // At this stage, we now have a bitstream of "01" ("1") or "10" ("0"), parse it into final decoded bitstream
2214 // Actually, we overwrite BitStream with the new decoded bitstream, we just need to be careful
2215 // to stop output at the final bitidx2 value, not bitidx
2216 for (i
= 0; i
< bitidx
; i
+= 2) {
2217 if ((BitStream
[i
] == 0) && (BitStream
[i
+1] == 1)) {
2218 BitStream
[bit2idx
++] = 1;
2219 } else if ((BitStream
[i
] == 1) && (BitStream
[i
+1] == 0)) {
2220 BitStream
[bit2idx
++] = 0;
2222 // We cannot end up in this state, this means we are unsynchronized,
2226 PrintToScrollback("Unsynchronized, resync...");
2227 PrintToScrollback("(too many of those messages mean the stream is not Manchester encoded)");
2231 PrintToScrollback("Error: too many decode errors, aborting.");
2238 PrintToScrollback("Manchester decoded bitstream");
2239 // Now output the bitstream to the scrollback by line of 16 bits
2240 for (i
= 0; i
< (bit2idx
-16); i
+=16) {
2241 PrintToScrollback("%i %i %i %i %i %i %i %i %i %i %i %i %i %i %i %i",
2266 static void CmdHiddemod(char *str
)
2268 if(GraphTraceLen
< 4800) {
2269 PrintToScrollback("too short; need at least 4800 samples");
2273 GraphTraceLen
= 4800;
2275 for(i
= 0; i
< GraphTraceLen
; i
++) {
2276 if(GraphBuffer
[i
] < 0) {
2282 RepaintGraphWindow();
2285 static void CmdPlot(char *str
)
2290 static void CmdHide(char *str
)
2295 static void CmdScale(char *str
)
2297 CursorScaleFactor
= atoi(str
);
2298 if(CursorScaleFactor
== 0) {
2299 PrintToScrollback("bad, can't have zero scale");
2300 CursorScaleFactor
= 1;
2302 RepaintGraphWindow();
2305 static void CmdSave(char *str
)
2307 FILE *f
= fopen(str
, "w");
2309 PrintToScrollback("couldn't open '%s'", str
);
2313 for(i
= 0; i
< GraphTraceLen
; i
++) {
2314 fprintf(f
, "%d\n", GraphBuffer
[i
]);
2317 PrintToScrollback("saved to '%s'", str
);
2320 static void CmdLoad(char *str
)
2322 FILE *f
= fopen(str
, "r");
2324 PrintToScrollback("couldn't open '%s'", str
);
2330 while(fgets(line
, sizeof(line
), f
)) {
2331 GraphBuffer
[GraphTraceLen
] = atoi(line
);
2335 PrintToScrollback("loaded %d samples", GraphTraceLen
);
2336 RepaintGraphWindow();
2339 static void CmdHIDsimTAG(char *str
)
2341 unsigned int hi
=0, lo
=0;
2345 while (sscanf(&str
[i
++], "%1x", &n
) == 1) {
2346 hi
=(hi
<<4)|(lo
>>28);
2350 PrintToScrollback("Emulating tag with ID %x%16x", hi
, lo
);
2352 c
.cmd
= CMD_HID_SIM_TAG
;
2355 SendCommand(&c
, FALSE
);
2358 static void CmdLcdReset(char *str
)
2361 c
.cmd
= CMD_LCD_RESET
;
2363 SendCommand(&c
, FALSE
);
2366 static void CmdLcd(char *str
)
2371 sscanf(str
, "%x %d", &i
, &j
);
2374 SendCommand(&c
, FALSE
);
2380 static void CmdTest(char *str
)
2385 * Sets the divisor for LF frequency clock: lets the user choose any LF frequency below
2388 static void CmdSetDivisor(char *str
)
2391 c
.cmd
= CMD_SET_LF_DIVISOR
;
2393 if (( c
.ext1
<0) || (c
.ext1
>255)) {
2394 PrintToScrollback("divisor must be between 19 and 255");
2396 SendCommand(&c
, FALSE
);
2397 PrintToScrollback("Divisor set, expected freq=%dHz", 12000000/(c
.ext1
+1));
2401 static void CmdSweepLF(char *str
)
2404 c
.cmd
= CMD_SWEEP_LF
;
2405 SendCommand(&c
, FALSE
);
2409 typedef void HandlerFunction(char *cmdline
);
2411 /* in alphabetic order */
2414 HandlerFunction
*handler
;
2415 int offline
; // 1 if the command can be used when in offline mode
2417 } CommandTable
[] = {
2418 "askdemod", Cmdaskdemod
,1, "<samples per bit> <0|1> -- Attempt to demodulate simple ASK tags",
2419 "autocorr", CmdAutoCorr
,1, "<window length> -- Autocorrelation over window",
2420 "bitsamples", CmdBitsamples
,0, " Get raw samples as bitstring",
2421 "bitstream", Cmdbitstream
,1, "[clock rate] -- Convert waveform into a bitstream",
2422 "buffclear", CmdBuffClear
,0, " Clear sample buffer and graph window",
2423 "dec", CmdDec
,1, " Decimate samples",
2424 "detectclock", Cmddetectclockrate
,1, " Detect clock rate",
2425 "em410xsim", CmdEM410xsim
,1, "<UID> -- Simulate EM410x tag",
2426 "em410xread", CmdEM410xread
,1, "[clock rate] -- Extract ID from EM410x tag",
2427 "em410xwatch", CmdEM410xwatch
,0, " Watches for EM410x tags",
2428 "exit", CmdQuit
,1, " Exit program",
2429 "flexdemod", CmdFlexdemod
,1, " Demodulate samples for FlexPass",
2430 "fpgaoff", CmdFPGAOff
,0, " Set FPGA off", // ## FPGA Control
2431 "hexsamples", CmdHexsamples
,0, "<blocks> -- Dump big buffer as hex bytes",
2432 "hi14alist", CmdHi14alist
,0, " List ISO 14443a history", // ## New list command
2433 "hi14areader", CmdHi14areader
,0, " Act like an ISO14443 Type A reader", // ## New reader command
2434 "hi14asim", CmdHi14asim
,0, "<UID> -- Fake ISO 14443a tag", // ## Simulate 14443a tag
2435 "hi14asnoop", CmdHi14asnoop
,0, " Eavesdrop ISO 14443 Type A", // ## New snoop command
2436 "hi14bdemod", CmdHi14bdemod
,1, " Demodulate ISO14443 Type B from tag",
2437 "hi14list", CmdHi14list
,0, " List ISO 14443 history",
2438 "hi14read", CmdHi14read
,0, " Read HF tag (ISO 14443)",
2439 "hi14sim", CmdHi14sim
,0, " Fake ISO 14443 tag",
2440 "hi14snoop", CmdHi14snoop
,0, " Eavesdrop ISO 14443",
2441 "hi15demod", CmdHi15demod
,1, " Demodulate ISO15693 from tag",
2442 "hi15read", CmdHi15read
,0, " Read HF tag (ISO 15693)",
2443 "hi15reader", CmdHi15reader
,0, " Act like an ISO15693 reader", // new command greg
2444 "hi15sim", CmdHi15tag
,0, " Fake an ISO15693 tag", // new command greg
2445 "hiddemod", CmdHiddemod
,1, " Demodulate HID Prox Card II (not optimal)",
2446 "hide", CmdHide
,1, " Hide graph window",
2447 "hidfskdemod", CmdHIDdemodFSK
,0, " Realtime HID FSK demodulator",
2448 "hidsimtag", CmdHIDsimTAG
,0, "<ID> -- HID tag simulator",
2449 "higet", CmdHi14read_sim
,0, "<samples> -- Get samples HF, 'analog'",
2450 "hisamples", CmdHisamples
,0, " Get raw samples for HF tag",
2451 "hisampless", CmdHisampless
,0, "<samples> -- Get signed raw samples, HF tag",
2452 "hisamplest", CmdHi14readt
,0, " Get samples HF, for testing",
2453 "hisimlisten", CmdHisimlisten
,0, " Get HF samples as fake tag",
2454 "hpf", CmdHpf
,1, " Remove DC offset from trace",
2455 "indalademod", CmdIndalademod
,0, "['224'] -- Demodulate samples for Indala",
2456 "lcd", CmdLcd
,0, "<HEX command> <count> -- Send command/data to LCD",
2457 "lcdreset", CmdLcdReset
,0, " Hardware reset LCD",
2458 "load", CmdLoad
,1, "<filename> -- Load trace (to graph window",
2459 "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)",
2460 "loread", CmdLoread
,0, "['h'] -- Read 125/134 kHz LF ID-only tag (option 'h' for 134)",
2461 "losamples", CmdLosamples
,0, "[128 - 16000] -- Get raw samples for LF tag",
2462 "losim", CmdLosim
,0, " Simulate LF tag",
2463 "ltrim", CmdLtrim
,1, "<samples> -- Trim samples from left of trace",
2464 "mandemod", Cmdmanchesterdemod
,1, "[clock rate] -- Try a Manchester demodulation on a binary stream",
2465 "manmod", Cmdmanchestermod
,1, "[clock rate] -- Manchester modulate a binary stream",
2466 "norm", CmdNorm
,1, " Normalize max/min to +/-500",
2467 "plot", CmdPlot
,1, " Show graph window",
2468 "quit", CmdQuit
,1, " Quit program",
2469 "reset", CmdReset
,0, " Reset the Proxmark3",
2470 "save", CmdSave
,1, "<filename> -- Save trace (from graph window)",
2471 "scale", CmdScale
,1, "<int> -- Set cursor display scale",
2472 "setlfdivisor", CmdSetDivisor
,0, "<19 - 255> -- Drive LF antenna at 12Mhz/(divisor+1)",
2473 "sri512read", CmdSri512read
,0, "<int> -- Read contents of a SRI512 tag",
2474 "sweeplf", CmdSweepLF
,0, " Sweep through LF freq range and store results in buffer",
2475 "tibits", CmdTibits
,0, " Get raw bits for TI-type LF tag",
2476 "tidemod", CmdTidemod
,0, " Demodulate raw bits for TI-type LF tag",
2477 "tiread", CmdTiread
,0, " Read a TI-type 134 kHz tag",
2478 "tune", CmdTune
,0, " Measure antenna tuning",
2479 "vchdemod", CmdVchdemod
,0, "['clone'] -- Demodulate samples for VeriChip",
2480 "zerocrossings", CmdZerocrossings
,1, " Count time between zero-crossings",
2484 //-----------------------------------------------------------------------------
2485 // Entry point into our code: called whenever the user types a command and
2486 // then presses Enter, which the full command line that they typed.
2487 //-----------------------------------------------------------------------------
2488 void CommandReceived(char *cmd
)
2492 PrintToScrollback("> %s", cmd
);
2494 if(strcmp(cmd
, "help")==0) {
2495 if (offline
) PrintToScrollback("Operating in OFFLINE mode (no device connected)");
2496 PrintToScrollback("\r\nAvailable commands:");
2497 for(i
= 0; i
< sizeof(CommandTable
) / sizeof(CommandTable
[0]); i
++) {
2498 if (offline
&& (CommandTable
[i
].offline
==0)) continue;
2500 memset(line
, ' ', sizeof(line
));
2501 strcpy(line
+2, CommandTable
[i
].name
);
2502 line
[strlen(line
)] = ' ';
2503 sprintf(line
+15, " -- %s", CommandTable
[i
].docString
);
2504 PrintToScrollback("%s", line
);
2506 PrintToScrollback("");
2507 PrintToScrollback("and also: help, cls");
2511 for(i
= 0; i
< sizeof(CommandTable
) / sizeof(CommandTable
[0]); i
++) {
2512 char *name
= CommandTable
[i
].name
;
2513 if(memcmp(cmd
, name
, strlen(name
))==0 &&
2514 (cmd
[strlen(name
)] == ' ' || cmd
[strlen(name
)] == '\0'))
2516 cmd
+= strlen(name
);
2517 while(*cmd
== ' ') {
2520 if (offline
&& (CommandTable
[i
].offline
==0)) {
2521 PrintToScrollback("Offline mode, cannot use this command.");
2524 (CommandTable
[i
].handler
)(cmd
);
2528 PrintToScrollback(">> bad command '%s'", cmd
);
2531 //-----------------------------------------------------------------------------
2532 // Entry point into our code: called whenever we received a packet over USB
2533 // that we weren't necessarily expecting, for example a debug print.
2534 //-----------------------------------------------------------------------------
2535 void UsbCommandReceived(UsbCommand
*c
)
2538 case CMD_DEBUG_PRINT_STRING
: {
2540 if(c
->ext1
> 70 || c
->ext1
< 0) {
2543 memcpy(s
, c
->d
.asBytes
, c
->ext1
);
2545 PrintToScrollback("#db# %s", s
);
2549 case CMD_DEBUG_PRINT_INTEGERS
:
2550 PrintToScrollback("#db# %08x, %08x, %08x\r\n", c
->ext1
, c
->ext2
, c
->ext3
);
2553 case CMD_MEASURED_ANTENNA_TUNING
: {
2555 int vLf125
, vLf134
, vHf
;
2556 vLf125
= c
->ext1
& 0xffff;
2557 vLf134
= c
->ext1
>> 16;
2559 zLf
= c
->ext3
& 0xffff;
2560 zHf
= c
->ext3
>> 16;
2561 PrintToScrollback("# LF antenna @ %3d mA / %5d mV [%d ohms] 125Khz",
2562 vLf125
/zLf
, vLf125
, zLf
);
2563 PrintToScrollback("# LF antenna @ %3d mA / %5d mV [%d ohms] 134Khz",
2564 vLf134
/((zLf
*125)/134), vLf134
, (zLf
*125)/134);
2565 PrintToScrollback("# HF antenna @ %3d mA / %5d mV [%d ohms] 13.56Mhz",
2570 PrintToScrollback("unrecognized command %08x\n", c
->cmd
);