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]))
18 static int CmdHisamplest(char *str
, int nrlow
);
20 static void GetFromBigBuf(BYTE
*dest
, int bytes
)
25 PrintToScrollback("bad len in GetFromBigBuf");
30 for(i
= 0; i
< n
; i
+= 12) {
32 c
.cmd
= CMD_DOWNLOAD_RAW_ADC_SAMPLES_125K
;
34 SendCommand(&c
, FALSE
);
36 if(c
.cmd
!= CMD_DOWNLOADED_RAW_ADC_SAMPLES_125K
) {
37 PrintToScrollback("bad resp\n");
41 memcpy(dest
+(i
*4), c
.d
.asBytes
, 48);
45 static void CmdReset(char *str
)
48 c
.cmd
= CMD_HARDWARE_RESET
;
49 SendCommand(&c
, FALSE
);
53 static void CmdQuit(char *str
)
58 static void CmdHIDdemodFSK(char *str
)
61 c
.cmd
= CMD_HID_DEMOD_FSK
;
62 SendCommand(&c
, FALSE
);
65 static void CmdTune(char *str
)
68 c
.cmd
= CMD_MEASURE_ANTENNA_TUNING
;
69 SendCommand(&c
, FALSE
);
72 static void CmdHi15read(char *str
)
75 c
.cmd
= CMD_ACQUIRE_RAW_ADC_SAMPLES_ISO_15693
;
76 SendCommand(&c
, FALSE
);
79 static void CmdHi14read(char *str
)
82 c
.cmd
= CMD_ACQUIRE_RAW_ADC_SAMPLES_ISO_14443
;
84 SendCommand(&c
, FALSE
);
88 /* New command to read the contents of a SRI512 tag
89 * SRI512 tags are ISO14443-B modulated memory tags,
90 * this command just dumps the contents of the memory/
92 static void CmdSri512read(char *str
)
95 c
.cmd
= CMD_READ_SRI512_TAG
;
97 SendCommand(&c
, FALSE
);
101 static void CmdHi14areader(char *str
)
104 c
.cmd
= CMD_READER_ISO_14443a
;
106 SendCommand(&c
, FALSE
);
110 static void CmdHi15reader(char *str
)
113 c
.cmd
= CMD_READER_ISO_15693
;
115 SendCommand(&c
, FALSE
);
119 static void CmdHi15tag(char *str
)
122 c
.cmd
= CMD_SIMTAG_ISO_15693
;
124 SendCommand(&c
, FALSE
);
127 static void CmdHi14read_sim(char *str
)
130 c
.cmd
= CMD_ACQUIRE_RAW_ADC_SAMPLES_ISO_14443_SIM
;
132 SendCommand(&c
, FALSE
);
135 static void CmdHi14readt(char *str
)
138 c
.cmd
= CMD_ACQUIRE_RAW_ADC_SAMPLES_ISO_14443
;
140 SendCommand(&c
, FALSE
);
142 //CmdHisamplest(str);
143 while(CmdHisamplest(str
,atoi(str
))==0) {
144 c
.cmd
= CMD_ACQUIRE_RAW_ADC_SAMPLES_ISO_14443
;
146 SendCommand(&c
, FALSE
);
148 RepaintGraphWindow();
151 static void CmdHisimlisten(char *str
)
154 c
.cmd
= CMD_SIMULATE_TAG_HF_LISTEN
;
155 SendCommand(&c
, FALSE
);
158 static void CmdHi14sim(char *str
)
161 c
.cmd
= CMD_SIMULATE_TAG_ISO_14443
;
162 SendCommand(&c
, FALSE
);
167 static void CmdHi14asim(char *str
) // ## simulate iso14443a tag
168 { // ## greg - added ability to specify tag UID
170 unsigned int hi
=0, lo
=0;
174 while (sscanf(&str
[i
++], "%1x", &n
) == 1) {
179 c
.cmd
= CMD_SIMULATE_TAG_ISO_14443a
;
180 // c.ext should be set to *str or convert *str to the correct format for a uid
183 PrintToScrollback("Emulating 14443A TAG with UID %x%16x", hi
, lo
);
184 SendCommand(&c
, FALSE
);
187 static void CmdHi14snoop(char *str
)
190 c
.cmd
= CMD_SNOOP_ISO_14443
;
191 SendCommand(&c
, FALSE
);
194 static void CmdHi14asnoop(char *str
)
197 c
.cmd
= CMD_SNOOP_ISO_14443a
;
198 SendCommand(&c
, FALSE
);
201 static void CmdFPGAOff(char *str
) // ## FPGA Control
204 c
.cmd
= CMD_FPGA_MAJOR_MODE_OFF
;
205 SendCommand(&c
, FALSE
);
208 static void CmdLosim(char *str
)
212 for(i
= 0; i
< GraphTraceLen
; i
+= 48) {
215 for(j
= 0; j
< 48; j
++) {
216 c
.d
.asBytes
[j
] = GraphBuffer
[i
+j
];
218 c
.cmd
= CMD_DOWNLOADED_SIM_SAMPLES_125K
;
220 SendCommand(&c
, FALSE
);
224 c
.cmd
= CMD_SIMULATE_TAG_125K
;
225 c
.ext1
= GraphTraceLen
;
226 SendCommand(&c
, FALSE
);
229 static void CmdLoread(char *str
)
232 // 'h' means higher-low-frequency, 134 kHz
235 } else if (*str
== '\0') {
238 PrintToScrollback("use 'loread' or 'loread h'");
241 c
.cmd
= CMD_ACQUIRE_RAW_ADC_SAMPLES_125K
;
242 SendCommand(&c
, FALSE
);
245 static void CmdLosamples(char *str
)
253 if (n
>16000) n
=16000;
255 for(i
= 0; i
< n
; i
+= 12) {
257 c
.cmd
= CMD_DOWNLOAD_RAW_ADC_SAMPLES_125K
;
259 SendCommand(&c
, FALSE
);
261 if(c
.cmd
!= CMD_DOWNLOADED_RAW_ADC_SAMPLES_125K
) {
262 PrintToScrollback("bad resp\n");
266 for(j
= 0; j
< 48; j
++) {
267 GraphBuffer
[cnt
++] = ((int)c
.d
.asBytes
[j
]) - 128;
271 RepaintGraphWindow();
274 static void CmdBitsamples(char *str
)
281 for(i
= 0; i
< n
; i
+= 12) {
283 c
.cmd
= CMD_DOWNLOAD_RAW_ADC_SAMPLES_125K
;
285 SendCommand(&c
, FALSE
);
287 if(c
.cmd
!= CMD_DOWNLOADED_RAW_ADC_SAMPLES_125K
) {
288 PrintToScrollback("bad resp\n");
292 for(j
= 0; j
< 48; j
++) {
293 for(k
= 0; k
< 8; k
++) {
294 if(c
.d
.asBytes
[j
] & (1 << (7 - k
))) {
295 GraphBuffer
[cnt
++] = 1;
297 GraphBuffer
[cnt
++] = 0;
303 RepaintGraphWindow();
306 static void CmdHisamples(char *str
)
312 for(i
= 0; i
< n
; i
+= 12) {
314 c
.cmd
= CMD_DOWNLOAD_RAW_ADC_SAMPLES_125K
;
316 SendCommand(&c
, FALSE
);
318 if(c
.cmd
!= CMD_DOWNLOADED_RAW_ADC_SAMPLES_125K
) {
319 PrintToScrollback("bad resp\n");
323 for(j
= 0; j
< 48; j
++) {
324 GraphBuffer
[cnt
++] = (int)((BYTE
)c
.d
.asBytes
[j
]);
329 RepaintGraphWindow();
333 static int CmdHisamplest(char *str
, int nrlow
)
345 for(i
= 0; i
< n
; i
+= 12) {
347 c
.cmd
= CMD_DOWNLOAD_RAW_ADC_SAMPLES_125K
;
349 SendCommand(&c
, FALSE
);
351 if(c
.cmd
!= CMD_DOWNLOADED_RAW_ADC_SAMPLES_125K
) {
352 PrintToScrollback("bad resp\n");
356 for(j
= 0; j
< 48; j
++) {
357 t2
= (int)((BYTE
)c
.d
.asBytes
[j
]);
358 if((t2
^ 0xC0) & 0xC0) { hasbeennull
++; }
364 t1
= (t2
& 0x80) ^ (t2
& 0x20);
365 t2
= ((t2
<< 1) & 0x80) ^ ((t2
<< 1) & 0x20);
371 t2
= ((t2
<< 1) & 0x80);
377 t2
= ((t2
<< 1) & 0x20);
381 // both, but tag with other algorithm
382 t1
= (t2
& 0x80) ^ (t2
& 0x08);
383 t2
= ((t2
<< 1) & 0x80) ^ ((t2
<< 1) & 0x08);
387 GraphBuffer
[cnt
++] = t1
;
388 GraphBuffer
[cnt
++] = t2
;
393 if(hasbeennull
>nrlow
|| nrlow
==0) {
394 PrintToScrollback("hasbeennull=%d", hasbeennull
);
403 static void CmdHexsamples(char *str
)
414 for(i
= 0; i
< n
; i
+= 12) {
416 c
.cmd
= CMD_DOWNLOAD_RAW_ADC_SAMPLES_125K
;
418 SendCommand(&c
, FALSE
);
420 if(c
.cmd
!= CMD_DOWNLOADED_RAW_ADC_SAMPLES_125K
) {
421 PrintToScrollback("bad resp\n");
425 for(j
= 0; j
< 48; j
+= 8) {
426 PrintToScrollback("%02x %02x %02x %02x %02x %02x %02x %02x",
441 static void CmdHisampless(char *str
)
453 for(i
= 0; i
< n
; i
+= 12) {
455 c
.cmd
= CMD_DOWNLOAD_RAW_ADC_SAMPLES_125K
;
457 SendCommand(&c
, FALSE
);
459 if(c
.cmd
!= CMD_DOWNLOADED_RAW_ADC_SAMPLES_125K
) {
460 PrintToScrollback("bad resp\n");
464 for(j
= 0; j
< 48; j
++) {
465 GraphBuffer
[cnt
++] = (int)((signed char)c
.d
.asBytes
[j
]);
470 RepaintGraphWindow();
473 static WORD
Iso15693Crc(BYTE
*v
, int n
)
479 for(i
= 0; i
< n
; i
++) {
480 reg
= reg
^ ((DWORD
)v
[i
]);
481 for (j
= 0; j
< 8; j
++) {
483 reg
= (reg
>> 1) ^ 0x8408;
493 static void CmdHi14bdemod(char *str
)
498 BOOL negateI
, negateQ
;
503 // As received, the samples are pairs, correlations against I and Q
504 // square waves. So estimate angle of initial carrier (or just
505 // quadrant, actually), and then do the demod.
507 // First, estimate where the tag starts modulating.
508 for(i
= 0; i
< GraphTraceLen
; i
+= 2) {
509 if(abs(GraphBuffer
[i
]) + abs(GraphBuffer
[i
+1]) > 40) {
513 if(i
>= GraphTraceLen
) {
514 PrintToScrollback("too weak to sync");
517 PrintToScrollback("out of weak at %d", i
);
520 // Now, estimate the phase in the initial modulation of the tag
523 for(; i
< (outOfWeakAt
+ 16); i
+= 2) {
524 isum
+= GraphBuffer
[i
+0];
525 qsum
+= GraphBuffer
[i
+1];
527 negateI
= (isum
< 0);
528 negateQ
= (qsum
< 0);
530 // Turn the correlation pairs into soft decisions on the bit.
532 for(i
= 0; i
< GraphTraceLen
/2; i
++) {
533 int si
= GraphBuffer
[j
];
534 int sq
= GraphBuffer
[j
+1];
535 if(negateI
) si
= -si
;
536 if(negateQ
) sq
= -sq
;
537 GraphBuffer
[i
] = si
+ sq
;
543 while(GraphBuffer
[i
] > 0 && i
< GraphTraceLen
)
545 if(i
>= GraphTraceLen
) goto demodError
;
548 while(GraphBuffer
[i
] < 0 && i
< GraphTraceLen
)
550 if(i
>= GraphTraceLen
) goto demodError
;
551 if((i
- iold
) > 23) goto demodError
;
553 PrintToScrollback("make it to demod loop");
557 while(GraphBuffer
[i
] >= 0 && i
< GraphTraceLen
)
559 if(i
>= GraphTraceLen
) goto demodError
;
560 if((i
- iold
) > 6) goto demodError
;
563 if(i
+ 20 >= GraphTraceLen
) goto demodError
;
565 for(j
= 0; j
< 10; j
++) {
566 int soft
= GraphBuffer
[i
] + GraphBuffer
[i
+1];
568 if(abs(soft
) < ((abs(isum
) + abs(qsum
))/20)) {
569 PrintToScrollback("weak bit");
573 if(GraphBuffer
[i
] + GraphBuffer
[i
+1] >= 0) {
580 if( (shiftReg
& 0x200) &&
583 // valid data byte, start and stop bits okay
584 PrintToScrollback(" %02x", (shiftReg
>> 1) & 0xff);
585 data
[dataLen
++] = (shiftReg
>> 1) & 0xff;
586 if(dataLen
>= sizeof(data
)) {
589 } else if(shiftReg
== 0x000) {
598 ComputeCrc14443(CRC_14443_B
, data
, dataLen
-2, &first
, &second
);
599 PrintToScrollback("CRC: %02x %02x (%s)\n", first
, second
,
600 (first
== data
[dataLen
-2] && second
== data
[dataLen
-1]) ?
601 "ok" : "****FAIL****");
603 RepaintGraphWindow();
607 PrintToScrollback("demod error");
608 RepaintGraphWindow();
611 static void CmdHi14list(char *str
)
614 GetFromBigBuf(got
, sizeof(got
));
616 PrintToScrollback("recorded activity:");
617 PrintToScrollback(" time :rssi: who bytes");
618 PrintToScrollback("---------+----+----+-----------");
629 int timestamp
= *((DWORD
*)(got
+i
));
630 if(timestamp
& 0x80000000) {
631 timestamp
&= 0x7fffffff;
636 int metric
= *((DWORD
*)(got
+i
+4));
647 BYTE
*frame
= (got
+i
+9);
649 char line
[1000] = "";
651 for(j
= 0; j
< len
; j
++) {
652 sprintf(line
+(j
*3), "%02x ", frame
[j
]);
658 ComputeCrc14443(CRC_14443_B
, frame
, len
-2, &b1
, &b2
);
659 if(b1
!= frame
[len
-2] || b2
!= frame
[len
-1]) {
660 crc
= "**FAIL CRC**";
668 char metricString
[100];
670 sprintf(metricString
, "%3d", metric
);
672 strcpy(metricString
, " ");
675 PrintToScrollback(" +%7d: %s: %s %s %s",
676 (prev
< 0 ? 0 : timestamp
- prev
),
678 (isResponse
? "TAG" : " "), line
, crc
);
685 static void CmdHi14alist(char *str
)
688 GetFromBigBuf(got
, sizeof(got
));
690 PrintToScrollback("recorded activity:");
691 PrintToScrollback(" ETU :rssi: who bytes");
692 PrintToScrollback("---------+----+----+-----------");
703 int timestamp
= *((DWORD
*)(got
+i
));
704 if(timestamp
& 0x80000000) {
705 timestamp
&= 0x7fffffff;
712 int parityBits
= *((DWORD
*)(got
+i
+4));
713 // 4 bytes of additional information...
714 // maximum of 32 additional parity bit information
717 // at each quarter bit period we can send power level (16 levels)
718 // or each half bit period in 256 levels.
726 if(i
+ len
>= 1900) {
730 BYTE
*frame
= (got
+i
+9);
732 // Break and stick with current result if buffer was not completely full
733 if(frame
[0] == 0x44 && frame
[1] == 0x44 && frame
[3] == 0x44) { break; }
735 char line
[1000] = "";
737 for(j
= 0; j
< len
; j
++) {
738 int oddparity
= 0x01;
742 oddparity
^= (((frame
[j
] & 0xFF) >> k
) & 0x01);
745 //if((parityBits >> (len - j - 1)) & 0x01) {
746 if(isResponse
&& (oddparity
!= ((parityBits
>> (len
- j
- 1)) & 0x01))) {
747 sprintf(line
+(j
*4), "%02x! ", frame
[j
]);
750 sprintf(line
+(j
*4), "%02x ", frame
[j
]);
758 for(j
= 0; j
< (len
- 1); j
++) {
759 // gives problems... search for the reason..
760 /*if(frame[j] == 0xAA) {
763 crc = "[1] Two drops close after each other";
766 crc = "[2] Potential SOC with a drop in second half of bitperiod";
769 crc = "[3] Segment Z after segment X is not possible";
772 crc = "[4] Parity bit of a fully received byte was wrong";
775 crc = "[?] Unknown error";
783 ComputeCrc14443(CRC_14443_A
, frame
, len
-2, &b1
, &b2
);
784 if(b1
!= frame
[len
-2] || b2
!= frame
[len
-1]) {
785 crc
= (isResponse
& (len
< 6)) ? "" : " !crc";
794 char metricString
[100];
796 sprintf(metricString
, "%3d", metric
);
798 strcpy(metricString
, " ");
801 PrintToScrollback(" +%7d: %s: %s %s %s",
802 (prev
< 0 ? 0 : (timestamp
- prev
)),
804 (isResponse
? "TAG" : " "), line
, crc
);
812 static void CmdHi15demod(char *str
)
814 // The sampling rate is 106.353 ksps/s, for T = 18.8 us
817 // 1) Unmodulated time of 56.64us
818 // 2) 24 pulses of 423.75khz
819 // 3) logic '1' (unmodulated for 18.88us followed by 8 pulses of 423.75khz)
821 static const int FrameSOF
[] = {
822 -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
823 -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
824 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
825 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
831 static const int Logic0
[] = {
837 static const int Logic1
[] = {
845 // 1) logic '0' (8 pulses of 423.75khz followed by unmodulated for 18.88us)
846 // 2) 24 pulses of 423.75khz
847 // 3) Unmodulated time of 56.64us
849 static const int FrameEOF
[] = {
854 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
855 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
856 -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
857 -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1
865 if(GraphTraceLen
< 1000) return;
867 // First, correlate for SOF
868 for(i
= 0; i
< 100; i
++) {
870 for(j
= 0; j
< arraylen(FrameSOF
); j
+= skip
) {
871 corr
+= FrameSOF
[j
]*GraphBuffer
[i
+(j
/skip
)];
878 PrintToScrollback("SOF at %d, correlation %d", maxPos
,
879 max
/(arraylen(FrameSOF
)/skip
));
881 i
= maxPos
+ arraylen(FrameSOF
)/skip
;
884 memset(outBuf
, 0, sizeof(outBuf
));
887 int corr0
= 0, corr1
= 0, corrEOF
= 0;
888 for(j
= 0; j
< arraylen(Logic0
); j
+= skip
) {
889 corr0
+= Logic0
[j
]*GraphBuffer
[i
+(j
/skip
)];
891 for(j
= 0; j
< arraylen(Logic1
); j
+= skip
) {
892 corr1
+= Logic1
[j
]*GraphBuffer
[i
+(j
/skip
)];
894 for(j
= 0; j
< arraylen(FrameEOF
); j
+= skip
) {
895 corrEOF
+= FrameEOF
[j
]*GraphBuffer
[i
+(j
/skip
)];
897 // Even things out by the length of the target waveform.
901 if(corrEOF
> corr1
&& corrEOF
> corr0
) {
902 PrintToScrollback("EOF at %d", i
);
904 } else if(corr1
> corr0
) {
905 i
+= arraylen(Logic1
)/skip
;
908 i
+= arraylen(Logic0
)/skip
;
915 if((i
+(int)arraylen(FrameEOF
)) >= GraphTraceLen
) {
916 PrintToScrollback("ran off end!");
921 PrintToScrollback("error, uneven octet! (discard extra bits!)");
922 PrintToScrollback(" mask=%02x", mask
);
924 PrintToScrollback("%d octets", k
);
926 for(i
= 0; i
< k
; i
++) {
927 PrintToScrollback("# %2d: %02x ", i
, outBuf
[i
]);
929 PrintToScrollback("CRC=%04x", Iso15693Crc(outBuf
, k
-2));
932 static void CmdTiread(char *str
)
935 c
.cmd
= CMD_ACQUIRE_RAW_BITS_TI_TYPE
;
936 SendCommand(&c
, FALSE
);
939 static void CmdTibits(char *str
)
943 for(i
= 0; i
< 1536; i
+= 12) {
945 c
.cmd
= CMD_DOWNLOAD_RAW_BITS_TI_TYPE
;
947 SendCommand(&c
, FALSE
);
949 if(c
.cmd
!= CMD_DOWNLOADED_RAW_BITS_TI_TYPE
) {
950 PrintToScrollback("bad resp\n");
954 for(j
= 0; j
< 12; j
++) {
956 for(k
= 31; k
>= 0; k
--) {
957 if(c
.d
.asDwords
[j
] & (1 << k
)) {
958 GraphBuffer
[cnt
++] = 1;
960 GraphBuffer
[cnt
++] = -1;
965 GraphTraceLen
= 1536*32;
966 RepaintGraphWindow();
969 static void CmdTidemod(char *cmdline
)
971 /* MATLAB as follows:
972 f_s = 2000000; % sampling frequency
973 f_l = 123200; % low FSK tone
974 f_h = 134200; % high FSK tone
976 T_l = 119e-6; % low bit duration
977 T_h = 130e-6; % high bit duration
979 l = 2*pi*ones(1, floor(f_s*T_l))*(f_l/f_s);
980 h = 2*pi*ones(1, floor(f_s*T_h))*(f_h/f_s);
982 l = sign(sin(cumsum(l)));
983 h = sign(sin(cumsum(h)));
985 static const int LowTone
[] = {
986 1, 1, 1, 1, 1, 1, 1, 1, -1, -1, -1, -1, -1, -1, -1, -1, 1, 1, 1,
987 1, 1, 1, 1, 1, -1, -1, -1, -1, -1, -1, -1, -1, 1, 1, 1, 1, 1, 1,
988 1, 1, -1, -1, -1, -1, -1, -1, -1, -1, 1, 1, 1, 1, 1, 1, 1, 1, -1,
989 -1, -1, -1, -1, -1, -1, -1, 1, 1, 1, 1, 1, 1, 1, 1, 1, -1, -1, -1,
990 -1, -1, -1, -1, -1, 1, 1, 1, 1, 1, 1, 1, 1, -1, -1, -1, -1, -1, -1,
991 -1, -1, 1, 1, 1, 1, 1, 1, 1, 1, -1, -1, -1, -1, -1, -1, -1, -1, 1,
992 1, 1, 1, 1, 1, 1, 1, -1, -1, -1, -1, -1, -1, -1, -1, 1, 1, 1, 1,
993 1, 1, 1, 1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 1, 1, 1, 1, 1, 1,
994 1, 1, -1, -1, -1, -1, -1, -1, -1, -1, 1, 1, 1, 1, 1, 1, 1, 1, -1,
995 -1, -1, -1, -1, -1, -1, -1, 1, 1, 1, 1, 1, 1, 1, 1, -1, -1, -1, -1,
996 -1, -1, -1, -1, 1, 1, 1, 1, 1, 1, 1, 1, -1, -1, -1, -1, -1, -1, -1,
997 -1, -1, 1, 1, 1, 1, 1, 1, 1, 1, -1, -1, -1, -1, -1, -1, -1, -1, 1,
998 1, 1, 1, 1, 1, 1, 1, -1, -1, -1,
1000 static const int HighTone
[] = {
1001 1, 1, 1, 1, 1, 1, 1, -1, -1, -1, -1, -1, -1, -1, 1, 1, 1, 1, 1, 1,
1002 1, 1, -1, -1, -1, -1, -1, -1, -1, 1, 1, 1, 1, 1, 1, 1, 1, -1, -1,
1003 -1, -1, -1, -1, -1, 1, 1, 1, 1, 1, 1, 1, 1, -1, -1, -1, -1, -1,
1004 -1, -1, 1, 1, 1, 1, 1, 1, 1, 1, -1, -1, -1, -1, -1, -1, -1, 1, 1,
1005 1, 1, 1, 1, 1, -1, -1, -1, -1, -1, -1, -1, -1, 1, 1, 1, 1, 1, 1,
1006 1, -1, -1, -1, -1, -1, -1, -1, -1, 1, 1, 1, 1, 1, 1, 1, -1, -1,
1007 -1, -1, -1, -1, -1, -1, 1, 1, 1, 1, 1, 1, 1, -1, -1, -1, -1, -1,
1008 -1, -1, -1, 1, 1, 1, 1, 1, 1, 1, -1, -1, -1, -1, -1, -1, -1, -1,
1009 1, 1, 1, 1, 1, 1, 1, -1, -1, -1, -1, -1, -1, -1, 1, 1, 1, 1, 1, 1,
1010 1, 1, -1, -1, -1, -1, -1, -1, -1, 1, 1, 1, 1, 1, 1, 1, 1, -1, -1,
1011 -1, -1, -1, -1, -1, 1, 1, 1, 1, 1, 1, 1, 1, -1, -1, -1, -1, -1,
1012 -1, -1, 1, 1, 1, 1, 1, 1, 1, 1, -1, -1, -1, -1, -1, -1, -1, 1, 1,
1013 1, 1, 1, 1, 1, -1, -1, -1, -1, -1, -1, -1, -1, 1, 1, 1, 1, 1, 1,
1014 1, -1, -1, -1, -1, -1, -1, -1, -1, 1, 1, 1, 1, 1, 1, 1,
1017 int convLen
= max(arraylen(HighTone
), arraylen(LowTone
));
1020 for(i
= 0; i
< GraphTraceLen
- convLen
; i
++) {
1022 int lowSum
= 0, highSum
= 0;;
1023 int lowLen
= arraylen(LowTone
);
1024 int highLen
= arraylen(HighTone
);
1026 for(j
= 0; j
< lowLen
; j
++) {
1027 lowSum
+= LowTone
[j
]*GraphBuffer
[i
+j
];
1029 for(j
= 0; j
< highLen
; j
++) {
1030 highSum
+= HighTone
[j
]*GraphBuffer
[i
+j
];
1032 lowSum
= abs((100*lowSum
) / lowLen
);
1033 highSum
= abs((100*highSum
) / highLen
);
1034 GraphBuffer
[i
] = (highSum
<< 16) | lowSum
;
1037 for(i
= 0; i
< GraphTraceLen
- convLen
- 16; i
++) {
1039 int lowTot
= 0, highTot
= 0;
1040 // 16 and 15 are f_s divided by f_l and f_h, rounded
1041 for(j
= 0; j
< 16; j
++) {
1042 lowTot
+= (GraphBuffer
[i
+j
] & 0xffff);
1044 for(j
= 0; j
< 15; j
++) {
1045 highTot
+= (GraphBuffer
[i
+j
] >> 16);
1047 GraphBuffer
[i
] = lowTot
- highTot
;
1050 GraphTraceLen
-= (convLen
+ 16);
1052 RepaintGraphWindow();
1054 // Okay, so now we have unsliced soft decisions; find bit-sync, and then
1057 int max
= 0, maxPos
= 0;
1058 for(i
= 0; i
< 6000; i
++) {
1061 for(j
= 0; j
< 8*arraylen(LowTone
); j
++) {
1062 dec
-= GraphBuffer
[i
+j
];
1064 for(; j
< 8*arraylen(LowTone
) + 8*arraylen(HighTone
); j
++) {
1065 dec
+= GraphBuffer
[i
+j
];
1072 GraphBuffer
[maxPos
] = 800;
1073 GraphBuffer
[maxPos
+1] = -800;
1075 maxPos
+= 8*arraylen(LowTone
);
1076 GraphBuffer
[maxPos
] = 800;
1077 GraphBuffer
[maxPos
+1] = -800;
1078 maxPos
+= 8*arraylen(HighTone
);
1080 GraphBuffer
[maxPos
] = 800;
1081 GraphBuffer
[maxPos
+1] = -800;
1083 PrintToScrollback("actual data bits start at sample %d", maxPos
);
1085 PrintToScrollback("length %d/%d", arraylen(HighTone
), arraylen(LowTone
));
1087 GraphBuffer
[maxPos
] = 800;
1088 GraphBuffer
[maxPos
+1] = -800;
1090 BYTE bits
[64+16+8+1];
1091 bits
[sizeof(bits
)-1] = '\0';
1093 for(i
= 0; i
< arraylen(bits
); i
++) {
1097 for(j
= 0; j
< arraylen(LowTone
); j
++) {
1098 low
-= GraphBuffer
[maxPos
+j
];
1100 for(j
= 0; j
< arraylen(HighTone
); j
++) {
1101 high
+= GraphBuffer
[maxPos
+j
];
1105 maxPos
+= arraylen(HighTone
);
1108 maxPos
+= arraylen(LowTone
);
1110 GraphBuffer
[maxPos
] = 800;
1111 GraphBuffer
[maxPos
+1] = -800;
1113 PrintToScrollback("bits: '%s'", bits
);
1116 for(i
= 0; i
< 32; i
++) {
1117 if(bits
[i
] == '1') {
1121 for(i
= 32; i
< 64; i
++) {
1122 if(bits
[i
] == '1') {
1126 PrintToScrollback("hex: %08x %08x", h
, l
);
1129 static void CmdNorm(char *str
)
1132 int max
= INT_MIN
, min
= INT_MAX
;
1133 for(i
= 10; i
< GraphTraceLen
; i
++) {
1134 if(GraphBuffer
[i
] > max
) {
1135 max
= GraphBuffer
[i
];
1137 if(GraphBuffer
[i
] < min
) {
1138 min
= GraphBuffer
[i
];
1142 for(i
= 0; i
< GraphTraceLen
; i
++) {
1143 GraphBuffer
[i
] = (GraphBuffer
[i
] - ((max
+ min
)/2))*1000/
1147 RepaintGraphWindow();
1150 static void CmdDec(char *str
)
1153 for(i
= 0; i
< (GraphTraceLen
/2); i
++) {
1154 GraphBuffer
[i
] = GraphBuffer
[i
*2];
1157 PrintToScrollback("decimated by 2");
1158 RepaintGraphWindow();
1161 static void CmdHpf(char *str
)
1165 for(i
= 10; i
< GraphTraceLen
; i
++) {
1166 accum
+= GraphBuffer
[i
];
1168 accum
/= (GraphTraceLen
- 10);
1169 for(i
= 0; i
< GraphTraceLen
; i
++) {
1170 GraphBuffer
[i
] -= accum
;
1173 RepaintGraphWindow();
1176 static void CmdZerocrossings(char *str
)
1179 // Zero-crossings aren't meaningful unless the signal is zero-mean.
1185 for(i
= 0; i
< GraphTraceLen
; i
++) {
1186 if(GraphBuffer
[i
]*sign
>= 0) {
1187 // No change in sign, reproduce the previous sample count.
1189 GraphBuffer
[i
] = lastZc
;
1191 // Change in sign, reset the sample count.
1193 GraphBuffer
[i
] = lastZc
;
1201 RepaintGraphWindow();
1204 static void CmdLtrim(char *str
)
1209 for(i
= ds
; i
< GraphTraceLen
; i
++) {
1210 GraphBuffer
[i
-ds
] = GraphBuffer
[i
];
1212 GraphTraceLen
-= ds
;
1214 RepaintGraphWindow();
1217 static void CmdAutoCorr(char *str
)
1219 static int CorrelBuffer
[MAX_GRAPH_TRACE_LEN
];
1221 int window
= atoi(str
);
1224 PrintToScrollback("needs a window");
1228 if(window
>= GraphTraceLen
) {
1229 PrintToScrollback("window must be smaller than trace (%d samples)",
1234 PrintToScrollback("performing %d correlations", GraphTraceLen
- window
);
1237 for(i
= 0; i
< GraphTraceLen
- window
; i
++) {
1240 for(j
= 0; j
< window
; j
++) {
1241 sum
+= (GraphBuffer
[j
]*GraphBuffer
[i
+j
]) / 256;
1243 CorrelBuffer
[i
] = sum
;
1245 GraphTraceLen
= GraphTraceLen
- window
;
1246 memcpy(GraphBuffer
, CorrelBuffer
, GraphTraceLen
*sizeof(int));
1248 RepaintGraphWindow();
1251 static void CmdVchdemod(char *str
)
1253 // Is this the entire sync pattern, or does this also include some
1254 // data bits that happen to be the same everywhere? That would be
1256 static const int SyncPattern
[] = {
1257 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
1258 1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
1259 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
1260 1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
1261 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
1262 1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
1263 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
1264 1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
1265 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
1266 1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
1269 // So first, we correlate for the sync pattern, and mark that.
1270 int bestCorrel
= 0, bestPos
= 0;
1272 // It does us no good to find the sync pattern, with fewer than
1273 // 2048 samples after it...
1274 for(i
= 0; i
< (GraphTraceLen
-2048); i
++) {
1277 for(j
= 0; j
< arraylen(SyncPattern
); j
++) {
1278 sum
+= GraphBuffer
[i
+j
]*SyncPattern
[j
];
1280 if(sum
> bestCorrel
) {
1285 PrintToScrollback("best sync at %d [metric %d]", bestPos
, bestCorrel
);
1290 int worst
= INT_MAX
;
1293 for(i
= 0; i
< 2048; i
+= 8) {
1296 for(j
= 0; j
< 8; j
++) {
1297 sum
+= GraphBuffer
[bestPos
+i
+j
];
1304 if(abs(sum
) < worst
) {
1309 PrintToScrollback("bits:");
1310 PrintToScrollback("%s", bits
);
1311 PrintToScrollback("worst metric: %d at pos %d", worst
, worstPos
);
1313 if(strcmp(str
, "clone")==0) {
1316 for(s
= bits
; *s
; s
++) {
1318 for(j
= 0; j
< 16; j
++) {
1319 GraphBuffer
[GraphTraceLen
++] = (*s
== '1') ? 1 : 0;
1322 RepaintGraphWindow();
1326 static void CmdIndalademod(char *str
)
1328 // Usage: recover 64bit UID by default, specify "224" as arg to recover a 224bit UID
1333 // worst case with GraphTraceLen=64000 is < 4096
1334 // under normal conditions it's < 2048
1337 int worst
= 0, worstPos
= 0;
1338 PrintToScrollback("Expecting a bit less than %d raw bits", GraphTraceLen
/32);
1339 for(i
= 0; i
< GraphTraceLen
-1; i
+= 2) {
1341 if((GraphBuffer
[i
] > GraphBuffer
[i
+ 1]) && (state
!= 1)) {
1343 for(j
= 0; j
< count
- 8; j
+= 16) {
1344 rawbits
[rawbit
++] = 0;
1346 if ((abs(count
- j
)) > worst
) {
1347 worst
= abs(count
- j
);
1353 } else if((GraphBuffer
[i
] < GraphBuffer
[i
+ 1]) && (state
!= 0)) {
1355 for(j
= 0; j
< count
- 8; j
+= 16) {
1356 rawbits
[rawbit
++] = 1;
1358 if ((abs(count
- j
)) > worst
) {
1359 worst
= abs(count
- j
);
1367 PrintToScrollback("Recovered %d raw bits", rawbit
);
1368 PrintToScrollback("worst metric (0=best..7=worst): %d at pos %d", worst
, worstPos
);
1370 // Finding the start of a UID
1371 int uidlen
, long_wait
;
1372 if(strcmp(str
, "224") == 0) {
1381 for(start
= 0; start
<= rawbit
- uidlen
; start
++) {
1382 first
= rawbits
[start
];
1383 for(i
= start
; i
< start
+ long_wait
; i
++) {
1384 if(rawbits
[i
] != first
) {
1388 if(i
== (start
+ long_wait
)) {
1392 if(start
== rawbit
- uidlen
+ 1) {
1393 PrintToScrollback("nothing to wait for");
1397 // Inverting signal if needed
1399 for(i
= start
; i
< rawbit
; i
++) {
1400 rawbits
[i
] = !rawbits
[i
];
1407 showbits
[uidlen
]='\0';
1411 if(uidlen
> rawbit
) {
1412 PrintToScrollback("Warning: not enough raw bits to get a full UID");
1413 for(bit
= 0; bit
< rawbit
; bit
++) {
1414 bits
[bit
] = rawbits
[i
++];
1415 // As we cannot know the parity, let's use "." and "/"
1416 showbits
[bit
] = '.' + bits
[bit
];
1418 showbits
[bit
+1]='\0';
1419 PrintToScrollback("Partial UID=%s", showbits
);
1422 for(bit
= 0; bit
< uidlen
; bit
++) {
1423 bits
[bit
] = rawbits
[i
++];
1424 showbits
[bit
] = '0' + bits
[bit
];
1428 PrintToScrollback("UID=%s", showbits
);
1430 // Checking UID against next occurences
1431 for(; i
+ uidlen
<= rawbit
;) {
1433 for(bit
= 0; bit
< uidlen
; bit
++) {
1434 if(bits
[bit
] != rawbits
[i
++]) {
1444 PrintToScrollback("Occurences: %d (expected %d)", times
, (rawbit
- start
) / uidlen
);
1446 // Remodulating for tag cloning
1447 GraphTraceLen
= 32*uidlen
;
1450 for(bit
= 0; bit
< uidlen
; bit
++) {
1451 if(bits
[bit
] == 0) {
1457 for(j
= 0; j
< 32; j
++) {
1458 GraphBuffer
[i
++] = phase
;
1463 RepaintGraphWindow();
1466 static void CmdFlexdemod(char *str
)
1469 for(i
= 0; i
< GraphTraceLen
; i
++) {
1470 if(GraphBuffer
[i
] < 0) {
1471 GraphBuffer
[i
] = -1;
1477 #define LONG_WAIT 100
1479 for(start
= 0; start
< GraphTraceLen
- LONG_WAIT
; start
++) {
1480 int first
= GraphBuffer
[start
];
1481 for(i
= start
; i
< start
+ LONG_WAIT
; i
++) {
1482 if(GraphBuffer
[i
] != first
) {
1486 if(i
== (start
+ LONG_WAIT
)) {
1490 if(start
== GraphTraceLen
- LONG_WAIT
) {
1491 PrintToScrollback("nothing to wait for");
1495 GraphBuffer
[start
] = 2;
1496 GraphBuffer
[start
+1] = -2;
1502 for(bit
= 0; bit
< 64; bit
++) {
1505 for(j
= 0; j
< 16; j
++) {
1506 sum
+= GraphBuffer
[i
++];
1513 PrintToScrollback("bit %d sum %d", bit
, sum
);
1516 for(bit
= 0; bit
< 64; bit
++) {
1519 for(j
= 0; j
< 16; j
++) {
1520 sum
+= GraphBuffer
[i
++];
1522 if(sum
> 0 && bits
[bit
] != 1) {
1523 PrintToScrollback("oops1 at %d", bit
);
1525 if(sum
< 0 && bits
[bit
] != 0) {
1526 PrintToScrollback("oops2 at %d", bit
);
1530 GraphTraceLen
= 32*64;
1533 for(bit
= 0; bit
< 64; bit
++) {
1534 if(bits
[bit
] == 0) {
1540 for(j
= 0; j
< 32; j
++) {
1541 GraphBuffer
[i
++] = phase
;
1546 RepaintGraphWindow();
1550 * Generic command to demodulate ASK. bit length in argument.
1551 * Giving the bit length helps discriminate ripple effects
1552 * upon zero crossing for noisy traces.
1554 * Second is convention: positive or negative (High mod means zero
1555 * or high mod means one)
1557 * Updates the Graph trace with 0/1 values
1560 * sl : bit length in terms of number of samples per bit
1561 * (use yellow/purple markers to compute).
1565 static void Cmdaskdemod(char *str
) {
1572 // TODO: complain if we do not give 2 arguments here !
1573 sscanf(str
, "%i %i", &n
, &c
);
1580 if (GraphBuffer
[0]*c
> 0) {
1585 for(i
=1;i
<GraphTraceLen
;i
++) {
1586 /* Analyse signal within the symbol length */
1587 /* Decide if we crossed a zero */
1588 if (GraphBuffer
[i
]*sign
< 0) {
1589 /* Crossed a zero, check if this is a ripple or not */
1590 if ( (i
-t1
) > n
/4 ) {
1593 if (GraphBuffer
[i
]*c
> 0){
1599 /* This is a ripple, set the current sample value
1600 to the same as previous */
1601 GraphBuffer
[i
] = GraphBuffer
[i
-1];
1604 GraphBuffer
[i
] = GraphBuffer
[i
-1];
1607 RepaintGraphWindow();
1612 * Manchester demodulate a bitstream. The bitstream needs to be already in
1613 * the GraphBuffer as 0 and 1 values
1615 * Give the clock rate as argument in order to help the sync - the algorithm
1616 * resyncs at each pulse anyway.
1618 * Not optimized by any means, this is the 1st time I'm writing this type of
1619 * routine, feel free to improve...
1621 * 1st argument: clock rate (as number of samples per clock rate)
1622 * Typical values can be 64, 32, 128...
1624 static void Cmdmanchesterdemod(char *str
) {
1631 int hithigh
, hitlow
, first
;
1637 sscanf(str
, "%i", &clock
);
1640 PrintToScrollback("You must provide a clock rate.");
1644 int tolerance
= clock
/4;
1645 /* Holds the decoded bitstream: each clock period contains 2 bits */
1646 /* later simplified to 1 bit after manchester decoding. */
1647 /* Add 10 bits to allow for noisy / uncertain traces without aborting */
1648 /* int BitStream[GraphTraceLen*2/clock+10]; */
1650 /* But it does not work if compiling on WIndows: therefore we just allocate a */
1652 int BitStream
[MAX_GRAPH_TRACE_LEN
];
1654 /* Detect high and lows */
1655 for (i
= 0; i
< GraphTraceLen
; i
++)
1657 if (GraphBuffer
[i
] > high
)
1658 high
= GraphBuffer
[i
];
1659 else if (GraphBuffer
[i
] < low
)
1660 low
= GraphBuffer
[i
];
1663 /* Detect first transition */
1664 /* Lo-Hi (arbitrary) */
1665 for (i
= 0; i
< GraphTraceLen
; i
++)
1667 if (GraphBuffer
[i
] == low
)
1669 // BitStream[0]=0; // Previous state = 0;
1674 //PrintToScrollback("cool %d %d %d %d", low, high, lastval, GraphBuffer[i]);
1676 /* If we're not working with 1/0s, demod based off clock */
1680 for (i
= 0; i
< (GraphTraceLen
/ clock
); i
++)
1686 /* Find out if we hit both high and low peaks */
1687 for (j
= 0; j
< clock
; j
++)
1689 if (GraphBuffer
[(i
* clock
) + j
] == high
)
1691 else if (GraphBuffer
[(i
* clock
) + j
] == low
)
1694 /* it doesn't count if it's the first part of our read
1695 because it's really just trailing from the last sequence */
1696 if (first
&& (hithigh
|| hitlow
))
1697 hithigh
= hitlow
= 0;
1701 if (hithigh
&& hitlow
)
1705 /* If we didn't hit both high and low peaks, we had a bit transition */
1706 if (!hithigh
|| !hitlow
)
1709 BitStream
[bit2idx
++] = bit
;
1713 /* standard 1/0 bitstream */
1717 /* Then detect duration between 2 successive transitions */
1718 for (bitidx
= 1; i
< GraphTraceLen
; i
++)
1720 if (GraphBuffer
[i
-1] != GraphBuffer
[i
])
1725 // Error check: if bitidx becomes too large, we do not
1726 // have a Manchester encoded bitstream or the clock is really
1728 if (bitidx
> (GraphTraceLen
*2/clock
+8) ) {
1729 PrintToScrollback("Error: the clock you gave is probably wrong, aborting.");
1732 // Then switch depending on lc length:
1733 // Tolerance is 1/4 of clock rate (arbitrary)
1734 if (abs(lc
-clock
/2) < tolerance
) {
1735 // Short pulse : either "1" or "0"
1736 BitStream
[bitidx
++]=GraphBuffer
[i
-1];
1737 } else if (abs(lc
-clock
) < tolerance
) {
1738 // Long pulse: either "11" or "00"
1739 BitStream
[bitidx
++]=GraphBuffer
[i
-1];
1740 BitStream
[bitidx
++]=GraphBuffer
[i
-1];
1744 PrintToScrollback("Warning: Manchester decode error for pulse width detection.");
1745 PrintToScrollback("(too many of those messages mean either the stream is not Manchester encoded, or clock is wrong)");
1749 PrintToScrollback("Error: too many detection errors, aborting.");
1756 // At this stage, we now have a bitstream of "01" ("1") or "10" ("0"), parse it into final decoded bitstream
1757 // Actually, we overwrite BitStream with the new decoded bitstream, we just need to be careful
1758 // to stop output at the final bitidx2 value, not bitidx
1759 for (i
= 0; i
< bitidx
; i
+= 2) {
1760 if ((BitStream
[i
] == 0) && (BitStream
[i
+1] == 1)) {
1761 BitStream
[bit2idx
++] = 1;
1762 } else if ((BitStream
[i
] == 1) && (BitStream
[i
+1] == 0)) {
1763 BitStream
[bit2idx
++] = 0;
1765 // We cannot end up in this state, this means we are unsynchronized,
1769 PrintToScrollback("Unsynchronized, resync...");
1770 PrintToScrollback("(too many of those messages mean the stream is not Manchester encoded)");
1774 PrintToScrollback("Error: too many decode errors, aborting.");
1781 PrintToScrollback("Manchester decoded bitstream");
1782 // Now output the bitstream to the scrollback by line of 16 bits
1783 for (i
= 0; i
< (bit2idx
-16); i
+=16) {
1784 PrintToScrollback("%i %i %i %i %i %i %i %i %i %i %i %i %i %i %i %i",
1809 static void CmdHiddemod(char *str
)
1811 if(GraphTraceLen
< 4800) {
1812 PrintToScrollback("too short; need at least 4800 samples");
1816 GraphTraceLen
= 4800;
1818 for(i
= 0; i
< GraphTraceLen
; i
++) {
1819 if(GraphBuffer
[i
] < 0) {
1825 RepaintGraphWindow();
1828 static void CmdPlot(char *str
)
1833 static void CmdHide(char *str
)
1838 static void CmdScale(char *str
)
1840 CursorScaleFactor
= atoi(str
);
1841 if(CursorScaleFactor
== 0) {
1842 PrintToScrollback("bad, can't have zero scale");
1843 CursorScaleFactor
= 1;
1845 RepaintGraphWindow();
1848 static void CmdSave(char *str
)
1850 FILE *f
= fopen(str
, "w");
1852 PrintToScrollback("couldn't open '%s'", str
);
1856 for(i
= 0; i
< GraphTraceLen
; i
++) {
1857 fprintf(f
, "%d\n", GraphBuffer
[i
]);
1860 PrintToScrollback("saved to '%s'", str
);
1863 static void CmdLoad(char *str
)
1865 FILE *f
= fopen(str
, "r");
1867 PrintToScrollback("couldn't open '%s'", str
);
1873 while(fgets(line
, sizeof(line
), f
)) {
1874 GraphBuffer
[GraphTraceLen
] = atoi(line
);
1878 PrintToScrollback("loaded %d samples", GraphTraceLen
);
1879 RepaintGraphWindow();
1882 static void CmdHIDsimTAG(char *str
)
1884 unsigned int hi
=0, lo
=0;
1888 while (sscanf(&str
[i
++], "%1x", &n
) == 1) {
1889 hi
=(hi
<<4)|(lo
>>28);
1893 PrintToScrollback("Emulating tag with ID %x%16x", hi
, lo
);
1895 c
.cmd
= CMD_HID_SIM_TAG
;
1898 SendCommand(&c
, FALSE
);
1901 static void CmdLcdReset(char *str
)
1904 c
.cmd
= CMD_LCD_RESET
;
1906 SendCommand(&c
, FALSE
);
1909 static void CmdLcd(char *str
)
1914 sscanf(str
, "%x %d", &i
, &j
);
1917 SendCommand(&c
, FALSE
);
1923 static void CmdTest(char *str
)
1928 * Sets the divisor for LF frequency clock: lets the user choose any LF frequency below
1931 static void CmdSetDivisor(char *str
)
1934 c
.cmd
= CMD_SET_LF_DIVISOR
;
1936 if (( c
.ext1
<0) || (c
.ext1
>255)) {
1937 PrintToScrollback("divisor must be between 19 and 255");
1939 SendCommand(&c
, FALSE
);
1940 PrintToScrollback("Divisor set, expected freq=%dHz", 12000000/(c
.ext1
+1));
1944 static void CmdSweepLF(char *str
)
1947 c
.cmd
= CMD_SWEEP_LF
;
1948 SendCommand(&c
, FALSE
);
1952 typedef void HandlerFunction(char *cmdline
);
1956 HandlerFunction
*handler
;
1957 int offline
; // 1 if the command can be used when in offline mode
1959 } CommandTable
[] = {
1960 "tune", CmdTune
,0, "measure antenna tuning",
1961 "tiread", CmdTiread
,0, "read a TI-type 134 kHz tag",
1962 "tibits", CmdTibits
,0, "get raw bits for TI-type LF tag",
1963 "tidemod", CmdTidemod
,0, "demod raw bits for TI-type LF tag",
1964 "vchdemod", CmdVchdemod
,0, "demod samples for VeriChip",
1965 "plot", CmdPlot
,1, "show graph window",
1966 "hide", CmdHide
,1, "hide graph window",
1967 "losim", CmdLosim
,0, "simulate LF tag",
1968 "loread", CmdLoread
,0, "read (125/134 kHz) LF ID-only tag",
1969 "losamples", CmdLosamples
,0, "get raw samples for LF tag",
1970 "hisamples", CmdHisamples
,0, "get raw samples for HF tag",
1971 "hisampless", CmdHisampless
,0, "get signed raw samples, HF tag",
1972 "hisamplest", CmdHi14readt
,0, "get samples HF, for testing",
1973 "higet", CmdHi14read_sim
,0, "get samples HF, 'analog'",
1974 "bitsamples", CmdBitsamples
,0, "get raw samples as bitstring",
1975 "hexsamples", CmdHexsamples
,0, "dump big buffer as hex bytes",
1976 "hi15read", CmdHi15read
,0, "read HF tag (ISO 15693)",
1977 "hi15reader", CmdHi15reader
,0, "act like an ISO15693 reader", // new command greg
1978 "hi15sim", CmdHi15tag
,0, "fake an ISO15693 tag", // new command greg
1979 "hi14read", CmdHi14read
,0, "read HF tag (ISO 14443)",
1980 "sri512read", CmdSri512read
,0, "Read contents of a SRI512 tag",
1981 "hi14areader", CmdHi14areader
,0, "act like an ISO14443 Type A reader", // ## New reader command
1982 "hi15demod", CmdHi15demod
,1, "demod ISO15693 from tag",
1983 "hi14bdemod", CmdHi14bdemod
,1, "demod ISO14443 Type B from tag",
1984 "autocorr", CmdAutoCorr
,1, "autocorrelation over window",
1985 "norm", CmdNorm
,1, "normalize max/min to +/-500",
1986 "dec", CmdDec
,1, "decimate",
1987 "hpf", CmdHpf
,1, "remove DC offset from trace",
1988 "zerocrossings", CmdZerocrossings
,1, "count time between zero-crossings",
1989 "ltrim", CmdLtrim
,1, "trim from left of trace",
1990 "scale", CmdScale
,1, "set cursor display scale",
1991 "flexdemod", CmdFlexdemod
,1, "demod samples for FlexPass",
1992 "save", CmdSave
,1, "save trace (from graph window)",
1993 "load", CmdLoad
,1, "load trace (to graph window",
1994 "hisimlisten", CmdHisimlisten
,0, "get HF samples as fake tag",
1995 "hi14sim", CmdHi14sim
,0, "fake ISO 14443 tag",
1996 "hi14asim", CmdHi14asim
,0, "fake ISO 14443a tag", // ## Simulate 14443a tag
1997 "hi14snoop", CmdHi14snoop
,0, "eavesdrop ISO 14443",
1998 "hi14asnoop", CmdHi14asnoop
,0, "eavesdrop ISO 14443 Type A", // ## New snoop command
1999 "hi14list", CmdHi14list
,0, "list ISO 14443 history",
2000 "hi14alist", CmdHi14alist
,0, "list ISO 14443a history", // ## New list command
2001 "hiddemod", CmdHiddemod
,1, "HID Prox Card II (not optimal)",
2002 "hidfskdemod", CmdHIDdemodFSK
,0, "HID FSK demodulator",
2003 "indalademod", CmdIndalademod
,0, "demod samples for Indala",
2004 "askdemod", Cmdaskdemod
,1, "Attempt to demodulate simple ASK tags",
2005 "hidsimtag", CmdHIDsimTAG
,0, "HID tag simulator",
2006 "mandemod", Cmdmanchesterdemod
,1, "Try a Manchester demodulation on a binary stream",
2007 "fpgaoff", CmdFPGAOff
,0, "set FPGA off", // ## FPGA Control
2008 "lcdreset", CmdLcdReset
,0, "Hardware reset LCD",
2009 "lcd", CmdLcd
,0, "Send command/data to LCD",
2010 "setlfdivisor", CmdSetDivisor
,0, "Drive LF antenna at 12Mhz/(divisor+1)",
2011 "sweeplf", CmdSweepLF
,0, "Sweep through LF freq range and store results in buffer",
2012 "reset", CmdReset
,0, "Reset the Proxmark3",
2013 "quit", CmdQuit
,1, "quit program"
2017 //-----------------------------------------------------------------------------
2018 // Entry point into our code: called whenever the user types a command and
2019 // then presses Enter, which the full command line that they typed.
2020 //-----------------------------------------------------------------------------
2021 void CommandReceived(char *cmd
)
2025 PrintToScrollback("> %s", cmd
);
2027 if(strcmp(cmd
, "help")==0) {
2028 if (offline
) PrintToScrollback("Operating in OFFLINE mode (no device connected)");
2029 PrintToScrollback("\r\nAvailable commands:");
2030 for(i
= 0; i
< sizeof(CommandTable
) / sizeof(CommandTable
[0]); i
++) {
2031 if (offline
&& (CommandTable
[i
].offline
==0)) continue;
2033 memset(line
, ' ', sizeof(line
));
2034 strcpy(line
+2, CommandTable
[i
].name
);
2035 line
[strlen(line
)] = ' ';
2036 sprintf(line
+15, " -- %s", CommandTable
[i
].docString
);
2037 PrintToScrollback("%s", line
);
2039 PrintToScrollback("");
2040 PrintToScrollback("and also: help, cls");
2044 for(i
= 0; i
< sizeof(CommandTable
) / sizeof(CommandTable
[0]); i
++) {
2045 char *name
= CommandTable
[i
].name
;
2046 if(memcmp(cmd
, name
, strlen(name
))==0 &&
2047 (cmd
[strlen(name
)] == ' ' || cmd
[strlen(name
)] == '\0'))
2049 cmd
+= strlen(name
);
2050 while(*cmd
== ' ') {
2053 if (offline
&& (CommandTable
[i
].offline
==0)) {
2054 PrintToScrollback("Offline mode, cannot use this command.");
2057 (CommandTable
[i
].handler
)(cmd
);
2061 PrintToScrollback(">> bad command '%s'", cmd
);
2064 //-----------------------------------------------------------------------------
2065 // Entry point into our code: called whenever we received a packet over USB
2066 // that we weren't necessarily expecting, for example a debug print.
2067 //-----------------------------------------------------------------------------
2068 void UsbCommandReceived(UsbCommand
*c
)
2071 case CMD_DEBUG_PRINT_STRING
: {
2073 if(c
->ext1
> 70 || c
->ext1
< 0) {
2076 memcpy(s
, c
->d
.asBytes
, c
->ext1
);
2078 PrintToScrollback("#db# %s", s
);
2082 case CMD_DEBUG_PRINT_INTEGERS
:
2083 PrintToScrollback("#db# %08x, %08x, %08x\r\n", c
->ext1
, c
->ext2
, c
->ext3
);
2086 case CMD_MEASURED_ANTENNA_TUNING
: {
2088 int vLf125
, vLf134
, vHf
;
2089 vLf125
= c
->ext1
& 0xffff;
2090 vLf134
= c
->ext1
>> 16;
2092 zLf
= c
->ext3
& 0xffff;
2093 zHf
= c
->ext3
>> 16;
2094 PrintToScrollback("# LF antenna @ %3d mA / %5d mV [%d ohms] 125Khz",
2095 vLf125
/zLf
, vLf125
, zLf
);
2096 PrintToScrollback("# LF antenna @ %3d mA / %5d mV [%d ohms] 134Khz",
2097 vLf134
/((zLf
*125)/134), vLf134
, (zLf
*125)/134);
2098 PrintToScrollback("# HF antenna @ %3d mA / %5d mV [%d ohms] 13.56Mhz",
2103 PrintToScrollback("unrecognized command %08x\n", c
->cmd
);