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 CmdQuit(char *str
)
50 static void CmdHIDdemodFSK(char *str
)
53 c
.cmd
= CMD_HID_DEMOD_FSK
;
54 SendCommand(&c
, FALSE
);
57 static void CmdTune(char *str
)
60 c
.cmd
= CMD_MEASURE_ANTENNA_TUNING
;
61 SendCommand(&c
, FALSE
);
64 static void CmdHi15read(char *str
)
67 c
.cmd
= CMD_ACQUIRE_RAW_ADC_SAMPLES_ISO_15693
;
68 SendCommand(&c
, FALSE
);
71 static void CmdHi14read(char *str
)
74 c
.cmd
= CMD_ACQUIRE_RAW_ADC_SAMPLES_ISO_14443
;
76 SendCommand(&c
, FALSE
);
80 /* New command to read the contents of a SRI512 tag
81 * SRI512 tags are ISO14443-B modulated memory tags,
82 * this command just dumps the contents of the memory/
84 static void CmdSri512read(char *str
)
87 c
.cmd
= CMD_READ_SRI512_TAG
;
89 SendCommand(&c
, FALSE
);
93 static void CmdHi14areader(char *str
)
96 c
.cmd
= CMD_READER_ISO_14443a
;
98 SendCommand(&c
, FALSE
);
102 static void CmdHi15reader(char *str
)
105 c
.cmd
= CMD_READER_ISO_15693
;
107 SendCommand(&c
, FALSE
);
111 static void CmdHi15tag(char *str
)
114 c
.cmd
= CMD_SIMTAG_ISO_15693
;
116 SendCommand(&c
, FALSE
);
119 static void CmdHi14read_sim(char *str
)
122 c
.cmd
= CMD_ACQUIRE_RAW_ADC_SAMPLES_ISO_14443_SIM
;
124 SendCommand(&c
, FALSE
);
127 static void CmdHi14readt(char *str
)
130 c
.cmd
= CMD_ACQUIRE_RAW_ADC_SAMPLES_ISO_14443
;
132 SendCommand(&c
, FALSE
);
134 //CmdHisamplest(str);
135 while(CmdHisamplest(str
,atoi(str
))==0) {
136 c
.cmd
= CMD_ACQUIRE_RAW_ADC_SAMPLES_ISO_14443
;
138 SendCommand(&c
, FALSE
);
140 RepaintGraphWindow();
143 static void CmdHisimlisten(char *str
)
146 c
.cmd
= CMD_SIMULATE_TAG_HF_LISTEN
;
147 SendCommand(&c
, FALSE
);
150 static void CmdHi14sim(char *str
)
153 c
.cmd
= CMD_SIMULATE_TAG_ISO_14443
;
154 SendCommand(&c
, FALSE
);
159 static void CmdHi14asim(char *str
) // ## simulate iso14443a tag
160 { // ## greg - added ability to specify tag UID
162 unsigned int hi
=0, lo
=0;
166 while (sscanf(&str
[i
++], "%1x", &n
) == 1) {
171 c
.cmd
= CMD_SIMULATE_TAG_ISO_14443a
;
172 // c.ext should be set to *str or convert *str to the correct format for a uid
175 PrintToScrollback("Emulating 14443A TAG with UID %x%16x", hi
, lo
);
176 SendCommand(&c
, FALSE
);
179 static void CmdHi14snoop(char *str
)
182 c
.cmd
= CMD_SNOOP_ISO_14443
;
183 SendCommand(&c
, FALSE
);
186 static void CmdHi14asnoop(char *str
)
189 c
.cmd
= CMD_SNOOP_ISO_14443a
;
190 SendCommand(&c
, FALSE
);
193 static void CmdFPGAOff(char *str
) // ## FPGA Control
196 c
.cmd
= CMD_FPGA_MAJOR_MODE_OFF
;
197 SendCommand(&c
, FALSE
);
200 static void CmdLosim(char *str
)
204 for(i
= 0; i
< GraphTraceLen
; i
+= 48) {
207 for(j
= 0; j
< 48; j
++) {
208 c
.d
.asBytes
[j
] = GraphBuffer
[i
+j
];
210 c
.cmd
= CMD_DOWNLOADED_SIM_SAMPLES_125K
;
212 SendCommand(&c
, FALSE
);
216 c
.cmd
= CMD_SIMULATE_TAG_125K
;
217 c
.ext1
= GraphTraceLen
;
218 SendCommand(&c
, FALSE
);
221 static void CmdLoread(char *str
)
224 // 'h' means higher-low-frequency, 134 kHz
227 } else if (*str
== '\0') {
230 PrintToScrollback("use 'loread' or 'loread h'");
233 c
.cmd
= CMD_ACQUIRE_RAW_ADC_SAMPLES_125K
;
234 SendCommand(&c
, FALSE
);
237 static void CmdLosamples(char *str
)
245 if (n
>16000) n
=16000;
247 for(i
= 0; i
< n
; i
+= 12) {
249 c
.cmd
= CMD_DOWNLOAD_RAW_ADC_SAMPLES_125K
;
251 SendCommand(&c
, FALSE
);
253 if(c
.cmd
!= CMD_DOWNLOADED_RAW_ADC_SAMPLES_125K
) {
254 PrintToScrollback("bad resp\n");
258 for(j
= 0; j
< 48; j
++) {
259 GraphBuffer
[cnt
++] = ((int)c
.d
.asBytes
[j
]) - 128;
263 RepaintGraphWindow();
266 static void CmdBitsamples(char *str
)
273 for(i
= 0; i
< n
; i
+= 12) {
275 c
.cmd
= CMD_DOWNLOAD_RAW_ADC_SAMPLES_125K
;
277 SendCommand(&c
, FALSE
);
279 if(c
.cmd
!= CMD_DOWNLOADED_RAW_ADC_SAMPLES_125K
) {
280 PrintToScrollback("bad resp\n");
284 for(j
= 0; j
< 48; j
++) {
285 for(k
= 0; k
< 8; k
++) {
286 if(c
.d
.asBytes
[j
] & (1 << (7 - k
))) {
287 GraphBuffer
[cnt
++] = 1;
289 GraphBuffer
[cnt
++] = 0;
295 RepaintGraphWindow();
298 static void CmdHisamples(char *str
)
304 for(i
= 0; i
< n
; i
+= 12) {
306 c
.cmd
= CMD_DOWNLOAD_RAW_ADC_SAMPLES_125K
;
308 SendCommand(&c
, FALSE
);
310 if(c
.cmd
!= CMD_DOWNLOADED_RAW_ADC_SAMPLES_125K
) {
311 PrintToScrollback("bad resp\n");
315 for(j
= 0; j
< 48; j
++) {
316 GraphBuffer
[cnt
++] = (int)((BYTE
)c
.d
.asBytes
[j
]);
321 RepaintGraphWindow();
325 static int CmdHisamplest(char *str
, int nrlow
)
337 for(i
= 0; i
< n
; i
+= 12) {
339 c
.cmd
= CMD_DOWNLOAD_RAW_ADC_SAMPLES_125K
;
341 SendCommand(&c
, FALSE
);
343 if(c
.cmd
!= CMD_DOWNLOADED_RAW_ADC_SAMPLES_125K
) {
344 PrintToScrollback("bad resp\n");
348 for(j
= 0; j
< 48; j
++) {
349 t2
= (int)((BYTE
)c
.d
.asBytes
[j
]);
350 if((t2
^ 0xC0) & 0xC0) { hasbeennull
++; }
356 t1
= (t2
& 0x80) ^ (t2
& 0x20);
357 t2
= ((t2
<< 1) & 0x80) ^ ((t2
<< 1) & 0x20);
363 t2
= ((t2
<< 1) & 0x80);
369 t2
= ((t2
<< 1) & 0x20);
373 // both, but tag with other algorithm
374 t1
= (t2
& 0x80) ^ (t2
& 0x08);
375 t2
= ((t2
<< 1) & 0x80) ^ ((t2
<< 1) & 0x08);
379 GraphBuffer
[cnt
++] = t1
;
380 GraphBuffer
[cnt
++] = t2
;
385 if(hasbeennull
>nrlow
|| nrlow
==0) {
386 PrintToScrollback("hasbeennull=%d", hasbeennull
);
395 static void CmdHexsamples(char *str
)
406 for(i
= 0; i
< n
; i
+= 12) {
408 c
.cmd
= CMD_DOWNLOAD_RAW_ADC_SAMPLES_125K
;
410 SendCommand(&c
, FALSE
);
412 if(c
.cmd
!= CMD_DOWNLOADED_RAW_ADC_SAMPLES_125K
) {
413 PrintToScrollback("bad resp\n");
417 for(j
= 0; j
< 48; j
+= 8) {
418 PrintToScrollback("%02x %02x %02x %02x %02x %02x %02x %02x",
433 static void CmdHisampless(char *str
)
445 for(i
= 0; i
< n
; i
+= 12) {
447 c
.cmd
= CMD_DOWNLOAD_RAW_ADC_SAMPLES_125K
;
449 SendCommand(&c
, FALSE
);
451 if(c
.cmd
!= CMD_DOWNLOADED_RAW_ADC_SAMPLES_125K
) {
452 PrintToScrollback("bad resp\n");
456 for(j
= 0; j
< 48; j
++) {
457 GraphBuffer
[cnt
++] = (int)((signed char)c
.d
.asBytes
[j
]);
462 RepaintGraphWindow();
465 static WORD
Iso15693Crc(BYTE
*v
, int n
)
471 for(i
= 0; i
< n
; i
++) {
472 reg
= reg
^ ((DWORD
)v
[i
]);
473 for (j
= 0; j
< 8; j
++) {
475 reg
= (reg
>> 1) ^ 0x8408;
485 static void CmdHi14bdemod(char *str
)
490 BOOL negateI
, negateQ
;
495 // As received, the samples are pairs, correlations against I and Q
496 // square waves. So estimate angle of initial carrier (or just
497 // quadrant, actually), and then do the demod.
499 // First, estimate where the tag starts modulating.
500 for(i
= 0; i
< GraphTraceLen
; i
+= 2) {
501 if(abs(GraphBuffer
[i
]) + abs(GraphBuffer
[i
+1]) > 40) {
505 if(i
>= GraphTraceLen
) {
506 PrintToScrollback("too weak to sync");
509 PrintToScrollback("out of weak at %d", i
);
512 // Now, estimate the phase in the initial modulation of the tag
515 for(; i
< (outOfWeakAt
+ 16); i
+= 2) {
516 isum
+= GraphBuffer
[i
+0];
517 qsum
+= GraphBuffer
[i
+1];
519 negateI
= (isum
< 0);
520 negateQ
= (qsum
< 0);
522 // Turn the correlation pairs into soft decisions on the bit.
524 for(i
= 0; i
< GraphTraceLen
/2; i
++) {
525 int si
= GraphBuffer
[j
];
526 int sq
= GraphBuffer
[j
+1];
527 if(negateI
) si
= -si
;
528 if(negateQ
) sq
= -sq
;
529 GraphBuffer
[i
] = si
+ sq
;
535 while(GraphBuffer
[i
] > 0 && i
< GraphTraceLen
)
537 if(i
>= GraphTraceLen
) goto demodError
;
540 while(GraphBuffer
[i
] < 0 && i
< GraphTraceLen
)
542 if(i
>= GraphTraceLen
) goto demodError
;
543 if((i
- iold
) > 23) goto demodError
;
545 PrintToScrollback("make it to demod loop");
549 while(GraphBuffer
[i
] >= 0 && i
< GraphTraceLen
)
551 if(i
>= GraphTraceLen
) goto demodError
;
552 if((i
- iold
) > 6) goto demodError
;
555 if(i
+ 20 >= GraphTraceLen
) goto demodError
;
557 for(j
= 0; j
< 10; j
++) {
558 int soft
= GraphBuffer
[i
] + GraphBuffer
[i
+1];
560 if(abs(soft
) < ((abs(isum
) + abs(qsum
))/20)) {
561 PrintToScrollback("weak bit");
565 if(GraphBuffer
[i
] + GraphBuffer
[i
+1] >= 0) {
572 if( (shiftReg
& 0x200) &&
575 // valid data byte, start and stop bits okay
576 PrintToScrollback(" %02x", (shiftReg
>> 1) & 0xff);
577 data
[dataLen
++] = (shiftReg
>> 1) & 0xff;
578 if(dataLen
>= sizeof(data
)) {
581 } else if(shiftReg
== 0x000) {
590 ComputeCrc14443(CRC_14443_B
, data
, dataLen
-2, &first
, &second
);
591 PrintToScrollback("CRC: %02x %02x (%s)\n", first
, second
,
592 (first
== data
[dataLen
-2] && second
== data
[dataLen
-1]) ?
593 "ok" : "****FAIL****");
595 RepaintGraphWindow();
599 PrintToScrollback("demod error");
600 RepaintGraphWindow();
603 static void CmdHi14list(char *str
)
606 GetFromBigBuf(got
, sizeof(got
));
608 PrintToScrollback("recorded activity:");
609 PrintToScrollback(" time :rssi: who bytes");
610 PrintToScrollback("---------+----+----+-----------");
621 int timestamp
= *((DWORD
*)(got
+i
));
622 if(timestamp
& 0x80000000) {
623 timestamp
&= 0x7fffffff;
628 int metric
= *((DWORD
*)(got
+i
+4));
639 BYTE
*frame
= (got
+i
+9);
641 char line
[1000] = "";
643 for(j
= 0; j
< len
; j
++) {
644 sprintf(line
+(j
*3), "%02x ", frame
[j
]);
650 ComputeCrc14443(CRC_14443_B
, frame
, len
-2, &b1
, &b2
);
651 if(b1
!= frame
[len
-2] || b2
!= frame
[len
-1]) {
652 crc
= "**FAIL CRC**";
660 char metricString
[100];
662 sprintf(metricString
, "%3d", metric
);
664 strcpy(metricString
, " ");
667 PrintToScrollback(" +%7d: %s: %s %s %s",
668 (prev
< 0 ? 0 : timestamp
- prev
),
670 (isResponse
? "TAG" : " "), line
, crc
);
677 static void CmdHi14alist(char *str
)
680 GetFromBigBuf(got
, sizeof(got
));
682 PrintToScrollback("recorded activity:");
683 PrintToScrollback(" ETU :rssi: who bytes");
684 PrintToScrollback("---------+----+----+-----------");
695 int timestamp
= *((DWORD
*)(got
+i
));
696 if(timestamp
& 0x80000000) {
697 timestamp
&= 0x7fffffff;
704 int parityBits
= *((DWORD
*)(got
+i
+4));
705 // 4 bytes of additional information...
706 // maximum of 32 additional parity bit information
709 // at each quarter bit period we can send power level (16 levels)
710 // or each half bit period in 256 levels.
718 if(i
+ len
>= 1900) {
722 BYTE
*frame
= (got
+i
+9);
724 // Break and stick with current result if buffer was not completely full
725 if(frame
[0] == 0x44 && frame
[1] == 0x44 && frame
[3] == 0x44) { break; }
727 char line
[1000] = "";
729 for(j
= 0; j
< len
; j
++) {
730 int oddparity
= 0x01;
734 oddparity
^= (((frame
[j
] & 0xFF) >> k
) & 0x01);
737 //if((parityBits >> (len - j - 1)) & 0x01) {
738 if(isResponse
&& (oddparity
!= ((parityBits
>> (len
- j
- 1)) & 0x01))) {
739 sprintf(line
+(j
*4), "%02x! ", frame
[j
]);
742 sprintf(line
+(j
*4), "%02x ", frame
[j
]);
750 for(j
= 0; j
< (len
- 1); j
++) {
751 // gives problems... search for the reason..
752 /*if(frame[j] == 0xAA) {
755 crc = "[1] Two drops close after each other";
758 crc = "[2] Potential SOC with a drop in second half of bitperiod";
761 crc = "[3] Segment Z after segment X is not possible";
764 crc = "[4] Parity bit of a fully received byte was wrong";
767 crc = "[?] Unknown error";
775 ComputeCrc14443(CRC_14443_A
, frame
, len
-2, &b1
, &b2
);
776 if(b1
!= frame
[len
-2] || b2
!= frame
[len
-1]) {
777 crc
= (isResponse
& (len
< 6)) ? "" : " !crc";
786 char metricString
[100];
788 sprintf(metricString
, "%3d", metric
);
790 strcpy(metricString
, " ");
793 PrintToScrollback(" +%7d: %s: %s %s %s",
794 (prev
< 0 ? 0 : (timestamp
- prev
)),
796 (isResponse
? "TAG" : " "), line
, crc
);
804 static void CmdHi15demod(char *str
)
806 // The sampling rate is 106.353 ksps/s, for T = 18.8 us
809 // 1) Unmodulated time of 56.64us
810 // 2) 24 pulses of 423.75khz
811 // 3) logic '1' (unmodulated for 18.88us followed by 8 pulses of 423.75khz)
813 static const int FrameSOF
[] = {
814 -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
815 -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
816 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
817 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
823 static const int Logic0
[] = {
829 static const int Logic1
[] = {
837 // 1) logic '0' (8 pulses of 423.75khz followed by unmodulated for 18.88us)
838 // 2) 24 pulses of 423.75khz
839 // 3) Unmodulated time of 56.64us
841 static const int FrameEOF
[] = {
846 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
847 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
848 -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
849 -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1
857 if(GraphTraceLen
< 1000) return;
859 // First, correlate for SOF
860 for(i
= 0; i
< 100; i
++) {
862 for(j
= 0; j
< arraylen(FrameSOF
); j
+= skip
) {
863 corr
+= FrameSOF
[j
]*GraphBuffer
[i
+(j
/skip
)];
870 PrintToScrollback("SOF at %d, correlation %d", maxPos
,
871 max
/(arraylen(FrameSOF
)/skip
));
873 i
= maxPos
+ arraylen(FrameSOF
)/skip
;
876 memset(outBuf
, 0, sizeof(outBuf
));
879 int corr0
= 0, corr1
= 0, corrEOF
= 0;
880 for(j
= 0; j
< arraylen(Logic0
); j
+= skip
) {
881 corr0
+= Logic0
[j
]*GraphBuffer
[i
+(j
/skip
)];
883 for(j
= 0; j
< arraylen(Logic1
); j
+= skip
) {
884 corr1
+= Logic1
[j
]*GraphBuffer
[i
+(j
/skip
)];
886 for(j
= 0; j
< arraylen(FrameEOF
); j
+= skip
) {
887 corrEOF
+= FrameEOF
[j
]*GraphBuffer
[i
+(j
/skip
)];
889 // Even things out by the length of the target waveform.
893 if(corrEOF
> corr1
&& corrEOF
> corr0
) {
894 PrintToScrollback("EOF at %d", i
);
896 } else if(corr1
> corr0
) {
897 i
+= arraylen(Logic1
)/skip
;
900 i
+= arraylen(Logic0
)/skip
;
907 if((i
+(int)arraylen(FrameEOF
)) >= GraphTraceLen
) {
908 PrintToScrollback("ran off end!");
913 PrintToScrollback("error, uneven octet! (discard extra bits!)");
914 PrintToScrollback(" mask=%02x", mask
);
916 PrintToScrollback("%d octets", k
);
918 for(i
= 0; i
< k
; i
++) {
919 PrintToScrollback("# %2d: %02x ", i
, outBuf
[i
]);
921 PrintToScrollback("CRC=%04x", Iso15693Crc(outBuf
, k
-2));
924 static void CmdTiread(char *str
)
927 c
.cmd
= CMD_ACQUIRE_RAW_BITS_TI_TYPE
;
928 SendCommand(&c
, FALSE
);
931 static void CmdTibits(char *str
)
935 for(i
= 0; i
< 1536; i
+= 12) {
937 c
.cmd
= CMD_DOWNLOAD_RAW_BITS_TI_TYPE
;
939 SendCommand(&c
, FALSE
);
941 if(c
.cmd
!= CMD_DOWNLOADED_RAW_BITS_TI_TYPE
) {
942 PrintToScrollback("bad resp\n");
946 for(j
= 0; j
< 12; j
++) {
948 for(k
= 31; k
>= 0; k
--) {
949 if(c
.d
.asDwords
[j
] & (1 << k
)) {
950 GraphBuffer
[cnt
++] = 1;
952 GraphBuffer
[cnt
++] = -1;
957 GraphTraceLen
= 1536*32;
958 RepaintGraphWindow();
961 static void CmdTidemod(char *cmdline
)
963 /* MATLAB as follows:
964 f_s = 2000000; % sampling frequency
965 f_l = 123200; % low FSK tone
966 f_h = 134200; % high FSK tone
968 T_l = 119e-6; % low bit duration
969 T_h = 130e-6; % high bit duration
971 l = 2*pi*ones(1, floor(f_s*T_l))*(f_l/f_s);
972 h = 2*pi*ones(1, floor(f_s*T_h))*(f_h/f_s);
974 l = sign(sin(cumsum(l)));
975 h = sign(sin(cumsum(h)));
977 static const int LowTone
[] = {
978 1, 1, 1, 1, 1, 1, 1, 1, -1, -1, -1, -1, -1, -1, -1, -1, 1, 1, 1,
979 1, 1, 1, 1, 1, -1, -1, -1, -1, -1, -1, -1, -1, 1, 1, 1, 1, 1, 1,
980 1, 1, -1, -1, -1, -1, -1, -1, -1, -1, 1, 1, 1, 1, 1, 1, 1, 1, -1,
981 -1, -1, -1, -1, -1, -1, -1, 1, 1, 1, 1, 1, 1, 1, 1, 1, -1, -1, -1,
982 -1, -1, -1, -1, -1, 1, 1, 1, 1, 1, 1, 1, 1, -1, -1, -1, -1, -1, -1,
983 -1, -1, 1, 1, 1, 1, 1, 1, 1, 1, -1, -1, -1, -1, -1, -1, -1, -1, 1,
984 1, 1, 1, 1, 1, 1, 1, -1, -1, -1, -1, -1, -1, -1, -1, 1, 1, 1, 1,
985 1, 1, 1, 1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 1, 1, 1, 1, 1, 1,
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,
992 static const int HighTone
[] = {
993 1, 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,
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, 1, 1, 1, 1, 1, 1, -1, -1,
999 -1, -1, -1, -1, -1, -1, 1, 1, 1, 1, 1, 1, 1, -1, -1, -1, -1, -1,
1000 -1, -1, -1, 1, 1, 1, 1, 1, 1, 1, -1, -1, -1, -1, -1, -1, -1, -1,
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,
1009 int convLen
= max(arraylen(HighTone
), arraylen(LowTone
));
1012 for(i
= 0; i
< GraphTraceLen
- convLen
; i
++) {
1014 int lowSum
= 0, highSum
= 0;;
1015 int lowLen
= arraylen(LowTone
);
1016 int highLen
= arraylen(HighTone
);
1018 for(j
= 0; j
< lowLen
; j
++) {
1019 lowSum
+= LowTone
[j
]*GraphBuffer
[i
+j
];
1021 for(j
= 0; j
< highLen
; j
++) {
1022 highSum
+= HighTone
[j
]*GraphBuffer
[i
+j
];
1024 lowSum
= abs((100*lowSum
) / lowLen
);
1025 highSum
= abs((100*highSum
) / highLen
);
1026 GraphBuffer
[i
] = (highSum
<< 16) | lowSum
;
1029 for(i
= 0; i
< GraphTraceLen
- convLen
- 16; i
++) {
1031 int lowTot
= 0, highTot
= 0;
1032 // 16 and 15 are f_s divided by f_l and f_h, rounded
1033 for(j
= 0; j
< 16; j
++) {
1034 lowTot
+= (GraphBuffer
[i
+j
] & 0xffff);
1036 for(j
= 0; j
< 15; j
++) {
1037 highTot
+= (GraphBuffer
[i
+j
] >> 16);
1039 GraphBuffer
[i
] = lowTot
- highTot
;
1042 GraphTraceLen
-= (convLen
+ 16);
1044 RepaintGraphWindow();
1046 // Okay, so now we have unsliced soft decisions; find bit-sync, and then
1049 int max
= 0, maxPos
= 0;
1050 for(i
= 0; i
< 6000; i
++) {
1053 for(j
= 0; j
< 8*arraylen(LowTone
); j
++) {
1054 dec
-= GraphBuffer
[i
+j
];
1056 for(; j
< 8*arraylen(LowTone
) + 8*arraylen(HighTone
); j
++) {
1057 dec
+= GraphBuffer
[i
+j
];
1064 GraphBuffer
[maxPos
] = 800;
1065 GraphBuffer
[maxPos
+1] = -800;
1067 maxPos
+= 8*arraylen(LowTone
);
1068 GraphBuffer
[maxPos
] = 800;
1069 GraphBuffer
[maxPos
+1] = -800;
1070 maxPos
+= 8*arraylen(HighTone
);
1072 GraphBuffer
[maxPos
] = 800;
1073 GraphBuffer
[maxPos
+1] = -800;
1075 PrintToScrollback("actual data bits start at sample %d", maxPos
);
1077 PrintToScrollback("length %d/%d", arraylen(HighTone
), arraylen(LowTone
));
1079 GraphBuffer
[maxPos
] = 800;
1080 GraphBuffer
[maxPos
+1] = -800;
1082 BYTE bits
[64+16+8+1];
1083 bits
[sizeof(bits
)-1] = '\0';
1085 for(i
= 0; i
< arraylen(bits
); i
++) {
1089 for(j
= 0; j
< arraylen(LowTone
); j
++) {
1090 low
-= GraphBuffer
[maxPos
+j
];
1092 for(j
= 0; j
< arraylen(HighTone
); j
++) {
1093 high
+= GraphBuffer
[maxPos
+j
];
1097 maxPos
+= arraylen(HighTone
);
1100 maxPos
+= arraylen(LowTone
);
1102 GraphBuffer
[maxPos
] = 800;
1103 GraphBuffer
[maxPos
+1] = -800;
1105 PrintToScrollback("bits: '%s'", bits
);
1108 for(i
= 0; i
< 32; i
++) {
1109 if(bits
[i
] == '1') {
1113 for(i
= 32; i
< 64; i
++) {
1114 if(bits
[i
] == '1') {
1118 PrintToScrollback("hex: %08x %08x", h
, l
);
1121 static void CmdNorm(char *str
)
1124 int max
= INT_MIN
, min
= INT_MAX
;
1125 for(i
= 10; i
< GraphTraceLen
; i
++) {
1126 if(GraphBuffer
[i
] > max
) {
1127 max
= GraphBuffer
[i
];
1129 if(GraphBuffer
[i
] < min
) {
1130 min
= GraphBuffer
[i
];
1134 for(i
= 0; i
< GraphTraceLen
; i
++) {
1135 GraphBuffer
[i
] = (GraphBuffer
[i
] - ((max
+ min
)/2))*1000/
1139 RepaintGraphWindow();
1142 static void CmdDec(char *str
)
1145 for(i
= 0; i
< (GraphTraceLen
/2); i
++) {
1146 GraphBuffer
[i
] = GraphBuffer
[i
*2];
1149 PrintToScrollback("decimated by 2");
1150 RepaintGraphWindow();
1153 static void CmdHpf(char *str
)
1157 for(i
= 10; i
< GraphTraceLen
; i
++) {
1158 accum
+= GraphBuffer
[i
];
1160 accum
/= (GraphTraceLen
- 10);
1161 for(i
= 0; i
< GraphTraceLen
; i
++) {
1162 GraphBuffer
[i
] -= accum
;
1165 RepaintGraphWindow();
1168 static void CmdZerocrossings(char *str
)
1171 // Zero-crossings aren't meaningful unless the signal is zero-mean.
1177 for(i
= 0; i
< GraphTraceLen
; i
++) {
1178 if(GraphBuffer
[i
]*sign
>= 0) {
1179 // No change in sign, reproduce the previous sample count.
1181 GraphBuffer
[i
] = lastZc
;
1183 // Change in sign, reset the sample count.
1185 GraphBuffer
[i
] = lastZc
;
1193 RepaintGraphWindow();
1196 static void CmdLtrim(char *str
)
1201 for(i
= ds
; i
< GraphTraceLen
; i
++) {
1202 GraphBuffer
[i
-ds
] = GraphBuffer
[i
];
1204 GraphTraceLen
-= ds
;
1206 RepaintGraphWindow();
1209 static void CmdAutoCorr(char *str
)
1211 static int CorrelBuffer
[MAX_GRAPH_TRACE_LEN
];
1213 int window
= atoi(str
);
1216 PrintToScrollback("needs a window");
1220 if(window
>= GraphTraceLen
) {
1221 PrintToScrollback("window must be smaller than trace (%d samples)",
1226 PrintToScrollback("performing %d correlations", GraphTraceLen
- window
);
1229 for(i
= 0; i
< GraphTraceLen
- window
; i
++) {
1232 for(j
= 0; j
< window
; j
++) {
1233 sum
+= (GraphBuffer
[j
]*GraphBuffer
[i
+j
]) / 256;
1235 CorrelBuffer
[i
] = sum
;
1237 GraphTraceLen
= GraphTraceLen
- window
;
1238 memcpy(GraphBuffer
, CorrelBuffer
, GraphTraceLen
*sizeof(int));
1240 RepaintGraphWindow();
1243 static void CmdVchdemod(char *str
)
1245 // Is this the entire sync pattern, or does this also include some
1246 // data bits that happen to be the same everywhere? That would be
1248 static const int SyncPattern
[] = {
1249 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
1250 1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
1251 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
1252 1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
1253 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
1254 1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
1255 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
1256 1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
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,
1261 // So first, we correlate for the sync pattern, and mark that.
1262 int bestCorrel
= 0, bestPos
= 0;
1264 // It does us no good to find the sync pattern, with fewer than
1265 // 2048 samples after it...
1266 for(i
= 0; i
< (GraphTraceLen
-2048); i
++) {
1269 for(j
= 0; j
< arraylen(SyncPattern
); j
++) {
1270 sum
+= GraphBuffer
[i
+j
]*SyncPattern
[j
];
1272 if(sum
> bestCorrel
) {
1277 PrintToScrollback("best sync at %d [metric %d]", bestPos
, bestCorrel
);
1282 int worst
= INT_MAX
;
1285 for(i
= 0; i
< 2048; i
+= 8) {
1288 for(j
= 0; j
< 8; j
++) {
1289 sum
+= GraphBuffer
[bestPos
+i
+j
];
1296 if(abs(sum
) < worst
) {
1301 PrintToScrollback("bits:");
1302 PrintToScrollback("%s", bits
);
1303 PrintToScrollback("worst metric: %d at pos %d", worst
, worstPos
);
1305 if(strcmp(str
, "clone")==0) {
1308 for(s
= bits
; *s
; s
++) {
1310 for(j
= 0; j
< 16; j
++) {
1311 GraphBuffer
[GraphTraceLen
++] = (*s
== '1') ? 1 : 0;
1314 RepaintGraphWindow();
1318 static void CmdIndalademod(char *str
)
1320 // Usage: recover 64bit UID by default, specify "224" as arg to recover a 224bit UID
1325 // worst case with GraphTraceLen=64000 is < 4096
1326 // under normal conditions it's < 2048
1329 int worst
= 0, worstPos
= 0;
1330 PrintToScrollback("Expecting a bit less than %d raw bits", GraphTraceLen
/32);
1331 for(i
= 0; i
< GraphTraceLen
-1; i
+= 2) {
1333 if((GraphBuffer
[i
] > GraphBuffer
[i
+ 1]) && (state
!= 1)) {
1335 for(j
= 0; j
< count
- 8; j
+= 16) {
1336 rawbits
[rawbit
++] = 0;
1338 if ((abs(count
- j
)) > worst
) {
1339 worst
= abs(count
- j
);
1345 } else if((GraphBuffer
[i
] < GraphBuffer
[i
+ 1]) && (state
!= 0)) {
1347 for(j
= 0; j
< count
- 8; j
+= 16) {
1348 rawbits
[rawbit
++] = 1;
1350 if ((abs(count
- j
)) > worst
) {
1351 worst
= abs(count
- j
);
1359 PrintToScrollback("Recovered %d raw bits", rawbit
);
1360 PrintToScrollback("worst metric (0=best..7=worst): %d at pos %d", worst
, worstPos
);
1362 // Finding the start of a UID
1363 int uidlen
, long_wait
;
1364 if(strcmp(str
, "224") == 0) {
1373 for(start
= 0; start
<= rawbit
- uidlen
; start
++) {
1374 first
= rawbits
[start
];
1375 for(i
= start
; i
< start
+ long_wait
; i
++) {
1376 if(rawbits
[i
] != first
) {
1380 if(i
== (start
+ long_wait
)) {
1384 if(start
== rawbit
- uidlen
+ 1) {
1385 PrintToScrollback("nothing to wait for");
1389 // Inverting signal if needed
1391 for(i
= start
; i
< rawbit
; i
++) {
1392 rawbits
[i
] = !rawbits
[i
];
1399 showbits
[uidlen
]='\0';
1403 if(uidlen
> rawbit
) {
1404 PrintToScrollback("Warning: not enough raw bits to get a full UID");
1405 for(bit
= 0; bit
< rawbit
; bit
++) {
1406 bits
[bit
] = rawbits
[i
++];
1407 // As we cannot know the parity, let's use "." and "/"
1408 showbits
[bit
] = '.' + bits
[bit
];
1410 showbits
[bit
+1]='\0';
1411 PrintToScrollback("Partial UID=%s", showbits
);
1414 for(bit
= 0; bit
< uidlen
; bit
++) {
1415 bits
[bit
] = rawbits
[i
++];
1416 showbits
[bit
] = '0' + bits
[bit
];
1420 PrintToScrollback("UID=%s", showbits
);
1422 // Checking UID against next occurences
1423 for(; i
+ uidlen
<= rawbit
;) {
1425 for(bit
= 0; bit
< uidlen
; bit
++) {
1426 if(bits
[bit
] != rawbits
[i
++]) {
1436 PrintToScrollback("Occurences: %d (expected %d)", times
, (rawbit
- start
) / uidlen
);
1438 // Remodulating for tag cloning
1439 GraphTraceLen
= 32*uidlen
;
1442 for(bit
= 0; bit
< uidlen
; bit
++) {
1443 if(bits
[bit
] == 0) {
1449 for(j
= 0; j
< 32; j
++) {
1450 GraphBuffer
[i
++] = phase
;
1455 RepaintGraphWindow();
1458 static void CmdFlexdemod(char *str
)
1461 for(i
= 0; i
< GraphTraceLen
; i
++) {
1462 if(GraphBuffer
[i
] < 0) {
1463 GraphBuffer
[i
] = -1;
1469 #define LONG_WAIT 100
1471 for(start
= 0; start
< GraphTraceLen
- LONG_WAIT
; start
++) {
1472 int first
= GraphBuffer
[start
];
1473 for(i
= start
; i
< start
+ LONG_WAIT
; i
++) {
1474 if(GraphBuffer
[i
] != first
) {
1478 if(i
== (start
+ LONG_WAIT
)) {
1482 if(start
== GraphTraceLen
- LONG_WAIT
) {
1483 PrintToScrollback("nothing to wait for");
1487 GraphBuffer
[start
] = 2;
1488 GraphBuffer
[start
+1] = -2;
1494 for(bit
= 0; bit
< 64; bit
++) {
1497 for(j
= 0; j
< 16; j
++) {
1498 sum
+= GraphBuffer
[i
++];
1505 PrintToScrollback("bit %d sum %d", bit
, sum
);
1508 for(bit
= 0; bit
< 64; bit
++) {
1511 for(j
= 0; j
< 16; j
++) {
1512 sum
+= GraphBuffer
[i
++];
1514 if(sum
> 0 && bits
[bit
] != 1) {
1515 PrintToScrollback("oops1 at %d", bit
);
1517 if(sum
< 0 && bits
[bit
] != 0) {
1518 PrintToScrollback("oops2 at %d", bit
);
1522 GraphTraceLen
= 32*64;
1525 for(bit
= 0; bit
< 64; bit
++) {
1526 if(bits
[bit
] == 0) {
1532 for(j
= 0; j
< 32; j
++) {
1533 GraphBuffer
[i
++] = phase
;
1538 RepaintGraphWindow();
1542 * Generic command to demodulate ASK. bit length in argument.
1543 * Giving the bit length helps discriminate ripple effects
1544 * upon zero crossing for noisy traces.
1546 * Second is convention: positive or negative (High mod means zero
1547 * or high mod means one)
1549 * Updates the Graph trace with 0/1 values
1552 * sl : bit length in terms of number of samples per bit
1553 * (use yellow/purple markers to compute).
1557 static void Cmdaskdemod(char *str
) {
1564 // TODO: complain if we do not give 2 arguments here !
1565 sscanf(str
, "%i %i", &n
, &c
);
1572 if (GraphBuffer
[0]*c
> 0) {
1577 for(i
=1;i
<GraphTraceLen
;i
++) {
1578 /* Analyse signal within the symbol length */
1579 /* Decide if we crossed a zero */
1580 if (GraphBuffer
[i
]*sign
< 0) {
1581 /* Crossed a zero, check if this is a ripple or not */
1582 if ( (i
-t1
) > n
/4 ) {
1585 if (GraphBuffer
[i
]*c
> 0){
1591 /* This is a ripple, set the current sample value
1592 to the same as previous */
1593 GraphBuffer
[i
] = GraphBuffer
[i
-1];
1596 GraphBuffer
[i
] = GraphBuffer
[i
-1];
1599 RepaintGraphWindow();
1604 * Manchester demodulate a bitstream. The bitstream needs to be already in
1605 * the GraphBuffer as 0 and 1 values
1607 * Give the clock rate as argument in order to help the sync - the algorithm
1608 * resyncs at each pulse anyway.
1610 * Not optimized by any means, this is the 1st time I'm writing this type of
1611 * routine, feel free to improve...
1613 * 1st argument: clock rate (as number of samples per clock rate)
1614 * Typical values can be 64, 32, 128...
1616 static void Cmdmanchesterdemod(char *str
) {
1625 sscanf(str
, "%i", &clock
);
1627 int tolerance
= clock
/4;
1628 /* Holds the decoded bitstream: each clock period contains 2 bits */
1629 /* later simplified to 1 bit after manchester decoding. */
1630 /* Add 10 bits to allow for noisy / uncertain traces without aborting */
1631 /* int BitStream[GraphTraceLen*2/clock+10]; */
1633 /* But it does not work if compiling on WIndows: therefore we just allocate a */
1635 int BitStream
[MAX_GRAPH_TRACE_LEN
];
1637 /* Detect first transition */
1638 /* Lo-Hi (arbitrary) */
1639 for(i
=1;i
<GraphTraceLen
;i
++) {
1640 if (GraphBuffer
[i
-1]<GraphBuffer
[i
]) {
1642 BitStream
[0]=0; // Previous state = 0;
1647 /* Then detect duration between 2 successive transitions */
1648 for(bitidx
= 1 ;i
<GraphTraceLen
;i
++) {
1649 if (GraphBuffer
[i
-1] != GraphBuffer
[i
]) {
1652 // Error check: if bitidx becomes too large, we do not
1653 // have a Manchester encoded bitstream or the clock is really
1655 if (bitidx
> (GraphTraceLen
*2/clock
+8) ) {
1656 PrintToScrollback("Error: the clock you gave is probably wrong, aborting.");
1659 // Then switch depending on lc length:
1660 // Tolerance is 1/4 of clock rate (arbitrary)
1661 if (abs(lc
-clock
/2) < tolerance
) {
1662 // Short pulse : either "1" or "0"
1663 BitStream
[bitidx
++]=GraphBuffer
[i
-1];
1664 } else if (abs(lc
-clock
) < tolerance
) {
1665 // Long pulse: either "11" or "00"
1666 BitStream
[bitidx
++]=GraphBuffer
[i
-1];
1667 BitStream
[bitidx
++]=GraphBuffer
[i
-1];
1670 PrintToScrollback("Warning: Manchester decode error for pulse width detection.");
1671 PrintToScrollback("(too many of those messages mean either the stream is not Manchester encoded, or clock is wrong)");
1676 // At this stage, we now have a bitstream of "01" ("1") or "10" ("0"), parse it into final decoded bitstream
1677 // Actually, we overwrite BitStream with the new decoded bitstream, we just need to be careful
1678 // to stop output at the final bitidx2 value, not bitidx
1679 for (i
= 0; i
< bitidx
; i
+= 2) {
1680 if ((BitStream
[i
] == 0) && (BitStream
[i
+1] == 1)) {
1681 BitStream
[bit2idx
++] = 1;
1682 } else if ((BitStream
[i
] == 1) && (BitStream
[i
+1] == 0)) {
1683 BitStream
[bit2idx
++] = 0;
1685 // We cannot end up in this state, this means we are unsynchronized,
1688 PrintToScrollback("Unsynchronized, resync...");
1689 PrintToScrollback("(too many of those messages mean the stream is not Manchester encoded)");
1692 PrintToScrollback("Manchester decoded bitstream \n---------");
1693 // Now output the bitstream to the scrollback by line of 16 bits
1694 for (i
= 0; i
< (bit2idx
-16); i
+=16) {
1695 PrintToScrollback("%i %i %i %i %i %i %i %i %i %i %i %i %i %i %i %i",
1720 static void CmdHiddemod(char *str
)
1722 if(GraphTraceLen
< 4800) {
1723 PrintToScrollback("too short; need at least 4800 samples");
1727 GraphTraceLen
= 4800;
1729 for(i
= 0; i
< GraphTraceLen
; i
++) {
1730 if(GraphBuffer
[i
] < 0) {
1736 RepaintGraphWindow();
1739 static void CmdPlot(char *str
)
1744 static void CmdHide(char *str
)
1749 static void CmdScale(char *str
)
1751 CursorScaleFactor
= atoi(str
);
1752 if(CursorScaleFactor
== 0) {
1753 PrintToScrollback("bad, can't have zero scale");
1754 CursorScaleFactor
= 1;
1756 RepaintGraphWindow();
1759 static void CmdSave(char *str
)
1761 FILE *f
= fopen(str
, "w");
1763 PrintToScrollback("couldn't open '%s'", str
);
1767 for(i
= 0; i
< GraphTraceLen
; i
++) {
1768 fprintf(f
, "%d\n", GraphBuffer
[i
]);
1771 PrintToScrollback("saved to '%s'", str
);
1774 static void CmdLoad(char *str
)
1776 FILE *f
= fopen(str
, "r");
1778 PrintToScrollback("couldn't open '%s'", str
);
1784 while(fgets(line
, sizeof(line
), f
)) {
1785 GraphBuffer
[GraphTraceLen
] = atoi(line
);
1789 PrintToScrollback("loaded %d samples", GraphTraceLen
);
1790 RepaintGraphWindow();
1793 static void CmdHIDsimTAG(char *str
)
1795 unsigned int hi
=0, lo
=0;
1799 while (sscanf(&str
[i
++], "%1x", &n
) == 1) {
1800 hi
=(hi
<<4)|(lo
>>28);
1804 PrintToScrollback("Emulating tag with ID %x%16x", hi
, lo
);
1806 c
.cmd
= CMD_HID_SIM_TAG
;
1809 SendCommand(&c
, FALSE
);
1812 static void CmdLcdReset(char *str
)
1815 c
.cmd
= CMD_LCD_RESET
;
1817 SendCommand(&c
, FALSE
);
1820 static void CmdLcd(char *str
)
1825 sscanf(str
, "%x %d", &i
, &j
);
1828 SendCommand(&c
, FALSE
);
1832 static void CmdTest(char *str
)
1837 * Sets the divisor for LF frequency clock: lets the user choose any LF frequency below
1840 static void CmdSetDivisor(char *str
)
1843 c
.cmd
= CMD_SET_LF_DIVISOR
;
1845 if (( c
.ext1
<0) || (c
.ext1
>255)) {
1846 PrintToScrollback("divisor must be between 19 and 255");
1848 SendCommand(&c
, FALSE
);
1849 PrintToScrollback("Divisor set, expected freq=%dHz", 12000000/(c
.ext1
+1));
1853 static void CmdSweepLF(char *str
)
1856 c
.cmd
= CMD_SWEEP_LF
;
1857 SendCommand(&c
, FALSE
);
1861 typedef void HandlerFunction(char *cmdline
);
1865 HandlerFunction
*handler
;
1866 int offline
; // 1 if the command can be used when in offline mode
1868 } CommandTable
[] = {
1869 "tune", CmdTune
,0, "measure antenna tuning",
1870 "tiread", CmdTiread
,0, "read a TI-type 134 kHz tag",
1871 "tibits", CmdTibits
,0, "get raw bits for TI-type LF tag",
1872 "tidemod", CmdTidemod
,0, "demod raw bits for TI-type LF tag",
1873 "vchdemod", CmdVchdemod
,0, "demod samples for VeriChip",
1874 "plot", CmdPlot
,1, "show graph window",
1875 "hide", CmdHide
,1, "hide graph window",
1876 "losim", CmdLosim
,0, "simulate LF tag",
1877 "loread", CmdLoread
,0, "read (125/134 kHz) LF ID-only tag",
1878 "losamples", CmdLosamples
,0, "get raw samples for LF tag",
1879 "hisamples", CmdHisamples
,0, "get raw samples for HF tag",
1880 "hisampless", CmdHisampless
,0, "get signed raw samples, HF tag",
1881 "hisamplest", CmdHi14readt
,0, "get samples HF, for testing",
1882 "higet", CmdHi14read_sim
,0, "get samples HF, 'analog'",
1883 "bitsamples", CmdBitsamples
,0, "get raw samples as bitstring",
1884 "hexsamples", CmdHexsamples
,0, "dump big buffer as hex bytes",
1885 "hi15read", CmdHi15read
,0, "read HF tag (ISO 15693)",
1886 "hi15reader", CmdHi15reader
,0, "act like an ISO15693 reader", // new command greg
1887 "hi15sim", CmdHi15tag
,0, "fake an ISO15693 tag", // new command greg
1888 "hi14read", CmdHi14read
,0, "read HF tag (ISO 14443)",
1889 "sri512read", CmdSri512read
,0, "Read contents of a SRI512 tag",
1890 "hi14areader", CmdHi14areader
,0, "act like an ISO14443 Type A reader", // ## New reader command
1891 "hi15demod", CmdHi15demod
,1, "demod ISO15693 from tag",
1892 "hi14bdemod", CmdHi14bdemod
,1, "demod ISO14443 Type B from tag",
1893 "autocorr", CmdAutoCorr
,1, "autocorrelation over window",
1894 "norm", CmdNorm
,1, "normalize max/min to +/-500",
1895 "dec", CmdDec
,1, "decimate",
1896 "hpf", CmdHpf
,1, "remove DC offset from trace",
1897 "zerocrossings", CmdZerocrossings
,1, "count time between zero-crossings",
1898 "ltrim", CmdLtrim
,1, "trim from left of trace",
1899 "scale", CmdScale
,1, "set cursor display scale",
1900 "flexdemod", CmdFlexdemod
,1, "demod samples for FlexPass",
1901 "save", CmdSave
,1, "save trace (from graph window)",
1902 "load", CmdLoad
,1, "load trace (to graph window",
1903 "hisimlisten", CmdHisimlisten
,0, "get HF samples as fake tag",
1904 "hi14sim", CmdHi14sim
,0, "fake ISO 14443 tag",
1905 "hi14asim", CmdHi14asim
,0, "fake ISO 14443a tag", // ## Simulate 14443a tag
1906 "hi14snoop", CmdHi14snoop
,0, "eavesdrop ISO 14443",
1907 "hi14asnoop", CmdHi14asnoop
,0, "eavesdrop ISO 14443 Type A", // ## New snoop command
1908 "hi14list", CmdHi14list
,0, "list ISO 14443 history",
1909 "hi14alist", CmdHi14alist
,0, "list ISO 14443a history", // ## New list command
1910 "hiddemod", CmdHiddemod
,1, "HID Prox Card II (not optimal)",
1911 "hidfskdemod", CmdHIDdemodFSK
,0, "HID FSK demodulator",
1912 "askdemod", Cmdaskdemod
,1, "Attempt to demodulate simple ASK tags",
1913 "hidsimtag", CmdHIDsimTAG
,0, "HID tag simulator",
1914 "mandemod", Cmdmanchesterdemod
,1, "Try a Manchester demodulation on a binary stream",
1915 "fpgaoff", CmdFPGAOff
,0, "set FPGA off", // ## FPGA Control
1916 "lcdreset", CmdLcdReset
,0, "Hardware reset LCD",
1917 "lcd", CmdLcd
,0, "Send command/data to LCD",
1918 "setlfdivisor", CmdSetDivisor
,0, "Drive LF antenna at 12Mhz/(divisor+1)",
1919 "sweeplf", CmdSweepLF
,0, "Sweep through LF freq range and store results in buffer",
1920 "quit", CmdQuit
,0, "quit program"
1924 //-----------------------------------------------------------------------------
1925 // Entry point into our code: called whenever the user types a command and
1926 // then presses Enter, which the full command line that they typed.
1927 //-----------------------------------------------------------------------------
1928 void CommandReceived(char *cmd
)
1932 PrintToScrollback("> %s", cmd
);
1934 if(strcmp(cmd
, "help")==0) {
1935 PrintToScrollback("\r\nAvailable commands:");
1936 for(i
= 0; i
< sizeof(CommandTable
) / sizeof(CommandTable
[0]); i
++) {
1938 memset(line
, ' ', sizeof(line
));
1939 strcpy(line
+2, CommandTable
[i
].name
);
1940 line
[strlen(line
)] = ' ';
1941 sprintf(line
+15, " -- %s", CommandTable
[i
].docString
);
1942 PrintToScrollback("%s", line
);
1944 PrintToScrollback("");
1945 PrintToScrollback("and also: help, cls");
1949 for(i
= 0; i
< sizeof(CommandTable
) / sizeof(CommandTable
[0]); i
++) {
1950 char *name
= CommandTable
[i
].name
;
1951 if(memcmp(cmd
, name
, strlen(name
))==0 &&
1952 (cmd
[strlen(name
)] == ' ' || cmd
[strlen(name
)] == '\0'))
1954 cmd
+= strlen(name
);
1955 while(*cmd
== ' ') {
1958 (CommandTable
[i
].handler
)(cmd
);
1962 PrintToScrollback(">> bad command '%s'", cmd
);
1965 //-----------------------------------------------------------------------------
1966 // Entry point into our code: called whenever we received a packet over USB
1967 // that we weren't necessarily expecting, for example a debug print.
1968 //-----------------------------------------------------------------------------
1969 void UsbCommandReceived(UsbCommand
*c
)
1972 case CMD_DEBUG_PRINT_STRING
: {
1974 if(c
->ext1
> 70 || c
->ext1
< 0) {
1977 memcpy(s
, c
->d
.asBytes
, c
->ext1
);
1979 PrintToScrollback("#db# %s", s
);
1983 case CMD_DEBUG_PRINT_INTEGERS
:
1984 PrintToScrollback("#db# %08x, %08x, %08x\r\n", c
->ext1
, c
->ext2
, c
->ext3
);
1987 case CMD_MEASURED_ANTENNA_TUNING
: {
1989 int vLf125
, vLf134
, vHf
;
1990 vLf125
= c
->ext1
& 0xffff;
1991 vLf134
= c
->ext1
>> 16;
1993 zLf
= c
->ext3
& 0xffff;
1994 zHf
= c
->ext3
>> 16;
1995 PrintToScrollback("# LF antenna @ %3d mA / %5d mV [%d ohms] 125Khz",
1996 vLf125
/zLf
, vLf125
, zLf
);
1997 PrintToScrollback("# LF antenna @ %3d mA / %5d mV [%d ohms] 134Khz",
1998 vLf134
/((zLf
*125)/134), vLf134
, (zLf
*125)/134);
1999 PrintToScrollback("# HF antenna @ %3d mA / %5d mV [%d ohms] 13.56Mhz",
2004 PrintToScrollback("unrecognized command %08x\n", c
->cmd
);