1 //-----------------------------------------------------------------------------
2 // The actual command interpeter for what the user types at the command line.
3 // Jonathan Westhues, Sept 2005
4 // Edits by Gerhard de Koning Gans, Sep 2007 (##)
5 //-----------------------------------------------------------------------------
14 #include "../common/iso14443_crc.c"
16 #define arraylen(x) (sizeof(x)/sizeof((x)[0]))
17 #define BIT(x) GraphBuffer[x * clock]
18 #define BITS (GraphTraceLen / clock)
21 static int CmdHisamplest(char *str
, int nrlow
);
23 static void GetFromBigBuf(BYTE
*dest
, int bytes
)
28 PrintToScrollback("bad len in GetFromBigBuf");
33 for(i
= 0; i
< n
; i
+= 12) {
35 c
.cmd
= CMD_DOWNLOAD_RAW_ADC_SAMPLES_125K
;
37 SendCommand(&c
, FALSE
);
39 if(c
.cmd
!= CMD_DOWNLOADED_RAW_ADC_SAMPLES_125K
) {
40 PrintToScrollback("bad resp");
44 memcpy(dest
+(i
*4), c
.d
.asBytes
, 48);
48 static void CmdReset(char *str
)
51 c
.cmd
= CMD_HARDWARE_RESET
;
52 SendCommand(&c
, FALSE
);
56 static void CmdQuit(char *str
)
61 static void CmdHIDdemodFSK(char *str
)
64 c
.cmd
= CMD_HID_DEMOD_FSK
;
65 SendCommand(&c
, FALSE
);
68 static void CmdTune(char *str
)
71 c
.cmd
= CMD_MEASURE_ANTENNA_TUNING
;
72 SendCommand(&c
, FALSE
);
75 static void CmdHi15read(char *str
)
78 c
.cmd
= CMD_ACQUIRE_RAW_ADC_SAMPLES_ISO_15693
;
79 SendCommand(&c
, FALSE
);
82 static void CmdHi14read(char *str
)
85 c
.cmd
= CMD_ACQUIRE_RAW_ADC_SAMPLES_ISO_14443
;
87 SendCommand(&c
, FALSE
);
91 /* New command to read the contents of a SRI512 tag
92 * SRI512 tags are ISO14443-B modulated memory tags,
93 * this command just dumps the contents of the memory/
95 static void CmdSri512read(char *str
)
98 c
.cmd
= CMD_READ_SRI512_TAG
;
100 SendCommand(&c
, FALSE
);
104 static void CmdHi14areader(char *str
)
107 c
.cmd
= CMD_READER_ISO_14443a
;
109 SendCommand(&c
, FALSE
);
113 static void CmdHi15reader(char *str
)
116 c
.cmd
= CMD_READER_ISO_15693
;
118 SendCommand(&c
, FALSE
);
122 static void CmdHi15tag(char *str
)
125 c
.cmd
= CMD_SIMTAG_ISO_15693
;
127 SendCommand(&c
, FALSE
);
130 static void CmdHi14read_sim(char *str
)
133 c
.cmd
= CMD_ACQUIRE_RAW_ADC_SAMPLES_ISO_14443_SIM
;
135 SendCommand(&c
, FALSE
);
138 static void CmdHi14readt(char *str
)
141 c
.cmd
= CMD_ACQUIRE_RAW_ADC_SAMPLES_ISO_14443
;
143 SendCommand(&c
, FALSE
);
145 //CmdHisamplest(str);
146 while(CmdHisamplest(str
,atoi(str
))==0) {
147 c
.cmd
= CMD_ACQUIRE_RAW_ADC_SAMPLES_ISO_14443
;
149 SendCommand(&c
, FALSE
);
151 RepaintGraphWindow();
154 static void CmdHisimlisten(char *str
)
157 c
.cmd
= CMD_SIMULATE_TAG_HF_LISTEN
;
158 SendCommand(&c
, FALSE
);
161 static void CmdHi14sim(char *str
)
164 c
.cmd
= CMD_SIMULATE_TAG_ISO_14443
;
165 SendCommand(&c
, FALSE
);
168 static void CmdHi14asim(char *str
) // ## simulate iso14443a tag
169 { // ## greg - added ability to specify tag UID
171 unsigned int hi
=0, lo
=0;
175 while (sscanf(&str
[i
++], "%1x", &n
) == 1) {
180 c
.cmd
= CMD_SIMULATE_TAG_ISO_14443a
;
181 // c.ext should be set to *str or convert *str to the correct format for a uid
184 PrintToScrollback("Emulating 14443A TAG with UID %x%16x", hi
, lo
);
185 SendCommand(&c
, FALSE
);
188 static void CmdHi14snoop(char *str
)
191 c
.cmd
= CMD_SNOOP_ISO_14443
;
192 SendCommand(&c
, FALSE
);
195 static void CmdHi14asnoop(char *str
)
198 c
.cmd
= CMD_SNOOP_ISO_14443a
;
199 SendCommand(&c
, FALSE
);
202 static void CmdFPGAOff(char *str
) // ## FPGA Control
205 c
.cmd
= CMD_FPGA_MAJOR_MODE_OFF
;
206 SendCommand(&c
, FALSE
);
209 /* clear out our graph window */
210 int CmdClearGraph(int redraw
)
212 int gtl
= GraphTraceLen
;
216 RepaintGraphWindow();
221 /* write a bit to the graph */
222 static void CmdAppendGraph(int redraw
, int clock
, int bit
)
226 for (i
= 0; i
< (int)(clock
/2); i
++)
227 GraphBuffer
[GraphTraceLen
++] = bit
^ 1;
229 for (i
= (int)(clock
/2); i
< clock
; i
++)
230 GraphBuffer
[GraphTraceLen
++] = bit
;
233 RepaintGraphWindow();
236 /* Function is equivalent of loread + losamples + em410xread
237 * looped until an EM410x tag is detected */
238 static void CmdEM410xwatch(char *str
)
252 /* Read the ID of an EM410x tag.
254 * 1111 1111 1 <-- standard non-repeatable header
255 * XXXX [row parity bit] <-- 10 rows of 5 bits for our 40 bit tag ID
257 * CCCC <-- each bit here is parity for the 10 bits above in corresponding column
258 * 0 <-- stop bit, end of tag
260 static void CmdEM410xread(char *str
)
262 int i
, j
, clock
, header
, rows
, bit
, hithigh
, hitlow
, first
, bit2idx
, high
, low
;
265 int BitStream
[MAX_GRAPH_TRACE_LEN
];
268 /* Detect high and lows and clock */
269 for (i
= 0; i
< GraphTraceLen
; i
++)
271 if (GraphBuffer
[i
] > high
)
272 high
= GraphBuffer
[i
];
273 else if (GraphBuffer
[i
] < low
)
274 low
= GraphBuffer
[i
];
278 clock
= GetClock(str
, high
);
280 /* parity for our 4 columns */
281 parity
[0] = parity
[1] = parity
[2] = parity
[3] = 0;
284 /* manchester demodulate */
286 for (i
= 0; i
< (int)(GraphTraceLen
/ clock
); i
++)
292 /* Find out if we hit both high and low peaks */
293 for (j
= 0; j
< clock
; j
++)
295 if (GraphBuffer
[(i
* clock
) + j
] == high
)
297 else if (GraphBuffer
[(i
* clock
) + j
] == low
)
300 /* it doesn't count if it's the first part of our read
301 because it's really just trailing from the last sequence */
302 if (first
&& (hithigh
|| hitlow
))
303 hithigh
= hitlow
= 0;
307 if (hithigh
&& hitlow
)
311 /* If we didn't hit both high and low peaks, we had a bit transition */
312 if (!hithigh
|| !hitlow
)
315 BitStream
[bit2idx
++] = bit
;
318 /* We go till 5 before the graph ends because we'll get that far below */
319 for (i
= 1; i
< bit2idx
- 5; i
++)
321 /* Step 2: We have our header but need our tag ID */
322 if (header
== 9 && rows
< 10)
324 /* Confirm parity is correct */
325 if ((BitStream
[i
] ^ BitStream
[i
+1] ^ BitStream
[i
+2] ^ BitStream
[i
+3]) == BitStream
[i
+4])
327 /* Read another byte! */
328 sprintf(id
+rows
, "%x", (8 * BitStream
[i
]) + (4 * BitStream
[i
+1]) + (2 * BitStream
[i
+2]) + (1 * BitStream
[i
+3]));
331 /* Keep parity info */
332 parity
[0] ^= BitStream
[i
];
333 parity
[1] ^= BitStream
[i
+1];
334 parity
[2] ^= BitStream
[i
+2];
335 parity
[3] ^= BitStream
[i
+3];
337 /* Move 4 bits ahead */
341 /* Damn, something wrong! reset */
344 PrintToScrollback("Thought we had a valid tag but failed at word %d (i=%d)", rows
+ 1, i
);
346 /* Start back rows * 5 + 9 header bits, -1 to not start at same place */
347 i
-= 9 + (5 * rows
) - 5;
353 /* Step 3: Got our 40 bits! confirm column parity */
356 /* We need to make sure our 4 bits of parity are correct and we have a stop bit */
357 if (BitStream
[i
] == parity
[0] && BitStream
[i
+1] == parity
[1] &&
358 BitStream
[i
+2] == parity
[2] && BitStream
[i
+3] == parity
[3] &&
362 PrintToScrollback("EM410x Tag ID: %s", id
);
369 /* Crap! Incorrect parity or no stop bit, start all over */
374 /* Go back 59 bits (9 header bits + 10 rows at 4+1 parity) */
379 /* Step 1: get our header */
382 /* Need 9 consecutive 1's */
383 if (BitStream
[i
] == 1)
386 /* We don't have a header, not enough consecutive 1 bits */
393 /* emulate an EM410X tag
395 * 1111 1111 1 <-- standard non-repeatable header
396 * XXXX [row parity bit] <-- 10 rows of 5 bits for our 40 bit tag ID
398 * CCCC <-- each bit here is parity for the 10 bits above in corresponding column
399 * 0 <-- stop bit, end of tag
401 static void CmdEM410xsim(char *str
)
403 int i
, n
, j
, h
, binary
[4], parity
[4];
406 /* clock is 64 in EM410x tags */
409 /* clear our graph */
412 /* write it out a few times */
413 for (h
= 0; h
< 4; h
++)
415 /* write 9 start bits */
416 for (i
= 0; i
< 9; i
++)
417 CmdAppendGraph(0, clock
, 1);
419 /* for each hex char */
420 parity
[0] = parity
[1] = parity
[2] = parity
[3] = 0;
421 for (i
= 0; i
< 10; i
++)
423 /* read each hex char */
424 sscanf(&str
[i
], "%1x", &n
);
425 for (j
= 3; j
>= 0; j
--, n
/= 2)
428 /* append each bit */
429 CmdAppendGraph(0, clock
, binary
[0]);
430 CmdAppendGraph(0, clock
, binary
[1]);
431 CmdAppendGraph(0, clock
, binary
[2]);
432 CmdAppendGraph(0, clock
, binary
[3]);
434 /* append parity bit */
435 CmdAppendGraph(0, clock
, binary
[0] ^ binary
[1] ^ binary
[2] ^ binary
[3]);
437 /* keep track of column parity */
438 parity
[0] ^= binary
[0];
439 parity
[1] ^= binary
[1];
440 parity
[2] ^= binary
[2];
441 parity
[3] ^= binary
[3];
445 CmdAppendGraph(0, clock
, parity
[0]);
446 CmdAppendGraph(0, clock
, parity
[1]);
447 CmdAppendGraph(0, clock
, parity
[2]);
448 CmdAppendGraph(0, clock
, parity
[3]);
451 CmdAppendGraph(0, clock
, 0);
454 /* modulate that biatch */
458 RepaintGraphWindow();
463 static void ChkBitstream(char *str
)
467 /* convert to bitstream if necessary */
468 for (i
= 0; i
< (int)(GraphTraceLen
/ 2); i
++)
470 if (GraphBuffer
[i
] > 1 || GraphBuffer
[i
] < 0)
478 static void CmdLosim(char *str
)
483 /* convert to bitstream if necessary */
486 for (i
= 0; i
< GraphTraceLen
; i
+= 48) {
489 for(j
= 0; j
< 48; j
++) {
490 c
.d
.asBytes
[j
] = GraphBuffer
[i
+j
];
492 c
.cmd
= CMD_DOWNLOADED_SIM_SAMPLES_125K
;
494 SendCommand(&c
, FALSE
);
498 c
.cmd
= CMD_SIMULATE_TAG_125K
;
499 c
.ext1
= GraphTraceLen
;
500 SendCommand(&c
, FALSE
);
503 static void CmdLoread(char *str
)
506 // 'h' means higher-low-frequency, 134 kHz
509 } else if (*str
== '\0') {
512 PrintToScrollback("use 'loread' or 'loread h'");
515 c
.cmd
= CMD_ACQUIRE_RAW_ADC_SAMPLES_125K
;
516 SendCommand(&c
, FALSE
);
519 static void CmdLosamples(char *str
)
527 if (n
>16000) n
=16000;
529 for(i
= 0; i
< n
; i
+= 12) {
531 c
.cmd
= CMD_DOWNLOAD_RAW_ADC_SAMPLES_125K
;
533 SendCommand(&c
, FALSE
);
535 if(c
.cmd
!= CMD_DOWNLOADED_RAW_ADC_SAMPLES_125K
) {
537 PrintToScrollback("bad resp");
541 for(j
= 0; j
< 48; j
++) {
542 GraphBuffer
[cnt
++] = ((int)c
.d
.asBytes
[j
]) - 128;
546 RepaintGraphWindow();
549 static void CmdBitsamples(char *str
)
556 for(i
= 0; i
< n
; i
+= 12) {
558 c
.cmd
= CMD_DOWNLOAD_RAW_ADC_SAMPLES_125K
;
560 SendCommand(&c
, FALSE
);
562 if(c
.cmd
!= CMD_DOWNLOADED_RAW_ADC_SAMPLES_125K
) {
563 PrintToScrollback("bad resp");
567 for(j
= 0; j
< 48; j
++) {
568 for(k
= 0; k
< 8; k
++) {
569 if(c
.d
.asBytes
[j
] & (1 << (7 - k
))) {
570 GraphBuffer
[cnt
++] = 1;
572 GraphBuffer
[cnt
++] = 0;
578 RepaintGraphWindow();
581 static void CmdHisamples(char *str
)
587 for(i
= 0; i
< n
; i
+= 12) {
589 c
.cmd
= CMD_DOWNLOAD_RAW_ADC_SAMPLES_125K
;
591 SendCommand(&c
, FALSE
);
593 if(c
.cmd
!= CMD_DOWNLOADED_RAW_ADC_SAMPLES_125K
) {
594 PrintToScrollback("bad resp");
598 for(j
= 0; j
< 48; j
++) {
599 GraphBuffer
[cnt
++] = (int)((BYTE
)c
.d
.asBytes
[j
]);
604 RepaintGraphWindow();
608 static int CmdHisamplest(char *str
, int nrlow
)
620 for(i
= 0; i
< n
; i
+= 12) {
622 c
.cmd
= CMD_DOWNLOAD_RAW_ADC_SAMPLES_125K
;
624 SendCommand(&c
, FALSE
);
626 if(c
.cmd
!= CMD_DOWNLOADED_RAW_ADC_SAMPLES_125K
) {
627 PrintToScrollback("bad resp");
631 for(j
= 0; j
< 48; j
++) {
632 t2
= (int)((BYTE
)c
.d
.asBytes
[j
]);
633 if((t2
^ 0xC0) & 0xC0) { hasbeennull
++; }
639 t1
= (t2
& 0x80) ^ (t2
& 0x20);
640 t2
= ((t2
<< 1) & 0x80) ^ ((t2
<< 1) & 0x20);
646 t2
= ((t2
<< 1) & 0x80);
652 t2
= ((t2
<< 1) & 0x20);
656 // both, but tag with other algorithm
657 t1
= (t2
& 0x80) ^ (t2
& 0x08);
658 t2
= ((t2
<< 1) & 0x80) ^ ((t2
<< 1) & 0x08);
662 GraphBuffer
[cnt
++] = t1
;
663 GraphBuffer
[cnt
++] = t2
;
668 if(hasbeennull
>nrlow
|| nrlow
==0) {
669 PrintToScrollback("hasbeennull=%d", hasbeennull
);
678 static void CmdHexsamples(char *str
)
689 for(i
= 0; i
< n
; i
+= 12) {
691 c
.cmd
= CMD_DOWNLOAD_RAW_ADC_SAMPLES_125K
;
693 SendCommand(&c
, FALSE
);
695 if(c
.cmd
!= CMD_DOWNLOADED_RAW_ADC_SAMPLES_125K
) {
696 PrintToScrollback("bad resp");
700 for(j
= 0; j
< 48; j
+= 8) {
701 PrintToScrollback("%02x %02x %02x %02x %02x %02x %02x %02x",
716 static void CmdHisampless(char *str
)
728 for(i
= 0; i
< n
; i
+= 12) {
730 c
.cmd
= CMD_DOWNLOAD_RAW_ADC_SAMPLES_125K
;
732 SendCommand(&c
, FALSE
);
734 if(c
.cmd
!= CMD_DOWNLOADED_RAW_ADC_SAMPLES_125K
) {
735 PrintToScrollback("bad resp");
739 for(j
= 0; j
< 48; j
++) {
740 GraphBuffer
[cnt
++] = (int)((signed char)c
.d
.asBytes
[j
]);
745 RepaintGraphWindow();
748 static WORD
Iso15693Crc(BYTE
*v
, int n
)
754 for(i
= 0; i
< n
; i
++) {
755 reg
= reg
^ ((DWORD
)v
[i
]);
756 for (j
= 0; j
< 8; j
++) {
758 reg
= (reg
>> 1) ^ 0x8408;
768 static void CmdHi14bdemod(char *str
)
773 BOOL negateI
, negateQ
;
778 // As received, the samples are pairs, correlations against I and Q
779 // square waves. So estimate angle of initial carrier (or just
780 // quadrant, actually), and then do the demod.
782 // First, estimate where the tag starts modulating.
783 for(i
= 0; i
< GraphTraceLen
; i
+= 2) {
784 if(abs(GraphBuffer
[i
]) + abs(GraphBuffer
[i
+1]) > 40) {
788 if(i
>= GraphTraceLen
) {
789 PrintToScrollback("too weak to sync");
792 PrintToScrollback("out of weak at %d", i
);
795 // Now, estimate the phase in the initial modulation of the tag
798 for(; i
< (outOfWeakAt
+ 16); i
+= 2) {
799 isum
+= GraphBuffer
[i
+0];
800 qsum
+= GraphBuffer
[i
+1];
802 negateI
= (isum
< 0);
803 negateQ
= (qsum
< 0);
805 // Turn the correlation pairs into soft decisions on the bit.
807 for(i
= 0; i
< GraphTraceLen
/2; i
++) {
808 int si
= GraphBuffer
[j
];
809 int sq
= GraphBuffer
[j
+1];
810 if(negateI
) si
= -si
;
811 if(negateQ
) sq
= -sq
;
812 GraphBuffer
[i
] = si
+ sq
;
818 while(GraphBuffer
[i
] > 0 && i
< GraphTraceLen
)
820 if(i
>= GraphTraceLen
) goto demodError
;
823 while(GraphBuffer
[i
] < 0 && i
< GraphTraceLen
)
825 if(i
>= GraphTraceLen
) goto demodError
;
826 if((i
- iold
) > 23) goto demodError
;
828 PrintToScrollback("make it to demod loop");
832 while(GraphBuffer
[i
] >= 0 && i
< GraphTraceLen
)
834 if(i
>= GraphTraceLen
) goto demodError
;
835 if((i
- iold
) > 6) goto demodError
;
838 if(i
+ 20 >= GraphTraceLen
) goto demodError
;
840 for(j
= 0; j
< 10; j
++) {
841 int soft
= GraphBuffer
[i
] + GraphBuffer
[i
+1];
843 if(abs(soft
) < ((abs(isum
) + abs(qsum
))/20)) {
844 PrintToScrollback("weak bit");
848 if(GraphBuffer
[i
] + GraphBuffer
[i
+1] >= 0) {
855 if( (shiftReg
& 0x200) &&
858 // valid data byte, start and stop bits okay
859 PrintToScrollback(" %02x", (shiftReg
>> 1) & 0xff);
860 data
[dataLen
++] = (shiftReg
>> 1) & 0xff;
861 if(dataLen
>= sizeof(data
)) {
864 } else if(shiftReg
== 0x000) {
873 ComputeCrc14443(CRC_14443_B
, data
, dataLen
-2, &first
, &second
);
874 PrintToScrollback("CRC: %02x %02x (%s)\n", first
, second
,
875 (first
== data
[dataLen
-2] && second
== data
[dataLen
-1]) ?
876 "ok" : "****FAIL****");
878 RepaintGraphWindow();
882 PrintToScrollback("demod error");
883 RepaintGraphWindow();
886 static void CmdHi14list(char *str
)
889 GetFromBigBuf(got
, sizeof(got
));
891 PrintToScrollback("recorded activity:");
892 PrintToScrollback(" time :rssi: who bytes");
893 PrintToScrollback("---------+----+----+-----------");
904 int timestamp
= *((DWORD
*)(got
+i
));
905 if(timestamp
& 0x80000000) {
906 timestamp
&= 0x7fffffff;
911 int metric
= *((DWORD
*)(got
+i
+4));
922 BYTE
*frame
= (got
+i
+9);
924 char line
[1000] = "";
926 for(j
= 0; j
< len
; j
++) {
927 sprintf(line
+(j
*3), "%02x ", frame
[j
]);
933 ComputeCrc14443(CRC_14443_B
, frame
, len
-2, &b1
, &b2
);
934 if(b1
!= frame
[len
-2] || b2
!= frame
[len
-1]) {
935 crc
= "**FAIL CRC**";
943 char metricString
[100];
945 sprintf(metricString
, "%3d", metric
);
947 strcpy(metricString
, " ");
950 PrintToScrollback(" +%7d: %s: %s %s %s",
951 (prev
< 0 ? 0 : timestamp
- prev
),
953 (isResponse
? "TAG" : " "), line
, crc
);
960 static void CmdHi14alist(char *str
)
963 GetFromBigBuf(got
, sizeof(got
));
965 PrintToScrollback("recorded activity:");
966 PrintToScrollback(" ETU :rssi: who bytes");
967 PrintToScrollback("---------+----+----+-----------");
978 int timestamp
= *((DWORD
*)(got
+i
));
979 if(timestamp
& 0x80000000) {
980 timestamp
&= 0x7fffffff;
987 int parityBits
= *((DWORD
*)(got
+i
+4));
988 // 4 bytes of additional information...
989 // maximum of 32 additional parity bit information
992 // at each quarter bit period we can send power level (16 levels)
993 // or each half bit period in 256 levels.
1001 if(i
+ len
>= 1900) {
1005 BYTE
*frame
= (got
+i
+9);
1007 // Break and stick with current result if buffer was not completely full
1008 if(frame
[0] == 0x44 && frame
[1] == 0x44 && frame
[3] == 0x44) { break; }
1010 char line
[1000] = "";
1012 for(j
= 0; j
< len
; j
++) {
1013 int oddparity
= 0x01;
1017 oddparity
^= (((frame
[j
] & 0xFF) >> k
) & 0x01);
1020 //if((parityBits >> (len - j - 1)) & 0x01) {
1021 if(isResponse
&& (oddparity
!= ((parityBits
>> (len
- j
- 1)) & 0x01))) {
1022 sprintf(line
+(j
*4), "%02x! ", frame
[j
]);
1025 sprintf(line
+(j
*4), "%02x ", frame
[j
]);
1033 for(j
= 0; j
< (len
- 1); j
++) {
1034 // gives problems... search for the reason..
1035 /*if(frame[j] == 0xAA) {
1036 switch(frame[j+1]) {
1038 crc = "[1] Two drops close after each other";
1041 crc = "[2] Potential SOC with a drop in second half of bitperiod";
1044 crc = "[3] Segment Z after segment X is not possible";
1047 crc = "[4] Parity bit of a fully received byte was wrong";
1050 crc = "[?] Unknown error";
1057 if(strlen(crc
)==0) {
1058 ComputeCrc14443(CRC_14443_A
, frame
, len
-2, &b1
, &b2
);
1059 if(b1
!= frame
[len
-2] || b2
!= frame
[len
-1]) {
1060 crc
= (isResponse
& (len
< 6)) ? "" : " !crc";
1069 char metricString
[100];
1071 sprintf(metricString
, "%3d", metric
);
1073 strcpy(metricString
, " ");
1076 PrintToScrollback(" +%7d: %s: %s %s %s",
1077 (prev
< 0 ? 0 : (timestamp
- prev
)),
1079 (isResponse
? "TAG" : " "), line
, crc
);
1084 CommandFinished
= 1;
1087 static void CmdHi15demod(char *str
)
1089 // The sampling rate is 106.353 ksps/s, for T = 18.8 us
1092 // 1) Unmodulated time of 56.64us
1093 // 2) 24 pulses of 423.75khz
1094 // 3) logic '1' (unmodulated for 18.88us followed by 8 pulses of 423.75khz)
1096 static const int FrameSOF
[] = {
1097 -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
1098 -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
1099 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
1100 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
1106 static const int Logic0
[] = {
1112 static const int Logic1
[] = {
1120 // 1) logic '0' (8 pulses of 423.75khz followed by unmodulated for 18.88us)
1121 // 2) 24 pulses of 423.75khz
1122 // 3) Unmodulated time of 56.64us
1124 static const int FrameEOF
[] = {
1129 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
1130 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
1131 -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
1132 -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1
1136 int max
= 0, maxPos
;
1140 if(GraphTraceLen
< 1000) return;
1142 // First, correlate for SOF
1143 for(i
= 0; i
< 100; i
++) {
1145 for(j
= 0; j
< arraylen(FrameSOF
); j
+= skip
) {
1146 corr
+= FrameSOF
[j
]*GraphBuffer
[i
+(j
/skip
)];
1153 PrintToScrollback("SOF at %d, correlation %d", maxPos
,
1154 max
/(arraylen(FrameSOF
)/skip
));
1156 i
= maxPos
+ arraylen(FrameSOF
)/skip
;
1159 memset(outBuf
, 0, sizeof(outBuf
));
1162 int corr0
= 0, corr1
= 0, corrEOF
= 0;
1163 for(j
= 0; j
< arraylen(Logic0
); j
+= skip
) {
1164 corr0
+= Logic0
[j
]*GraphBuffer
[i
+(j
/skip
)];
1166 for(j
= 0; j
< arraylen(Logic1
); j
+= skip
) {
1167 corr1
+= Logic1
[j
]*GraphBuffer
[i
+(j
/skip
)];
1169 for(j
= 0; j
< arraylen(FrameEOF
); j
+= skip
) {
1170 corrEOF
+= FrameEOF
[j
]*GraphBuffer
[i
+(j
/skip
)];
1172 // Even things out by the length of the target waveform.
1176 if(corrEOF
> corr1
&& corrEOF
> corr0
) {
1177 PrintToScrollback("EOF at %d", i
);
1179 } else if(corr1
> corr0
) {
1180 i
+= arraylen(Logic1
)/skip
;
1183 i
+= arraylen(Logic0
)/skip
;
1190 if((i
+(int)arraylen(FrameEOF
)) >= GraphTraceLen
) {
1191 PrintToScrollback("ran off end!");
1196 PrintToScrollback("error, uneven octet! (discard extra bits!)");
1197 PrintToScrollback(" mask=%02x", mask
);
1199 PrintToScrollback("%d octets", k
);
1201 for(i
= 0; i
< k
; i
++) {
1202 PrintToScrollback("# %2d: %02x ", i
, outBuf
[i
]);
1204 PrintToScrollback("CRC=%04x", Iso15693Crc(outBuf
, k
-2));
1207 static void CmdTiread(char *str
)
1210 c
.cmd
= CMD_ACQUIRE_RAW_BITS_TI_TYPE
;
1211 SendCommand(&c
, FALSE
);
1214 static void CmdTibits(char *str
)
1218 for(i
= 0; i
< 1536; i
+= 12) {
1220 c
.cmd
= CMD_DOWNLOAD_RAW_BITS_TI_TYPE
;
1222 SendCommand(&c
, FALSE
);
1224 if(c
.cmd
!= CMD_DOWNLOADED_RAW_BITS_TI_TYPE
) {
1225 PrintToScrollback("bad resp");
1229 for(j
= 0; j
< 12; j
++) {
1231 for(k
= 31; k
>= 0; k
--) {
1232 if(c
.d
.asDwords
[j
] & (1 << k
)) {
1233 GraphBuffer
[cnt
++] = 1;
1235 GraphBuffer
[cnt
++] = -1;
1240 GraphTraceLen
= 1536*32;
1241 RepaintGraphWindow();
1244 static void CmdTidemod(char *cmdline
)
1246 /* MATLAB as follows:
1247 f_s = 2000000; % sampling frequency
1248 f_l = 123200; % low FSK tone
1249 f_h = 134200; % high FSK tone
1251 T_l = 119e-6; % low bit duration
1252 T_h = 130e-6; % high bit duration
1254 l = 2*pi*ones(1, floor(f_s*T_l))*(f_l/f_s);
1255 h = 2*pi*ones(1, floor(f_s*T_h))*(f_h/f_s);
1257 l = sign(sin(cumsum(l)));
1258 h = sign(sin(cumsum(h)));
1260 static const int LowTone
[] = {
1261 1, 1, 1, 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, 1, 1, 1,
1263 1, 1, -1, -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, -1, -1, -1,
1265 -1, -1, -1, -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, -1, -1, 1,
1267 1, 1, 1, 1, 1, 1, 1, -1, -1, -1, -1, -1, -1, -1, -1, 1, 1, 1, 1,
1268 1, 1, 1, 1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 1, 1, 1, 1, 1, 1,
1269 1, 1, -1, -1, -1, -1, -1, -1, -1, -1, 1, 1, 1, 1, 1, 1, 1, 1, -1,
1270 -1, -1, -1, -1, -1, -1, -1, 1, 1, 1, 1, 1, 1, 1, 1, -1, -1, -1, -1,
1271 -1, -1, -1, -1, 1, 1, 1, 1, 1, 1, 1, 1, -1, -1, -1, -1, -1, -1, -1,
1272 -1, -1, 1, 1, 1, 1, 1, 1, 1, 1, -1, -1, -1, -1, -1, -1, -1, -1, 1,
1273 1, 1, 1, 1, 1, 1, 1, -1, -1, -1,
1275 static const int HighTone
[] = {
1276 1, 1, 1, 1, 1, 1, 1, -1, -1, -1, -1, -1, -1, -1, 1, 1, 1, 1, 1, 1,
1277 1, 1, -1, -1, -1, -1, -1, -1, -1, 1, 1, 1, 1, 1, 1, 1, 1, -1, -1,
1278 -1, -1, -1, -1, -1, 1, 1, 1, 1, 1, 1, 1, 1, -1, -1, -1, -1, -1,
1279 -1, -1, 1, 1, 1, 1, 1, 1, 1, 1, -1, -1, -1, -1, -1, -1, -1, 1, 1,
1280 1, 1, 1, 1, 1, -1, -1, -1, -1, -1, -1, -1, -1, 1, 1, 1, 1, 1, 1,
1281 1, -1, -1, -1, -1, -1, -1, -1, -1, 1, 1, 1, 1, 1, 1, 1, -1, -1,
1282 -1, -1, -1, -1, -1, -1, 1, 1, 1, 1, 1, 1, 1, -1, -1, -1, -1, -1,
1283 -1, -1, -1, 1, 1, 1, 1, 1, 1, 1, -1, -1, -1, -1, -1, -1, -1, -1,
1284 1, 1, 1, 1, 1, 1, 1, -1, -1, -1, -1, -1, -1, -1, 1, 1, 1, 1, 1, 1,
1285 1, 1, -1, -1, -1, -1, -1, -1, -1, 1, 1, 1, 1, 1, 1, 1, 1, -1, -1,
1286 -1, -1, -1, -1, -1, 1, 1, 1, 1, 1, 1, 1, 1, -1, -1, -1, -1, -1,
1287 -1, -1, 1, 1, 1, 1, 1, 1, 1, 1, -1, -1, -1, -1, -1, -1, -1, 1, 1,
1288 1, 1, 1, 1, 1, -1, -1, -1, -1, -1, -1, -1, -1, 1, 1, 1, 1, 1, 1,
1289 1, -1, -1, -1, -1, -1, -1, -1, -1, 1, 1, 1, 1, 1, 1, 1,
1292 int convLen
= max(arraylen(HighTone
), arraylen(LowTone
));
1295 for(i
= 0; i
< GraphTraceLen
- convLen
; i
++) {
1297 int lowSum
= 0, highSum
= 0;;
1298 int lowLen
= arraylen(LowTone
);
1299 int highLen
= arraylen(HighTone
);
1301 for(j
= 0; j
< lowLen
; j
++) {
1302 lowSum
+= LowTone
[j
]*GraphBuffer
[i
+j
];
1304 for(j
= 0; j
< highLen
; j
++) {
1305 highSum
+= HighTone
[j
]*GraphBuffer
[i
+j
];
1307 lowSum
= abs((100*lowSum
) / lowLen
);
1308 highSum
= abs((100*highSum
) / highLen
);
1309 GraphBuffer
[i
] = (highSum
<< 16) | lowSum
;
1312 for(i
= 0; i
< GraphTraceLen
- convLen
- 16; i
++) {
1314 int lowTot
= 0, highTot
= 0;
1315 // 16 and 15 are f_s divided by f_l and f_h, rounded
1316 for(j
= 0; j
< 16; j
++) {
1317 lowTot
+= (GraphBuffer
[i
+j
] & 0xffff);
1319 for(j
= 0; j
< 15; j
++) {
1320 highTot
+= (GraphBuffer
[i
+j
] >> 16);
1322 GraphBuffer
[i
] = lowTot
- highTot
;
1325 GraphTraceLen
-= (convLen
+ 16);
1327 RepaintGraphWindow();
1329 // Okay, so now we have unsliced soft decisions; find bit-sync, and then
1332 int max
= 0, maxPos
= 0;
1333 for(i
= 0; i
< 6000; i
++) {
1336 for(j
= 0; j
< 8*arraylen(LowTone
); j
++) {
1337 dec
-= GraphBuffer
[i
+j
];
1339 for(; j
< 8*arraylen(LowTone
) + 8*arraylen(HighTone
); j
++) {
1340 dec
+= GraphBuffer
[i
+j
];
1347 GraphBuffer
[maxPos
] = 800;
1348 GraphBuffer
[maxPos
+1] = -800;
1350 maxPos
+= 8*arraylen(LowTone
);
1351 GraphBuffer
[maxPos
] = 800;
1352 GraphBuffer
[maxPos
+1] = -800;
1353 maxPos
+= 8*arraylen(HighTone
);
1355 GraphBuffer
[maxPos
] = 800;
1356 GraphBuffer
[maxPos
+1] = -800;
1358 PrintToScrollback("actual data bits start at sample %d", maxPos
);
1360 PrintToScrollback("length %d/%d", arraylen(HighTone
), arraylen(LowTone
));
1362 GraphBuffer
[maxPos
] = 800;
1363 GraphBuffer
[maxPos
+1] = -800;
1365 BYTE bits
[64+16+8+1];
1366 bits
[sizeof(bits
)-1] = '\0';
1368 for(i
= 0; i
< arraylen(bits
); i
++) {
1372 for(j
= 0; j
< arraylen(LowTone
); j
++) {
1373 low
-= GraphBuffer
[maxPos
+j
];
1375 for(j
= 0; j
< arraylen(HighTone
); j
++) {
1376 high
+= GraphBuffer
[maxPos
+j
];
1380 maxPos
+= arraylen(HighTone
);
1383 maxPos
+= arraylen(LowTone
);
1385 GraphBuffer
[maxPos
] = 800;
1386 GraphBuffer
[maxPos
+1] = -800;
1388 PrintToScrollback("bits: '%s'", bits
);
1391 for(i
= 0; i
< 32; i
++) {
1392 if(bits
[i
] == '1') {
1396 for(i
= 32; i
< 64; i
++) {
1397 if(bits
[i
] == '1') {
1401 PrintToScrollback("hex: %08x %08x", h
, l
);
1404 static void CmdNorm(char *str
)
1407 int max
= INT_MIN
, min
= INT_MAX
;
1408 for(i
= 10; i
< GraphTraceLen
; i
++) {
1409 if(GraphBuffer
[i
] > max
) {
1410 max
= GraphBuffer
[i
];
1412 if(GraphBuffer
[i
] < min
) {
1413 min
= GraphBuffer
[i
];
1417 for(i
= 0; i
< GraphTraceLen
; i
++) {
1418 GraphBuffer
[i
] = (GraphBuffer
[i
] - ((max
+ min
)/2))*1000/
1422 RepaintGraphWindow();
1425 static void CmdDec(char *str
)
1428 for(i
= 0; i
< (GraphTraceLen
/2); i
++) {
1429 GraphBuffer
[i
] = GraphBuffer
[i
*2];
1432 PrintToScrollback("decimated by 2");
1433 RepaintGraphWindow();
1436 static void CmdHpf(char *str
)
1440 for(i
= 10; i
< GraphTraceLen
; i
++) {
1441 accum
+= GraphBuffer
[i
];
1443 accum
/= (GraphTraceLen
- 10);
1444 for(i
= 0; i
< GraphTraceLen
; i
++) {
1445 GraphBuffer
[i
] -= accum
;
1448 RepaintGraphWindow();
1451 static void CmdZerocrossings(char *str
)
1454 // Zero-crossings aren't meaningful unless the signal is zero-mean.
1460 for(i
= 0; i
< GraphTraceLen
; i
++) {
1461 if(GraphBuffer
[i
]*sign
>= 0) {
1462 // No change in sign, reproduce the previous sample count.
1464 GraphBuffer
[i
] = lastZc
;
1466 // Change in sign, reset the sample count.
1468 GraphBuffer
[i
] = lastZc
;
1476 RepaintGraphWindow();
1479 static void CmdLtrim(char *str
)
1484 for(i
= ds
; i
< GraphTraceLen
; i
++) {
1485 GraphBuffer
[i
-ds
] = GraphBuffer
[i
];
1487 GraphTraceLen
-= ds
;
1489 RepaintGraphWindow();
1492 static void CmdAutoCorr(char *str
)
1494 static int CorrelBuffer
[MAX_GRAPH_TRACE_LEN
];
1496 int window
= atoi(str
);
1499 PrintToScrollback("needs a window");
1503 if(window
>= GraphTraceLen
) {
1504 PrintToScrollback("window must be smaller than trace (%d samples)",
1509 PrintToScrollback("performing %d correlations", GraphTraceLen
- window
);
1512 for(i
= 0; i
< GraphTraceLen
- window
; i
++) {
1515 for(j
= 0; j
< window
; j
++) {
1516 sum
+= (GraphBuffer
[j
]*GraphBuffer
[i
+j
]) / 256;
1518 CorrelBuffer
[i
] = sum
;
1520 GraphTraceLen
= GraphTraceLen
- window
;
1521 memcpy(GraphBuffer
, CorrelBuffer
, GraphTraceLen
*sizeof(int));
1523 RepaintGraphWindow();
1526 static void CmdVchdemod(char *str
)
1528 // Is this the entire sync pattern, or does this also include some
1529 // data bits that happen to be the same everywhere? That would be
1531 static const int SyncPattern
[] = {
1532 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
1533 1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
1534 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
1535 1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
1536 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
1537 1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
1538 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
1539 1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
1540 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
1541 1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
1544 // So first, we correlate for the sync pattern, and mark that.
1545 int bestCorrel
= 0, bestPos
= 0;
1547 // It does us no good to find the sync pattern, with fewer than
1548 // 2048 samples after it...
1549 for(i
= 0; i
< (GraphTraceLen
-2048); i
++) {
1552 for(j
= 0; j
< arraylen(SyncPattern
); j
++) {
1553 sum
+= GraphBuffer
[i
+j
]*SyncPattern
[j
];
1555 if(sum
> bestCorrel
) {
1560 PrintToScrollback("best sync at %d [metric %d]", bestPos
, bestCorrel
);
1565 int worst
= INT_MAX
;
1568 for(i
= 0; i
< 2048; i
+= 8) {
1571 for(j
= 0; j
< 8; j
++) {
1572 sum
+= GraphBuffer
[bestPos
+i
+j
];
1579 if(abs(sum
) < worst
) {
1584 PrintToScrollback("bits:");
1585 PrintToScrollback("%s", bits
);
1586 PrintToScrollback("worst metric: %d at pos %d", worst
, worstPos
);
1588 if(strcmp(str
, "clone")==0) {
1591 for(s
= bits
; *s
; s
++) {
1593 for(j
= 0; j
< 16; j
++) {
1594 GraphBuffer
[GraphTraceLen
++] = (*s
== '1') ? 1 : 0;
1597 RepaintGraphWindow();
1601 static void CmdIndalademod(char *str
)
1603 // Usage: recover 64bit UID by default, specify "224" as arg to recover a 224bit UID
1608 // worst case with GraphTraceLen=64000 is < 4096
1609 // under normal conditions it's < 2048
1612 int worst
= 0, worstPos
= 0;
1613 PrintToScrollback("Expecting a bit less than %d raw bits", GraphTraceLen
/32);
1614 for(i
= 0; i
< GraphTraceLen
-1; i
+= 2) {
1616 if((GraphBuffer
[i
] > GraphBuffer
[i
+ 1]) && (state
!= 1)) {
1618 for(j
= 0; j
< count
- 8; j
+= 16) {
1619 rawbits
[rawbit
++] = 0;
1621 if ((abs(count
- j
)) > worst
) {
1622 worst
= abs(count
- j
);
1628 } else if((GraphBuffer
[i
] < GraphBuffer
[i
+ 1]) && (state
!= 0)) {
1630 for(j
= 0; j
< count
- 8; j
+= 16) {
1631 rawbits
[rawbit
++] = 1;
1633 if ((abs(count
- j
)) > worst
) {
1634 worst
= abs(count
- j
);
1642 PrintToScrollback("Recovered %d raw bits", rawbit
);
1643 PrintToScrollback("worst metric (0=best..7=worst): %d at pos %d", worst
, worstPos
);
1645 // Finding the start of a UID
1646 int uidlen
, long_wait
;
1647 if(strcmp(str
, "224") == 0) {
1656 for(start
= 0; start
<= rawbit
- uidlen
; start
++) {
1657 first
= rawbits
[start
];
1658 for(i
= start
; i
< start
+ long_wait
; i
++) {
1659 if(rawbits
[i
] != first
) {
1663 if(i
== (start
+ long_wait
)) {
1667 if(start
== rawbit
- uidlen
+ 1) {
1668 PrintToScrollback("nothing to wait for");
1672 // Inverting signal if needed
1674 for(i
= start
; i
< rawbit
; i
++) {
1675 rawbits
[i
] = !rawbits
[i
];
1682 showbits
[uidlen
]='\0';
1686 if(uidlen
> rawbit
) {
1687 PrintToScrollback("Warning: not enough raw bits to get a full UID");
1688 for(bit
= 0; bit
< rawbit
; bit
++) {
1689 bits
[bit
] = rawbits
[i
++];
1690 // As we cannot know the parity, let's use "." and "/"
1691 showbits
[bit
] = '.' + bits
[bit
];
1693 showbits
[bit
+1]='\0';
1694 PrintToScrollback("Partial UID=%s", showbits
);
1697 for(bit
= 0; bit
< uidlen
; bit
++) {
1698 bits
[bit
] = rawbits
[i
++];
1699 showbits
[bit
] = '0' + bits
[bit
];
1703 PrintToScrollback("UID=%s", showbits
);
1705 // Checking UID against next occurences
1706 for(; i
+ uidlen
<= rawbit
;) {
1708 for(bit
= 0; bit
< uidlen
; bit
++) {
1709 if(bits
[bit
] != rawbits
[i
++]) {
1719 PrintToScrollback("Occurences: %d (expected %d)", times
, (rawbit
- start
) / uidlen
);
1721 // Remodulating for tag cloning
1722 GraphTraceLen
= 32*uidlen
;
1725 for(bit
= 0; bit
< uidlen
; bit
++) {
1726 if(bits
[bit
] == 0) {
1732 for(j
= 0; j
< 32; j
++) {
1733 GraphBuffer
[i
++] = phase
;
1738 RepaintGraphWindow();
1741 static void CmdFlexdemod(char *str
)
1744 for(i
= 0; i
< GraphTraceLen
; i
++) {
1745 if(GraphBuffer
[i
] < 0) {
1746 GraphBuffer
[i
] = -1;
1752 #define LONG_WAIT 100
1754 for(start
= 0; start
< GraphTraceLen
- LONG_WAIT
; start
++) {
1755 int first
= GraphBuffer
[start
];
1756 for(i
= start
; i
< start
+ LONG_WAIT
; i
++) {
1757 if(GraphBuffer
[i
] != first
) {
1761 if(i
== (start
+ LONG_WAIT
)) {
1765 if(start
== GraphTraceLen
- LONG_WAIT
) {
1766 PrintToScrollback("nothing to wait for");
1770 GraphBuffer
[start
] = 2;
1771 GraphBuffer
[start
+1] = -2;
1777 for(bit
= 0; bit
< 64; bit
++) {
1780 for(j
= 0; j
< 16; j
++) {
1781 sum
+= GraphBuffer
[i
++];
1788 PrintToScrollback("bit %d sum %d", bit
, sum
);
1791 for(bit
= 0; bit
< 64; bit
++) {
1794 for(j
= 0; j
< 16; j
++) {
1795 sum
+= GraphBuffer
[i
++];
1797 if(sum
> 0 && bits
[bit
] != 1) {
1798 PrintToScrollback("oops1 at %d", bit
);
1800 if(sum
< 0 && bits
[bit
] != 0) {
1801 PrintToScrollback("oops2 at %d", bit
);
1805 GraphTraceLen
= 32*64;
1808 for(bit
= 0; bit
< 64; bit
++) {
1809 if(bits
[bit
] == 0) {
1815 for(j
= 0; j
< 32; j
++) {
1816 GraphBuffer
[i
++] = phase
;
1821 RepaintGraphWindow();
1825 * Generic command to demodulate ASK.
1827 * Argument is convention: positive or negative (High mod means zero
1828 * or high mod means one)
1830 * Updates the Graph trace with 0/1 values
1836 static void Cmdaskdemod(char *str
) {
1841 // TODO: complain if we do not give 2 arguments here !
1842 sscanf(str
, "%i", &c
);
1844 /* Detect high and lows and clock */
1845 for (i
= 0; i
< GraphTraceLen
; i
++)
1847 if (GraphBuffer
[i
] > high
)
1848 high
= GraphBuffer
[i
];
1849 else if (GraphBuffer
[i
] < low
)
1850 low
= GraphBuffer
[i
];
1853 if (GraphBuffer
[0] > 0) {
1854 GraphBuffer
[0] = 1-c
;
1858 for(i
=1;i
<GraphTraceLen
;i
++) {
1859 /* Transitions are detected at each peak
1860 * Transitions are either:
1861 * - we're low: transition if we hit a high
1862 * - we're high: transition if we hit a low
1863 * (we need to do it this way because some tags keep high or
1864 * low for long periods, others just reach the peak and go
1867 if ((GraphBuffer
[i
]==high
) && (GraphBuffer
[i
-1] == c
)) {
1869 } else if ((GraphBuffer
[i
]==low
) && (GraphBuffer
[i
-1] == (1-c
))){
1873 GraphBuffer
[i
] = GraphBuffer
[i
-1];
1876 RepaintGraphWindow();
1879 /* Print our clock rate */
1880 static void Cmddetectclockrate(char *str
)
1882 int clock
= detectclock(0);
1883 PrintToScrollback("Auto-detected clock rate: %d", clock
);
1889 int detectclock(int peak
)
1895 /* Detect peak if we don't have one */
1897 for (i
= 0; i
< GraphTraceLen
; i
++)
1898 if (GraphBuffer
[i
] > peak
)
1899 peak
= GraphBuffer
[i
];
1901 for (i
= 1; i
< GraphTraceLen
; i
++)
1903 /* If this is the beginning of a peak */
1904 if (GraphBuffer
[i
-1] != GraphBuffer
[i
] && GraphBuffer
[i
] == peak
)
1906 /* Find lowest difference between peaks */
1907 if (lastpeak
&& i
- lastpeak
< clock
)
1909 clock
= i
- lastpeak
;
1918 /* Get or auto-detect clock rate */
1919 int GetClock(char *str
, int peak
)
1923 sscanf(str
, "%i", &clock
);
1924 if (!strcmp(str
, ""))
1927 /* Auto-detect clock */
1930 clock
= detectclock(peak
);
1932 /* Only print this message if we're not looping something */
1934 PrintToScrollback("Auto-detected clock rate: %d", clock
);
1941 * Convert to a bitstream
1943 static void Cmdbitstream(char *str
) {
1950 int hithigh
, hitlow
, first
;
1952 /* Detect high and lows and clock */
1953 for (i
= 0; i
< GraphTraceLen
; i
++)
1955 if (GraphBuffer
[i
] > high
)
1956 high
= GraphBuffer
[i
];
1957 else if (GraphBuffer
[i
] < low
)
1958 low
= GraphBuffer
[i
];
1962 clock
= GetClock(str
, high
);
1964 gtl
= CmdClearGraph(0);
1967 for (i
= 0; i
< (int)(gtl
/ clock
); i
++)
1973 /* Find out if we hit both high and low peaks */
1974 for (j
= 0; j
< clock
; j
++)
1976 if (GraphBuffer
[(i
* clock
) + j
] == high
)
1978 else if (GraphBuffer
[(i
* clock
) + j
] == low
)
1981 /* it doesn't count if it's the first part of our read
1982 because it's really just trailing from the last sequence */
1983 if (first
&& (hithigh
|| hitlow
))
1984 hithigh
= hitlow
= 0;
1988 if (hithigh
&& hitlow
)
1992 /* If we didn't hit both high and low peaks, we had a bit transition */
1993 if (!hithigh
|| !hitlow
)
1996 CmdAppendGraph(0, clock
, bit
);
1997 // for (j = 0; j < (int)(clock/2); j++)
1998 // GraphBuffer[(i * clock) + j] = bit ^ 1;
1999 // for (j = (int)(clock/2); j < clock; j++)
2000 // GraphBuffer[(i * clock) + j] = bit;
2003 RepaintGraphWindow();
2006 /* Modulate our data into manchester */
2007 static void Cmdmanchestermod(char *str
)
2011 int bit
, lastbit
, wave
;
2014 clock
= GetClock(str
, 0);
2018 for (i
= 0; i
< (int)(GraphTraceLen
/ clock
); i
++)
2020 bit
= GraphBuffer
[i
* clock
] ^ 1;
2022 for (j
= 0; j
< (int)(clock
/2); j
++)
2023 GraphBuffer
[(i
* clock
) + j
] = bit
^ lastbit
^ wave
;
2024 for (j
= (int)(clock
/2); j
< clock
; j
++)
2025 GraphBuffer
[(i
* clock
) + j
] = bit
^ lastbit
^ wave
^ 1;
2027 /* Keep track of how we start our wave and if we changed or not this time */
2028 wave
^= bit
^ lastbit
;
2032 RepaintGraphWindow();
2036 * Manchester demodulate a bitstream. The bitstream needs to be already in
2037 * the GraphBuffer as 0 and 1 values
2039 * Give the clock rate as argument in order to help the sync - the algorithm
2040 * resyncs at each pulse anyway.
2042 * Not optimized by any means, this is the 1st time I'm writing this type of
2043 * routine, feel free to improve...
2045 * 1st argument: clock rate (as number of samples per clock rate)
2046 * Typical values can be 64, 32, 128...
2048 static void Cmdmanchesterdemod(char *str
) {
2055 int hithigh
, hitlow
, first
;
2061 /* Holds the decoded bitstream: each clock period contains 2 bits */
2062 /* later simplified to 1 bit after manchester decoding. */
2063 /* Add 10 bits to allow for noisy / uncertain traces without aborting */
2064 /* int BitStream[GraphTraceLen*2/clock+10]; */
2066 /* But it does not work if compiling on WIndows: therefore we just allocate a */
2068 int BitStream
[MAX_GRAPH_TRACE_LEN
];
2070 /* Detect high and lows */
2071 for (i
= 0; i
< GraphTraceLen
; i
++)
2073 if (GraphBuffer
[i
] > high
)
2074 high
= GraphBuffer
[i
];
2075 else if (GraphBuffer
[i
] < low
)
2076 low
= GraphBuffer
[i
];
2080 clock
= GetClock(str
, high
);
2082 int tolerance
= clock
/4;
2084 /* Detect first transition */
2085 /* Lo-Hi (arbitrary) */
2086 for (i
= 0; i
< GraphTraceLen
; i
++)
2088 if (GraphBuffer
[i
] == low
)
2095 /* If we're not working with 1/0s, demod based off clock */
2098 bit
= 0; /* We assume the 1st bit is zero, it may not be
2099 * the case: this routine (I think) has an init problem.
2102 for (; i
< (int)(GraphTraceLen
/ clock
); i
++)
2108 /* Find out if we hit both high and low peaks */
2109 for (j
= 0; j
< clock
; j
++)
2111 if (GraphBuffer
[(i
* clock
) + j
] == high
)
2113 else if (GraphBuffer
[(i
* clock
) + j
] == low
)
2116 /* it doesn't count if it's the first part of our read
2117 because it's really just trailing from the last sequence */
2118 if (first
&& (hithigh
|| hitlow
))
2119 hithigh
= hitlow
= 0;
2123 if (hithigh
&& hitlow
)
2127 /* If we didn't hit both high and low peaks, we had a bit transition */
2128 if (!hithigh
|| !hitlow
)
2131 BitStream
[bit2idx
++] = bit
;
2135 /* standard 1/0 bitstream */
2139 /* Then detect duration between 2 successive transitions */
2140 for (bitidx
= 1; i
< GraphTraceLen
; i
++)
2142 if (GraphBuffer
[i
-1] != GraphBuffer
[i
])
2147 // Error check: if bitidx becomes too large, we do not
2148 // have a Manchester encoded bitstream or the clock is really
2150 if (bitidx
> (GraphTraceLen
*2/clock
+8) ) {
2151 PrintToScrollback("Error: the clock you gave is probably wrong, aborting.");
2154 // Then switch depending on lc length:
2155 // Tolerance is 1/4 of clock rate (arbitrary)
2156 if (abs(lc
-clock
/2) < tolerance
) {
2157 // Short pulse : either "1" or "0"
2158 BitStream
[bitidx
++]=GraphBuffer
[i
-1];
2159 } else if (abs(lc
-clock
) < tolerance
) {
2160 // Long pulse: either "11" or "00"
2161 BitStream
[bitidx
++]=GraphBuffer
[i
-1];
2162 BitStream
[bitidx
++]=GraphBuffer
[i
-1];
2166 PrintToScrollback("Warning: Manchester decode error for pulse width detection.");
2167 PrintToScrollback("(too many of those messages mean either the stream is not Manchester encoded, or clock is wrong)");
2171 PrintToScrollback("Error: too many detection errors, aborting.");
2178 // At this stage, we now have a bitstream of "01" ("1") or "10" ("0"), parse it into final decoded bitstream
2179 // Actually, we overwrite BitStream with the new decoded bitstream, we just need to be careful
2180 // to stop output at the final bitidx2 value, not bitidx
2181 for (i
= 0; i
< bitidx
; i
+= 2) {
2182 if ((BitStream
[i
] == 0) && (BitStream
[i
+1] == 1)) {
2183 BitStream
[bit2idx
++] = 1;
2184 } else if ((BitStream
[i
] == 1) && (BitStream
[i
+1] == 0)) {
2185 BitStream
[bit2idx
++] = 0;
2187 // We cannot end up in this state, this means we are unsynchronized,
2191 PrintToScrollback("Unsynchronized, resync...");
2192 PrintToScrollback("(too many of those messages mean the stream is not Manchester encoded)");
2196 PrintToScrollback("Error: too many decode errors, aborting.");
2203 PrintToScrollback("Manchester decoded bitstream");
2204 // Now output the bitstream to the scrollback by line of 16 bits
2205 for (i
= 0; i
< (bit2idx
-16); i
+=16) {
2206 PrintToScrollback("%i %i %i %i %i %i %i %i %i %i %i %i %i %i %i %i",
2231 static void CmdHiddemod(char *str
)
2233 if(GraphTraceLen
< 4800) {
2234 PrintToScrollback("too short; need at least 4800 samples");
2238 GraphTraceLen
= 4800;
2240 for(i
= 0; i
< GraphTraceLen
; i
++) {
2241 if(GraphBuffer
[i
] < 0) {
2247 RepaintGraphWindow();
2250 static void CmdPlot(char *str
)
2255 static void CmdHide(char *str
)
2260 static void CmdScale(char *str
)
2262 CursorScaleFactor
= atoi(str
);
2263 if(CursorScaleFactor
== 0) {
2264 PrintToScrollback("bad, can't have zero scale");
2265 CursorScaleFactor
= 1;
2267 RepaintGraphWindow();
2270 static void CmdSave(char *str
)
2272 FILE *f
= fopen(str
, "w");
2274 PrintToScrollback("couldn't open '%s'", str
);
2278 for(i
= 0; i
< GraphTraceLen
; i
++) {
2279 fprintf(f
, "%d\n", GraphBuffer
[i
]);
2282 PrintToScrollback("saved to '%s'", str
);
2285 static void CmdLoad(char *str
)
2287 FILE *f
= fopen(str
, "r");
2289 PrintToScrollback("couldn't open '%s'", str
);
2295 while(fgets(line
, sizeof(line
), f
)) {
2296 GraphBuffer
[GraphTraceLen
] = atoi(line
);
2300 PrintToScrollback("loaded %d samples", GraphTraceLen
);
2301 RepaintGraphWindow();
2304 static void CmdHIDsimTAG(char *str
)
2306 unsigned int hi
=0, lo
=0;
2310 while (sscanf(&str
[i
++], "%1x", &n
) == 1) {
2311 hi
=(hi
<<4)|(lo
>>28);
2315 PrintToScrollback("Emulating tag with ID %x%16x", hi
, lo
);
2317 c
.cmd
= CMD_HID_SIM_TAG
;
2320 SendCommand(&c
, FALSE
);
2323 static void CmdLcdReset(char *str
)
2326 c
.cmd
= CMD_LCD_RESET
;
2328 SendCommand(&c
, FALSE
);
2331 static void CmdLcd(char *str
)
2336 sscanf(str
, "%x %d", &i
, &j
);
2339 SendCommand(&c
, FALSE
);
2345 static void CmdTest(char *str
)
2350 * Sets the divisor for LF frequency clock: lets the user choose any LF frequency below
2353 static void CmdSetDivisor(char *str
)
2356 c
.cmd
= CMD_SET_LF_DIVISOR
;
2358 if (( c
.ext1
<0) || (c
.ext1
>255)) {
2359 PrintToScrollback("divisor must be between 19 and 255");
2361 SendCommand(&c
, FALSE
);
2362 PrintToScrollback("Divisor set, expected freq=%dHz", 12000000/(c
.ext1
+1));
2366 static void CmdSweepLF(char *str
)
2369 c
.cmd
= CMD_SWEEP_LF
;
2370 SendCommand(&c
, FALSE
);
2374 typedef void HandlerFunction(char *cmdline
);
2376 /* in alphabetic order */
2379 HandlerFunction
*handler
;
2380 int offline
; // 1 if the command can be used when in offline mode
2382 } CommandTable
[] = {
2383 "askdemod", Cmdaskdemod
,1, "<samples per bit> <0|1> -- Attempt to demodulate simple ASK tags",
2384 "autocorr", CmdAutoCorr
,1, "<window length> -- Autocorrelation over window",
2385 "bitsamples", CmdBitsamples
,0, " Get raw samples as bitstring",
2386 "bitstream", Cmdbitstream
,1, "[clock rate] -- Convert waveform into a bitstream",
2387 "dec", CmdDec
,1, " Decimate samples",
2388 "detectclock", Cmddetectclockrate
,1, " Detect clock rate",
2389 "em410xsim", CmdEM410xsim
,1, "<UID> -- Simulate EM410x tag",
2390 "em410xread", CmdEM410xread
,1, "[clock rate] -- Extract ID from EM410x tag",
2391 "em410xwatch", CmdEM410xwatch
,0, " Watches for EM410x tags",
2392 "exit", CmdQuit
,1, " Exit program",
2393 "flexdemod", CmdFlexdemod
,1, " Demodulate samples for FlexPass",
2394 "fpgaoff", CmdFPGAOff
,0, " Set FPGA off", // ## FPGA Control
2395 "hexsamples", CmdHexsamples
,0, "<blocks> -- Dump big buffer as hex bytes",
2396 "hi14alist", CmdHi14alist
,0, " List ISO 14443a history", // ## New list command
2397 "hi14areader", CmdHi14areader
,0, " Act like an ISO14443 Type A reader", // ## New reader command
2398 "hi14asim", CmdHi14asim
,0, "<UID> -- Fake ISO 14443a tag", // ## Simulate 14443a tag
2399 "hi14asnoop", CmdHi14asnoop
,0, " Eavesdrop ISO 14443 Type A", // ## New snoop command
2400 "hi14bdemod", CmdHi14bdemod
,1, " Demodulate ISO14443 Type B from tag",
2401 "hi14list", CmdHi14list
,0, " List ISO 14443 history",
2402 "hi14read", CmdHi14read
,0, " Read HF tag (ISO 14443)",
2403 "hi14sim", CmdHi14sim
,0, " Fake ISO 14443 tag",
2404 "hi14snoop", CmdHi14snoop
,0, " Eavesdrop ISO 14443",
2405 "hi15demod", CmdHi15demod
,1, " Demodulate ISO15693 from tag",
2406 "hi15read", CmdHi15read
,0, " Read HF tag (ISO 15693)",
2407 "hi15reader", CmdHi15reader
,0, " Act like an ISO15693 reader", // new command greg
2408 "hi15sim", CmdHi15tag
,0, " Fake an ISO15693 tag", // new command greg
2409 "hiddemod", CmdHiddemod
,1, " Demodulate HID Prox Card II (not optimal)",
2410 "hide", CmdHide
,1, " Hide graph window",
2411 "hidfskdemod", CmdHIDdemodFSK
,0, " Realtime HID FSK demodulator",
2412 "hidsimtag", CmdHIDsimTAG
,0, "<ID> -- HID tag simulator",
2413 "higet", CmdHi14read_sim
,0, "<samples> -- Get samples HF, 'analog'",
2414 "hisamples", CmdHisamples
,0, " Get raw samples for HF tag",
2415 "hisampless", CmdHisampless
,0, "<samples> -- Get signed raw samples, HF tag",
2416 "hisamplest", CmdHi14readt
,0, " Get samples HF, for testing",
2417 "hisimlisten", CmdHisimlisten
,0, " Get HF samples as fake tag",
2418 "hpf", CmdHpf
,1, " Remove DC offset from trace",
2419 "indalademod", CmdIndalademod
,0, "['224'] -- Demodulate samples for Indala",
2420 "lcd", CmdLcd
,0, "<HEX command> <count> -- Send command/data to LCD",
2421 "lcdreset", CmdLcdReset
,0, " Hardware reset LCD",
2422 "load", CmdLoad
,1, "<filename> -- Load trace (to graph window",
2423 "loread", CmdLoread
,0, "['h'] -- Read 125/134 kHz LF ID-only tag (option 'h' for 134)",
2424 "losamples", CmdLosamples
,0, "[128 - 16000] -- Get raw samples for LF tag",
2425 "losim", CmdLosim
,0, " Simulate LF tag",
2426 "ltrim", CmdLtrim
,1, "<samples> -- Trim samples from left of trace",
2427 "mandemod", Cmdmanchesterdemod
,1, "[clock rate] -- Try a Manchester demodulation on a binary stream",
2428 "manmod", Cmdmanchestermod
,1, "[clock rate] -- Manchester modulate a binary stream",
2429 "norm", CmdNorm
,1, " Normalize max/min to +/-500",
2430 "plot", CmdPlot
,1, " Show graph window",
2431 "quit", CmdQuit
,1, " Quit program",
2432 "reset", CmdReset
,0, " Reset the Proxmark3",
2433 "save", CmdSave
,1, "<filename> -- Save trace (from graph window)",
2434 "scale", CmdScale
,1, "<int> -- Set cursor display scale",
2435 "setlfdivisor", CmdSetDivisor
,0, "<19 - 255> -- Drive LF antenna at 12Mhz/(divisor+1)",
2436 "sri512read", CmdSri512read
,0, "<int> -- Read contents of a SRI512 tag",
2437 "sweeplf", CmdSweepLF
,0, " Sweep through LF freq range and store results in buffer",
2438 "tibits", CmdTibits
,0, " Get raw bits for TI-type LF tag",
2439 "tidemod", CmdTidemod
,0, " Demodulate raw bits for TI-type LF tag",
2440 "tiread", CmdTiread
,0, " Read a TI-type 134 kHz tag",
2441 "tune", CmdTune
,0, " Measure antenna tuning",
2442 "vchdemod", CmdVchdemod
,0, "['clone'] -- Demodulate samples for VeriChip",
2443 "zerocrossings", CmdZerocrossings
,1, " Count time between zero-crossings",
2447 //-----------------------------------------------------------------------------
2448 // Entry point into our code: called whenever the user types a command and
2449 // then presses Enter, which the full command line that they typed.
2450 //-----------------------------------------------------------------------------
2451 void CommandReceived(char *cmd
)
2455 PrintToScrollback("> %s", cmd
);
2457 if(strcmp(cmd
, "help")==0) {
2458 if (offline
) PrintToScrollback("Operating in OFFLINE mode (no device connected)");
2459 PrintToScrollback("\r\nAvailable commands:");
2460 for(i
= 0; i
< sizeof(CommandTable
) / sizeof(CommandTable
[0]); i
++) {
2461 if (offline
&& (CommandTable
[i
].offline
==0)) continue;
2463 memset(line
, ' ', sizeof(line
));
2464 strcpy(line
+2, CommandTable
[i
].name
);
2465 line
[strlen(line
)] = ' ';
2466 sprintf(line
+15, " -- %s", CommandTable
[i
].docString
);
2467 PrintToScrollback("%s", line
);
2469 PrintToScrollback("");
2470 PrintToScrollback("and also: help, cls");
2474 for(i
= 0; i
< sizeof(CommandTable
) / sizeof(CommandTable
[0]); i
++) {
2475 char *name
= CommandTable
[i
].name
;
2476 if(memcmp(cmd
, name
, strlen(name
))==0 &&
2477 (cmd
[strlen(name
)] == ' ' || cmd
[strlen(name
)] == '\0'))
2479 cmd
+= strlen(name
);
2480 while(*cmd
== ' ') {
2483 if (offline
&& (CommandTable
[i
].offline
==0)) {
2484 PrintToScrollback("Offline mode, cannot use this command.");
2487 (CommandTable
[i
].handler
)(cmd
);
2491 PrintToScrollback(">> bad command '%s'", cmd
);
2494 //-----------------------------------------------------------------------------
2495 // Entry point into our code: called whenever we received a packet over USB
2496 // that we weren't necessarily expecting, for example a debug print.
2497 //-----------------------------------------------------------------------------
2498 void UsbCommandReceived(UsbCommand
*c
)
2501 case CMD_DEBUG_PRINT_STRING
: {
2503 if(c
->ext1
> 70 || c
->ext1
< 0) {
2506 memcpy(s
, c
->d
.asBytes
, c
->ext1
);
2508 PrintToScrollback("#db# %s", s
);
2512 case CMD_DEBUG_PRINT_INTEGERS
:
2513 PrintToScrollback("#db# %08x, %08x, %08x\r\n", c
->ext1
, c
->ext2
, c
->ext3
);
2516 case CMD_MEASURED_ANTENNA_TUNING
: {
2518 int vLf125
, vLf134
, vHf
;
2519 vLf125
= c
->ext1
& 0xffff;
2520 vLf134
= c
->ext1
>> 16;
2522 zLf
= c
->ext3
& 0xffff;
2523 zHf
= c
->ext3
>> 16;
2524 PrintToScrollback("# LF antenna @ %3d mA / %5d mV [%d ohms] 125Khz",
2525 vLf125
/zLf
, vLf125
, zLf
);
2526 PrintToScrollback("# LF antenna @ %3d mA / %5d mV [%d ohms] 134Khz",
2527 vLf134
/((zLf
*125)/134), vLf134
, (zLf
*125)/134);
2528 PrintToScrollback("# HF antenna @ %3d mA / %5d mV [%d ohms] 13.56Mhz",
2533 PrintToScrollback("unrecognized command %08x\n", c
->cmd
);