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
);
56 static void CmdQuit(char *str
)
61 static void CmdHIDdemodFSK(char *str
)
64 c
.cmd
= CMD_HID_DEMOD_FSK
;
65 SendCommand(&c
, FALSE
);
68 static void CmdTune(char *str
)
71 c
.cmd
= CMD_MEASURE_ANTENNA_TUNING
;
72 SendCommand(&c
, FALSE
);
75 static void CmdHi15read(char *str
)
78 c
.cmd
= CMD_ACQUIRE_RAW_ADC_SAMPLES_ISO_15693
;
79 SendCommand(&c
, FALSE
);
82 static void CmdHi14read(char *str
)
85 c
.cmd
= CMD_ACQUIRE_RAW_ADC_SAMPLES_ISO_14443
;
87 SendCommand(&c
, FALSE
);
91 /* New command to read the contents of a SRI512 tag
92 * SRI512 tags are ISO14443-B modulated memory tags,
93 * this command just dumps the contents of the memory/
95 static void CmdSri512read(char *str
)
98 c
.cmd
= CMD_READ_SRI512_TAG
;
100 SendCommand(&c
, FALSE
);
104 static void CmdHi14areader(char *str
)
107 c
.cmd
= CMD_READER_ISO_14443a
;
109 SendCommand(&c
, FALSE
);
113 static void CmdHi15reader(char *str
)
116 c
.cmd
= CMD_READER_ISO_15693
;
118 SendCommand(&c
, FALSE
);
122 static void CmdHi15tag(char *str
)
125 c
.cmd
= CMD_SIMTAG_ISO_15693
;
127 SendCommand(&c
, FALSE
);
130 static void CmdHi14read_sim(char *str
)
133 c
.cmd
= CMD_ACQUIRE_RAW_ADC_SAMPLES_ISO_14443_SIM
;
135 SendCommand(&c
, FALSE
);
138 static void CmdHi14readt(char *str
)
141 c
.cmd
= CMD_ACQUIRE_RAW_ADC_SAMPLES_ISO_14443
;
143 SendCommand(&c
, FALSE
);
145 //CmdHisamplest(str);
146 while(CmdHisamplest(str
,atoi(str
))==0) {
147 c
.cmd
= CMD_ACQUIRE_RAW_ADC_SAMPLES_ISO_14443
;
149 SendCommand(&c
, FALSE
);
151 RepaintGraphWindow();
154 static void CmdHisimlisten(char *str
)
157 c
.cmd
= CMD_SIMULATE_TAG_HF_LISTEN
;
158 SendCommand(&c
, FALSE
);
161 static void CmdHi14sim(char *str
)
164 c
.cmd
= CMD_SIMULATE_TAG_ISO_14443
;
165 SendCommand(&c
, FALSE
);
168 static void CmdHi14asim(char *str
) // ## simulate iso14443a tag
169 { // ## greg - added ability to specify tag UID
171 unsigned int hi
=0, lo
=0;
175 while (sscanf(&str
[i
++], "%1x", &n
) == 1) {
180 c
.cmd
= CMD_SIMULATE_TAG_ISO_14443a
;
181 // c.ext should be set to *str or convert *str to the correct format for a uid
184 PrintToScrollback("Emulating 14443A TAG with UID %x%16x", hi
, lo
);
185 SendCommand(&c
, FALSE
);
188 static void CmdHi14snoop(char *str
)
191 c
.cmd
= CMD_SNOOP_ISO_14443
;
192 SendCommand(&c
, FALSE
);
195 static void CmdHi14asnoop(char *str
)
198 c
.cmd
= CMD_SNOOP_ISO_14443a
;
199 SendCommand(&c
, FALSE
);
202 static void CmdFPGAOff(char *str
) // ## FPGA Control
205 c
.cmd
= CMD_FPGA_MAJOR_MODE_OFF
;
206 SendCommand(&c
, FALSE
);
209 /* clear out our graph window */
210 int CmdClearGraph(int redraw
)
212 int gtl
= GraphTraceLen
;
216 RepaintGraphWindow();
221 /* write a bit to the graph */
222 static void CmdAppendGraph(int redraw
, int clock
, int bit
)
226 for (i
= 0; i
< (int)(clock
/2); i
++)
227 GraphBuffer
[GraphTraceLen
++] = bit
^ 1;
229 for (i
= (int)(clock
/2); i
< clock
; i
++)
230 GraphBuffer
[GraphTraceLen
++] = bit
;
233 RepaintGraphWindow();
236 /* Function is equivalent of loread + losamples + em410xread
237 * looped until an EM410x tag is detected */
238 static void CmdEM410xwatch(char *str
)
252 /* Read the ID of an EM410x tag.
254 * 1111 1111 1 <-- standard non-repeatable header
255 * XXXX [row parity bit] <-- 10 rows of 5 bits for our 40 bit tag ID
257 * CCCC <-- each bit here is parity for the 10 bits above in corresponding column
258 * 0 <-- stop bit, end of tag
260 static void CmdEM410xread(char *str
)
262 int i
, j
, clock
, header
, rows
, bit
, hithigh
, hitlow
, first
, bit2idx
, high
, low
;
266 int BitStream
[MAX_GRAPH_TRACE_LEN
];
269 /* Detect high and lows and clock */
270 for (i
= 0; i
< GraphTraceLen
; i
++)
272 if (GraphBuffer
[i
] > high
)
273 high
= GraphBuffer
[i
];
274 else if (GraphBuffer
[i
] < low
)
275 low
= GraphBuffer
[i
];
279 clock
= GetClock(str
, high
);
281 /* parity for our 4 columns */
282 parity
[0] = parity
[1] = parity
[2] = parity
[3] = 0;
285 /* manchester demodulate */
287 for (i
= 0; i
< (int)(GraphTraceLen
/ clock
); i
++)
293 /* Find out if we hit both high and low peaks */
294 for (j
= 0; j
< clock
; j
++)
296 if (GraphBuffer
[(i
* clock
) + j
] == high
)
298 else if (GraphBuffer
[(i
* clock
) + j
] == low
)
301 /* it doesn't count if it's the first part of our read
302 because it's really just trailing from the last sequence */
303 if (first
&& (hithigh
|| hitlow
))
304 hithigh
= hitlow
= 0;
308 if (hithigh
&& hitlow
)
312 /* If we didn't hit both high and low peaks, we had a bit transition */
313 if (!hithigh
|| !hitlow
)
316 BitStream
[bit2idx
++] = bit
;
320 /* We go till 5 before the graph ends because we'll get that far below */
321 for (i
= 1; i
< bit2idx
- 5; i
++)
323 /* Step 2: We have our header but need our tag ID */
324 if (header
== 9 && rows
< 10)
326 /* Confirm parity is correct */
327 if ((BitStream
[i
] ^ BitStream
[i
+1] ^ BitStream
[i
+2] ^ BitStream
[i
+3]) == BitStream
[i
+4])
329 /* Read another byte! */
330 sprintf(id
+rows
, "%x", (8 * BitStream
[i
]) + (4 * BitStream
[i
+1]) + (2 * BitStream
[i
+2]) + (1 * BitStream
[i
+3]));
333 /* Keep parity info */
334 parity
[0] ^= BitStream
[i
];
335 parity
[1] ^= BitStream
[i
+1];
336 parity
[2] ^= BitStream
[i
+2];
337 parity
[3] ^= BitStream
[i
+3];
339 /* Move 4 bits ahead */
343 /* Damn, something wrong! reset */
346 PrintToScrollback("Thought we had a valid tag but failed at word %d (i=%d)", rows
+ 1, i
);
348 /* Start back rows * 5 + 9 header bits, -1 to not start at same place */
349 i
-= 9 + (5 * rows
) - 5;
355 /* Step 3: Got our 40 bits! confirm column parity */
358 /* We need to make sure our 4 bits of parity are correct and we have a stop bit */
359 if (BitStream
[i
] == parity
[0] && BitStream
[i
+1] == parity
[1] &&
360 BitStream
[i
+2] == parity
[2] && BitStream
[i
+3] == parity
[3] &&
364 PrintToScrollback("EM410x Tag ID: %s", id
);
371 /* Crap! Incorrect parity or no stop bit, start all over */
376 /* Go back 59 bits (9 header bits + 10 rows at 4+1 parity) */
381 /* Step 1: get our header */
384 /* Need 9 consecutive 1's */
385 if (BitStream
[i
] == 1)
388 /* We don't have a header, not enough consecutive 1 bits */
394 /* if we've already retested after flipping bits, return */
398 /* if this didn't work, try flipping bits */
399 for (i
= 0; i
< bit2idx
; i
++)
405 /* emulate an EM410X tag
407 * 1111 1111 1 <-- standard non-repeatable header
408 * XXXX [row parity bit] <-- 10 rows of 5 bits for our 40 bit tag ID
410 * CCCC <-- each bit here is parity for the 10 bits above in corresponding column
411 * 0 <-- stop bit, end of tag
413 static void CmdEM410xsim(char *str
)
415 int i
, n
, j
, h
, binary
[4], parity
[4];
418 /* clock is 64 in EM410x tags */
421 /* clear our graph */
424 /* write it out a few times */
425 for (h
= 0; h
< 4; h
++)
427 /* write 9 start bits */
428 for (i
= 0; i
< 9; i
++)
429 CmdAppendGraph(0, clock
, 1);
431 /* for each hex char */
432 parity
[0] = parity
[1] = parity
[2] = parity
[3] = 0;
433 for (i
= 0; i
< 10; i
++)
435 /* read each hex char */
436 sscanf(&str
[i
], "%1x", &n
);
437 for (j
= 3; j
>= 0; j
--, n
/= 2)
440 /* append each bit */
441 CmdAppendGraph(0, clock
, binary
[0]);
442 CmdAppendGraph(0, clock
, binary
[1]);
443 CmdAppendGraph(0, clock
, binary
[2]);
444 CmdAppendGraph(0, clock
, binary
[3]);
446 /* append parity bit */
447 CmdAppendGraph(0, clock
, binary
[0] ^ binary
[1] ^ binary
[2] ^ binary
[3]);
449 /* keep track of column parity */
450 parity
[0] ^= binary
[0];
451 parity
[1] ^= binary
[1];
452 parity
[2] ^= binary
[2];
453 parity
[3] ^= binary
[3];
457 CmdAppendGraph(0, clock
, parity
[0]);
458 CmdAppendGraph(0, clock
, parity
[1]);
459 CmdAppendGraph(0, clock
, parity
[2]);
460 CmdAppendGraph(0, clock
, parity
[3]);
463 CmdAppendGraph(0, clock
, 0);
466 /* modulate that biatch */
470 RepaintGraphWindow();
475 static void ChkBitstream(char *str
)
479 /* convert to bitstream if necessary */
480 for (i
= 0; i
< (int)(GraphTraceLen
/ 2); i
++)
482 if (GraphBuffer
[i
] > 1 || GraphBuffer
[i
] < 0)
490 static void CmdLosim(char *str
)
495 /* convert to bitstream if necessary */
498 for (i
= 0; i
< GraphTraceLen
; i
+= 48) {
501 for(j
= 0; j
< 48; j
++) {
502 c
.d
.asBytes
[j
] = GraphBuffer
[i
+j
];
504 c
.cmd
= CMD_DOWNLOADED_SIM_SAMPLES_125K
;
506 SendCommand(&c
, FALSE
);
510 c
.cmd
= CMD_SIMULATE_TAG_125K
;
511 c
.ext1
= GraphTraceLen
;
512 SendCommand(&c
, FALSE
);
515 static void CmdLoread(char *str
)
518 // 'h' means higher-low-frequency, 134 kHz
521 } else if (*str
== '\0') {
524 PrintToScrollback("use 'loread' or 'loread h'");
527 c
.cmd
= CMD_ACQUIRE_RAW_ADC_SAMPLES_125K
;
528 SendCommand(&c
, FALSE
);
531 static void CmdLosamples(char *str
)
539 if (n
>16000) n
=16000;
541 for(i
= 0; i
< n
; i
+= 12) {
543 c
.cmd
= CMD_DOWNLOAD_RAW_ADC_SAMPLES_125K
;
545 SendCommand(&c
, FALSE
);
547 if(c
.cmd
!= CMD_DOWNLOADED_RAW_ADC_SAMPLES_125K
) {
549 PrintToScrollback("bad resp");
553 for(j
= 0; j
< 48; j
++) {
554 GraphBuffer
[cnt
++] = ((int)c
.d
.asBytes
[j
]) - 128;
558 RepaintGraphWindow();
561 static void CmdBitsamples(char *str
)
568 for(i
= 0; i
< n
; i
+= 12) {
570 c
.cmd
= CMD_DOWNLOAD_RAW_ADC_SAMPLES_125K
;
572 SendCommand(&c
, FALSE
);
574 if(c
.cmd
!= CMD_DOWNLOADED_RAW_ADC_SAMPLES_125K
) {
575 PrintToScrollback("bad resp");
579 for(j
= 0; j
< 48; j
++) {
580 for(k
= 0; k
< 8; k
++) {
581 if(c
.d
.asBytes
[j
] & (1 << (7 - k
))) {
582 GraphBuffer
[cnt
++] = 1;
584 GraphBuffer
[cnt
++] = 0;
590 RepaintGraphWindow();
593 static void CmdHisamples(char *str
)
599 for(i
= 0; i
< n
; i
+= 12) {
601 c
.cmd
= CMD_DOWNLOAD_RAW_ADC_SAMPLES_125K
;
603 SendCommand(&c
, FALSE
);
605 if(c
.cmd
!= CMD_DOWNLOADED_RAW_ADC_SAMPLES_125K
) {
606 PrintToScrollback("bad resp");
610 for(j
= 0; j
< 48; j
++) {
611 GraphBuffer
[cnt
++] = (int)((BYTE
)c
.d
.asBytes
[j
]);
616 RepaintGraphWindow();
620 static int CmdHisamplest(char *str
, int nrlow
)
632 for(i
= 0; i
< n
; i
+= 12) {
634 c
.cmd
= CMD_DOWNLOAD_RAW_ADC_SAMPLES_125K
;
636 SendCommand(&c
, FALSE
);
638 if(c
.cmd
!= CMD_DOWNLOADED_RAW_ADC_SAMPLES_125K
) {
639 PrintToScrollback("bad resp");
643 for(j
= 0; j
< 48; j
++) {
644 t2
= (int)((BYTE
)c
.d
.asBytes
[j
]);
645 if((t2
^ 0xC0) & 0xC0) { hasbeennull
++; }
651 t1
= (t2
& 0x80) ^ (t2
& 0x20);
652 t2
= ((t2
<< 1) & 0x80) ^ ((t2
<< 1) & 0x20);
658 t2
= ((t2
<< 1) & 0x80);
664 t2
= ((t2
<< 1) & 0x20);
668 // both, but tag with other algorithm
669 t1
= (t2
& 0x80) ^ (t2
& 0x08);
670 t2
= ((t2
<< 1) & 0x80) ^ ((t2
<< 1) & 0x08);
674 GraphBuffer
[cnt
++] = t1
;
675 GraphBuffer
[cnt
++] = t2
;
680 if(hasbeennull
>nrlow
|| nrlow
==0) {
681 PrintToScrollback("hasbeennull=%d", hasbeennull
);
690 static void CmdHexsamples(char *str
)
701 for(i
= 0; i
< n
; i
+= 12) {
703 c
.cmd
= CMD_DOWNLOAD_RAW_ADC_SAMPLES_125K
;
705 SendCommand(&c
, FALSE
);
707 if(c
.cmd
!= CMD_DOWNLOADED_RAW_ADC_SAMPLES_125K
) {
708 PrintToScrollback("bad resp");
712 for(j
= 0; j
< 48; j
+= 8) {
713 PrintToScrollback("%02x %02x %02x %02x %02x %02x %02x %02x",
728 static void CmdHisampless(char *str
)
740 for(i
= 0; i
< n
; i
+= 12) {
742 c
.cmd
= CMD_DOWNLOAD_RAW_ADC_SAMPLES_125K
;
744 SendCommand(&c
, FALSE
);
746 if(c
.cmd
!= CMD_DOWNLOADED_RAW_ADC_SAMPLES_125K
) {
747 PrintToScrollback("bad resp");
751 for(j
= 0; j
< 48; j
++) {
752 GraphBuffer
[cnt
++] = (int)((signed char)c
.d
.asBytes
[j
]);
757 RepaintGraphWindow();
760 static WORD
Iso15693Crc(BYTE
*v
, int n
)
766 for(i
= 0; i
< n
; i
++) {
767 reg
= reg
^ ((DWORD
)v
[i
]);
768 for (j
= 0; j
< 8; j
++) {
770 reg
= (reg
>> 1) ^ 0x8408;
780 static void CmdHi14bdemod(char *str
)
785 BOOL negateI
, negateQ
;
790 // As received, the samples are pairs, correlations against I and Q
791 // square waves. So estimate angle of initial carrier (or just
792 // quadrant, actually), and then do the demod.
794 // First, estimate where the tag starts modulating.
795 for(i
= 0; i
< GraphTraceLen
; i
+= 2) {
796 if(abs(GraphBuffer
[i
]) + abs(GraphBuffer
[i
+1]) > 40) {
800 if(i
>= GraphTraceLen
) {
801 PrintToScrollback("too weak to sync");
804 PrintToScrollback("out of weak at %d", i
);
807 // Now, estimate the phase in the initial modulation of the tag
810 for(; i
< (outOfWeakAt
+ 16); i
+= 2) {
811 isum
+= GraphBuffer
[i
+0];
812 qsum
+= GraphBuffer
[i
+1];
814 negateI
= (isum
< 0);
815 negateQ
= (qsum
< 0);
817 // Turn the correlation pairs into soft decisions on the bit.
819 for(i
= 0; i
< GraphTraceLen
/2; i
++) {
820 int si
= GraphBuffer
[j
];
821 int sq
= GraphBuffer
[j
+1];
822 if(negateI
) si
= -si
;
823 if(negateQ
) sq
= -sq
;
824 GraphBuffer
[i
] = si
+ sq
;
830 while(GraphBuffer
[i
] > 0 && i
< GraphTraceLen
)
832 if(i
>= GraphTraceLen
) goto demodError
;
835 while(GraphBuffer
[i
] < 0 && i
< GraphTraceLen
)
837 if(i
>= GraphTraceLen
) goto demodError
;
838 if((i
- iold
) > 23) goto demodError
;
840 PrintToScrollback("make it to demod loop");
844 while(GraphBuffer
[i
] >= 0 && i
< GraphTraceLen
)
846 if(i
>= GraphTraceLen
) goto demodError
;
847 if((i
- iold
) > 6) goto demodError
;
850 if(i
+ 20 >= GraphTraceLen
) goto demodError
;
852 for(j
= 0; j
< 10; j
++) {
853 int soft
= GraphBuffer
[i
] + GraphBuffer
[i
+1];
855 if(abs(soft
) < ((abs(isum
) + abs(qsum
))/20)) {
856 PrintToScrollback("weak bit");
860 if(GraphBuffer
[i
] + GraphBuffer
[i
+1] >= 0) {
867 if( (shiftReg
& 0x200) &&
870 // valid data byte, start and stop bits okay
871 PrintToScrollback(" %02x", (shiftReg
>> 1) & 0xff);
872 data
[dataLen
++] = (shiftReg
>> 1) & 0xff;
873 if(dataLen
>= sizeof(data
)) {
876 } else if(shiftReg
== 0x000) {
885 ComputeCrc14443(CRC_14443_B
, data
, dataLen
-2, &first
, &second
);
886 PrintToScrollback("CRC: %02x %02x (%s)\n", first
, second
,
887 (first
== data
[dataLen
-2] && second
== data
[dataLen
-1]) ?
888 "ok" : "****FAIL****");
890 RepaintGraphWindow();
894 PrintToScrollback("demod error");
895 RepaintGraphWindow();
898 static void CmdHi14list(char *str
)
901 GetFromBigBuf(got
, sizeof(got
));
903 PrintToScrollback("recorded activity:");
904 PrintToScrollback(" time :rssi: who bytes");
905 PrintToScrollback("---------+----+----+-----------");
916 int timestamp
= *((DWORD
*)(got
+i
));
917 if(timestamp
& 0x80000000) {
918 timestamp
&= 0x7fffffff;
923 int metric
= *((DWORD
*)(got
+i
+4));
934 BYTE
*frame
= (got
+i
+9);
936 char line
[1000] = "";
938 for(j
= 0; j
< len
; j
++) {
939 sprintf(line
+(j
*3), "%02x ", frame
[j
]);
945 ComputeCrc14443(CRC_14443_B
, frame
, len
-2, &b1
, &b2
);
946 if(b1
!= frame
[len
-2] || b2
!= frame
[len
-1]) {
947 crc
= "**FAIL CRC**";
955 char metricString
[100];
957 sprintf(metricString
, "%3d", metric
);
959 strcpy(metricString
, " ");
962 PrintToScrollback(" +%7d: %s: %s %s %s",
963 (prev
< 0 ? 0 : timestamp
- prev
),
965 (isResponse
? "TAG" : " "), line
, crc
);
972 static void CmdHi14alist(char *str
)
975 GetFromBigBuf(got
, sizeof(got
));
977 PrintToScrollback("recorded activity:");
978 PrintToScrollback(" ETU :rssi: who bytes");
979 PrintToScrollback("---------+----+----+-----------");
990 int timestamp
= *((DWORD
*)(got
+i
));
991 if(timestamp
& 0x80000000) {
992 timestamp
&= 0x7fffffff;
999 int parityBits
= *((DWORD
*)(got
+i
+4));
1000 // 4 bytes of additional information...
1001 // maximum of 32 additional parity bit information
1004 // at each quarter bit period we can send power level (16 levels)
1005 // or each half bit period in 256 levels.
1013 if(i
+ len
>= 1900) {
1017 BYTE
*frame
= (got
+i
+9);
1019 // Break and stick with current result if buffer was not completely full
1020 if(frame
[0] == 0x44 && frame
[1] == 0x44 && frame
[3] == 0x44) { break; }
1022 char line
[1000] = "";
1024 for(j
= 0; j
< len
; j
++) {
1025 int oddparity
= 0x01;
1029 oddparity
^= (((frame
[j
] & 0xFF) >> k
) & 0x01);
1032 //if((parityBits >> (len - j - 1)) & 0x01) {
1033 if(isResponse
&& (oddparity
!= ((parityBits
>> (len
- j
- 1)) & 0x01))) {
1034 sprintf(line
+(j
*4), "%02x! ", frame
[j
]);
1037 sprintf(line
+(j
*4), "%02x ", frame
[j
]);
1045 for(j
= 0; j
< (len
- 1); j
++) {
1046 // gives problems... search for the reason..
1047 /*if(frame[j] == 0xAA) {
1048 switch(frame[j+1]) {
1050 crc = "[1] Two drops close after each other";
1053 crc = "[2] Potential SOC with a drop in second half of bitperiod";
1056 crc = "[3] Segment Z after segment X is not possible";
1059 crc = "[4] Parity bit of a fully received byte was wrong";
1062 crc = "[?] Unknown error";
1069 if(strlen(crc
)==0) {
1070 ComputeCrc14443(CRC_14443_A
, frame
, len
-2, &b1
, &b2
);
1071 if(b1
!= frame
[len
-2] || b2
!= frame
[len
-1]) {
1072 crc
= (isResponse
& (len
< 6)) ? "" : " !crc";
1081 char metricString
[100];
1083 sprintf(metricString
, "%3d", metric
);
1085 strcpy(metricString
, " ");
1088 PrintToScrollback(" +%7d: %s: %s %s %s",
1089 (prev
< 0 ? 0 : (timestamp
- prev
)),
1091 (isResponse
? "TAG" : " "), line
, crc
);
1096 CommandFinished
= 1;
1099 static void CmdHi15demod(char *str
)
1101 // The sampling rate is 106.353 ksps/s, for T = 18.8 us
1104 // 1) Unmodulated time of 56.64us
1105 // 2) 24 pulses of 423.75khz
1106 // 3) logic '1' (unmodulated for 18.88us followed by 8 pulses of 423.75khz)
1108 static const int FrameSOF
[] = {
1109 -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
1110 -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
1111 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
1112 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
1118 static const int Logic0
[] = {
1124 static const int Logic1
[] = {
1132 // 1) logic '0' (8 pulses of 423.75khz followed by unmodulated for 18.88us)
1133 // 2) 24 pulses of 423.75khz
1134 // 3) Unmodulated time of 56.64us
1136 static const int FrameEOF
[] = {
1141 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
1142 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
1143 -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
1144 -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1
1148 int max
= 0, maxPos
;
1152 if(GraphTraceLen
< 1000) return;
1154 // First, correlate for SOF
1155 for(i
= 0; i
< 100; i
++) {
1157 for(j
= 0; j
< arraylen(FrameSOF
); j
+= skip
) {
1158 corr
+= FrameSOF
[j
]*GraphBuffer
[i
+(j
/skip
)];
1165 PrintToScrollback("SOF at %d, correlation %d", maxPos
,
1166 max
/(arraylen(FrameSOF
)/skip
));
1168 i
= maxPos
+ arraylen(FrameSOF
)/skip
;
1171 memset(outBuf
, 0, sizeof(outBuf
));
1174 int corr0
= 0, corr1
= 0, corrEOF
= 0;
1175 for(j
= 0; j
< arraylen(Logic0
); j
+= skip
) {
1176 corr0
+= Logic0
[j
]*GraphBuffer
[i
+(j
/skip
)];
1178 for(j
= 0; j
< arraylen(Logic1
); j
+= skip
) {
1179 corr1
+= Logic1
[j
]*GraphBuffer
[i
+(j
/skip
)];
1181 for(j
= 0; j
< arraylen(FrameEOF
); j
+= skip
) {
1182 corrEOF
+= FrameEOF
[j
]*GraphBuffer
[i
+(j
/skip
)];
1184 // Even things out by the length of the target waveform.
1188 if(corrEOF
> corr1
&& corrEOF
> corr0
) {
1189 PrintToScrollback("EOF at %d", i
);
1191 } else if(corr1
> corr0
) {
1192 i
+= arraylen(Logic1
)/skip
;
1195 i
+= arraylen(Logic0
)/skip
;
1202 if((i
+(int)arraylen(FrameEOF
)) >= GraphTraceLen
) {
1203 PrintToScrollback("ran off end!");
1208 PrintToScrollback("error, uneven octet! (discard extra bits!)");
1209 PrintToScrollback(" mask=%02x", mask
);
1211 PrintToScrollback("%d octets", k
);
1213 for(i
= 0; i
< k
; i
++) {
1214 PrintToScrollback("# %2d: %02x ", i
, outBuf
[i
]);
1216 PrintToScrollback("CRC=%04x", Iso15693Crc(outBuf
, k
-2));
1219 static void CmdTiread(char *str
)
1222 c
.cmd
= CMD_ACQUIRE_RAW_BITS_TI_TYPE
;
1223 SendCommand(&c
, FALSE
);
1226 static void CmdTibits(char *str
)
1230 for(i
= 0; i
< 1536; i
+= 12) {
1232 c
.cmd
= CMD_DOWNLOAD_RAW_BITS_TI_TYPE
;
1234 SendCommand(&c
, FALSE
);
1236 if(c
.cmd
!= CMD_DOWNLOADED_RAW_BITS_TI_TYPE
) {
1237 PrintToScrollback("bad resp");
1241 for(j
= 0; j
< 12; j
++) {
1243 for(k
= 31; k
>= 0; k
--) {
1244 if(c
.d
.asDwords
[j
] & (1 << k
)) {
1245 GraphBuffer
[cnt
++] = 1;
1247 GraphBuffer
[cnt
++] = -1;
1252 GraphTraceLen
= 1536*32;
1253 RepaintGraphWindow();
1256 static void CmdTidemod(char *cmdline
)
1258 /* MATLAB as follows:
1259 f_s = 2000000; % sampling frequency
1260 f_l = 123200; % low FSK tone
1261 f_h = 134200; % high FSK tone
1263 T_l = 119e-6; % low bit duration
1264 T_h = 130e-6; % high bit duration
1266 l = 2*pi*ones(1, floor(f_s*T_l))*(f_l/f_s);
1267 h = 2*pi*ones(1, floor(f_s*T_h))*(f_h/f_s);
1269 l = sign(sin(cumsum(l)));
1270 h = sign(sin(cumsum(h)));
1272 static const int LowTone
[] = {
1273 1, 1, 1, 1, 1, 1, 1, 1, -1, -1, -1, -1, -1, -1, -1, -1, 1, 1, 1,
1274 1, 1, 1, 1, 1, -1, -1, -1, -1, -1, -1, -1, -1, 1, 1, 1, 1, 1, 1,
1275 1, 1, -1, -1, -1, -1, -1, -1, -1, -1, 1, 1, 1, 1, 1, 1, 1, 1, -1,
1276 -1, -1, -1, -1, -1, -1, -1, 1, 1, 1, 1, 1, 1, 1, 1, 1, -1, -1, -1,
1277 -1, -1, -1, -1, -1, 1, 1, 1, 1, 1, 1, 1, 1, -1, -1, -1, -1, -1, -1,
1278 -1, -1, 1, 1, 1, 1, 1, 1, 1, 1, -1, -1, -1, -1, -1, -1, -1, -1, 1,
1279 1, 1, 1, 1, 1, 1, 1, -1, -1, -1, -1, -1, -1, -1, -1, 1, 1, 1, 1,
1280 1, 1, 1, 1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 1, 1, 1, 1, 1, 1,
1281 1, 1, -1, -1, -1, -1, -1, -1, -1, -1, 1, 1, 1, 1, 1, 1, 1, 1, -1,
1282 -1, -1, -1, -1, -1, -1, -1, 1, 1, 1, 1, 1, 1, 1, 1, -1, -1, -1, -1,
1283 -1, -1, -1, -1, 1, 1, 1, 1, 1, 1, 1, 1, -1, -1, -1, -1, -1, -1, -1,
1284 -1, -1, 1, 1, 1, 1, 1, 1, 1, 1, -1, -1, -1, -1, -1, -1, -1, -1, 1,
1285 1, 1, 1, 1, 1, 1, 1, -1, -1, -1,
1287 static const int HighTone
[] = {
1288 1, 1, 1, 1, 1, 1, 1, -1, -1, -1, -1, -1, -1, -1, 1, 1, 1, 1, 1, 1,
1289 1, 1, -1, -1, -1, -1, -1, -1, -1, 1, 1, 1, 1, 1, 1, 1, 1, -1, -1,
1290 -1, -1, -1, -1, -1, 1, 1, 1, 1, 1, 1, 1, 1, -1, -1, -1, -1, -1,
1291 -1, -1, 1, 1, 1, 1, 1, 1, 1, 1, -1, -1, -1, -1, -1, -1, -1, 1, 1,
1292 1, 1, 1, 1, 1, -1, -1, -1, -1, -1, -1, -1, -1, 1, 1, 1, 1, 1, 1,
1293 1, -1, -1, -1, -1, -1, -1, -1, -1, 1, 1, 1, 1, 1, 1, 1, -1, -1,
1294 -1, -1, -1, -1, -1, -1, 1, 1, 1, 1, 1, 1, 1, -1, -1, -1, -1, -1,
1295 -1, -1, -1, 1, 1, 1, 1, 1, 1, 1, -1, -1, -1, -1, -1, -1, -1, -1,
1296 1, 1, 1, 1, 1, 1, 1, -1, -1, -1, -1, -1, -1, -1, 1, 1, 1, 1, 1, 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,
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,
1304 int convLen
= max(arraylen(HighTone
), arraylen(LowTone
));
1307 for(i
= 0; i
< GraphTraceLen
- convLen
; i
++) {
1309 int lowSum
= 0, highSum
= 0;;
1310 int lowLen
= arraylen(LowTone
);
1311 int highLen
= arraylen(HighTone
);
1313 for(j
= 0; j
< lowLen
; j
++) {
1314 lowSum
+= LowTone
[j
]*GraphBuffer
[i
+j
];
1316 for(j
= 0; j
< highLen
; j
++) {
1317 highSum
+= HighTone
[j
]*GraphBuffer
[i
+j
];
1319 lowSum
= abs((100*lowSum
) / lowLen
);
1320 highSum
= abs((100*highSum
) / highLen
);
1321 GraphBuffer
[i
] = (highSum
<< 16) | lowSum
;
1324 for(i
= 0; i
< GraphTraceLen
- convLen
- 16; i
++) {
1326 int lowTot
= 0, highTot
= 0;
1327 // 16 and 15 are f_s divided by f_l and f_h, rounded
1328 for(j
= 0; j
< 16; j
++) {
1329 lowTot
+= (GraphBuffer
[i
+j
] & 0xffff);
1331 for(j
= 0; j
< 15; j
++) {
1332 highTot
+= (GraphBuffer
[i
+j
] >> 16);
1334 GraphBuffer
[i
] = lowTot
- highTot
;
1337 GraphTraceLen
-= (convLen
+ 16);
1339 RepaintGraphWindow();
1341 // Okay, so now we have unsliced soft decisions; find bit-sync, and then
1344 int max
= 0, maxPos
= 0;
1345 for(i
= 0; i
< 6000; i
++) {
1348 for(j
= 0; j
< 8*arraylen(LowTone
); j
++) {
1349 dec
-= GraphBuffer
[i
+j
];
1351 for(; j
< 8*arraylen(LowTone
) + 8*arraylen(HighTone
); j
++) {
1352 dec
+= GraphBuffer
[i
+j
];
1359 GraphBuffer
[maxPos
] = 800;
1360 GraphBuffer
[maxPos
+1] = -800;
1362 maxPos
+= 8*arraylen(LowTone
);
1363 GraphBuffer
[maxPos
] = 800;
1364 GraphBuffer
[maxPos
+1] = -800;
1365 maxPos
+= 8*arraylen(HighTone
);
1367 GraphBuffer
[maxPos
] = 800;
1368 GraphBuffer
[maxPos
+1] = -800;
1370 PrintToScrollback("actual data bits start at sample %d", maxPos
);
1372 PrintToScrollback("length %d/%d", arraylen(HighTone
), arraylen(LowTone
));
1374 GraphBuffer
[maxPos
] = 800;
1375 GraphBuffer
[maxPos
+1] = -800;
1377 BYTE bits
[64+16+8+1];
1378 bits
[sizeof(bits
)-1] = '\0';
1380 for(i
= 0; i
< arraylen(bits
); i
++) {
1384 for(j
= 0; j
< arraylen(LowTone
); j
++) {
1385 low
-= GraphBuffer
[maxPos
+j
];
1387 for(j
= 0; j
< arraylen(HighTone
); j
++) {
1388 high
+= GraphBuffer
[maxPos
+j
];
1392 maxPos
+= arraylen(HighTone
);
1395 maxPos
+= arraylen(LowTone
);
1397 GraphBuffer
[maxPos
] = 800;
1398 GraphBuffer
[maxPos
+1] = -800;
1400 PrintToScrollback("bits: '%s'", bits
);
1403 for(i
= 0; i
< 32; i
++) {
1404 if(bits
[i
] == '1') {
1408 for(i
= 32; i
< 64; i
++) {
1409 if(bits
[i
] == '1') {
1413 PrintToScrollback("hex: %08x %08x", h
, l
);
1416 static void CmdNorm(char *str
)
1419 int max
= INT_MIN
, min
= INT_MAX
;
1420 for(i
= 10; i
< GraphTraceLen
; i
++) {
1421 if(GraphBuffer
[i
] > max
) {
1422 max
= GraphBuffer
[i
];
1424 if(GraphBuffer
[i
] < min
) {
1425 min
= GraphBuffer
[i
];
1429 for(i
= 0; i
< GraphTraceLen
; i
++) {
1430 GraphBuffer
[i
] = (GraphBuffer
[i
] - ((max
+ min
)/2))*1000/
1434 RepaintGraphWindow();
1437 static void CmdDec(char *str
)
1440 for(i
= 0; i
< (GraphTraceLen
/2); i
++) {
1441 GraphBuffer
[i
] = GraphBuffer
[i
*2];
1444 PrintToScrollback("decimated by 2");
1445 RepaintGraphWindow();
1448 static void CmdHpf(char *str
)
1452 for(i
= 10; i
< GraphTraceLen
; i
++) {
1453 accum
+= GraphBuffer
[i
];
1455 accum
/= (GraphTraceLen
- 10);
1456 for(i
= 0; i
< GraphTraceLen
; i
++) {
1457 GraphBuffer
[i
] -= accum
;
1460 RepaintGraphWindow();
1463 static void CmdZerocrossings(char *str
)
1466 // Zero-crossings aren't meaningful unless the signal is zero-mean.
1472 for(i
= 0; i
< GraphTraceLen
; i
++) {
1473 if(GraphBuffer
[i
]*sign
>= 0) {
1474 // No change in sign, reproduce the previous sample count.
1476 GraphBuffer
[i
] = lastZc
;
1478 // Change in sign, reset the sample count.
1480 GraphBuffer
[i
] = lastZc
;
1488 RepaintGraphWindow();
1491 static void CmdLtrim(char *str
)
1496 for(i
= ds
; i
< GraphTraceLen
; i
++) {
1497 GraphBuffer
[i
-ds
] = GraphBuffer
[i
];
1499 GraphTraceLen
-= ds
;
1501 RepaintGraphWindow();
1504 static void CmdAutoCorr(char *str
)
1506 static int CorrelBuffer
[MAX_GRAPH_TRACE_LEN
];
1508 int window
= atoi(str
);
1511 PrintToScrollback("needs a window");
1515 if(window
>= GraphTraceLen
) {
1516 PrintToScrollback("window must be smaller than trace (%d samples)",
1521 PrintToScrollback("performing %d correlations", GraphTraceLen
- window
);
1524 for(i
= 0; i
< GraphTraceLen
- window
; i
++) {
1527 for(j
= 0; j
< window
; j
++) {
1528 sum
+= (GraphBuffer
[j
]*GraphBuffer
[i
+j
]) / 256;
1530 CorrelBuffer
[i
] = sum
;
1532 GraphTraceLen
= GraphTraceLen
- window
;
1533 memcpy(GraphBuffer
, CorrelBuffer
, GraphTraceLen
*sizeof(int));
1535 RepaintGraphWindow();
1538 static void CmdVchdemod(char *str
)
1540 // Is this the entire sync pattern, or does this also include some
1541 // data bits that happen to be the same everywhere? That would be
1543 static const int SyncPattern
[] = {
1544 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
1545 1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
1546 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
1547 1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
1548 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
1549 1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
1550 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
1551 1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
1552 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
1553 1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
1556 // So first, we correlate for the sync pattern, and mark that.
1557 int bestCorrel
= 0, bestPos
= 0;
1559 // It does us no good to find the sync pattern, with fewer than
1560 // 2048 samples after it...
1561 for(i
= 0; i
< (GraphTraceLen
-2048); i
++) {
1564 for(j
= 0; j
< arraylen(SyncPattern
); j
++) {
1565 sum
+= GraphBuffer
[i
+j
]*SyncPattern
[j
];
1567 if(sum
> bestCorrel
) {
1572 PrintToScrollback("best sync at %d [metric %d]", bestPos
, bestCorrel
);
1577 int worst
= INT_MAX
;
1580 for(i
= 0; i
< 2048; i
+= 8) {
1583 for(j
= 0; j
< 8; j
++) {
1584 sum
+= GraphBuffer
[bestPos
+i
+j
];
1591 if(abs(sum
) < worst
) {
1596 PrintToScrollback("bits:");
1597 PrintToScrollback("%s", bits
);
1598 PrintToScrollback("worst metric: %d at pos %d", worst
, worstPos
);
1600 if(strcmp(str
, "clone")==0) {
1603 for(s
= bits
; *s
; s
++) {
1605 for(j
= 0; j
< 16; j
++) {
1606 GraphBuffer
[GraphTraceLen
++] = (*s
== '1') ? 1 : 0;
1609 RepaintGraphWindow();
1613 static void CmdIndalademod(char *str
)
1615 // Usage: recover 64bit UID by default, specify "224" as arg to recover a 224bit UID
1620 // worst case with GraphTraceLen=64000 is < 4096
1621 // under normal conditions it's < 2048
1624 int worst
= 0, worstPos
= 0;
1625 PrintToScrollback("Expecting a bit less than %d raw bits", GraphTraceLen
/32);
1626 for(i
= 0; i
< GraphTraceLen
-1; i
+= 2) {
1628 if((GraphBuffer
[i
] > GraphBuffer
[i
+ 1]) && (state
!= 1)) {
1630 for(j
= 0; j
< count
- 8; j
+= 16) {
1631 rawbits
[rawbit
++] = 0;
1633 if ((abs(count
- j
)) > worst
) {
1634 worst
= abs(count
- j
);
1640 } else if((GraphBuffer
[i
] < GraphBuffer
[i
+ 1]) && (state
!= 0)) {
1642 for(j
= 0; j
< count
- 8; j
+= 16) {
1643 rawbits
[rawbit
++] = 1;
1645 if ((abs(count
- j
)) > worst
) {
1646 worst
= abs(count
- j
);
1654 PrintToScrollback("Recovered %d raw bits", rawbit
);
1655 PrintToScrollback("worst metric (0=best..7=worst): %d at pos %d", worst
, worstPos
);
1657 // Finding the start of a UID
1658 int uidlen
, long_wait
;
1659 if(strcmp(str
, "224") == 0) {
1668 for(start
= 0; start
<= rawbit
- uidlen
; start
++) {
1669 first
= rawbits
[start
];
1670 for(i
= start
; i
< start
+ long_wait
; i
++) {
1671 if(rawbits
[i
] != first
) {
1675 if(i
== (start
+ long_wait
)) {
1679 if(start
== rawbit
- uidlen
+ 1) {
1680 PrintToScrollback("nothing to wait for");
1684 // Inverting signal if needed
1686 for(i
= start
; i
< rawbit
; i
++) {
1687 rawbits
[i
] = !rawbits
[i
];
1694 showbits
[uidlen
]='\0';
1698 if(uidlen
> rawbit
) {
1699 PrintToScrollback("Warning: not enough raw bits to get a full UID");
1700 for(bit
= 0; bit
< rawbit
; bit
++) {
1701 bits
[bit
] = rawbits
[i
++];
1702 // As we cannot know the parity, let's use "." and "/"
1703 showbits
[bit
] = '.' + bits
[bit
];
1705 showbits
[bit
+1]='\0';
1706 PrintToScrollback("Partial UID=%s", showbits
);
1709 for(bit
= 0; bit
< uidlen
; bit
++) {
1710 bits
[bit
] = rawbits
[i
++];
1711 showbits
[bit
] = '0' + bits
[bit
];
1715 PrintToScrollback("UID=%s", showbits
);
1717 // Checking UID against next occurences
1718 for(; i
+ uidlen
<= rawbit
;) {
1720 for(bit
= 0; bit
< uidlen
; bit
++) {
1721 if(bits
[bit
] != rawbits
[i
++]) {
1731 PrintToScrollback("Occurences: %d (expected %d)", times
, (rawbit
- start
) / uidlen
);
1733 // Remodulating for tag cloning
1734 GraphTraceLen
= 32*uidlen
;
1737 for(bit
= 0; bit
< uidlen
; bit
++) {
1738 if(bits
[bit
] == 0) {
1744 for(j
= 0; j
< 32; j
++) {
1745 GraphBuffer
[i
++] = phase
;
1750 RepaintGraphWindow();
1753 static void CmdFlexdemod(char *str
)
1756 for(i
= 0; i
< GraphTraceLen
; i
++) {
1757 if(GraphBuffer
[i
] < 0) {
1758 GraphBuffer
[i
] = -1;
1764 #define LONG_WAIT 100
1766 for(start
= 0; start
< GraphTraceLen
- LONG_WAIT
; start
++) {
1767 int first
= GraphBuffer
[start
];
1768 for(i
= start
; i
< start
+ LONG_WAIT
; i
++) {
1769 if(GraphBuffer
[i
] != first
) {
1773 if(i
== (start
+ LONG_WAIT
)) {
1777 if(start
== GraphTraceLen
- LONG_WAIT
) {
1778 PrintToScrollback("nothing to wait for");
1782 GraphBuffer
[start
] = 2;
1783 GraphBuffer
[start
+1] = -2;
1789 for(bit
= 0; bit
< 64; bit
++) {
1792 for(j
= 0; j
< 16; j
++) {
1793 sum
+= GraphBuffer
[i
++];
1800 PrintToScrollback("bit %d sum %d", bit
, sum
);
1803 for(bit
= 0; bit
< 64; bit
++) {
1806 for(j
= 0; j
< 16; j
++) {
1807 sum
+= GraphBuffer
[i
++];
1809 if(sum
> 0 && bits
[bit
] != 1) {
1810 PrintToScrollback("oops1 at %d", bit
);
1812 if(sum
< 0 && bits
[bit
] != 0) {
1813 PrintToScrollback("oops2 at %d", bit
);
1817 GraphTraceLen
= 32*64;
1820 for(bit
= 0; bit
< 64; bit
++) {
1821 if(bits
[bit
] == 0) {
1827 for(j
= 0; j
< 32; j
++) {
1828 GraphBuffer
[i
++] = phase
;
1833 RepaintGraphWindow();
1837 * Generic command to demodulate ASK.
1839 * Argument is convention: positive or negative (High mod means zero
1840 * or high mod means one)
1842 * Updates the Graph trace with 0/1 values
1848 static void Cmdaskdemod(char *str
) {
1853 // TODO: complain if we do not give 2 arguments here !
1854 sscanf(str
, "%i", &c
);
1856 /* Detect high and lows and clock */
1857 for (i
= 0; i
< GraphTraceLen
; i
++)
1859 if (GraphBuffer
[i
] > high
)
1860 high
= GraphBuffer
[i
];
1861 else if (GraphBuffer
[i
] < low
)
1862 low
= GraphBuffer
[i
];
1865 if (GraphBuffer
[0] > 0) {
1866 GraphBuffer
[0] = 1-c
;
1870 for(i
=1;i
<GraphTraceLen
;i
++) {
1871 /* Transitions are detected at each peak
1872 * Transitions are either:
1873 * - we're low: transition if we hit a high
1874 * - we're high: transition if we hit a low
1875 * (we need to do it this way because some tags keep high or
1876 * low for long periods, others just reach the peak and go
1879 if ((GraphBuffer
[i
]==high
) && (GraphBuffer
[i
-1] == c
)) {
1881 } else if ((GraphBuffer
[i
]==low
) && (GraphBuffer
[i
-1] == (1-c
))){
1885 GraphBuffer
[i
] = GraphBuffer
[i
-1];
1888 RepaintGraphWindow();
1891 /* Print our clock rate */
1892 static void Cmddetectclockrate(char *str
)
1894 int clock
= detectclock(0);
1895 PrintToScrollback("Auto-detected clock rate: %d", clock
);
1901 int detectclock(int peak
)
1907 /* Detect peak if we don't have one */
1909 for (i
= 0; i
< GraphTraceLen
; i
++)
1910 if (GraphBuffer
[i
] > peak
)
1911 peak
= GraphBuffer
[i
];
1913 for (i
= 1; i
< GraphTraceLen
; i
++)
1915 /* If this is the beginning of a peak */
1916 if (GraphBuffer
[i
-1] != GraphBuffer
[i
] && GraphBuffer
[i
] == peak
)
1918 /* Find lowest difference between peaks */
1919 if (lastpeak
&& i
- lastpeak
< clock
)
1921 clock
= i
- lastpeak
;
1930 /* Get or auto-detect clock rate */
1931 int GetClock(char *str
, int peak
)
1935 sscanf(str
, "%i", &clock
);
1936 if (!strcmp(str
, ""))
1939 /* Auto-detect clock */
1942 clock
= detectclock(peak
);
1944 /* Only print this message if we're not looping something */
1946 PrintToScrollback("Auto-detected clock rate: %d", clock
);
1953 * Convert to a bitstream
1955 static void Cmdbitstream(char *str
) {
1962 int hithigh
, hitlow
, first
;
1964 /* Detect high and lows and clock */
1965 for (i
= 0; i
< GraphTraceLen
; i
++)
1967 if (GraphBuffer
[i
] > high
)
1968 high
= GraphBuffer
[i
];
1969 else if (GraphBuffer
[i
] < low
)
1970 low
= GraphBuffer
[i
];
1974 clock
= GetClock(str
, high
);
1976 gtl
= CmdClearGraph(0);
1979 for (i
= 0; i
< (int)(gtl
/ clock
); i
++)
1985 /* Find out if we hit both high and low peaks */
1986 for (j
= 0; j
< clock
; j
++)
1988 if (GraphBuffer
[(i
* clock
) + j
] == high
)
1990 else if (GraphBuffer
[(i
* clock
) + j
] == low
)
1993 /* it doesn't count if it's the first part of our read
1994 because it's really just trailing from the last sequence */
1995 if (first
&& (hithigh
|| hitlow
))
1996 hithigh
= hitlow
= 0;
2000 if (hithigh
&& hitlow
)
2004 /* If we didn't hit both high and low peaks, we had a bit transition */
2005 if (!hithigh
|| !hitlow
)
2008 CmdAppendGraph(0, clock
, bit
);
2009 // for (j = 0; j < (int)(clock/2); j++)
2010 // GraphBuffer[(i * clock) + j] = bit ^ 1;
2011 // for (j = (int)(clock/2); j < clock; j++)
2012 // GraphBuffer[(i * clock) + j] = bit;
2015 RepaintGraphWindow();
2018 /* Modulate our data into manchester */
2019 static void Cmdmanchestermod(char *str
)
2023 int bit
, lastbit
, wave
;
2026 clock
= GetClock(str
, 0);
2030 for (i
= 0; i
< (int)(GraphTraceLen
/ clock
); i
++)
2032 bit
= GraphBuffer
[i
* clock
] ^ 1;
2034 for (j
= 0; j
< (int)(clock
/2); j
++)
2035 GraphBuffer
[(i
* clock
) + j
] = bit
^ lastbit
^ wave
;
2036 for (j
= (int)(clock
/2); j
< clock
; j
++)
2037 GraphBuffer
[(i
* clock
) + j
] = bit
^ lastbit
^ wave
^ 1;
2039 /* Keep track of how we start our wave and if we changed or not this time */
2040 wave
^= bit
^ lastbit
;
2044 RepaintGraphWindow();
2048 * Manchester demodulate a bitstream. The bitstream needs to be already in
2049 * the GraphBuffer as 0 and 1 values
2051 * Give the clock rate as argument in order to help the sync - the algorithm
2052 * resyncs at each pulse anyway.
2054 * Not optimized by any means, this is the 1st time I'm writing this type of
2055 * routine, feel free to improve...
2057 * 1st argument: clock rate (as number of samples per clock rate)
2058 * Typical values can be 64, 32, 128...
2060 static void Cmdmanchesterdemod(char *str
) {
2067 int hithigh
, hitlow
, first
;
2073 /* Holds the decoded bitstream: each clock period contains 2 bits */
2074 /* later simplified to 1 bit after manchester decoding. */
2075 /* Add 10 bits to allow for noisy / uncertain traces without aborting */
2076 /* int BitStream[GraphTraceLen*2/clock+10]; */
2078 /* But it does not work if compiling on WIndows: therefore we just allocate a */
2080 int BitStream
[MAX_GRAPH_TRACE_LEN
];
2082 /* Detect high and lows */
2083 for (i
= 0; i
< GraphTraceLen
; i
++)
2085 if (GraphBuffer
[i
] > high
)
2086 high
= GraphBuffer
[i
];
2087 else if (GraphBuffer
[i
] < low
)
2088 low
= GraphBuffer
[i
];
2092 clock
= GetClock(str
, high
);
2094 int tolerance
= clock
/4;
2096 /* Detect first transition */
2097 /* Lo-Hi (arbitrary) */
2098 for (i
= 0; i
< GraphTraceLen
; i
++)
2100 if (GraphBuffer
[i
] == low
)
2107 /* If we're not working with 1/0s, demod based off clock */
2110 bit
= 0; /* We assume the 1st bit is zero, it may not be
2111 * the case: this routine (I think) has an init problem.
2114 for (; i
< (int)(GraphTraceLen
/ clock
); i
++)
2120 /* Find out if we hit both high and low peaks */
2121 for (j
= 0; j
< clock
; j
++)
2123 if (GraphBuffer
[(i
* clock
) + j
] == high
)
2125 else if (GraphBuffer
[(i
* clock
) + j
] == low
)
2128 /* it doesn't count if it's the first part of our read
2129 because it's really just trailing from the last sequence */
2130 if (first
&& (hithigh
|| hitlow
))
2131 hithigh
= hitlow
= 0;
2135 if (hithigh
&& hitlow
)
2139 /* If we didn't hit both high and low peaks, we had a bit transition */
2140 if (!hithigh
|| !hitlow
)
2143 BitStream
[bit2idx
++] = bit
;
2147 /* standard 1/0 bitstream */
2151 /* Then detect duration between 2 successive transitions */
2152 for (bitidx
= 1; i
< GraphTraceLen
; i
++)
2154 if (GraphBuffer
[i
-1] != GraphBuffer
[i
])
2159 // Error check: if bitidx becomes too large, we do not
2160 // have a Manchester encoded bitstream or the clock is really
2162 if (bitidx
> (GraphTraceLen
*2/clock
+8) ) {
2163 PrintToScrollback("Error: the clock you gave is probably wrong, aborting.");
2166 // Then switch depending on lc length:
2167 // Tolerance is 1/4 of clock rate (arbitrary)
2168 if (abs(lc
-clock
/2) < tolerance
) {
2169 // Short pulse : either "1" or "0"
2170 BitStream
[bitidx
++]=GraphBuffer
[i
-1];
2171 } else if (abs(lc
-clock
) < tolerance
) {
2172 // Long pulse: either "11" or "00"
2173 BitStream
[bitidx
++]=GraphBuffer
[i
-1];
2174 BitStream
[bitidx
++]=GraphBuffer
[i
-1];
2178 PrintToScrollback("Warning: Manchester decode error for pulse width detection.");
2179 PrintToScrollback("(too many of those messages mean either the stream is not Manchester encoded, or clock is wrong)");
2183 PrintToScrollback("Error: too many detection errors, aborting.");
2190 // At this stage, we now have a bitstream of "01" ("1") or "10" ("0"), parse it into final decoded bitstream
2191 // Actually, we overwrite BitStream with the new decoded bitstream, we just need to be careful
2192 // to stop output at the final bitidx2 value, not bitidx
2193 for (i
= 0; i
< bitidx
; i
+= 2) {
2194 if ((BitStream
[i
] == 0) && (BitStream
[i
+1] == 1)) {
2195 BitStream
[bit2idx
++] = 1;
2196 } else if ((BitStream
[i
] == 1) && (BitStream
[i
+1] == 0)) {
2197 BitStream
[bit2idx
++] = 0;
2199 // We cannot end up in this state, this means we are unsynchronized,
2203 PrintToScrollback("Unsynchronized, resync...");
2204 PrintToScrollback("(too many of those messages mean the stream is not Manchester encoded)");
2208 PrintToScrollback("Error: too many decode errors, aborting.");
2215 PrintToScrollback("Manchester decoded bitstream");
2216 // Now output the bitstream to the scrollback by line of 16 bits
2217 for (i
= 0; i
< (bit2idx
-16); i
+=16) {
2218 PrintToScrollback("%i %i %i %i %i %i %i %i %i %i %i %i %i %i %i %i",
2243 static void CmdHiddemod(char *str
)
2245 if(GraphTraceLen
< 4800) {
2246 PrintToScrollback("too short; need at least 4800 samples");
2250 GraphTraceLen
= 4800;
2252 for(i
= 0; i
< GraphTraceLen
; i
++) {
2253 if(GraphBuffer
[i
] < 0) {
2259 RepaintGraphWindow();
2262 static void CmdPlot(char *str
)
2267 static void CmdHide(char *str
)
2272 static void CmdScale(char *str
)
2274 CursorScaleFactor
= atoi(str
);
2275 if(CursorScaleFactor
== 0) {
2276 PrintToScrollback("bad, can't have zero scale");
2277 CursorScaleFactor
= 1;
2279 RepaintGraphWindow();
2282 static void CmdSave(char *str
)
2284 FILE *f
= fopen(str
, "w");
2286 PrintToScrollback("couldn't open '%s'", str
);
2290 for(i
= 0; i
< GraphTraceLen
; i
++) {
2291 fprintf(f
, "%d\n", GraphBuffer
[i
]);
2294 PrintToScrollback("saved to '%s'", str
);
2297 static void CmdLoad(char *str
)
2299 FILE *f
= fopen(str
, "r");
2301 PrintToScrollback("couldn't open '%s'", str
);
2307 while(fgets(line
, sizeof(line
), f
)) {
2308 GraphBuffer
[GraphTraceLen
] = atoi(line
);
2312 PrintToScrollback("loaded %d samples", GraphTraceLen
);
2313 RepaintGraphWindow();
2316 static void CmdHIDsimTAG(char *str
)
2318 unsigned int hi
=0, lo
=0;
2322 while (sscanf(&str
[i
++], "%1x", &n
) == 1) {
2323 hi
=(hi
<<4)|(lo
>>28);
2327 PrintToScrollback("Emulating tag with ID %x%16x", hi
, lo
);
2329 c
.cmd
= CMD_HID_SIM_TAG
;
2332 SendCommand(&c
, FALSE
);
2335 static void CmdLcdReset(char *str
)
2338 c
.cmd
= CMD_LCD_RESET
;
2340 SendCommand(&c
, FALSE
);
2343 static void CmdLcd(char *str
)
2348 sscanf(str
, "%x %d", &i
, &j
);
2351 SendCommand(&c
, FALSE
);
2357 static void CmdTest(char *str
)
2362 * Sets the divisor for LF frequency clock: lets the user choose any LF frequency below
2365 static void CmdSetDivisor(char *str
)
2368 c
.cmd
= CMD_SET_LF_DIVISOR
;
2370 if (( c
.ext1
<0) || (c
.ext1
>255)) {
2371 PrintToScrollback("divisor must be between 19 and 255");
2373 SendCommand(&c
, FALSE
);
2374 PrintToScrollback("Divisor set, expected freq=%dHz", 12000000/(c
.ext1
+1));
2378 static void CmdSweepLF(char *str
)
2381 c
.cmd
= CMD_SWEEP_LF
;
2382 SendCommand(&c
, FALSE
);
2386 typedef void HandlerFunction(char *cmdline
);
2388 /* in alphabetic order */
2391 HandlerFunction
*handler
;
2392 int offline
; // 1 if the command can be used when in offline mode
2394 } CommandTable
[] = {
2395 "askdemod", Cmdaskdemod
,1, "<samples per bit> <0|1> -- Attempt to demodulate simple ASK tags",
2396 "autocorr", CmdAutoCorr
,1, "<window length> -- Autocorrelation over window",
2397 "bitsamples", CmdBitsamples
,0, " Get raw samples as bitstring",
2398 "bitstream", Cmdbitstream
,1, "[clock rate] -- Convert waveform into a bitstream",
2399 "dec", CmdDec
,1, " Decimate samples",
2400 "detectclock", Cmddetectclockrate
,1, " Detect clock rate",
2401 "em410xsim", CmdEM410xsim
,1, "<UID> -- Simulate EM410x tag",
2402 "em410xread", CmdEM410xread
,1, "[clock rate] -- Extract ID from EM410x tag",
2403 "em410xwatch", CmdEM410xwatch
,0, " Watches for EM410x tags",
2404 "exit", CmdQuit
,1, " Exit program",
2405 "flexdemod", CmdFlexdemod
,1, " Demodulate samples for FlexPass",
2406 "fpgaoff", CmdFPGAOff
,0, " Set FPGA off", // ## FPGA Control
2407 "hexsamples", CmdHexsamples
,0, "<blocks> -- Dump big buffer as hex bytes",
2408 "hi14alist", CmdHi14alist
,0, " List ISO 14443a history", // ## New list command
2409 "hi14areader", CmdHi14areader
,0, " Act like an ISO14443 Type A reader", // ## New reader command
2410 "hi14asim", CmdHi14asim
,0, "<UID> -- Fake ISO 14443a tag", // ## Simulate 14443a tag
2411 "hi14asnoop", CmdHi14asnoop
,0, " Eavesdrop ISO 14443 Type A", // ## New snoop command
2412 "hi14bdemod", CmdHi14bdemod
,1, " Demodulate ISO14443 Type B from tag",
2413 "hi14list", CmdHi14list
,0, " List ISO 14443 history",
2414 "hi14read", CmdHi14read
,0, " Read HF tag (ISO 14443)",
2415 "hi14sim", CmdHi14sim
,0, " Fake ISO 14443 tag",
2416 "hi14snoop", CmdHi14snoop
,0, " Eavesdrop ISO 14443",
2417 "hi15demod", CmdHi15demod
,1, " Demodulate ISO15693 from tag",
2418 "hi15read", CmdHi15read
,0, " Read HF tag (ISO 15693)",
2419 "hi15reader", CmdHi15reader
,0, " Act like an ISO15693 reader", // new command greg
2420 "hi15sim", CmdHi15tag
,0, " Fake an ISO15693 tag", // new command greg
2421 "hiddemod", CmdHiddemod
,1, " Demodulate HID Prox Card II (not optimal)",
2422 "hide", CmdHide
,1, " Hide graph window",
2423 "hidfskdemod", CmdHIDdemodFSK
,0, " Realtime HID FSK demodulator",
2424 "hidsimtag", CmdHIDsimTAG
,0, "<ID> -- HID tag simulator",
2425 "higet", CmdHi14read_sim
,0, "<samples> -- Get samples HF, 'analog'",
2426 "hisamples", CmdHisamples
,0, " Get raw samples for HF tag",
2427 "hisampless", CmdHisampless
,0, "<samples> -- Get signed raw samples, HF tag",
2428 "hisamplest", CmdHi14readt
,0, " Get samples HF, for testing",
2429 "hisimlisten", CmdHisimlisten
,0, " Get HF samples as fake tag",
2430 "hpf", CmdHpf
,1, " Remove DC offset from trace",
2431 "indalademod", CmdIndalademod
,0, "['224'] -- Demodulate samples for Indala",
2432 "lcd", CmdLcd
,0, "<HEX command> <count> -- Send command/data to LCD",
2433 "lcdreset", CmdLcdReset
,0, " Hardware reset LCD",
2434 "load", CmdLoad
,1, "<filename> -- Load trace (to graph window",
2435 "loread", CmdLoread
,0, "['h'] -- Read 125/134 kHz LF ID-only tag (option 'h' for 134)",
2436 "losamples", CmdLosamples
,0, "[128 - 16000] -- Get raw samples for LF tag",
2437 "losim", CmdLosim
,0, " Simulate LF tag",
2438 "ltrim", CmdLtrim
,1, "<samples> -- Trim samples from left of trace",
2439 "mandemod", Cmdmanchesterdemod
,1, "[clock rate] -- Try a Manchester demodulation on a binary stream",
2440 "manmod", Cmdmanchestermod
,1, "[clock rate] -- Manchester modulate a binary stream",
2441 "norm", CmdNorm
,1, " Normalize max/min to +/-500",
2442 "plot", CmdPlot
,1, " Show graph window",
2443 "quit", CmdQuit
,1, " Quit program",
2444 "reset", CmdReset
,0, " Reset the Proxmark3",
2445 "save", CmdSave
,1, "<filename> -- Save trace (from graph window)",
2446 "scale", CmdScale
,1, "<int> -- Set cursor display scale",
2447 "setlfdivisor", CmdSetDivisor
,0, "<19 - 255> -- Drive LF antenna at 12Mhz/(divisor+1)",
2448 "sri512read", CmdSri512read
,0, "<int> -- Read contents of a SRI512 tag",
2449 "sweeplf", CmdSweepLF
,0, " Sweep through LF freq range and store results in buffer",
2450 "tibits", CmdTibits
,0, " Get raw bits for TI-type LF tag",
2451 "tidemod", CmdTidemod
,0, " Demodulate raw bits for TI-type LF tag",
2452 "tiread", CmdTiread
,0, " Read a TI-type 134 kHz tag",
2453 "tune", CmdTune
,0, " Measure antenna tuning",
2454 "vchdemod", CmdVchdemod
,0, "['clone'] -- Demodulate samples for VeriChip",
2455 "zerocrossings", CmdZerocrossings
,1, " Count time between zero-crossings",
2459 //-----------------------------------------------------------------------------
2460 // Entry point into our code: called whenever the user types a command and
2461 // then presses Enter, which the full command line that they typed.
2462 //-----------------------------------------------------------------------------
2463 void CommandReceived(char *cmd
)
2467 PrintToScrollback("> %s", cmd
);
2469 if(strcmp(cmd
, "help")==0) {
2470 if (offline
) PrintToScrollback("Operating in OFFLINE mode (no device connected)");
2471 PrintToScrollback("\r\nAvailable commands:");
2472 for(i
= 0; i
< sizeof(CommandTable
) / sizeof(CommandTable
[0]); i
++) {
2473 if (offline
&& (CommandTable
[i
].offline
==0)) continue;
2475 memset(line
, ' ', sizeof(line
));
2476 strcpy(line
+2, CommandTable
[i
].name
);
2477 line
[strlen(line
)] = ' ';
2478 sprintf(line
+15, " -- %s", CommandTable
[i
].docString
);
2479 PrintToScrollback("%s", line
);
2481 PrintToScrollback("");
2482 PrintToScrollback("and also: help, cls");
2486 for(i
= 0; i
< sizeof(CommandTable
) / sizeof(CommandTable
[0]); i
++) {
2487 char *name
= CommandTable
[i
].name
;
2488 if(memcmp(cmd
, name
, strlen(name
))==0 &&
2489 (cmd
[strlen(name
)] == ' ' || cmd
[strlen(name
)] == '\0'))
2491 cmd
+= strlen(name
);
2492 while(*cmd
== ' ') {
2495 if (offline
&& (CommandTable
[i
].offline
==0)) {
2496 PrintToScrollback("Offline mode, cannot use this command.");
2499 (CommandTable
[i
].handler
)(cmd
);
2503 PrintToScrollback(">> bad command '%s'", cmd
);
2506 //-----------------------------------------------------------------------------
2507 // Entry point into our code: called whenever we received a packet over USB
2508 // that we weren't necessarily expecting, for example a debug print.
2509 //-----------------------------------------------------------------------------
2510 void UsbCommandReceived(UsbCommand
*c
)
2513 case CMD_DEBUG_PRINT_STRING
: {
2515 if(c
->ext1
> 70 || c
->ext1
< 0) {
2518 memcpy(s
, c
->d
.asBytes
, c
->ext1
);
2520 PrintToScrollback("#db# %s", s
);
2524 case CMD_DEBUG_PRINT_INTEGERS
:
2525 PrintToScrollback("#db# %08x, %08x, %08x\r\n", c
->ext1
, c
->ext2
, c
->ext3
);
2528 case CMD_MEASURED_ANTENNA_TUNING
: {
2530 int vLf125
, vLf134
, vHf
;
2531 vLf125
= c
->ext1
& 0xffff;
2532 vLf134
= c
->ext1
>> 16;
2534 zLf
= c
->ext3
& 0xffff;
2535 zHf
= c
->ext3
>> 16;
2536 PrintToScrollback("# LF antenna @ %3d mA / %5d mV [%d ohms] 125Khz",
2537 vLf125
/zLf
, vLf125
, zLf
);
2538 PrintToScrollback("# LF antenna @ %3d mA / %5d mV [%d ohms] 134Khz",
2539 vLf134
/((zLf
*125)/134), vLf134
, (zLf
*125)/134);
2540 PrintToScrollback("# HF antenna @ %3d mA / %5d mV [%d ohms] 13.56Mhz",
2545 PrintToScrollback("unrecognized command %08x\n", c
->cmd
);