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 static void CmdHi14areader(char *str
)
83 c
.cmd
= CMD_READER_ISO_14443a
;
85 SendCommand(&c
, FALSE
);
89 static void CmdHi15reader(char *str
)
92 c
.cmd
= CMD_READER_ISO_15693
;
94 SendCommand(&c
, FALSE
);
98 static void CmdHi15tag(char *str
)
101 c
.cmd
= CMD_SIMTAG_ISO_15693
;
103 SendCommand(&c
, FALSE
);
106 static void CmdHi14read_sim(char *str
)
109 c
.cmd
= CMD_ACQUIRE_RAW_ADC_SAMPLES_ISO_14443_SIM
;
111 SendCommand(&c
, FALSE
);
114 static void CmdHi14readt(char *str
)
117 c
.cmd
= CMD_ACQUIRE_RAW_ADC_SAMPLES_ISO_14443
;
119 SendCommand(&c
, FALSE
);
121 //CmdHisamplest(str);
122 while(CmdHisamplest(str
,atoi(str
))==0) {
123 c
.cmd
= CMD_ACQUIRE_RAW_ADC_SAMPLES_ISO_14443
;
125 SendCommand(&c
, FALSE
);
127 RepaintGraphWindow();
130 static void CmdHisimlisten(char *str
)
133 c
.cmd
= CMD_SIMULATE_TAG_HF_LISTEN
;
134 SendCommand(&c
, FALSE
);
137 static void CmdHi14sim(char *str
)
140 c
.cmd
= CMD_SIMULATE_TAG_ISO_14443
;
141 SendCommand(&c
, FALSE
);
146 static void CmdHi14asim(char *str
) // ## simulate iso14443a tag
147 { // ## greg - added ability to specify tag UID
149 unsigned int hi
=0, lo
=0;
153 while (sscanf(&str
[i
++], "%1x", &n
) == 1) {
158 c
.cmd
= CMD_SIMULATE_TAG_ISO_14443a
;
159 // c.ext should be set to *str or convert *str to the correct format for a uid
162 PrintToScrollback("Emulating 14443A TAG with UID %x%16x", hi
, lo
);
163 SendCommand(&c
, FALSE
);
166 static void CmdHi14snoop(char *str
)
169 c
.cmd
= CMD_SNOOP_ISO_14443
;
170 SendCommand(&c
, FALSE
);
173 static void CmdHi14asnoop(char *str
)
176 c
.cmd
= CMD_SNOOP_ISO_14443a
;
177 SendCommand(&c
, FALSE
);
180 static void CmdFPGAOff(char *str
) // ## FPGA Control
183 c
.cmd
= CMD_FPGA_MAJOR_MODE_OFF
;
184 SendCommand(&c
, FALSE
);
187 static void CmdLosim(char *str
)
191 for(i
= 0; i
< GraphTraceLen
; i
+= 48) {
194 for(j
= 0; j
< 48; j
++) {
195 c
.d
.asBytes
[j
] = GraphBuffer
[i
+j
];
197 c
.cmd
= CMD_DOWNLOADED_SIM_SAMPLES_125K
;
199 SendCommand(&c
, FALSE
);
203 c
.cmd
= CMD_SIMULATE_TAG_125K
;
204 c
.ext1
= GraphTraceLen
;
205 SendCommand(&c
, FALSE
);
208 static void CmdLoread(char *str
)
211 // 'h' means higher-low-frequency, 134 kHz
214 } else if (*str
== '\0') {
217 PrintToScrollback("use 'loread' or 'loread h'");
220 c
.cmd
= CMD_ACQUIRE_RAW_ADC_SAMPLES_125K
;
221 SendCommand(&c
, FALSE
);
224 static void CmdLosamples(char *str
)
232 if (n
>16000) n
=16000;
234 for(i
= 0; i
< n
; i
+= 12) {
236 c
.cmd
= CMD_DOWNLOAD_RAW_ADC_SAMPLES_125K
;
238 SendCommand(&c
, FALSE
);
240 if(c
.cmd
!= CMD_DOWNLOADED_RAW_ADC_SAMPLES_125K
) {
241 PrintToScrollback("bad resp\n");
245 for(j
= 0; j
< 48; j
++) {
246 GraphBuffer
[cnt
++] = ((int)c
.d
.asBytes
[j
]) - 128;
250 RepaintGraphWindow();
253 static void CmdBitsamples(char *str
)
260 for(i
= 0; i
< n
; i
+= 12) {
262 c
.cmd
= CMD_DOWNLOAD_RAW_ADC_SAMPLES_125K
;
264 SendCommand(&c
, FALSE
);
266 if(c
.cmd
!= CMD_DOWNLOADED_RAW_ADC_SAMPLES_125K
) {
267 PrintToScrollback("bad resp\n");
271 for(j
= 0; j
< 48; j
++) {
272 for(k
= 0; k
< 8; k
++) {
273 if(c
.d
.asBytes
[j
] & (1 << (7 - k
))) {
274 GraphBuffer
[cnt
++] = 1;
276 GraphBuffer
[cnt
++] = 0;
282 RepaintGraphWindow();
285 static void CmdHisamples(char *str
)
291 for(i
= 0; i
< n
; i
+= 12) {
293 c
.cmd
= CMD_DOWNLOAD_RAW_ADC_SAMPLES_125K
;
295 SendCommand(&c
, FALSE
);
297 if(c
.cmd
!= CMD_DOWNLOADED_RAW_ADC_SAMPLES_125K
) {
298 PrintToScrollback("bad resp\n");
302 for(j
= 0; j
< 48; j
++) {
303 GraphBuffer
[cnt
++] = (int)((BYTE
)c
.d
.asBytes
[j
]);
308 RepaintGraphWindow();
312 static int CmdHisamplest(char *str
, int nrlow
)
324 for(i
= 0; i
< n
; i
+= 12) {
326 c
.cmd
= CMD_DOWNLOAD_RAW_ADC_SAMPLES_125K
;
328 SendCommand(&c
, FALSE
);
330 if(c
.cmd
!= CMD_DOWNLOADED_RAW_ADC_SAMPLES_125K
) {
331 PrintToScrollback("bad resp\n");
335 for(j
= 0; j
< 48; j
++) {
336 t2
= (int)((BYTE
)c
.d
.asBytes
[j
]);
337 if((t2
^ 0xC0) & 0xC0) { hasbeennull
++; }
343 t1
= (t2
& 0x80) ^ (t2
& 0x20);
344 t2
= ((t2
<< 1) & 0x80) ^ ((t2
<< 1) & 0x20);
350 t2
= ((t2
<< 1) & 0x80);
356 t2
= ((t2
<< 1) & 0x20);
360 // both, but tag with other algorithm
361 t1
= (t2
& 0x80) ^ (t2
& 0x08);
362 t2
= ((t2
<< 1) & 0x80) ^ ((t2
<< 1) & 0x08);
366 GraphBuffer
[cnt
++] = t1
;
367 GraphBuffer
[cnt
++] = t2
;
372 if(hasbeennull
>nrlow
|| nrlow
==0) {
373 PrintToScrollback("hasbeennull=%d", hasbeennull
);
382 static void CmdHexsamples(char *str
)
393 for(i
= 0; i
< n
; i
+= 12) {
395 c
.cmd
= CMD_DOWNLOAD_RAW_ADC_SAMPLES_125K
;
397 SendCommand(&c
, FALSE
);
399 if(c
.cmd
!= CMD_DOWNLOADED_RAW_ADC_SAMPLES_125K
) {
400 PrintToScrollback("bad resp\n");
404 for(j
= 0; j
< 48; j
+= 8) {
405 PrintToScrollback("%02x %02x %02x %02x %02x %02x %02x %02x",
420 static void CmdHisampless(char *str
)
432 for(i
= 0; i
< n
; i
+= 12) {
434 c
.cmd
= CMD_DOWNLOAD_RAW_ADC_SAMPLES_125K
;
436 SendCommand(&c
, FALSE
);
438 if(c
.cmd
!= CMD_DOWNLOADED_RAW_ADC_SAMPLES_125K
) {
439 PrintToScrollback("bad resp\n");
443 for(j
= 0; j
< 48; j
++) {
444 GraphBuffer
[cnt
++] = (int)((signed char)c
.d
.asBytes
[j
]);
449 RepaintGraphWindow();
452 static WORD
Iso15693Crc(BYTE
*v
, int n
)
458 for(i
= 0; i
< n
; i
++) {
459 reg
= reg
^ ((DWORD
)v
[i
]);
460 for (j
= 0; j
< 8; j
++) {
462 reg
= (reg
>> 1) ^ 0x8408;
472 static void CmdHi14bdemod(char *str
)
477 BOOL negateI
, negateQ
;
482 // As received, the samples are pairs, correlations against I and Q
483 // square waves. So estimate angle of initial carrier (or just
484 // quadrant, actually), and then do the demod.
486 // First, estimate where the tag starts modulating.
487 for(i
= 0; i
< GraphTraceLen
; i
+= 2) {
488 if(abs(GraphBuffer
[i
]) + abs(GraphBuffer
[i
+1]) > 40) {
492 if(i
>= GraphTraceLen
) {
493 PrintToScrollback("too weak to sync");
496 PrintToScrollback("out of weak at %d", i
);
499 // Now, estimate the phase in the initial modulation of the tag
502 for(; i
< (outOfWeakAt
+ 16); i
+= 2) {
503 isum
+= GraphBuffer
[i
+0];
504 qsum
+= GraphBuffer
[i
+1];
506 negateI
= (isum
< 0);
507 negateQ
= (qsum
< 0);
509 // Turn the correlation pairs into soft decisions on the bit.
511 for(i
= 0; i
< GraphTraceLen
/2; i
++) {
512 int si
= GraphBuffer
[j
];
513 int sq
= GraphBuffer
[j
+1];
514 if(negateI
) si
= -si
;
515 if(negateQ
) sq
= -sq
;
516 GraphBuffer
[i
] = si
+ sq
;
522 while(GraphBuffer
[i
] > 0 && i
< GraphTraceLen
)
524 if(i
>= GraphTraceLen
) goto demodError
;
527 while(GraphBuffer
[i
] < 0 && i
< GraphTraceLen
)
529 if(i
>= GraphTraceLen
) goto demodError
;
530 if((i
- iold
) > 23) goto demodError
;
532 PrintToScrollback("make it to demod loop");
536 while(GraphBuffer
[i
] >= 0 && i
< GraphTraceLen
)
538 if(i
>= GraphTraceLen
) goto demodError
;
539 if((i
- iold
) > 6) goto demodError
;
542 if(i
+ 20 >= GraphTraceLen
) goto demodError
;
544 for(j
= 0; j
< 10; j
++) {
545 int soft
= GraphBuffer
[i
] + GraphBuffer
[i
+1];
547 if(abs(soft
) < ((abs(isum
) + abs(qsum
))/20)) {
548 PrintToScrollback("weak bit");
552 if(GraphBuffer
[i
] + GraphBuffer
[i
+1] >= 0) {
559 if( (shiftReg
& 0x200) &&
562 // valid data byte, start and stop bits okay
563 PrintToScrollback(" %02x", (shiftReg
>> 1) & 0xff);
564 data
[dataLen
++] = (shiftReg
>> 1) & 0xff;
565 if(dataLen
>= sizeof(data
)) {
568 } else if(shiftReg
== 0x000) {
577 ComputeCrc14443(CRC_14443_B
, data
, dataLen
-2, &first
, &second
);
578 PrintToScrollback("CRC: %02x %02x (%s)\n", first
, second
,
579 (first
== data
[dataLen
-2] && second
== data
[dataLen
-1]) ?
580 "ok" : "****FAIL****");
582 RepaintGraphWindow();
586 PrintToScrollback("demod error");
587 RepaintGraphWindow();
590 static void CmdHi14list(char *str
)
593 GetFromBigBuf(got
, sizeof(got
));
595 PrintToScrollback("recorded activity:");
596 PrintToScrollback(" time :rssi: who bytes");
597 PrintToScrollback("---------+----+----+-----------");
608 int timestamp
= *((DWORD
*)(got
+i
));
609 if(timestamp
& 0x80000000) {
610 timestamp
&= 0x7fffffff;
615 int metric
= *((DWORD
*)(got
+i
+4));
626 BYTE
*frame
= (got
+i
+9);
628 char line
[1000] = "";
630 for(j
= 0; j
< len
; j
++) {
631 sprintf(line
+(j
*3), "%02x ", frame
[j
]);
637 ComputeCrc14443(CRC_14443_B
, frame
, len
-2, &b1
, &b2
);
638 if(b1
!= frame
[len
-2] || b2
!= frame
[len
-1]) {
639 crc
= "**FAIL CRC**";
647 char metricString
[100];
649 sprintf(metricString
, "%3d", metric
);
651 strcpy(metricString
, " ");
654 PrintToScrollback(" +%7d: %s: %s %s %s",
655 (prev
< 0 ? 0 : timestamp
- prev
),
657 (isResponse
? "TAG" : " "), line
, crc
);
664 static void CmdHi14alist(char *str
)
667 GetFromBigBuf(got
, sizeof(got
));
669 PrintToScrollback("recorded activity:");
670 PrintToScrollback(" ETU :rssi: who bytes");
671 PrintToScrollback("---------+----+----+-----------");
682 int timestamp
= *((DWORD
*)(got
+i
));
683 if(timestamp
& 0x80000000) {
684 timestamp
&= 0x7fffffff;
691 int parityBits
= *((DWORD
*)(got
+i
+4));
692 // 4 bytes of additional information...
693 // maximum of 32 additional parity bit information
696 // at each quarter bit period we can send power level (16 levels)
697 // or each half bit period in 256 levels.
705 if(i
+ len
>= 1900) {
709 BYTE
*frame
= (got
+i
+9);
711 // Break and stick with current result if buffer was not completely full
712 if(frame
[0] == 0x44 && frame
[1] == 0x44 && frame
[3] == 0x44) { break; }
714 char line
[1000] = "";
716 for(j
= 0; j
< len
; j
++) {
717 int oddparity
= 0x01;
721 oddparity
^= (((frame
[j
] & 0xFF) >> k
) & 0x01);
724 //if((parityBits >> (len - j - 1)) & 0x01) {
725 if(isResponse
&& (oddparity
!= ((parityBits
>> (len
- j
- 1)) & 0x01))) {
726 sprintf(line
+(j
*4), "%02x! ", frame
[j
]);
729 sprintf(line
+(j
*4), "%02x ", frame
[j
]);
737 for(j
= 0; j
< (len
- 1); j
++) {
738 // gives problems... search for the reason..
739 /*if(frame[j] == 0xAA) {
742 crc = "[1] Two drops close after each other";
745 crc = "[2] Potential SOC with a drop in second half of bitperiod";
748 crc = "[3] Segment Z after segment X is not possible";
751 crc = "[4] Parity bit of a fully received byte was wrong";
754 crc = "[?] Unknown error";
762 ComputeCrc14443(CRC_14443_A
, frame
, len
-2, &b1
, &b2
);
763 if(b1
!= frame
[len
-2] || b2
!= frame
[len
-1]) {
764 crc
= (isResponse
& (len
< 6)) ? "" : " !crc";
773 char metricString
[100];
775 sprintf(metricString
, "%3d", metric
);
777 strcpy(metricString
, " ");
780 PrintToScrollback(" +%7d: %s: %s %s %s",
781 (prev
< 0 ? 0 : (timestamp
- prev
)),
783 (isResponse
? "TAG" : " "), line
, crc
);
791 static void CmdHi15demod(char *str
)
793 // The sampling rate is 106.353 ksps/s, for T = 18.8 us
796 // 1) Unmodulated time of 56.64us
797 // 2) 24 pulses of 423.75khz
798 // 3) logic '1' (unmodulated for 18.88us followed by 8 pulses of 423.75khz)
800 static const int FrameSOF
[] = {
801 -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
802 -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
803 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
804 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
810 static const int Logic0
[] = {
816 static const int Logic1
[] = {
824 // 1) logic '0' (8 pulses of 423.75khz followed by unmodulated for 18.88us)
825 // 2) 24 pulses of 423.75khz
826 // 3) Unmodulated time of 56.64us
828 static const int FrameEOF
[] = {
833 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
834 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
835 -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
836 -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1
844 if(GraphTraceLen
< 1000) return;
846 // First, correlate for SOF
847 for(i
= 0; i
< 100; i
++) {
849 for(j
= 0; j
< arraylen(FrameSOF
); j
+= skip
) {
850 corr
+= FrameSOF
[j
]*GraphBuffer
[i
+(j
/skip
)];
857 PrintToScrollback("SOF at %d, correlation %d", maxPos
,
858 max
/(arraylen(FrameSOF
)/skip
));
860 i
= maxPos
+ arraylen(FrameSOF
)/skip
;
863 memset(outBuf
, 0, sizeof(outBuf
));
866 int corr0
= 0, corr1
= 0, corrEOF
= 0;
867 for(j
= 0; j
< arraylen(Logic0
); j
+= skip
) {
868 corr0
+= Logic0
[j
]*GraphBuffer
[i
+(j
/skip
)];
870 for(j
= 0; j
< arraylen(Logic1
); j
+= skip
) {
871 corr1
+= Logic1
[j
]*GraphBuffer
[i
+(j
/skip
)];
873 for(j
= 0; j
< arraylen(FrameEOF
); j
+= skip
) {
874 corrEOF
+= FrameEOF
[j
]*GraphBuffer
[i
+(j
/skip
)];
876 // Even things out by the length of the target waveform.
880 if(corrEOF
> corr1
&& corrEOF
> corr0
) {
881 PrintToScrollback("EOF at %d", i
);
883 } else if(corr1
> corr0
) {
884 i
+= arraylen(Logic1
)/skip
;
887 i
+= arraylen(Logic0
)/skip
;
894 if((i
+(int)arraylen(FrameEOF
)) >= GraphTraceLen
) {
895 PrintToScrollback("ran off end!");
900 PrintToScrollback("error, uneven octet! (discard extra bits!)");
901 PrintToScrollback(" mask=%02x", mask
);
903 PrintToScrollback("%d octets", k
);
905 for(i
= 0; i
< k
; i
++) {
906 PrintToScrollback("# %2d: %02x ", i
, outBuf
[i
]);
908 PrintToScrollback("CRC=%04x", Iso15693Crc(outBuf
, k
-2));
911 static void CmdTiread(char *str
)
914 c
.cmd
= CMD_ACQUIRE_RAW_BITS_TI_TYPE
;
915 SendCommand(&c
, FALSE
);
918 static void CmdTibits(char *str
)
922 for(i
= 0; i
< 1536; i
+= 12) {
924 c
.cmd
= CMD_DOWNLOAD_RAW_BITS_TI_TYPE
;
926 SendCommand(&c
, FALSE
);
928 if(c
.cmd
!= CMD_DOWNLOADED_RAW_BITS_TI_TYPE
) {
929 PrintToScrollback("bad resp\n");
933 for(j
= 0; j
< 12; j
++) {
935 for(k
= 31; k
>= 0; k
--) {
936 if(c
.d
.asDwords
[j
] & (1 << k
)) {
937 GraphBuffer
[cnt
++] = 1;
939 GraphBuffer
[cnt
++] = -1;
944 GraphTraceLen
= 1536*32;
945 RepaintGraphWindow();
948 static void CmdTidemod(char *cmdline
)
950 /* MATLAB as follows:
951 f_s = 2000000; % sampling frequency
952 f_l = 123200; % low FSK tone
953 f_h = 134200; % high FSK tone
955 T_l = 119e-6; % low bit duration
956 T_h = 130e-6; % high bit duration
958 l = 2*pi*ones(1, floor(f_s*T_l))*(f_l/f_s);
959 h = 2*pi*ones(1, floor(f_s*T_h))*(f_h/f_s);
961 l = sign(sin(cumsum(l)));
962 h = sign(sin(cumsum(h)));
964 static const int LowTone
[] = {
965 1, 1, 1, 1, 1, 1, 1, 1, -1, -1, -1, -1, -1, -1, -1, -1, 1, 1, 1,
966 1, 1, 1, 1, 1, -1, -1, -1, -1, -1, -1, -1, -1, 1, 1, 1, 1, 1, 1,
967 1, 1, -1, -1, -1, -1, -1, -1, -1, -1, 1, 1, 1, 1, 1, 1, 1, 1, -1,
968 -1, -1, -1, -1, -1, -1, -1, 1, 1, 1, 1, 1, 1, 1, 1, 1, -1, -1, -1,
969 -1, -1, -1, -1, -1, 1, 1, 1, 1, 1, 1, 1, 1, -1, -1, -1, -1, -1, -1,
970 -1, -1, 1, 1, 1, 1, 1, 1, 1, 1, -1, -1, -1, -1, -1, -1, -1, -1, 1,
971 1, 1, 1, 1, 1, 1, 1, -1, -1, -1, -1, -1, -1, -1, -1, 1, 1, 1, 1,
972 1, 1, 1, 1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 1, 1, 1, 1, 1, 1,
973 1, 1, -1, -1, -1, -1, -1, -1, -1, -1, 1, 1, 1, 1, 1, 1, 1, 1, -1,
974 -1, -1, -1, -1, -1, -1, -1, 1, 1, 1, 1, 1, 1, 1, 1, -1, -1, -1, -1,
975 -1, -1, -1, -1, 1, 1, 1, 1, 1, 1, 1, 1, -1, -1, -1, -1, -1, -1, -1,
976 -1, -1, 1, 1, 1, 1, 1, 1, 1, 1, -1, -1, -1, -1, -1, -1, -1, -1, 1,
977 1, 1, 1, 1, 1, 1, 1, -1, -1, -1,
979 static const int HighTone
[] = {
980 1, 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,
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,
986 -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,
988 1, 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,
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,
996 int convLen
= max(arraylen(HighTone
), arraylen(LowTone
));
999 for(i
= 0; i
< GraphTraceLen
- convLen
; i
++) {
1001 int lowSum
= 0, highSum
= 0;;
1002 int lowLen
= arraylen(LowTone
);
1003 int highLen
= arraylen(HighTone
);
1005 for(j
= 0; j
< lowLen
; j
++) {
1006 lowSum
+= LowTone
[j
]*GraphBuffer
[i
+j
];
1008 for(j
= 0; j
< highLen
; j
++) {
1009 highSum
+= HighTone
[j
]*GraphBuffer
[i
+j
];
1011 lowSum
= abs((100*lowSum
) / lowLen
);
1012 highSum
= abs((100*highSum
) / highLen
);
1013 GraphBuffer
[i
] = (highSum
<< 16) | lowSum
;
1016 for(i
= 0; i
< GraphTraceLen
- convLen
- 16; i
++) {
1018 int lowTot
= 0, highTot
= 0;
1019 // 16 and 15 are f_s divided by f_l and f_h, rounded
1020 for(j
= 0; j
< 16; j
++) {
1021 lowTot
+= (GraphBuffer
[i
+j
] & 0xffff);
1023 for(j
= 0; j
< 15; j
++) {
1024 highTot
+= (GraphBuffer
[i
+j
] >> 16);
1026 GraphBuffer
[i
] = lowTot
- highTot
;
1029 GraphTraceLen
-= (convLen
+ 16);
1031 RepaintGraphWindow();
1033 // Okay, so now we have unsliced soft decisions; find bit-sync, and then
1036 int max
= 0, maxPos
= 0;
1037 for(i
= 0; i
< 6000; i
++) {
1040 for(j
= 0; j
< 8*arraylen(LowTone
); j
++) {
1041 dec
-= GraphBuffer
[i
+j
];
1043 for(; j
< 8*arraylen(LowTone
) + 8*arraylen(HighTone
); j
++) {
1044 dec
+= GraphBuffer
[i
+j
];
1051 GraphBuffer
[maxPos
] = 800;
1052 GraphBuffer
[maxPos
+1] = -800;
1054 maxPos
+= 8*arraylen(LowTone
);
1055 GraphBuffer
[maxPos
] = 800;
1056 GraphBuffer
[maxPos
+1] = -800;
1057 maxPos
+= 8*arraylen(HighTone
);
1059 GraphBuffer
[maxPos
] = 800;
1060 GraphBuffer
[maxPos
+1] = -800;
1062 PrintToScrollback("actual data bits start at sample %d", maxPos
);
1064 PrintToScrollback("length %d/%d", arraylen(HighTone
), arraylen(LowTone
));
1066 GraphBuffer
[maxPos
] = 800;
1067 GraphBuffer
[maxPos
+1] = -800;
1069 BYTE bits
[64+16+8+1];
1070 bits
[sizeof(bits
)-1] = '\0';
1072 for(i
= 0; i
< arraylen(bits
); i
++) {
1076 for(j
= 0; j
< arraylen(LowTone
); j
++) {
1077 low
-= GraphBuffer
[maxPos
+j
];
1079 for(j
= 0; j
< arraylen(HighTone
); j
++) {
1080 high
+= GraphBuffer
[maxPos
+j
];
1084 maxPos
+= arraylen(HighTone
);
1087 maxPos
+= arraylen(LowTone
);
1089 GraphBuffer
[maxPos
] = 800;
1090 GraphBuffer
[maxPos
+1] = -800;
1092 PrintToScrollback("bits: '%s'", bits
);
1095 for(i
= 0; i
< 32; i
++) {
1096 if(bits
[i
] == '1') {
1100 for(i
= 32; i
< 64; i
++) {
1101 if(bits
[i
] == '1') {
1105 PrintToScrollback("hex: %08x %08x", h
, l
);
1108 static void CmdNorm(char *str
)
1111 int max
= INT_MIN
, min
= INT_MAX
;
1112 for(i
= 10; i
< GraphTraceLen
; i
++) {
1113 if(GraphBuffer
[i
] > max
) {
1114 max
= GraphBuffer
[i
];
1116 if(GraphBuffer
[i
] < min
) {
1117 min
= GraphBuffer
[i
];
1121 for(i
= 0; i
< GraphTraceLen
; i
++) {
1122 GraphBuffer
[i
] = (GraphBuffer
[i
] - ((max
+ min
)/2))*1000/
1126 RepaintGraphWindow();
1129 static void CmdDec(char *str
)
1132 for(i
= 0; i
< (GraphTraceLen
/2); i
++) {
1133 GraphBuffer
[i
] = GraphBuffer
[i
*2];
1136 PrintToScrollback("decimated by 2");
1137 RepaintGraphWindow();
1140 static void CmdHpf(char *str
)
1144 for(i
= 10; i
< GraphTraceLen
; i
++) {
1145 accum
+= GraphBuffer
[i
];
1147 accum
/= (GraphTraceLen
- 10);
1148 for(i
= 0; i
< GraphTraceLen
; i
++) {
1149 GraphBuffer
[i
] -= accum
;
1152 RepaintGraphWindow();
1155 static void CmdZerocrossings(char *str
)
1158 // Zero-crossings aren't meaningful unless the signal is zero-mean.
1164 for(i
= 0; i
< GraphTraceLen
; i
++) {
1165 if(GraphBuffer
[i
]*sign
>= 0) {
1166 // No change in sign, reproduce the previous sample count.
1168 GraphBuffer
[i
] = lastZc
;
1170 // Change in sign, reset the sample count.
1172 GraphBuffer
[i
] = lastZc
;
1180 RepaintGraphWindow();
1183 static void CmdLtrim(char *str
)
1188 for(i
= ds
; i
< GraphTraceLen
; i
++) {
1189 GraphBuffer
[i
-ds
] = GraphBuffer
[i
];
1191 GraphTraceLen
-= ds
;
1193 RepaintGraphWindow();
1196 static void CmdAutoCorr(char *str
)
1198 static int CorrelBuffer
[MAX_GRAPH_TRACE_LEN
];
1200 int window
= atoi(str
);
1203 PrintToScrollback("needs a window");
1207 if(window
>= GraphTraceLen
) {
1208 PrintToScrollback("window must be smaller than trace (%d samples)",
1213 PrintToScrollback("performing %d correlations", GraphTraceLen
- window
);
1216 for(i
= 0; i
< GraphTraceLen
- window
; i
++) {
1219 for(j
= 0; j
< window
; j
++) {
1220 sum
+= (GraphBuffer
[j
]*GraphBuffer
[i
+j
]) / 256;
1222 CorrelBuffer
[i
] = sum
;
1224 GraphTraceLen
= GraphTraceLen
- window
;
1225 memcpy(GraphBuffer
, CorrelBuffer
, GraphTraceLen
*sizeof(int));
1227 RepaintGraphWindow();
1230 static void CmdVchdemod(char *str
)
1232 // Is this the entire sync pattern, or does this also include some
1233 // data bits that happen to be the same everywhere? That would be
1235 static const int SyncPattern
[] = {
1236 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
1237 1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
1238 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
1239 1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
1240 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
1241 1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
1242 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
1243 1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
1244 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
1245 1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
1248 // So first, we correlate for the sync pattern, and mark that.
1249 int bestCorrel
= 0, bestPos
= 0;
1251 // It does us no good to find the sync pattern, with fewer than
1252 // 2048 samples after it...
1253 for(i
= 0; i
< (GraphTraceLen
-2048); i
++) {
1256 for(j
= 0; j
< arraylen(SyncPattern
); j
++) {
1257 sum
+= GraphBuffer
[i
+j
]*SyncPattern
[j
];
1259 if(sum
> bestCorrel
) {
1264 PrintToScrollback("best sync at %d [metric %d]", bestPos
, bestCorrel
);
1269 int worst
= INT_MAX
;
1272 for(i
= 0; i
< 2048; i
+= 8) {
1275 for(j
= 0; j
< 8; j
++) {
1276 sum
+= GraphBuffer
[bestPos
+i
+j
];
1283 if(abs(sum
) < worst
) {
1288 PrintToScrollback("bits:");
1289 PrintToScrollback("%s", bits
);
1290 PrintToScrollback("worst metric: %d at pos %d", worst
, worstPos
);
1292 if(strcmp(str
, "clone")==0) {
1295 for(s
= bits
; *s
; s
++) {
1297 for(j
= 0; j
< 16; j
++) {
1298 GraphBuffer
[GraphTraceLen
++] = (*s
== '1') ? 1 : 0;
1301 RepaintGraphWindow();
1305 static void CmdIndalademod(char *str
)
1307 // Usage: recover 64bit UID by default, specify "224" as arg to recover a 224bit UID
1312 // worst case with GraphTraceLen=64000 is < 4096
1313 // under normal conditions it's < 2048
1316 int worst
= 0, worstPos
= 0;
1317 PrintToScrollback("Expecting a bit less than %d raw bits", GraphTraceLen
/32);
1318 for(i
= 0; i
< GraphTraceLen
-1; i
+= 2) {
1320 if((GraphBuffer
[i
] > GraphBuffer
[i
+ 1]) && (state
!= 1)) {
1322 for(j
= 0; j
< count
- 8; j
+= 16) {
1323 rawbits
[rawbit
++] = 0;
1325 if ((abs(count
- j
)) > worst
) {
1326 worst
= abs(count
- j
);
1332 } else if((GraphBuffer
[i
] < GraphBuffer
[i
+ 1]) && (state
!= 0)) {
1334 for(j
= 0; j
< count
- 8; j
+= 16) {
1335 rawbits
[rawbit
++] = 1;
1337 if ((abs(count
- j
)) > worst
) {
1338 worst
= abs(count
- j
);
1346 PrintToScrollback("Recovered %d raw bits", rawbit
);
1347 PrintToScrollback("worst metric (0=best..7=worst): %d at pos %d", worst
, worstPos
);
1349 // Finding the start of a UID
1350 int uidlen
, long_wait
;
1351 if(strcmp(str
, "224") == 0) {
1360 for(start
= 0; start
<= rawbit
- uidlen
; start
++) {
1361 first
= rawbits
[start
];
1362 for(i
= start
; i
< start
+ long_wait
; i
++) {
1363 if(rawbits
[i
] != first
) {
1367 if(i
== (start
+ long_wait
)) {
1371 if(start
== rawbit
- uidlen
+ 1) {
1372 PrintToScrollback("nothing to wait for");
1376 // Inverting signal if needed
1378 for(i
= start
; i
< rawbit
; i
++) {
1379 rawbits
[i
] = !rawbits
[i
];
1386 showbits
[uidlen
]='\0';
1390 if(uidlen
> rawbit
) {
1391 PrintToScrollback("Warning: not enough raw bits to get a full UID");
1392 for(bit
= 0; bit
< rawbit
; bit
++) {
1393 bits
[bit
] = rawbits
[i
++];
1394 // As we cannot know the parity, let's use "." and "/"
1395 showbits
[bit
] = '.' + bits
[bit
];
1397 showbits
[bit
+1]='\0';
1398 PrintToScrollback("Partial UID=%s", showbits
);
1401 for(bit
= 0; bit
< uidlen
; bit
++) {
1402 bits
[bit
] = rawbits
[i
++];
1403 showbits
[bit
] = '0' + bits
[bit
];
1407 PrintToScrollback("UID=%s", showbits
);
1409 // Checking UID against next occurences
1410 for(; i
+ uidlen
<= rawbit
;) {
1412 for(bit
= 0; bit
< uidlen
; bit
++) {
1413 if(bits
[bit
] != rawbits
[i
++]) {
1423 PrintToScrollback("Occurences: %d (expected %d)", times
, (rawbit
- start
) / uidlen
);
1425 // Remodulating for tag cloning
1426 GraphTraceLen
= 32*uidlen
;
1429 for(bit
= 0; bit
< uidlen
; bit
++) {
1430 if(bits
[bit
] == 0) {
1436 for(j
= 0; j
< 32; j
++) {
1437 GraphBuffer
[i
++] = phase
;
1442 RepaintGraphWindow();
1445 static void CmdFlexdemod(char *str
)
1448 for(i
= 0; i
< GraphTraceLen
; i
++) {
1449 if(GraphBuffer
[i
] < 0) {
1450 GraphBuffer
[i
] = -1;
1456 #define LONG_WAIT 100
1458 for(start
= 0; start
< GraphTraceLen
- LONG_WAIT
; start
++) {
1459 int first
= GraphBuffer
[start
];
1460 for(i
= start
; i
< start
+ LONG_WAIT
; i
++) {
1461 if(GraphBuffer
[i
] != first
) {
1465 if(i
== (start
+ LONG_WAIT
)) {
1469 if(start
== GraphTraceLen
- LONG_WAIT
) {
1470 PrintToScrollback("nothing to wait for");
1474 GraphBuffer
[start
] = 2;
1475 GraphBuffer
[start
+1] = -2;
1481 for(bit
= 0; bit
< 64; bit
++) {
1484 for(j
= 0; j
< 16; j
++) {
1485 sum
+= GraphBuffer
[i
++];
1492 PrintToScrollback("bit %d sum %d", bit
, sum
);
1495 for(bit
= 0; bit
< 64; bit
++) {
1498 for(j
= 0; j
< 16; j
++) {
1499 sum
+= GraphBuffer
[i
++];
1501 if(sum
> 0 && bits
[bit
] != 1) {
1502 PrintToScrollback("oops1 at %d", bit
);
1504 if(sum
< 0 && bits
[bit
] != 0) {
1505 PrintToScrollback("oops2 at %d", bit
);
1509 GraphTraceLen
= 32*64;
1512 for(bit
= 0; bit
< 64; bit
++) {
1513 if(bits
[bit
] == 0) {
1519 for(j
= 0; j
< 32; j
++) {
1520 GraphBuffer
[i
++] = phase
;
1525 RepaintGraphWindow();
1529 * Generic command to demodulate ASK. bit length in argument.
1530 * Giving the bit length helps discriminate ripple effects
1531 * upon zero crossing for noisy traces.
1533 * Second is convention: positive or negative (High mod means zero
1534 * or high mod means one)
1536 * Updates the Graph trace with 0/1 values
1539 * sl : bit length in terms of number of samples per bit
1540 * (use yellow/purple markers to compute).
1544 static void Cmdaskdemod(char *str
) {
1551 // TODO: complain if we do not give 2 arguments here !
1552 sscanf(str
, "%i %i", &n
, &c
);
1559 if (GraphBuffer
[0]*c
> 0) {
1564 for(i
=1;i
<GraphTraceLen
;i
++) {
1565 /* Analyse signal within the symbol length */
1566 /* Decide if we crossed a zero */
1567 if (GraphBuffer
[i
]*sign
< 0) {
1568 /* Crossed a zero, check if this is a ripple or not */
1569 if ( (i
-t1
) > n
/4 ) {
1572 if (GraphBuffer
[i
]*c
> 0){
1578 /* This is a ripple, set the current sample value
1579 to the same as previous */
1580 GraphBuffer
[i
] = GraphBuffer
[i
-1];
1583 GraphBuffer
[i
] = GraphBuffer
[i
-1];
1586 RepaintGraphWindow();
1591 * Manchester demodulate a bitstream. The bitstream needs to be already in
1592 * the GraphBuffer as 0 and 1 values
1594 * Give the clock rate as argument in order to help the sync - the algorithm
1595 * resyncs at each pulse anyway.
1597 * Not optimized by any means, this is the 1st time I'm writing this type of
1598 * routine, feel free to improve...
1600 * 1st argument: clock rate (as number of samples per clock rate)
1601 * Typical values can be 64, 32, 128...
1603 static void Cmdmanchesterdemod(char *str
) {
1612 sscanf(str
, "%i", &clock
);
1614 int tolerance
= clock
/4;
1615 /* Holds the decoded bitstream: each clock period contains 2 bits */
1616 /* later simplified to 1 bit after manchester decoding. */
1617 /* Add 10 bits to allow for noisy / uncertain traces without aborting */
1618 /* int BitStream[GraphTraceLen*2/clock+10]; */
1620 /* But it does not work if compiling on WIndows: therefore we just allocate a */
1622 int BitStream
[MAX_GRAPH_TRACE_LEN
];
1624 /* Detect first transition */
1625 /* Lo-Hi (arbitrary) */
1626 for(i
=1;i
<GraphTraceLen
;i
++) {
1627 if (GraphBuffer
[i
-1]<GraphBuffer
[i
]) {
1629 BitStream
[0]=0; // Previous state = 0;
1634 /* Then detect duration between 2 successive transitions */
1635 for(bitidx
= 1 ;i
<GraphTraceLen
;i
++) {
1636 if (GraphBuffer
[i
-1] != GraphBuffer
[i
]) {
1639 // Error check: if bitidx becomes too large, we do not
1640 // have a Manchester encoded bitstream or the clock is really
1642 if (bitidx
> (GraphTraceLen
*2/clock
+8) ) {
1643 PrintToScrollback("Error: the clock you gave is probably wrong, aborting.");
1646 // Then switch depending on lc length:
1647 // Tolerance is 1/4 of clock rate (arbitrary)
1648 if (abs(lc
-clock
/2) < tolerance
) {
1649 // Short pulse : either "1" or "0"
1650 BitStream
[bitidx
++]=GraphBuffer
[i
-1];
1651 } else if (abs(lc
-clock
) < tolerance
) {
1652 // Long pulse: either "11" or "00"
1653 BitStream
[bitidx
++]=GraphBuffer
[i
-1];
1654 BitStream
[bitidx
++]=GraphBuffer
[i
-1];
1657 PrintToScrollback("Warning: Manchester decode error for pulse width detection.");
1658 PrintToScrollback("(too many of those messages mean either the stream is not Manchester encoded, or clock is wrong)");
1663 // At this stage, we now have a bitstream of "01" ("1") or "10" ("0"), parse it into final decoded bitstream
1664 // Actually, we overwrite BitStream with the new decoded bitstream, we just need to be careful
1665 // to stop output at the final bitidx2 value, not bitidx
1666 for (i
= 0; i
< bitidx
; i
+= 2) {
1667 if ((BitStream
[i
] == 0) && (BitStream
[i
+1] == 1)) {
1668 BitStream
[bit2idx
++] = 1;
1669 } else if ((BitStream
[i
] == 1) && (BitStream
[i
+1] == 0)) {
1670 BitStream
[bit2idx
++] = 0;
1672 // We cannot end up in this state, this means we are unsynchronized,
1675 PrintToScrollback("Unsynchronized, resync...");
1676 PrintToScrollback("(too many of those messages mean the stream is not Manchester encoded)");
1679 PrintToScrollback("Manchester decoded bitstream \n---------");
1680 // Now output the bitstream to the scrollback by line of 16 bits
1681 for (i
= 0; i
< (bit2idx
-16); i
+=16) {
1682 PrintToScrollback("%i %i %i %i %i %i %i %i %i %i %i %i %i %i %i %i",
1707 static void CmdHiddemod(char *str
)
1709 if(GraphTraceLen
< 4800) {
1710 PrintToScrollback("too short; need at least 4800 samples");
1714 GraphTraceLen
= 4800;
1716 for(i
= 0; i
< GraphTraceLen
; i
++) {
1717 if(GraphBuffer
[i
] < 0) {
1723 RepaintGraphWindow();
1726 static void CmdPlot(char *str
)
1731 static void CmdHide(char *str
)
1736 static void CmdScale(char *str
)
1738 CursorScaleFactor
= atoi(str
);
1739 if(CursorScaleFactor
== 0) {
1740 PrintToScrollback("bad, can't have zero scale");
1741 CursorScaleFactor
= 1;
1743 RepaintGraphWindow();
1746 static void CmdSave(char *str
)
1748 FILE *f
= fopen(str
, "w");
1750 PrintToScrollback("couldn't open '%s'", str
);
1754 for(i
= 0; i
< GraphTraceLen
; i
++) {
1755 fprintf(f
, "%d\n", GraphBuffer
[i
]);
1758 PrintToScrollback("saved to '%s'", str
);
1761 static void CmdLoad(char *str
)
1763 FILE *f
= fopen(str
, "r");
1765 PrintToScrollback("couldn't open '%s'", str
);
1771 while(fgets(line
, sizeof(line
), f
)) {
1772 GraphBuffer
[GraphTraceLen
] = atoi(line
);
1776 PrintToScrollback("loaded %d samples", GraphTraceLen
);
1777 RepaintGraphWindow();
1780 static void CmdHIDsimTAG(char *str
)
1782 unsigned int hi
=0, lo
=0;
1786 while (sscanf(&str
[i
++], "%1x", &n
) == 1) {
1787 hi
=(hi
<<4)|(lo
>>28);
1791 PrintToScrollback("Emulating tag with ID %x%16x", hi
, lo
);
1793 c
.cmd
= CMD_HID_SIM_TAG
;
1796 SendCommand(&c
, FALSE
);
1799 static void CmdLcdReset(char *str
)
1802 c
.cmd
= CMD_LCD_RESET
;
1804 SendCommand(&c
, FALSE
);
1807 static void CmdLcd(char *str
)
1812 sscanf(str
, "%x %d", &i
, &j
);
1815 SendCommand(&c
, FALSE
);
1819 static void CmdTest(char *str
)
1824 * Sets the divisor for LF frequency clock: lets the user choose any LF frequency below
1827 static void CmdSetDivisor(char *str
)
1830 c
.cmd
= CMD_SET_LF_DIVISOR
;
1832 if (( c
.ext1
<0) || (c
.ext1
>255)) {
1833 PrintToScrollback("divisor must be between 19 and 255");
1835 SendCommand(&c
, FALSE
);
1836 PrintToScrollback("Divisor set, expected freq=%dHz", 12000000/(c
.ext1
+1));
1840 static void CmdSweepLF(char *str
)
1843 c
.cmd
= CMD_SWEEP_LF
;
1844 SendCommand(&c
, FALSE
);
1849 typedef void HandlerFunction(char *cmdline
);
1853 HandlerFunction
*handler
;
1855 } CommandTable
[] = {
1856 "tune", CmdTune
, "measure antenna tuning",
1857 "tiread", CmdTiread
, "read a TI-type 134 kHz tag",
1858 "tibits", CmdTibits
, "get raw bits for TI-type LF tag",
1859 "tidemod", CmdTidemod
, "demod raw bits for TI-type LF tag",
1860 "vchdemod", CmdVchdemod
, "demod samples for VeriChip",
1861 "plot", CmdPlot
, "show graph window",
1862 "hide", CmdHide
, "hide graph window",
1863 "losim", CmdLosim
, "simulate LF tag",
1864 "loread", CmdLoread
, "read (125/134 kHz) LF ID-only tag",
1865 "losamples", CmdLosamples
, "get raw samples for LF tag",
1866 "hisamples", CmdHisamples
, "get raw samples for HF tag",
1867 "hisampless", CmdHisampless
, "get signed raw samples, HF tag",
1868 "hisamplest", CmdHi14readt
, "get samples HF, for testing",
1869 "higet", CmdHi14read_sim
, "get samples HF, 'analog'",
1870 "bitsamples", CmdBitsamples
, "get raw samples as bitstring",
1871 "hexsamples", CmdHexsamples
, "dump big buffer as hex bytes",
1872 "hi15read", CmdHi15read
, "read HF tag (ISO 15693)",
1873 "hi15reader", CmdHi15reader
, "act like an ISO15693 reader", // new command greg
1874 "hi15sim", CmdHi15tag
, "fake an ISO15693 tag", // new command greg
1875 "hi14read", CmdHi14read
, "read HF tag (ISO 14443)",
1876 "hi14areader", CmdHi14areader
, "act like an ISO14443 Type A reader", // ## New reader command
1877 "hi15demod", CmdHi15demod
, "demod ISO15693 from tag",
1878 "hi14bdemod", CmdHi14bdemod
, "demod ISO14443 Type B from tag",
1879 "autocorr", CmdAutoCorr
, "autocorrelation over window",
1880 "norm", CmdNorm
, "normalize max/min to +/-500",
1881 "dec", CmdDec
, "decimate",
1882 "hpf", CmdHpf
, "remove DC offset from trace",
1883 "zerocrossings", CmdZerocrossings
, "count time between zero-crossings",
1884 "ltrim", CmdLtrim
, "trim from left of trace",
1885 "scale", CmdScale
, "set cursor display scale",
1886 "flexdemod", CmdFlexdemod
, "demod samples for FlexPass",
1887 "indalademod", CmdIndalademod
, "demod samples for Indala",
1888 "save", CmdSave
, "save trace (from graph window)",
1889 "load", CmdLoad
, "load trace (to graph window",
1890 "hisimlisten", CmdHisimlisten
, "get HF samples as fake tag",
1891 "hi14sim", CmdHi14sim
, "fake ISO 14443 tag",
1892 "hi14asim", CmdHi14asim
, "fake ISO 14443a tag", // ## Simulate 14443a tag
1893 "hi14snoop", CmdHi14snoop
, "eavesdrop ISO 14443",
1894 "hi14asnoop", CmdHi14asnoop
, "eavesdrop ISO 14443 Type A", // ## New snoop command
1895 "hi14list", CmdHi14list
, "list ISO 14443 history",
1896 "hi14alist", CmdHi14alist
, "list ISO 14443a history", // ## New list command
1897 "hiddemod", CmdHiddemod
, "HID Prox Card II (not optimal)",
1898 "hidfskdemod", CmdHIDdemodFSK
, "HID FSK demodulator",
1899 "askdemod", Cmdaskdemod
, "Attempt to demodulate simple ASK tags",
1900 "hidsimtag", CmdHIDsimTAG
, "HID tag simulator",
1901 "mandemod", Cmdmanchesterdemod
, "Try a Manchester demodulation on a binary stream",
1902 "fpgaoff", CmdFPGAOff
, "set FPGA off", // ## FPGA Control
1903 "lcdreset", CmdLcdReset
, "Hardware reset LCD",
1904 "lcd", CmdLcd
, "Send command/data to LCD",
1905 "test", CmdTest
, "Placeholder command for testing new code",
1906 "setlfdivisor", CmdSetDivisor
, "Drive LF antenna at 12Mhz/(divisor+1)",
1907 "sweeplf", CmdSweepLF
, "Sweep through LF freq range and store results in buffer",
1908 "quit", CmdQuit
, "quit program"
1911 //-----------------------------------------------------------------------------
1912 // Entry point into our code: called whenever the user types a command and
1913 // then presses Enter, which the full command line that they typed.
1914 //-----------------------------------------------------------------------------
1915 void CommandReceived(char *cmd
)
1919 PrintToScrollback("> %s", cmd
);
1921 if(strcmp(cmd
, "help")==0) {
1922 PrintToScrollback("\r\nAvailable commands:");
1923 for(i
= 0; i
< sizeof(CommandTable
) / sizeof(CommandTable
[0]); i
++) {
1925 memset(line
, ' ', sizeof(line
));
1926 strcpy(line
+2, CommandTable
[i
].name
);
1927 line
[strlen(line
)] = ' ';
1928 sprintf(line
+15, " -- %s", CommandTable
[i
].docString
);
1929 PrintToScrollback("%s", line
);
1931 PrintToScrollback("");
1932 PrintToScrollback("and also: help, cls");
1936 for(i
= 0; i
< sizeof(CommandTable
) / sizeof(CommandTable
[0]); i
++) {
1937 char *name
= CommandTable
[i
].name
;
1938 if(memcmp(cmd
, name
, strlen(name
))==0 &&
1939 (cmd
[strlen(name
)] == ' ' || cmd
[strlen(name
)] == '\0'))
1941 cmd
+= strlen(name
);
1942 while(*cmd
== ' ') {
1945 (CommandTable
[i
].handler
)(cmd
);
1949 PrintToScrollback(">> bad command '%s'", cmd
);
1952 //-----------------------------------------------------------------------------
1953 // Entry point into our code: called whenever we received a packet over USB
1954 // that we weren't necessarily expecting, for example a debug print.
1955 //-----------------------------------------------------------------------------
1956 void UsbCommandReceived(UsbCommand
*c
)
1959 case CMD_DEBUG_PRINT_STRING
: {
1961 if(c
->ext1
> 70 || c
->ext1
< 0) {
1964 memcpy(s
, c
->d
.asBytes
, c
->ext1
);
1966 PrintToScrollback("#db# %s", s
);
1970 case CMD_DEBUG_PRINT_INTEGERS
:
1971 PrintToScrollback("#db# %08x, %08x, %08x\r\n", c
->ext1
, c
->ext2
, c
->ext3
);
1974 case CMD_MEASURED_ANTENNA_TUNING
: {
1976 int vLf125
, vLf134
, vHf
;
1977 vLf125
= c
->ext1
& 0xffff;
1978 vLf134
= c
->ext1
>> 16;
1980 zLf
= c
->ext3
& 0xffff;
1981 zHf
= c
->ext3
>> 16;
1982 PrintToScrollback("# LF antenna @ %3d mA / %5d mV [%d ohms] 125Khz",
1983 vLf125
/zLf
, vLf125
, zLf
);
1984 PrintToScrollback("# LF antenna @ %3d mA / %5d mV [%d ohms] 134Khz",
1985 vLf134
/((zLf
*125)/134), vLf134
, (zLf
*125)/134);
1986 PrintToScrollback("# HF antenna @ %3d mA / %5d mV [%d ohms] 13.56Mhz",
1991 PrintToScrollback("unrecognized command %08x\n", c
->cmd
);