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 //-----------------------------------------------------------------------------
17 #include "../common/iso14443_crc.c"
18 #include "../common/crc16.c"
19 #include "../include/usb_cmd.h"
21 #define arraylen(x) (sizeof(x)/sizeof((x)[0]))
22 #define BIT(x) GraphBuffer[x * clock]
23 #define BITS (GraphTraceLen / clock)
24 #define SAMPLE_BUFFER_SIZE 64 // XXX check this
27 static int CmdHisamplest(char *str
, int nrlow
);
28 unsigned int current_command
= CMD_UNKNOWN
;
29 unsigned int received_command
= CMD_UNKNOWN
;
30 static uint8_t sample_buf
[SAMPLE_BUFFER_SIZE
];
32 void wait_for_response(uint32_t response_type
)
34 while (received_command
!= response_type
) {
37 if (ReceiveCommandPoll(&c
))
38 UsbCommandReceived(&c
);
41 usleep(10000); // XXX ugh
44 received_command
= CMD_UNKNOWN
;
47 static void GetFromBigBuf(uint8_t *dest
, int bytes
)
52 PrintToScrollback("bad len in GetFromBigBuf");
57 for(i
= 0; i
< n
; i
+= 12) {
58 UsbCommand c
= {CMD_DOWNLOAD_RAW_ADC_SAMPLES_125K
, {i
, 0, 0}};
60 wait_for_response(CMD_DOWNLOADED_RAW_ADC_SAMPLES_125K
);
62 memcpy(dest
+(i
*4), sample_buf
, 48);
66 static void CmdReset(char *str
)
68 UsbCommand c
= {CMD_HARDWARE_RESET
};
72 static void CmdBuffClear(char *str
)
74 UsbCommand c
= {CMD_BUFF_CLEAR
};
79 static void CmdQuit(char *str
)
84 static void CmdHIDdemodFSK(char *str
)
86 UsbCommand c
={CMD_HID_DEMOD_FSK
};
90 static void CmdTune(char *str
)
92 UsbCommand c
={CMD_MEASURE_ANTENNA_TUNING
};
96 static void CmdHi15read(char *str
)
98 UsbCommand c
={CMD_ACQUIRE_RAW_ADC_SAMPLES_ISO_15693
};
102 static void CmdHi14read(char *str
)
104 UsbCommand c
= {CMD_ACQUIRE_RAW_ADC_SAMPLES_ISO_14443
, {strtol(str
, NULL
, 0), 0, 0}};
109 /* New command to read the contents of a SRI512 tag
110 * SRI512 tags are ISO14443-B modulated memory tags,
111 * this command just dumps the contents of the memory
113 static void CmdSri512read(char *str
)
115 UsbCommand c
={CMD_READ_SRI512_TAG
, {strtol(str
, NULL
, 0), 0, 0}};
119 /* New command to read the contents of a SRIX4K tag
120 * SRIX4K tags are ISO14443-B modulated memory tags,
121 * this command just dumps the contents of the memory/
123 static void CmdSrix4kread(char *str
)
125 UsbCommand c
={CMD_READ_SRIX4K_TAG
, {strtol(str
, NULL
, 0), 0, 0}};
129 static void CmdHi14areader(char *str
)
131 UsbCommand c
={CMD_READER_ISO_14443a
, {strtol(str
, NULL
, 0), 0, 0}};
135 static void CmdHi15reader(char *str
)
137 UsbCommand c
={CMD_READER_ISO_15693
, {strtol(str
, NULL
, 0), 0, 0}};
141 static void CmdHi15tag(char *str
)
143 UsbCommand c
={CMD_SIMTAG_ISO_15693
, {strtol(str
, NULL
, 0), 0, 0}};
147 static void CmdHi14read_sim(char *str
)
149 UsbCommand c
={CMD_ACQUIRE_RAW_ADC_SAMPLES_ISO_14443_SIM
, {strtol(str
, NULL
, 0), 0, 0}};
153 static void CmdHi14readt(char *str
)
155 UsbCommand c
={CMD_ACQUIRE_RAW_ADC_SAMPLES_ISO_14443
, {strtol(str
, NULL
, 0), 0, 0}};
158 //CmdHisamplest(str);
159 while(CmdHisamplest(str
,strtol(str
, NULL
, 0))==0) {
162 RepaintGraphWindow();
165 static void CmdHisimlisten(char *str
)
167 UsbCommand c
={CMD_SIMULATE_TAG_HF_LISTEN
};
171 static void CmdHi14sim(char *str
)
173 UsbCommand c
={CMD_SIMULATE_TAG_ISO_14443
};
177 static void CmdHi14asim(char *str
) // ## simulate iso14443a tag
178 { // ## greg - added ability to specify tag UID
180 unsigned int hi
=0, lo
=0;
182 while (sscanf(&str
[i
++], "%1x", &n
) == 1) {
187 // c.arg should be set to *str or convert *str to the correct format for a uid
188 UsbCommand c
= {CMD_SIMULATE_TAG_ISO_14443a
, {hi
, lo
, 0}};
189 PrintToScrollback("Emulating 14443A TAG with UID %x%16x", hi
, lo
);
193 static void CmdHi14snoop(char *str
)
195 UsbCommand c
={CMD_SNOOP_ISO_14443
};
199 static void CmdHi14asnoop(char *str
)
201 UsbCommand c
={CMD_SNOOP_ISO_14443a
};
205 static void CmdLegicRfRead(char *str
)
207 UsbCommand c
={CMD_READER_LEGIC_RF
};
211 static void CmdFPGAOff(char *str
) // ## FPGA Control
213 UsbCommand c
={CMD_FPGA_MAJOR_MODE_OFF
};
217 /* clear out our graph window */
218 int CmdClearGraph(int redraw
)
220 int gtl
= GraphTraceLen
;
224 RepaintGraphWindow();
229 /* write a bit to the graph */
230 static void CmdAppendGraph(int redraw
, int clock
, int bit
)
234 for (i
= 0; i
< (int)(clock
/2); i
++)
235 GraphBuffer
[GraphTraceLen
++] = bit
^ 1;
237 for (i
= (int)(clock
/2); i
< clock
; i
++)
238 GraphBuffer
[GraphTraceLen
++] = bit
;
241 RepaintGraphWindow();
244 /* Function is equivalent of loread + losamples + em410xread
245 * looped until an EM410x tag is detected */
246 static void CmdEM410xwatch(char *str
)
260 /* Read the transmitted data of an EM4x50 tag
263 * XXXXXXXX [row parity bit (even)] <- 8 bits plus parity
264 * XXXXXXXX [row parity bit (even)] <- 8 bits plus parity
265 * XXXXXXXX [row parity bit (even)] <- 8 bits plus parity
266 * XXXXXXXX [row parity bit (even)] <- 8 bits plus parity
267 * CCCCCCCC <- column parity bits
269 * LW <- Listen Window
271 * This pattern repeats for every block of data being transmitted.
272 * Transmission starts with two Listen Windows (LW - a modulated
273 * pattern of 320 cycles each (32/32/128/64/64)).
275 * Note that this data may or may not be the UID. It is whatever data
276 * is stored in the blocks defined in the control word First and Last
277 * Word Read values. UID is stored in block 32.
279 static void CmdEM4x50read(char *str
)
281 int i
, j
, startblock
, clock
, skip
, block
, start
, end
, low
, high
;
282 bool complete
= false;
283 int tmpbuff
[MAX_GRAPH_TRACE_LEN
/ 64];
289 /* first get high and low values */
290 for (i
= 0; i
< GraphTraceLen
; i
++)
292 if (GraphBuffer
[i
] > high
)
293 high
= GraphBuffer
[i
];
294 else if (GraphBuffer
[i
] < low
)
295 low
= GraphBuffer
[i
];
298 /* populate a buffer with pulse lengths */
301 while(i
< GraphTraceLen
)
303 // measure from low to low
304 while((GraphBuffer
[i
] > low
) && (i
<GraphTraceLen
))
307 while((GraphBuffer
[i
] < high
) && (i
<GraphTraceLen
))
309 while((GraphBuffer
[i
] > low
) && (i
<GraphTraceLen
))
311 if (j
>(MAX_GRAPH_TRACE_LEN
/64)) {
314 tmpbuff
[j
++]= i
- start
;
317 /* look for data start - should be 2 pairs of LW (pulses of 192,128) */
320 for (i
= 0; i
< j
- 4 ; ++i
)
323 if (tmpbuff
[i
] >= 190 && tmpbuff
[i
] <= 194)
324 if (tmpbuff
[i
+1] >= 126 && tmpbuff
[i
+1] <= 130)
325 if (tmpbuff
[i
+2] >= 190 && tmpbuff
[i
+2] <= 194)
326 if (tmpbuff
[i
+3] >= 126 && tmpbuff
[i
+3] <= 130)
334 /* skip over the remainder of the LW */
335 skip
+= tmpbuff
[i
+1]+tmpbuff
[i
+2];
336 while(skip
< MAX_GRAPH_TRACE_LEN
&& GraphBuffer
[skip
] > low
)
340 /* now do it again to find the end */
342 for (i
+= 3; i
< j
- 4 ; ++i
)
345 if (tmpbuff
[i
] >= 190 && tmpbuff
[i
] <= 194)
346 if (tmpbuff
[i
+1] >= 126 && tmpbuff
[i
+1] <= 130)
347 if (tmpbuff
[i
+2] >= 190 && tmpbuff
[i
+2] <= 194)
348 if (tmpbuff
[i
+3] >= 126 && tmpbuff
[i
+3] <= 130)
356 PrintToScrollback("Found data at sample: %i",skip
);
359 PrintToScrollback("No data found!");
360 PrintToScrollback("Try again with more samples.");
366 PrintToScrollback("*** Warning!");
367 PrintToScrollback("Partial data - no end found!");
368 PrintToScrollback("Try again with more samples.");
371 /* get rid of leading crap */
372 sprintf(tmp
,"%i",skip
);
375 /* now work through remaining buffer printing out data blocks */
380 PrintToScrollback("Block %i:", block
);
381 // mandemod routine needs to be split so we can call it for data
382 // just print for now for debugging
383 Cmdmanchesterdemod("i 64");
385 /* look for LW before start of next block */
386 for ( ; i
< j
- 4 ; ++i
)
389 if (tmpbuff
[i
] >= 190 && tmpbuff
[i
] <= 194)
390 if (tmpbuff
[i
+1] >= 126 && tmpbuff
[i
+1] <= 130)
393 while(GraphBuffer
[skip
] > low
)
396 sprintf(tmp
,"%i",skip
);
404 /* Read the ID of an EM410x tag.
406 * 1111 1111 1 <-- standard non-repeatable header
407 * XXXX [row parity bit] <-- 10 rows of 5 bits for our 40 bit tag ID
409 * CCCC <-- each bit here is parity for the 10 bits above in corresponding column
410 * 0 <-- stop bit, end of tag
412 static void CmdEM410xread(char *str
)
414 int i
, j
, clock
, header
, rows
, bit
, hithigh
, hitlow
, first
, bit2idx
, high
, low
;
418 int BitStream
[MAX_GRAPH_TRACE_LEN
];
421 /* Detect high and lows and clock */
422 for (i
= 0; i
< GraphTraceLen
; i
++)
424 if (GraphBuffer
[i
] > high
)
425 high
= GraphBuffer
[i
];
426 else if (GraphBuffer
[i
] < low
)
427 low
= GraphBuffer
[i
];
431 clock
= GetClock(str
, high
);
433 /* parity for our 4 columns */
434 parity
[0] = parity
[1] = parity
[2] = parity
[3] = 0;
437 /* manchester demodulate */
439 for (i
= 0; i
< (int)(GraphTraceLen
/ clock
); i
++)
445 /* Find out if we hit both high and low peaks */
446 for (j
= 0; j
< clock
; j
++)
448 if (GraphBuffer
[(i
* clock
) + j
] == high
)
450 else if (GraphBuffer
[(i
* clock
) + j
] == low
)
453 /* it doesn't count if it's the first part of our read
454 because it's really just trailing from the last sequence */
455 if (first
&& (hithigh
|| hitlow
))
456 hithigh
= hitlow
= 0;
460 if (hithigh
&& hitlow
)
464 /* If we didn't hit both high and low peaks, we had a bit transition */
465 if (!hithigh
|| !hitlow
)
468 BitStream
[bit2idx
++] = bit
;
472 /* We go till 5 before the graph ends because we'll get that far below */
473 for (i
= 1; i
< bit2idx
- 5; i
++)
475 /* Step 2: We have our header but need our tag ID */
476 if (header
== 9 && rows
< 10)
478 /* Confirm parity is correct */
479 if ((BitStream
[i
] ^ BitStream
[i
+1] ^ BitStream
[i
+2] ^ BitStream
[i
+3]) == BitStream
[i
+4])
481 /* Read another byte! */
482 sprintf(id
+rows
, "%x", (8 * BitStream
[i
]) + (4 * BitStream
[i
+1]) + (2 * BitStream
[i
+2]) + (1 * BitStream
[i
+3]));
485 /* Keep parity info */
486 parity
[0] ^= BitStream
[i
];
487 parity
[1] ^= BitStream
[i
+1];
488 parity
[2] ^= BitStream
[i
+2];
489 parity
[3] ^= BitStream
[i
+3];
491 /* Move 4 bits ahead */
495 /* Damn, something wrong! reset */
498 PrintToScrollback("Thought we had a valid tag but failed at word %d (i=%d)", rows
+ 1, i
);
500 /* Start back rows * 5 + 9 header bits, -1 to not start at same place */
501 i
-= 9 + (5 * rows
) - 5;
507 /* Step 3: Got our 40 bits! confirm column parity */
510 /* We need to make sure our 4 bits of parity are correct and we have a stop bit */
511 if (BitStream
[i
] == parity
[0] && BitStream
[i
+1] == parity
[1] &&
512 BitStream
[i
+2] == parity
[2] && BitStream
[i
+3] == parity
[3] &&
516 PrintToScrollback("EM410x Tag ID: %s", id
);
523 /* Crap! Incorrect parity or no stop bit, start all over */
528 /* Go back 59 bits (9 header bits + 10 rows at 4+1 parity) */
533 /* Step 1: get our header */
536 /* Need 9 consecutive 1's */
537 if (BitStream
[i
] == 1)
540 /* We don't have a header, not enough consecutive 1 bits */
546 /* if we've already retested after flipping bits, return */
550 /* if this didn't work, try flipping bits */
551 for (i
= 0; i
< bit2idx
; i
++)
557 /* emulate an EM410X tag
559 * 1111 1111 1 <-- standard non-repeatable header
560 * XXXX [row parity bit] <-- 10 rows of 5 bits for our 40 bit tag ID
562 * CCCC <-- each bit here is parity for the 10 bits above in corresponding column
563 * 0 <-- stop bit, end of tag
565 static void CmdEM410xsim(char *str
)
567 int i
, n
, j
, h
, binary
[4], parity
[4];
570 /* clock is 64 in EM410x tags */
573 /* clear our graph */
576 /* write it out a few times */
577 for (h
= 0; h
< 4; h
++)
579 /* write 9 start bits */
580 for (i
= 0; i
< 9; i
++)
581 CmdAppendGraph(0, clock
, 1);
583 /* for each hex char */
584 parity
[0] = parity
[1] = parity
[2] = parity
[3] = 0;
585 for (i
= 0; i
< 10; i
++)
587 /* read each hex char */
588 sscanf(&str
[i
], "%1x", &n
);
589 for (j
= 3; j
>= 0; j
--, n
/= 2)
592 /* append each bit */
593 CmdAppendGraph(0, clock
, binary
[0]);
594 CmdAppendGraph(0, clock
, binary
[1]);
595 CmdAppendGraph(0, clock
, binary
[2]);
596 CmdAppendGraph(0, clock
, binary
[3]);
598 /* append parity bit */
599 CmdAppendGraph(0, clock
, binary
[0] ^ binary
[1] ^ binary
[2] ^ binary
[3]);
601 /* keep track of column parity */
602 parity
[0] ^= binary
[0];
603 parity
[1] ^= binary
[1];
604 parity
[2] ^= binary
[2];
605 parity
[3] ^= binary
[3];
609 CmdAppendGraph(0, clock
, parity
[0]);
610 CmdAppendGraph(0, clock
, parity
[1]);
611 CmdAppendGraph(0, clock
, parity
[2]);
612 CmdAppendGraph(0, clock
, parity
[3]);
615 CmdAppendGraph(0, clock
, 0);
618 /* modulate that biatch */
622 RepaintGraphWindow();
627 static void ChkBitstream(char *str
)
631 /* convert to bitstream if necessary */
632 for (i
= 0; i
< (int)(GraphTraceLen
/ 2); i
++)
634 if (GraphBuffer
[i
] > 1 || GraphBuffer
[i
] < 0)
642 static void CmdLosim(char *str
)
646 /* convert to bitstream if necessary */
649 for (i
= 0; i
< GraphTraceLen
; i
+= 48) {
650 UsbCommand c
={CMD_DOWNLOADED_SIM_SAMPLES_125K
, {i
, 0, 0}};
652 for(j
= 0; j
< 48; j
++) {
653 c
.d
.asBytes
[j
] = GraphBuffer
[i
+j
];
658 UsbCommand c
={CMD_SIMULATE_TAG_125K
, {GraphTraceLen
, 0, 0}};
662 static void CmdLosimBidir(char *str
)
664 /* Set ADC to twice the carrier for a slight supersampling */
665 UsbCommand c
={CMD_LF_SIMULATE_BIDIR
, {47, 384, 0}};
669 static void CmdLoread(char *str
)
671 UsbCommand c
={CMD_ACQUIRE_RAW_ADC_SAMPLES_125K
};
672 // 'h' means higher-low-frequency, 134 kHz
675 } else if (*str
== '\0') {
678 PrintToScrollback("use 'loread' or 'loread h'");
684 static void CmdDetectReader(char *str
)
686 UsbCommand c
={CMD_LISTEN_READER_FIELD
};
687 // 'l' means LF - 125/134 kHz
690 } else if (*str
== 'h') {
692 } else if (*str
!= '\0') {
693 PrintToScrollback("use 'detectreader' or 'detectreader l' or 'detectreader h'");
699 /* send a command before reading */
700 static void CmdLoCommandRead(char *str
)
702 static char dummy
[3];
706 UsbCommand c
={CMD_MOD_THEN_ACQUIRE_RAW_ADC_SAMPLES_125K
};
707 sscanf(str
, "%i %i %i %s %s", &c
.arg
[0], &c
.arg
[1], &c
.arg
[2], (char *) &c
.d
.asBytes
,(char *) &dummy
+1);
708 // in case they specified 'h'
709 strcpy((char *)&c
.d
.asBytes
+ strlen((char *)c
.d
.asBytes
), dummy
);
713 static void CmdLosamples(char *str
)
718 n
=strtol(str
, NULL
, 0);
720 if (n
>16000) n
=16000;
722 PrintToScrollback("Reading %d samples\n", n
);
723 for(i
= 0; i
< n
; i
+= 12) {
724 UsbCommand c
= {CMD_DOWNLOAD_RAW_ADC_SAMPLES_125K
, {i
, 0, 0}};
726 wait_for_response(CMD_DOWNLOADED_RAW_ADC_SAMPLES_125K
);
727 for(j
= 0; j
< 48; j
++) {
728 GraphBuffer
[cnt
++] = ((int)sample_buf
[j
]) - 128;
731 PrintToScrollback("Done!\n");
733 RepaintGraphWindow();
736 static void CmdBitsamples(char *str
)
742 for(i
= 0; i
< n
; i
+= 12) {
743 UsbCommand c
= {CMD_DOWNLOAD_RAW_ADC_SAMPLES_125K
, {i
, 0, 0}};
745 wait_for_response(CMD_DOWNLOADED_RAW_ADC_SAMPLES_125K
);
747 for(j
= 0; j
< 48; j
++) {
748 for(k
= 0; k
< 8; k
++) {
749 if(sample_buf
[j
] & (1 << (7 - k
))) {
750 GraphBuffer
[cnt
++] = 1;
752 GraphBuffer
[cnt
++] = 0;
758 RepaintGraphWindow();
761 static void CmdHisamples(char *str
)
767 for(i
= 0; i
< n
; i
+= 12) {
768 UsbCommand c
= {CMD_DOWNLOAD_RAW_ADC_SAMPLES_125K
, {i
, 0, 0}};
770 wait_for_response(CMD_DOWNLOADED_RAW_ADC_SAMPLES_125K
);
771 for(j
= 0; j
< 48; j
++) {
772 GraphBuffer
[cnt
++] = (int)(sample_buf
[j
]);
777 RepaintGraphWindow();
780 static int CmdHisamplest(char *str
, int nrlow
)
790 for(i
= 0; i
< n
; i
+= 12) {
791 UsbCommand c
= {CMD_DOWNLOAD_RAW_ADC_SAMPLES_125K
, {i
, 0, 0}};
793 wait_for_response(CMD_DOWNLOADED_RAW_ADC_SAMPLES_125K
);
794 for(j
= 0; j
< 48; j
++) {
795 t2
= (int)(sample_buf
[j
]);
796 if((t2
^ 0xC0) & 0xC0) { hasbeennull
++; }
802 t1
= (t2
& 0x80) ^ (t2
& 0x20);
803 t2
= ((t2
<< 1) & 0x80) ^ ((t2
<< 1) & 0x20);
809 t2
= ((t2
<< 1) & 0x80);
815 t2
= ((t2
<< 1) & 0x20);
819 // both, but tag with other algorithm
820 t1
= (t2
& 0x80) ^ (t2
& 0x08);
821 t2
= ((t2
<< 1) & 0x80) ^ ((t2
<< 1) & 0x08);
825 GraphBuffer
[cnt
++] = t1
;
826 GraphBuffer
[cnt
++] = t2
;
831 if(hasbeennull
>nrlow
|| nrlow
==0) {
832 PrintToScrollback("hasbeennull=%d", hasbeennull
);
841 static void CmdHexsamples(char *str
)
844 int requested
= strtol(str
, NULL
, 0);
847 if (requested
== 0) {
854 for(i
= 0; i
< n
; i
+= 12) {
855 UsbCommand c
= {CMD_DOWNLOAD_RAW_ADC_SAMPLES_125K
, {i
, 0, 0}};
857 wait_for_response(CMD_DOWNLOADED_RAW_ADC_SAMPLES_125K
);
858 for (j
= 0; j
< 48; j
+= 8) {
859 PrintToScrollback("%02x %02x %02x %02x %02x %02x %02x %02x",
871 if (delivered
>= requested
)
874 if (delivered
>= requested
)
879 static void CmdHisampless(char *str
)
883 int n
= strtol(str
, NULL
, 0);
891 for(i
= 0; i
< n
; i
+= 12) {
892 UsbCommand c
= {CMD_DOWNLOAD_RAW_ADC_SAMPLES_125K
, {i
, 0, 0}};
894 wait_for_response(CMD_DOWNLOADED_RAW_ADC_SAMPLES_125K
);
895 for(j
= 0; j
< 48; j
++) {
896 GraphBuffer
[cnt
++] = (int)(sample_buf
[j
]);
901 RepaintGraphWindow();
904 static uint16_t Iso15693Crc(uint8_t *v
, int n
)
910 for(i
= 0; i
< n
; i
++) {
911 reg
= reg
^ ((uint32_t)v
[i
]);
912 for (j
= 0; j
< 8; j
++) {
914 reg
= (reg
>> 1) ^ 0x8408;
921 return (uint16_t)~reg
;
924 static void CmdHi14bdemod(char *str
)
929 bool negateI
, negateQ
;
934 // As received, the samples are pairs, correlations against I and Q
935 // square waves. So estimate angle of initial carrier (or just
936 // quadrant, actually), and then do the demod.
938 // First, estimate where the tag starts modulating.
939 for(i
= 0; i
< GraphTraceLen
; i
+= 2) {
940 if(abs(GraphBuffer
[i
]) + abs(GraphBuffer
[i
+1]) > 40) {
944 if(i
>= GraphTraceLen
) {
945 PrintToScrollback("too weak to sync");
948 PrintToScrollback("out of weak at %d", i
);
951 // Now, estimate the phase in the initial modulation of the tag
954 for(; i
< (outOfWeakAt
+ 16); i
+= 2) {
955 isum
+= GraphBuffer
[i
+0];
956 qsum
+= GraphBuffer
[i
+1];
958 negateI
= (isum
< 0);
959 negateQ
= (qsum
< 0);
961 // Turn the correlation pairs into soft decisions on the bit.
963 for(i
= 0; i
< GraphTraceLen
/2; i
++) {
964 int si
= GraphBuffer
[j
];
965 int sq
= GraphBuffer
[j
+1];
966 if(negateI
) si
= -si
;
967 if(negateQ
) sq
= -sq
;
968 GraphBuffer
[i
] = si
+ sq
;
974 while(GraphBuffer
[i
] > 0 && i
< GraphTraceLen
)
976 if(i
>= GraphTraceLen
) goto demodError
;
979 while(GraphBuffer
[i
] < 0 && i
< GraphTraceLen
)
981 if(i
>= GraphTraceLen
) goto demodError
;
982 if((i
- iold
) > 23) goto demodError
;
984 PrintToScrollback("make it to demod loop");
988 while(GraphBuffer
[i
] >= 0 && i
< GraphTraceLen
)
990 if(i
>= GraphTraceLen
) goto demodError
;
991 if((i
- iold
) > 6) goto demodError
;
993 uint16_t shiftReg
= 0;
994 if(i
+ 20 >= GraphTraceLen
) goto demodError
;
996 for(j
= 0; j
< 10; j
++) {
997 int soft
= GraphBuffer
[i
] + GraphBuffer
[i
+1];
999 if(abs(soft
) < ((abs(isum
) + abs(qsum
))/20)) {
1000 PrintToScrollback("weak bit");
1004 if(GraphBuffer
[i
] + GraphBuffer
[i
+1] >= 0) {
1011 if( (shiftReg
& 0x200) &&
1012 !(shiftReg
& 0x001))
1014 // valid data byte, start and stop bits okay
1015 PrintToScrollback(" %02x", (shiftReg
>> 1) & 0xff);
1016 data
[dataLen
++] = (shiftReg
>> 1) & 0xff;
1017 if(dataLen
>= sizeof(data
)) {
1020 } else if(shiftReg
== 0x000) {
1028 uint8_t first
, second
;
1029 ComputeCrc14443(CRC_14443_B
, data
, dataLen
-2, &first
, &second
);
1030 PrintToScrollback("CRC: %02x %02x (%s)\n", first
, second
,
1031 (first
== data
[dataLen
-2] && second
== data
[dataLen
-1]) ?
1032 "ok" : "****FAIL****");
1034 RepaintGraphWindow();
1038 PrintToScrollback("demod error");
1039 RepaintGraphWindow();
1042 static void CmdHi14list(char *str
)
1045 GetFromBigBuf(got
, sizeof(got
));
1047 PrintToScrollback("recorded activity:");
1048 PrintToScrollback(" time :rssi: who bytes");
1049 PrintToScrollback("---------+----+----+-----------");
1060 int timestamp
= *((uint32_t *)(got
+i
));
1061 if(timestamp
& 0x80000000) {
1062 timestamp
&= 0x7fffffff;
1067 int metric
= *((uint32_t *)(got
+i
+4));
1074 if(i
+ len
>= 900) {
1078 uint8_t *frame
= (got
+i
+9);
1080 char line
[1000] = "";
1082 for(j
= 0; j
< len
; j
++) {
1083 sprintf(line
+(j
*3), "%02x ", frame
[j
]);
1089 ComputeCrc14443(CRC_14443_B
, frame
, len
-2, &b1
, &b2
);
1090 if(b1
!= frame
[len
-2] || b2
!= frame
[len
-1]) {
1091 crc
= "**FAIL CRC**";
1099 char metricString
[100];
1101 sprintf(metricString
, "%3d", metric
);
1103 strcpy(metricString
, " ");
1106 PrintToScrollback(" +%7d: %s: %s %s %s",
1107 (prev
< 0 ? 0 : timestamp
- prev
),
1109 (isResponse
? "TAG" : " "), line
, crc
);
1116 static void CmdHi14alist(char *str
)
1119 GetFromBigBuf(got
, sizeof(got
));
1121 PrintToScrollback("recorded activity:");
1122 PrintToScrollback(" ETU :rssi: who bytes");
1123 PrintToScrollback("---------+----+----+-----------");
1134 int timestamp
= *((uint32_t *)(got
+i
));
1135 if(timestamp
& 0x80000000) {
1136 timestamp
&= 0x7fffffff;
1143 int parityBits
= *((uint32_t *)(got
+i
+4));
1144 // 4 bytes of additional information...
1145 // maximum of 32 additional parity bit information
1148 // at each quarter bit period we can send power level (16 levels)
1149 // or each half bit period in 256 levels.
1157 if(i
+ len
>= 1900) {
1161 uint8_t *frame
= (got
+i
+9);
1163 // Break and stick with current result if buffer was not completely full
1164 if(frame
[0] == 0x44 && frame
[1] == 0x44 && frame
[3] == 0x44) { break; }
1166 char line
[1000] = "";
1168 for(j
= 0; j
< len
; j
++) {
1169 int oddparity
= 0x01;
1173 oddparity
^= (((frame
[j
] & 0xFF) >> k
) & 0x01);
1176 //if((parityBits >> (len - j - 1)) & 0x01) {
1177 if(isResponse
&& (oddparity
!= ((parityBits
>> (len
- j
- 1)) & 0x01))) {
1178 sprintf(line
+(j
*4), "%02x! ", frame
[j
]);
1181 sprintf(line
+(j
*4), "%02x ", frame
[j
]);
1189 for(j
= 0; j
< (len
- 1); j
++) {
1190 // gives problems... search for the reason..
1191 /*if(frame[j] == 0xAA) {
1192 switch(frame[j+1]) {
1194 crc = "[1] Two drops close after each other";
1197 crc = "[2] Potential SOC with a drop in second half of bitperiod";
1200 crc = "[3] Segment Z after segment X is not possible";
1203 crc = "[4] Parity bit of a fully received byte was wrong";
1206 crc = "[?] Unknown error";
1213 if(strlen(crc
)==0) {
1214 ComputeCrc14443(CRC_14443_A
, frame
, len
-2, &b1
, &b2
);
1215 if(b1
!= frame
[len
-2] || b2
!= frame
[len
-1]) {
1216 crc
= (isResponse
& (len
< 6)) ? "" : " !crc";
1225 char metricString
[100];
1227 sprintf(metricString
, "%3d", metric
);
1229 strcpy(metricString
, " ");
1232 PrintToScrollback(" +%7d: %s: %s %s %s",
1233 (prev
< 0 ? 0 : (timestamp
- prev
)),
1235 (isResponse
? "TAG" : " "), line
, crc
);
1240 CommandFinished
= 1;
1243 static void CmdHi15demod(char *str
)
1245 // The sampling rate is 106.353 ksps/s, for T = 18.8 us
1248 // 1) Unmodulated time of 56.64us
1249 // 2) 24 pulses of 423.75khz
1250 // 3) logic '1' (unmodulated for 18.88us followed by 8 pulses of 423.75khz)
1252 static const int FrameSOF
[] = {
1253 -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,
1255 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,
1262 static const int Logic0
[] = {
1268 static const int Logic1
[] = {
1276 // 1) logic '0' (8 pulses of 423.75khz followed by unmodulated for 18.88us)
1277 // 2) 24 pulses of 423.75khz
1278 // 3) Unmodulated time of 56.64us
1280 static const int FrameEOF
[] = {
1285 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,
1287 -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
1292 int max
= 0, maxPos
;
1296 if(GraphTraceLen
< 1000) return;
1298 // First, correlate for SOF
1299 for(i
= 0; i
< 100; i
++) {
1301 for(j
= 0; j
< arraylen(FrameSOF
); j
+= skip
) {
1302 corr
+= FrameSOF
[j
]*GraphBuffer
[i
+(j
/skip
)];
1309 PrintToScrollback("SOF at %d, correlation %d", maxPos
,
1310 max
/(arraylen(FrameSOF
)/skip
));
1312 i
= maxPos
+ arraylen(FrameSOF
)/skip
;
1315 memset(outBuf
, 0, sizeof(outBuf
));
1316 uint8_t mask
= 0x01;
1318 int corr0
= 0, corr1
= 0, corrEOF
= 0;
1319 for(j
= 0; j
< arraylen(Logic0
); j
+= skip
) {
1320 corr0
+= Logic0
[j
]*GraphBuffer
[i
+(j
/skip
)];
1322 for(j
= 0; j
< arraylen(Logic1
); j
+= skip
) {
1323 corr1
+= Logic1
[j
]*GraphBuffer
[i
+(j
/skip
)];
1325 for(j
= 0; j
< arraylen(FrameEOF
); j
+= skip
) {
1326 corrEOF
+= FrameEOF
[j
]*GraphBuffer
[i
+(j
/skip
)];
1328 // Even things out by the length of the target waveform.
1332 if(corrEOF
> corr1
&& corrEOF
> corr0
) {
1333 PrintToScrollback("EOF at %d", i
);
1335 } else if(corr1
> corr0
) {
1336 i
+= arraylen(Logic1
)/skip
;
1339 i
+= arraylen(Logic0
)/skip
;
1346 if((i
+(int)arraylen(FrameEOF
)) >= GraphTraceLen
) {
1347 PrintToScrollback("ran off end!");
1352 PrintToScrollback("error, uneven octet! (discard extra bits!)");
1353 PrintToScrollback(" mask=%02x", mask
);
1355 PrintToScrollback("%d octets", k
);
1357 for(i
= 0; i
< k
; i
++) {
1358 PrintToScrollback("# %2d: %02x ", i
, outBuf
[i
]);
1360 PrintToScrollback("CRC=%04x", Iso15693Crc(outBuf
, k
-2));
1363 static void CmdFSKdemod(char *cmdline
)
1365 static const int LowTone
[] = {
1366 1, 1, 1, 1, 1, -1, -1, -1, -1, -1,
1367 1, 1, 1, 1, 1, -1, -1, -1, -1, -1,
1368 1, 1, 1, 1, 1, -1, -1, -1, -1, -1,
1369 1, 1, 1, 1, 1, -1, -1, -1, -1, -1,
1370 1, 1, 1, 1, 1, -1, -1, -1, -1, -1
1372 static const int HighTone
[] = {
1373 1, 1, 1, 1, 1, -1, -1, -1, -1,
1374 1, 1, 1, 1, -1, -1, -1, -1,
1375 1, 1, 1, 1, -1, -1, -1, -1,
1376 1, 1, 1, 1, -1, -1, -1, -1,
1377 1, 1, 1, 1, -1, -1, -1, -1,
1378 1, 1, 1, 1, -1, -1, -1, -1, -1,
1381 int lowLen
= sizeof(LowTone
)/sizeof(int);
1382 int highLen
= sizeof(HighTone
)/sizeof(int);
1383 int convLen
= (highLen
>lowLen
)?highLen
:lowLen
;
1384 uint32_t hi
= 0, lo
= 0;
1387 int minMark
=0, maxMark
=0;
1389 for(i
= 0; i
< GraphTraceLen
- convLen
; i
++) {
1390 int lowSum
= 0, highSum
= 0;
1392 for(j
= 0; j
< lowLen
; j
++) {
1393 lowSum
+= LowTone
[j
]*GraphBuffer
[i
+j
];
1395 for(j
= 0; j
< highLen
; j
++) {
1396 highSum
+= HighTone
[j
]*GraphBuffer
[i
+j
];
1398 lowSum
= abs((100*lowSum
) / lowLen
);
1399 highSum
= abs((100*highSum
) / highLen
);
1400 GraphBuffer
[i
] = (highSum
<< 16) | lowSum
;
1403 for(i
= 0; i
< GraphTraceLen
- convLen
- 16; i
++) {
1405 int lowTot
= 0, highTot
= 0;
1406 // 10 and 8 are f_s divided by f_l and f_h, rounded
1407 for(j
= 0; j
< 10; j
++) {
1408 lowTot
+= (GraphBuffer
[i
+j
] & 0xffff);
1410 for(j
= 0; j
< 8; j
++) {
1411 highTot
+= (GraphBuffer
[i
+j
] >> 16);
1413 GraphBuffer
[i
] = lowTot
- highTot
;
1414 if (GraphBuffer
[i
]>maxMark
) maxMark
=GraphBuffer
[i
];
1415 if (GraphBuffer
[i
]<minMark
) minMark
=GraphBuffer
[i
];
1418 GraphTraceLen
-= (convLen
+ 16);
1420 RepaintGraphWindow();
1422 // Find bit-sync (3 lo followed by 3 high)
1423 int max
= 0, maxPos
= 0;
1424 for(i
= 0; i
< 6000; i
++) {
1426 for(j
= 0; j
< 3*lowLen
; j
++) {
1427 dec
-= GraphBuffer
[i
+j
];
1429 for(; j
< 3*(lowLen
+ highLen
); j
++) {
1430 dec
+= GraphBuffer
[i
+j
];
1438 // place start of bit sync marker in graph
1439 GraphBuffer
[maxPos
] = maxMark
;
1440 GraphBuffer
[maxPos
+1] = minMark
;
1444 // place end of bit sync marker in graph
1445 GraphBuffer
[maxPos
] = maxMark
;
1446 GraphBuffer
[maxPos
+1] = minMark
;
1448 PrintToScrollback("actual data bits start at sample %d", maxPos
);
1449 PrintToScrollback("length %d/%d", highLen
, lowLen
);
1452 bits
[sizeof(bits
)-1] = '\0';
1454 // find bit pairs and manchester decode them
1455 for(i
= 0; i
< arraylen(bits
)-1; i
++) {
1457 for(j
= 0; j
< lowLen
; j
++) {
1458 dec
-= GraphBuffer
[maxPos
+j
];
1460 for(; j
< lowLen
+ highLen
; j
++) {
1461 dec
+= GraphBuffer
[maxPos
+j
];
1464 // place inter bit marker in graph
1465 GraphBuffer
[maxPos
] = maxMark
;
1466 GraphBuffer
[maxPos
+1] = minMark
;
1468 // hi and lo form a 64 bit pair
1469 hi
= (hi
<<1)|(lo
>>31);
1471 // store decoded bit as binary (in hi/lo) and text (in bits[])
1479 PrintToScrollback("bits: '%s'", bits
);
1480 PrintToScrollback("hex: %08x %08x", hi
, lo
);
1483 // read a TI tag and return its ID
1484 static void CmdTIRead(char *str
)
1486 UsbCommand c
={CMD_READ_TI_TYPE
};
1490 // write new data to a r/w TI tag
1491 static void CmdTIWrite(char *str
)
1493 UsbCommand c
={CMD_WRITE_TI_TYPE
};
1496 res
= sscanf(str
, "0x%x 0x%x 0x%x ", &c
.arg
[0], &c
.arg
[1], &c
.arg
[2]);
1497 if (res
== 2) c
.arg
[2]=0;
1499 PrintToScrollback("Please specify the data as two hex strings, optionally the CRC as a third");
1504 static void CmdTIDemod(char *cmdline
)
1506 /* MATLAB as follows:
1507 f_s = 2000000; % sampling frequency
1508 f_l = 123200; % low FSK tone
1509 f_h = 134200; % high FSK tone
1511 T_l = 119e-6; % low bit duration
1512 T_h = 130e-6; % high bit duration
1514 l = 2*pi*ones(1, floor(f_s*T_l))*(f_l/f_s);
1515 h = 2*pi*ones(1, floor(f_s*T_h))*(f_h/f_s);
1517 l = sign(sin(cumsum(l)));
1518 h = sign(sin(cumsum(h)));
1521 // 2M*16/134.2k = 238
1522 static const int LowTone
[] = {
1523 1, 1, 1, 1, 1, 1, 1, 1, 1, -1, -1, -1, -1, -1, -1, -1, -1,
1524 1, 1, 1, 1, 1, 1, 1, 1, -1, -1, -1, -1, -1, -1, -1, -1,
1525 1, 1, 1, 1, 1, 1, 1, 1, -1, -1, -1, -1, -1, -1, -1, -1,
1526 1, 1, 1, 1, 1, 1, 1, 1, -1, -1, -1, -1, -1, -1, -1, -1,
1527 1, 1, 1, 1, 1, 1, 1, 1, 1, -1, -1, -1, -1, -1, -1, -1, -1,
1528 1, 1, 1, 1, 1, 1, 1, 1, -1, -1, -1, -1, -1, -1, -1, -1,
1529 1, 1, 1, 1, 1, 1, 1, 1, -1, -1, -1, -1, -1, -1, -1, -1,
1530 1, 1, 1, 1, 1, 1, 1, 1, -1, -1, -1, -1, -1, -1, -1, -1,
1531 1, 1, 1, 1, 1, 1, 1, 1, 1, -1, -1, -1, -1, -1, -1, -1, -1,
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, -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
1539 // 2M*16/123.2k = 260
1540 static const int HighTone
[] = {
1541 1, 1, 1, 1, 1, 1, 1, 1, -1, -1, -1, -1, -1, -1, -1,
1542 1, 1, 1, 1, 1, 1, 1, 1, -1, -1, -1, -1, -1, -1, -1,
1543 1, 1, 1, 1, 1, 1, 1, -1, -1, -1, -1, -1, -1, -1, -1,
1544 1, 1, 1, 1, 1, 1, 1, -1, -1, -1, -1, -1, -1, -1, -1,
1545 1, 1, 1, 1, 1, 1, 1, -1, -1, -1, -1, -1, -1, -1, -1,
1546 1, 1, 1, 1, 1, 1, 1, -1, -1, -1, -1, -1, -1, -1,
1547 1, 1, 1, 1, 1, 1, 1, 1, -1, -1, -1, -1, -1, -1, -1,
1548 1, 1, 1, 1, 1, 1, 1, 1, -1, -1, -1, -1, -1, -1, -1,
1549 1, 1, 1, 1, 1, 1, 1, -1, -1, -1, -1, -1, -1, -1, -1,
1550 1, 1, 1, 1, 1, 1, 1, -1, -1, -1, -1, -1, -1, -1, -1,
1551 1, 1, 1, 1, 1, 1, 1, -1, -1, -1, -1, -1, -1, -1,
1552 1, 1, 1, 1, 1, 1, 1, 1, -1, -1, -1, -1, -1, -1, -1,
1553 1, 1, 1, 1, 1, 1, 1, 1, -1, -1, -1, -1, -1, -1, -1,
1554 1, 1, 1, 1, 1, 1, 1, 1, -1, -1, -1, -1, -1, -1, -1,
1555 1, 1, 1, 1, 1, 1, 1, -1, -1, -1, -1, -1, -1, -1, -1,
1556 1, 1, 1, 1, 1, 1, 1, -1, -1, -1, -1, -1, -1, -1, -1,
1557 1, 1, 1, 1, 1, 1, 1, -1, -1, -1, -1, -1, -1, -1,
1558 1, 1, 1, 1, 1, 1, 1, 1
1560 int lowLen
= sizeof(LowTone
)/sizeof(int);
1561 int highLen
= sizeof(HighTone
)/sizeof(int);
1562 int convLen
= (highLen
>lowLen
)?highLen
:lowLen
;
1565 int lowSum
= 0, highSum
= 0;;
1566 int lowTot
= 0, highTot
= 0;
1568 for(i
= 0; i
< GraphTraceLen
- convLen
; i
++) {
1572 for(j
= 0; j
< lowLen
; j
++) {
1573 lowSum
+= LowTone
[j
]*GraphBuffer
[i
+j
];
1575 for(j
= 0; j
< highLen
; j
++) {
1576 highSum
+= HighTone
[j
]*GraphBuffer
[i
+j
];
1578 lowSum
= abs((100*lowSum
) / lowLen
);
1579 highSum
= abs((100*highSum
) / highLen
);
1580 lowSum
= (lowSum
<0)?-lowSum
:lowSum
;
1581 highSum
= (highSum
<0)?-highSum
:highSum
;
1583 GraphBuffer
[i
] = (highSum
<< 16) | lowSum
;
1586 for(i
= 0; i
< GraphTraceLen
- convLen
- 16; i
++) {
1589 // 16 and 15 are f_s divided by f_l and f_h, rounded
1590 for(j
= 0; j
< 16; j
++) {
1591 lowTot
+= (GraphBuffer
[i
+j
] & 0xffff);
1593 for(j
= 0; j
< 15; j
++) {
1594 highTot
+= (GraphBuffer
[i
+j
] >> 16);
1596 GraphBuffer
[i
] = lowTot
- highTot
;
1599 GraphTraceLen
-= (convLen
+ 16);
1601 RepaintGraphWindow();
1603 // TI tag data format is 16 prebits, 8 start bits, 64 data bits,
1604 // 16 crc CCITT bits, 8 stop bits, 15 end bits
1606 // the 16 prebits are always low
1607 // the 8 start and stop bits of a tag must match
1608 // the start/stop prebits of a ro tag are 01111110
1609 // the start/stop prebits of a rw tag are 11111110
1610 // the 15 end bits of a ro tag are all low
1611 // the 15 end bits of a rw tag match bits 15-1 of the data bits
1613 // Okay, so now we have unsliced soft decisions;
1614 // find bit-sync, and then get some bits.
1615 // look for 17 low bits followed by 6 highs (common pattern for ro and rw tags)
1616 int max
= 0, maxPos
= 0;
1617 for(i
= 0; i
< 6000; i
++) {
1620 // searching 17 consecutive lows
1621 for(j
= 0; j
< 17*lowLen
; j
++) {
1622 dec
-= GraphBuffer
[i
+j
];
1624 // searching 7 consecutive highs
1625 for(; j
< 17*lowLen
+ 6*highLen
; j
++) {
1626 dec
+= GraphBuffer
[i
+j
];
1634 // place a marker in the buffer to visually aid location
1635 // of the start of sync
1636 GraphBuffer
[maxPos
] = 800;
1637 GraphBuffer
[maxPos
+1] = -800;
1639 // advance pointer to start of actual data stream (after 16 pre and 8 start bits)
1640 maxPos
+= 17*lowLen
;
1641 maxPos
+= 6*highLen
;
1643 // place a marker in the buffer to visually aid location
1644 // of the end of sync
1645 GraphBuffer
[maxPos
] = 800;
1646 GraphBuffer
[maxPos
+1] = -800;
1648 PrintToScrollback("actual data bits start at sample %d", maxPos
);
1650 PrintToScrollback("length %d/%d", highLen
, lowLen
);
1652 uint8_t bits
[1+64+16+8+16];
1653 bits
[sizeof(bits
)-1] = '\0';
1655 uint32_t shift3
= 0x7e000000, shift2
= 0, shift1
= 0, shift0
= 0;
1657 for(i
= 0; i
< arraylen(bits
)-1; i
++) {
1661 for(j
= 0; j
< lowLen
; j
++) {
1662 low
-= GraphBuffer
[maxPos
+j
];
1664 for(j
= 0; j
< highLen
; j
++) {
1665 high
+= GraphBuffer
[maxPos
+j
];
1671 // bitstream arrives lsb first so shift right
1678 // 128 bit right shift register
1679 shift0
= (shift0
>>1) | (shift1
<< 31);
1680 shift1
= (shift1
>>1) | (shift2
<< 31);
1681 shift2
= (shift2
>>1) | (shift3
<< 31);
1684 // place a marker in the buffer between bits to visually aid location
1685 GraphBuffer
[maxPos
] = 800;
1686 GraphBuffer
[maxPos
+1] = -800;
1688 PrintToScrollback("Info: raw tag bits = %s", bits
);
1690 TagType
= (shift3
>>8)&0xff;
1691 if ( TagType
!= ((shift0
>>16)&0xff) ) {
1692 PrintToScrollback("Error: start and stop bits do not match!");
1695 else if (TagType
== 0x7e) {
1696 PrintToScrollback("Info: Readonly TI tag detected.");
1699 else if (TagType
== 0xfe) {
1700 PrintToScrollback("Info: Rewriteable TI tag detected.");
1702 // put 64 bit data into shift1 and shift0
1703 shift0
= (shift0
>>24) | (shift1
<< 8);
1704 shift1
= (shift1
>>24) | (shift2
<< 8);
1706 // align 16 bit crc into lower half of shift2
1707 shift2
= ((shift2
>>24) | (shift3
<< 8)) & 0x0ffff;
1709 // align 16 bit "end bits" or "ident" into lower half of shift3
1712 // only 15 bits compare, last bit of ident is not valid
1713 if ( (shift3
^shift0
)&0x7fff ) {
1714 PrintToScrollback("Error: Ident mismatch!");
1716 // WARNING the order of the bytes in which we calc crc below needs checking
1717 // i'm 99% sure the crc algorithm is correct, but it may need to eat the
1718 // bytes in reverse or something
1721 crc
= update_crc16(crc
, (shift0
)&0xff);
1722 crc
= update_crc16(crc
, (shift0
>>8)&0xff);
1723 crc
= update_crc16(crc
, (shift0
>>16)&0xff);
1724 crc
= update_crc16(crc
, (shift0
>>24)&0xff);
1725 crc
= update_crc16(crc
, (shift1
)&0xff);
1726 crc
= update_crc16(crc
, (shift1
>>8)&0xff);
1727 crc
= update_crc16(crc
, (shift1
>>16)&0xff);
1728 crc
= update_crc16(crc
, (shift1
>>24)&0xff);
1729 PrintToScrollback("Info: Tag data = %08X%08X", shift1
, shift0
);
1730 if (crc
!= (shift2
&0xffff)) {
1731 PrintToScrollback("Error: CRC mismatch, calculated %04X, got ^04X", crc
, shift2
&0xffff);
1733 PrintToScrollback("Info: CRC %04X is good", crc
);
1737 PrintToScrollback("Unknown tag type.");
1742 static void CmdNorm(char *str
)
1745 int max
= INT_MIN
, min
= INT_MAX
;
1746 for(i
= 10; i
< GraphTraceLen
; i
++) {
1747 if(GraphBuffer
[i
] > max
) {
1748 max
= GraphBuffer
[i
];
1750 if(GraphBuffer
[i
] < min
) {
1751 min
= GraphBuffer
[i
];
1755 for(i
= 0; i
< GraphTraceLen
; i
++) {
1756 GraphBuffer
[i
] = (GraphBuffer
[i
] - ((max
+ min
)/2))*1000/
1760 RepaintGraphWindow();
1763 static void CmdAmp(char *str
)
1765 int i
, rising
, falling
;
1766 int max
= INT_MIN
, min
= INT_MAX
;
1767 for(i
= 10; i
< GraphTraceLen
; i
++) {
1768 if(GraphBuffer
[i
] > max
) {
1769 max
= GraphBuffer
[i
];
1771 if(GraphBuffer
[i
] < min
) {
1772 min
= GraphBuffer
[i
];
1777 for(i
= 0; i
< GraphTraceLen
; i
++) {
1778 if(GraphBuffer
[i
+1] < GraphBuffer
[i
]) {
1780 GraphBuffer
[i
]= max
;
1785 if(GraphBuffer
[i
+1] > GraphBuffer
[i
]) {
1787 GraphBuffer
[i
]= min
;
1794 RepaintGraphWindow();
1797 static void CmdDec(char *str
)
1800 for(i
= 0; i
< (GraphTraceLen
/2); i
++) {
1801 GraphBuffer
[i
] = GraphBuffer
[i
*2];
1804 PrintToScrollback("decimated by 2");
1805 RepaintGraphWindow();
1808 static void CmdHpf(char *str
)
1812 for(i
= 10; i
< GraphTraceLen
; i
++) {
1813 accum
+= GraphBuffer
[i
];
1815 accum
/= (GraphTraceLen
- 10);
1816 for(i
= 0; i
< GraphTraceLen
; i
++) {
1817 GraphBuffer
[i
] -= accum
;
1820 RepaintGraphWindow();
1823 static void CmdZerocrossings(char *str
)
1826 // Zero-crossings aren't meaningful unless the signal is zero-mean.
1832 for(i
= 0; i
< GraphTraceLen
; i
++) {
1833 if(GraphBuffer
[i
]*sign
>= 0) {
1834 // No change in sign, reproduce the previous sample count.
1836 GraphBuffer
[i
] = lastZc
;
1838 // Change in sign, reset the sample count.
1840 GraphBuffer
[i
] = lastZc
;
1848 RepaintGraphWindow();
1851 static void CmdThreshold(char *str
)
1854 int threshold
= atoi(str
);
1856 for(i
= 0; i
< GraphTraceLen
; i
++) {
1857 if(GraphBuffer
[i
]>= threshold
)
1862 RepaintGraphWindow();
1865 static void CmdLtrim(char *str
)
1870 for(i
= ds
; i
< GraphTraceLen
; i
++) {
1871 GraphBuffer
[i
-ds
] = GraphBuffer
[i
];
1873 GraphTraceLen
-= ds
;
1875 RepaintGraphWindow();
1878 static void CmdAutoCorr(char *str
)
1880 static int CorrelBuffer
[MAX_GRAPH_TRACE_LEN
];
1882 int window
= atoi(str
);
1885 PrintToScrollback("needs a window");
1889 if(window
>= GraphTraceLen
) {
1890 PrintToScrollback("window must be smaller than trace (%d samples)",
1895 PrintToScrollback("performing %d correlations", GraphTraceLen
- window
);
1898 for(i
= 0; i
< GraphTraceLen
- window
; i
++) {
1901 for(j
= 0; j
< window
; j
++) {
1902 sum
+= (GraphBuffer
[j
]*GraphBuffer
[i
+j
]) / 256;
1904 CorrelBuffer
[i
] = sum
;
1906 GraphTraceLen
= GraphTraceLen
- window
;
1907 memcpy(GraphBuffer
, CorrelBuffer
, GraphTraceLen
*sizeof(int));
1909 RepaintGraphWindow();
1912 static void CmdVchdemod(char *str
)
1914 // Is this the entire sync pattern, or does this also include some
1915 // data bits that happen to be the same everywhere? That would be
1917 static const int SyncPattern
[] = {
1918 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
1919 1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
1920 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
1921 1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
1922 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
1923 1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
1924 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
1925 1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
1926 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
1927 1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
1930 // So first, we correlate for the sync pattern, and mark that.
1931 int bestCorrel
= 0, bestPos
= 0;
1933 // It does us no good to find the sync pattern, with fewer than
1934 // 2048 samples after it...
1935 for(i
= 0; i
< (GraphTraceLen
-2048); i
++) {
1938 for(j
= 0; j
< arraylen(SyncPattern
); j
++) {
1939 sum
+= GraphBuffer
[i
+j
]*SyncPattern
[j
];
1941 if(sum
> bestCorrel
) {
1946 PrintToScrollback("best sync at %d [metric %d]", bestPos
, bestCorrel
);
1951 int worst
= INT_MAX
;
1954 for(i
= 0; i
< 2048; i
+= 8) {
1957 for(j
= 0; j
< 8; j
++) {
1958 sum
+= GraphBuffer
[bestPos
+i
+j
];
1965 if(abs(sum
) < worst
) {
1970 PrintToScrollback("bits:");
1971 PrintToScrollback("%s", bits
);
1972 PrintToScrollback("worst metric: %d at pos %d", worst
, worstPos
);
1974 if(strcmp(str
, "clone")==0) {
1977 for(s
= bits
; *s
; s
++) {
1979 for(j
= 0; j
< 16; j
++) {
1980 GraphBuffer
[GraphTraceLen
++] = (*s
== '1') ? 1 : 0;
1983 RepaintGraphWindow();
1987 static void CmdIndalademod(char *str
)
1989 // Usage: recover 64bit UID by default, specify "224" as arg to recover a 224bit UID
1994 // worst case with GraphTraceLen=64000 is < 4096
1995 // under normal conditions it's < 2048
1996 uint8_t rawbits
[4096];
1998 int worst
= 0, worstPos
= 0;
1999 PrintToScrollback("Expecting a bit less than %d raw bits", GraphTraceLen
/32);
2000 for(i
= 0; i
< GraphTraceLen
-1; i
+= 2) {
2002 if((GraphBuffer
[i
] > GraphBuffer
[i
+ 1]) && (state
!= 1)) {
2004 for(j
= 0; j
< count
- 8; j
+= 16) {
2005 rawbits
[rawbit
++] = 0;
2007 if ((abs(count
- j
)) > worst
) {
2008 worst
= abs(count
- j
);
2014 } else if((GraphBuffer
[i
] < GraphBuffer
[i
+ 1]) && (state
!= 0)) {
2016 for(j
= 0; j
< count
- 8; j
+= 16) {
2017 rawbits
[rawbit
++] = 1;
2019 if ((abs(count
- j
)) > worst
) {
2020 worst
= abs(count
- j
);
2028 PrintToScrollback("Recovered %d raw bits", rawbit
);
2029 PrintToScrollback("worst metric (0=best..7=worst): %d at pos %d", worst
, worstPos
);
2031 // Finding the start of a UID
2032 int uidlen
, long_wait
;
2033 if(strcmp(str
, "224") == 0) {
2042 for(start
= 0; start
<= rawbit
- uidlen
; start
++) {
2043 first
= rawbits
[start
];
2044 for(i
= start
; i
< start
+ long_wait
; i
++) {
2045 if(rawbits
[i
] != first
) {
2049 if(i
== (start
+ long_wait
)) {
2053 if(start
== rawbit
- uidlen
+ 1) {
2054 PrintToScrollback("nothing to wait for");
2058 // Inverting signal if needed
2060 for(i
= start
; i
< rawbit
; i
++) {
2061 rawbits
[i
] = !rawbits
[i
];
2068 showbits
[uidlen
]='\0';
2072 if(uidlen
> rawbit
) {
2073 PrintToScrollback("Warning: not enough raw bits to get a full UID");
2074 for(bit
= 0; bit
< rawbit
; bit
++) {
2075 bits
[bit
] = rawbits
[i
++];
2076 // As we cannot know the parity, let's use "." and "/"
2077 showbits
[bit
] = '.' + bits
[bit
];
2079 showbits
[bit
+1]='\0';
2080 PrintToScrollback("Partial UID=%s", showbits
);
2083 for(bit
= 0; bit
< uidlen
; bit
++) {
2084 bits
[bit
] = rawbits
[i
++];
2085 showbits
[bit
] = '0' + bits
[bit
];
2089 PrintToScrollback("UID=%s", showbits
);
2091 // Checking UID against next occurences
2092 for(; i
+ uidlen
<= rawbit
;) {
2094 for(bit
= 0; bit
< uidlen
; bit
++) {
2095 if(bits
[bit
] != rawbits
[i
++]) {
2105 PrintToScrollback("Occurences: %d (expected %d)", times
, (rawbit
- start
) / uidlen
);
2107 // Remodulating for tag cloning
2108 GraphTraceLen
= 32*uidlen
;
2111 for(bit
= 0; bit
< uidlen
; bit
++) {
2112 if(bits
[bit
] == 0) {
2118 for(j
= 0; j
< 32; j
++) {
2119 GraphBuffer
[i
++] = phase
;
2124 RepaintGraphWindow();
2127 static void CmdFlexdemod(char *str
)
2130 for(i
= 0; i
< GraphTraceLen
; i
++) {
2131 if(GraphBuffer
[i
] < 0) {
2132 GraphBuffer
[i
] = -1;
2138 #define LONG_WAIT 100
2140 for(start
= 0; start
< GraphTraceLen
- LONG_WAIT
; start
++) {
2141 int first
= GraphBuffer
[start
];
2142 for(i
= start
; i
< start
+ LONG_WAIT
; i
++) {
2143 if(GraphBuffer
[i
] != first
) {
2147 if(i
== (start
+ LONG_WAIT
)) {
2151 if(start
== GraphTraceLen
- LONG_WAIT
) {
2152 PrintToScrollback("nothing to wait for");
2156 GraphBuffer
[start
] = 2;
2157 GraphBuffer
[start
+1] = -2;
2163 for(bit
= 0; bit
< 64; bit
++) {
2166 for(j
= 0; j
< 16; j
++) {
2167 sum
+= GraphBuffer
[i
++];
2174 PrintToScrollback("bit %d sum %d", bit
, sum
);
2177 for(bit
= 0; bit
< 64; bit
++) {
2180 for(j
= 0; j
< 16; j
++) {
2181 sum
+= GraphBuffer
[i
++];
2183 if(sum
> 0 && bits
[bit
] != 1) {
2184 PrintToScrollback("oops1 at %d", bit
);
2186 if(sum
< 0 && bits
[bit
] != 0) {
2187 PrintToScrollback("oops2 at %d", bit
);
2191 GraphTraceLen
= 32*64;
2194 for(bit
= 0; bit
< 64; bit
++) {
2195 if(bits
[bit
] == 0) {
2201 for(j
= 0; j
< 32; j
++) {
2202 GraphBuffer
[i
++] = phase
;
2207 RepaintGraphWindow();
2211 * Generic command to demodulate ASK.
2213 * Argument is convention: positive or negative (High mod means zero
2214 * or high mod means one)
2216 * Updates the Graph trace with 0/1 values
2222 static void Cmdaskdemod(char *str
) {
2224 int c
, high
= 0, low
= 0;
2226 // TODO: complain if we do not give 2 arguments here !
2227 // (AL - this doesn't make sense! we're only using one argument!!!)
2228 sscanf(str
, "%i", &c
);
2230 /* Detect high and lows and clock */
2232 for (i
= 0; i
< GraphTraceLen
; i
++)
2234 if (GraphBuffer
[i
] > high
)
2235 high
= GraphBuffer
[i
];
2236 else if (GraphBuffer
[i
] < low
)
2237 low
= GraphBuffer
[i
];
2239 if(c
!= 0 && c
!= 1) {
2240 PrintToScrollback("Invalid argument: %s",str
);
2244 if (GraphBuffer
[0] > 0) {
2245 GraphBuffer
[0] = 1-c
;
2249 for(i
=1;i
<GraphTraceLen
;i
++) {
2250 /* Transitions are detected at each peak
2251 * Transitions are either:
2252 * - we're low: transition if we hit a high
2253 * - we're high: transition if we hit a low
2254 * (we need to do it this way because some tags keep high or
2255 * low for long periods, others just reach the peak and go
2258 if ((GraphBuffer
[i
]==high
) && (GraphBuffer
[i
-1] == c
)) {
2260 } else if ((GraphBuffer
[i
]==low
) && (GraphBuffer
[i
-1] == (1-c
))){
2264 GraphBuffer
[i
] = GraphBuffer
[i
-1];
2267 RepaintGraphWindow();
2270 /* Print our clock rate */
2271 static void Cmddetectclockrate(char *str
)
2273 int clock
= detectclock(0);
2274 PrintToScrollback("Auto-detected clock rate: %d", clock
);
2280 int detectclock(int peak
)
2286 /* Detect peak if we don't have one */
2288 for (i
= 0; i
< GraphTraceLen
; i
++)
2289 if (GraphBuffer
[i
] > peak
)
2290 peak
= GraphBuffer
[i
];
2292 for (i
= 1; i
< GraphTraceLen
; i
++)
2294 /* If this is the beginning of a peak */
2295 if (GraphBuffer
[i
-1] != GraphBuffer
[i
] && GraphBuffer
[i
] == peak
)
2297 /* Find lowest difference between peaks */
2298 if (lastpeak
&& i
- lastpeak
< clock
)
2300 clock
= i
- lastpeak
;
2309 /* Get or auto-detect clock rate */
2310 int GetClock(char *str
, int peak
)
2314 sscanf(str
, "%i", &clock
);
2315 if (!strcmp(str
, ""))
2318 /* Auto-detect clock */
2321 clock
= detectclock(peak
);
2323 /* Only print this message if we're not looping something */
2325 PrintToScrollback("Auto-detected clock rate: %d", clock
);
2332 * Convert to a bitstream
2334 static void Cmdbitstream(char *str
) {
2341 int hithigh
, hitlow
, first
;
2343 /* Detect high and lows and clock */
2344 for (i
= 0; i
< GraphTraceLen
; i
++)
2346 if (GraphBuffer
[i
] > high
)
2347 high
= GraphBuffer
[i
];
2348 else if (GraphBuffer
[i
] < low
)
2349 low
= GraphBuffer
[i
];
2353 clock
= GetClock(str
, high
);
2355 gtl
= CmdClearGraph(0);
2358 for (i
= 0; i
< (int)(gtl
/ clock
); i
++)
2364 /* Find out if we hit both high and low peaks */
2365 for (j
= 0; j
< clock
; j
++)
2367 if (GraphBuffer
[(i
* clock
) + j
] == high
)
2369 else if (GraphBuffer
[(i
* clock
) + j
] == low
)
2372 /* it doesn't count if it's the first part of our read
2373 because it's really just trailing from the last sequence */
2374 if (first
&& (hithigh
|| hitlow
))
2375 hithigh
= hitlow
= 0;
2379 if (hithigh
&& hitlow
)
2383 /* If we didn't hit both high and low peaks, we had a bit transition */
2384 if (!hithigh
|| !hitlow
)
2387 CmdAppendGraph(0, clock
, bit
);
2388 // for (j = 0; j < (int)(clock/2); j++)
2389 // GraphBuffer[(i * clock) + j] = bit ^ 1;
2390 // for (j = (int)(clock/2); j < clock; j++)
2391 // GraphBuffer[(i * clock) + j] = bit;
2394 RepaintGraphWindow();
2397 /* Modulate our data into manchester */
2398 static void Cmdmanchestermod(char *str
)
2402 int bit
, lastbit
, wave
;
2405 clock
= GetClock(str
, 0);
2409 for (i
= 0; i
< (int)(GraphTraceLen
/ clock
); i
++)
2411 bit
= GraphBuffer
[i
* clock
] ^ 1;
2413 for (j
= 0; j
< (int)(clock
/2); j
++)
2414 GraphBuffer
[(i
* clock
) + j
] = bit
^ lastbit
^ wave
;
2415 for (j
= (int)(clock
/2); j
< clock
; j
++)
2416 GraphBuffer
[(i
* clock
) + j
] = bit
^ lastbit
^ wave
^ 1;
2418 /* Keep track of how we start our wave and if we changed or not this time */
2419 wave
^= bit
^ lastbit
;
2423 RepaintGraphWindow();
2427 * Manchester demodulate a bitstream. The bitstream needs to be already in
2428 * the GraphBuffer as 0 and 1 values
2430 * Give the clock rate as argument in order to help the sync - the algorithm
2431 * resyncs at each pulse anyway.
2433 * Not optimized by any means, this is the 1st time I'm writing this type of
2434 * routine, feel free to improve...
2436 * 1st argument: clock rate (as number of samples per clock rate)
2437 * Typical values can be 64, 32, 128...
2439 static void Cmdmanchesterdemod(char *str
) {
2440 int i
, j
, invert
= 0;
2446 int hithigh
, hitlow
, first
;
2452 /* check if we're inverting output */
2455 PrintToScrollback("Inverting output");
2459 while(*str
== ' '); // in case a 2nd argument was given
2462 /* Holds the decoded bitstream: each clock period contains 2 bits */
2463 /* later simplified to 1 bit after manchester decoding. */
2464 /* Add 10 bits to allow for noisy / uncertain traces without aborting */
2465 /* int BitStream[GraphTraceLen*2/clock+10]; */
2467 /* But it does not work if compiling on WIndows: therefore we just allocate a */
2469 int BitStream
[MAX_GRAPH_TRACE_LEN
];
2471 /* Detect high and lows */
2472 for (i
= 0; i
< GraphTraceLen
; i
++)
2474 if (GraphBuffer
[i
] > high
)
2475 high
= GraphBuffer
[i
];
2476 else if (GraphBuffer
[i
] < low
)
2477 low
= GraphBuffer
[i
];
2481 clock
= GetClock(str
, high
);
2483 int tolerance
= clock
/4;
2485 /* Detect first transition */
2486 /* Lo-Hi (arbitrary) */
2487 /* skip to the first high */
2488 for (i
= 0; i
< GraphTraceLen
; i
++)
2489 if(GraphBuffer
[i
] == high
)
2491 /* now look for the first low */
2492 for (; i
< GraphTraceLen
; i
++)
2494 if (GraphBuffer
[i
] == low
)
2501 /* If we're not working with 1/0s, demod based off clock */
2504 bit
= 0; /* We assume the 1st bit is zero, it may not be
2505 * the case: this routine (I think) has an init problem.
2508 for (; i
< (int)(GraphTraceLen
/ clock
); i
++)
2514 /* Find out if we hit both high and low peaks */
2515 for (j
= 0; j
< clock
; j
++)
2517 if (GraphBuffer
[(i
* clock
) + j
] == high
)
2519 else if (GraphBuffer
[(i
* clock
) + j
] == low
)
2522 /* it doesn't count if it's the first part of our read
2523 because it's really just trailing from the last sequence */
2524 if (first
&& (hithigh
|| hitlow
))
2525 hithigh
= hitlow
= 0;
2529 if (hithigh
&& hitlow
)
2533 /* If we didn't hit both high and low peaks, we had a bit transition */
2534 if (!hithigh
|| !hitlow
)
2537 BitStream
[bit2idx
++] = bit
^ invert
;
2541 /* standard 1/0 bitstream */
2545 /* Then detect duration between 2 successive transitions */
2546 for (bitidx
= 1; i
< GraphTraceLen
; i
++)
2548 if (GraphBuffer
[i
-1] != GraphBuffer
[i
])
2553 // Error check: if bitidx becomes too large, we do not
2554 // have a Manchester encoded bitstream or the clock is really
2556 if (bitidx
> (GraphTraceLen
*2/clock
+8) ) {
2557 PrintToScrollback("Error: the clock you gave is probably wrong, aborting.");
2560 // Then switch depending on lc length:
2561 // Tolerance is 1/4 of clock rate (arbitrary)
2562 if (abs(lc
-clock
/2) < tolerance
) {
2563 // Short pulse : either "1" or "0"
2564 BitStream
[bitidx
++]=GraphBuffer
[i
-1];
2565 } else if (abs(lc
-clock
) < tolerance
) {
2566 // Long pulse: either "11" or "00"
2567 BitStream
[bitidx
++]=GraphBuffer
[i
-1];
2568 BitStream
[bitidx
++]=GraphBuffer
[i
-1];
2572 PrintToScrollback("Warning: Manchester decode error for pulse width detection.");
2573 PrintToScrollback("(too many of those messages mean either the stream is not Manchester encoded, or clock is wrong)");
2577 PrintToScrollback("Error: too many detection errors, aborting.");
2584 // At this stage, we now have a bitstream of "01" ("1") or "10" ("0"), parse it into final decoded bitstream
2585 // Actually, we overwrite BitStream with the new decoded bitstream, we just need to be careful
2586 // to stop output at the final bitidx2 value, not bitidx
2587 for (i
= 0; i
< bitidx
; i
+= 2) {
2588 if ((BitStream
[i
] == 0) && (BitStream
[i
+1] == 1)) {
2589 BitStream
[bit2idx
++] = 1 ^ invert
;
2590 } else if ((BitStream
[i
] == 1) && (BitStream
[i
+1] == 0)) {
2591 BitStream
[bit2idx
++] = 0 ^ invert
;
2593 // We cannot end up in this state, this means we are unsynchronized,
2597 PrintToScrollback("Unsynchronized, resync...");
2598 PrintToScrollback("(too many of those messages mean the stream is not Manchester encoded)");
2602 PrintToScrollback("Error: too many decode errors, aborting.");
2609 PrintToScrollback("Manchester decoded bitstream");
2610 // Now output the bitstream to the scrollback by line of 16 bits
2611 for (i
= 0; i
< (bit2idx
-16); i
+=16) {
2612 PrintToScrollback("%i %i %i %i %i %i %i %i %i %i %i %i %i %i %i %i",
2635 static void CmdHiddemod(char *str
)
2637 if(GraphTraceLen
< 4800) {
2638 PrintToScrollback("too short; need at least 4800 samples");
2642 GraphTraceLen
= 4800;
2644 for(i
= 0; i
< GraphTraceLen
; i
++) {
2645 if(GraphBuffer
[i
] < 0) {
2651 RepaintGraphWindow();
2654 static void CmdPlot(char *str
)
2659 static void CmdGrid(char *str
)
2661 sscanf(str
, "%i %i", &PlotGridX
, &PlotGridY
);
2662 RepaintGraphWindow();
2665 static void CmdHide(char *str
)
2670 static void CmdScale(char *str
)
2672 CursorScaleFactor
= atoi(str
);
2673 if(CursorScaleFactor
== 0) {
2674 PrintToScrollback("bad, can't have zero scale");
2675 CursorScaleFactor
= 1;
2677 RepaintGraphWindow();
2680 static void CmdSave(char *str
)
2682 FILE *f
= fopen(str
, "w");
2684 PrintToScrollback("couldn't open '%s'", str
);
2688 for(i
= 0; i
< GraphTraceLen
; i
++) {
2689 fprintf(f
, "%d\n", GraphBuffer
[i
]);
2692 PrintToScrollback("saved to '%s'", str
);
2695 static void CmdLoad(char *str
)
2697 FILE *f
= fopen(str
, "r");
2699 PrintToScrollback("couldn't open '%s'", str
);
2705 while(fgets(line
, sizeof(line
), f
)) {
2706 GraphBuffer
[GraphTraceLen
] = atoi(line
);
2710 PrintToScrollback("loaded %d samples", GraphTraceLen
);
2711 RepaintGraphWindow();
2714 static void CmdHIDsimTAG(char *str
)
2716 unsigned int hi
=0, lo
=0;
2719 while (sscanf(&str
[i
++], "%1x", &n
) == 1) {
2720 hi
=(hi
<<4)|(lo
>>28);
2724 PrintToScrollback("Emulating tag with ID %x%16x", hi
, lo
);
2726 UsbCommand c
={CMD_HID_SIM_TAG
, {hi
, lo
, 0}};
2730 static void CmdReadmem(char *str
)
2732 UsbCommand c
={CMD_READ_MEM
, {strtol(str
, NULL
, 0), 0, 0}};
2736 static void CmdVersion(char *str
)
2738 UsbCommand c
={CMD_VERSION
};
2742 static void CmdLcdReset(char *str
)
2744 UsbCommand c
={CMD_LCD_RESET
, {strtol(str
, NULL
, 0), 0, 0}};
2748 static void CmdLcd(char *str
)
2751 UsbCommand c
={CMD_LCD
};
2752 sscanf(str
, "%x %d", &i
, &j
);
2760 * Sets the divisor for LF frequency clock: lets the user choose any LF frequency below
2763 static void CmdSetDivisor(char *str
)
2765 UsbCommand c
={CMD_SET_LF_DIVISOR
, {strtol(str
, NULL
, 0), 0, 0}};
2766 if (( c
.arg
[0]<0) || (c
.arg
[0]>255)) {
2767 PrintToScrollback("divisor must be between 19 and 255");
2770 PrintToScrollback("Divisor set, expected freq=%dHz", 12000000/(c
.arg
[0]+1));
2774 static void CmdSetMux(char *str
)
2776 UsbCommand c
={CMD_SET_ADC_MUX
};
2777 if(strcmp(str
, "lopkd") == 0) {
2779 } else if(strcmp(str
, "loraw") == 0) {
2781 } else if(strcmp(str
, "hipkd") == 0) {
2783 } else if(strcmp(str
, "hiraw") == 0) {
2789 typedef void HandlerFunction(char *cmdline
);
2791 /* in alphabetic order */
2794 HandlerFunction
*handler
;
2795 int offline
; // 1 if the command can be used when in offline mode
2797 } CommandTable
[] = {
2798 {"amp", CmdAmp
, 1, "Amplify peaks"},
2799 {"askdemod", Cmdaskdemod
, 1, "<0|1> -- Attempt to demodulate simple ASK tags"},
2800 {"autocorr", CmdAutoCorr
, 1, "<window length> -- Autocorrelation over window"},
2801 {"bitsamples", CmdBitsamples
, 0, "Get raw samples as bitstring"},
2802 {"bitstream", Cmdbitstream
, 1, "[clock rate] -- Convert waveform into a bitstream"},
2803 {"buffclear", CmdBuffClear
, 1, "Clear sample buffer and graph window"},
2804 {"dec", CmdDec
, 1, "Decimate samples"},
2805 {"detectclock", Cmddetectclockrate
, 1, "Detect clock rate"},
2806 {"detectreader", CmdDetectReader
, 0, "['l'|'h'] -- Detect external reader field (option 'l' or 'h' to limit to LF or HF)"},
2807 {"em410xsim", CmdEM410xsim
, 1, "<UID> -- Simulate EM410x tag"},
2808 {"em410xread", CmdEM410xread
, 1, "[clock rate] -- Extract ID from EM410x tag"},
2809 {"em410xwatch", CmdEM410xwatch
, 0, "Watches for EM410x tags"},
2810 {"em4x50read", CmdEM4x50read
, 1, "Extract data from EM4x50 tag"},
2811 {"exit", CmdQuit
, 1, "Exit program"},
2812 {"flexdemod", CmdFlexdemod
, 1, "Demodulate samples for FlexPass"},
2813 {"fpgaoff", CmdFPGAOff
, 0, "Set FPGA off"},
2814 {"fskdemod", CmdFSKdemod
, 1, "Demodulate graph window as a HID FSK"},
2815 {"grid", CmdGrid
, 1, "<x> <y> -- overlay grid on graph window, use zero value to turn off either"},
2816 {"hexsamples", CmdHexsamples
, 0, "<blocks> -- Dump big buffer as hex bytes"},
2817 {"hi14alist", CmdHi14alist
, 0, "List ISO 14443a history"},
2818 {"hi14areader", CmdHi14areader
, 0, "Act like an ISO14443 Type A reader"},
2819 {"hi14asim", CmdHi14asim
, 0, "<UID> -- Fake ISO 14443a tag"},
2820 {"hi14asnoop", CmdHi14asnoop
, 0, "Eavesdrop ISO 14443 Type A"},
2821 {"hi14bdemod", CmdHi14bdemod
, 1, "Demodulate ISO14443 Type B from tag"},
2822 {"hi14list", CmdHi14list
, 0, "List ISO 14443 history"},
2823 {"hi14read", CmdHi14read
, 0, "Read HF tag (ISO 14443)"},
2824 {"hi14sim", CmdHi14sim
, 0, "Fake ISO 14443 tag"},
2825 {"hi14snoop", CmdHi14snoop
, 0, "Eavesdrop ISO 14443"},
2826 {"hi15demod", CmdHi15demod
, 1, "Demodulate ISO15693 from tag"},
2827 {"hi15read", CmdHi15read
, 0, "Read HF tag (ISO 15693)"},
2828 {"hi15reader", CmdHi15reader
, 0, "Act like an ISO15693 reader"},
2829 {"hi15sim", CmdHi15tag
, 0, "Fake an ISO15693 tag"},
2830 {"hiddemod", CmdHiddemod
, 1, "Demodulate HID Prox Card II (not optimal)"},
2831 {"hide", CmdHide
, 1, "Hide graph window"},
2832 {"hidfskdemod", CmdHIDdemodFSK
, 0, "Realtime HID FSK demodulator"},
2833 {"hidsimtag", CmdHIDsimTAG
, 0, "<ID> -- HID tag simulator"},
2834 {"higet", CmdHi14read_sim
, 0, "<samples> -- Get samples HF, 'analog'"},
2835 {"hisamples", CmdHisamples
, 0, "Get raw samples for HF tag"},
2836 {"hisampless", CmdHisampless
, 0, "<samples> -- Get signed raw samples, HF tag"},
2837 {"hisamplest", CmdHi14readt
, 0, "Get samples HF, for testing"},
2838 {"hisimlisten", CmdHisimlisten
, 0, "Get HF samples as fake tag"},
2839 {"hpf", CmdHpf
, 1, "Remove DC offset from trace"},
2840 {"indalademod", CmdIndalademod
, 0, "['224'] -- Demodulate samples for Indala 64 bit UID (option '224' for 224 bit)"},
2841 {"lcd", CmdLcd
, 0, "<HEX command> <count> -- Send command/data to LCD"},
2842 {"lcdreset", CmdLcdReset
, 0, "Hardware reset LCD"},
2843 {"legicrfread", CmdLegicRfRead
, 0, "Start the LEGIC RF reader"},
2844 {"load", CmdLoad
, 1, "<filename> -- Load trace (to graph window"},
2845 {"locomread", CmdLoCommandRead
, 0, "<off period> <'0' period> <'1' period> <command> ['h'] -- Modulate LF reader field to send command before read (all periods in microseconds) (option 'h' for 134)"},
2846 {"loread", CmdLoread
, 0, "['h'] -- Read 125/134 kHz LF ID-only tag (option 'h' for 134)"},
2847 {"losamples", CmdLosamples
, 0, "[128 - 16000] -- Get raw samples for LF tag"},
2848 {"losim", CmdLosim
, 0, "Simulate LF tag"},
2849 {"losimbidir", CmdLosimBidir
, 0, "Simulate LF tag (with bidirectional data transmission between reader and tag)"},
2850 {"ltrim", CmdLtrim
, 1, "<samples> -- Trim samples from left of trace"},
2851 {"mandemod", Cmdmanchesterdemod
, 1, "[i] [clock rate] -- Manchester demodulate binary stream (option 'i' to invert output)"},
2852 {"manmod", Cmdmanchestermod
, 1, "[clock rate] -- Manchester modulate a binary stream"},
2853 {"norm", CmdNorm
, 1, "Normalize max/min to +/-500"},
2854 {"plot", CmdPlot
, 1, "Show graph window"},
2855 {"quit", CmdQuit
, 1, "Quit program"},
2856 {"readmem", CmdReadmem
, 0, "[address] -- Read memory at decimal address from flash"},
2857 {"reset", CmdReset
, 0, "Reset the Proxmark3"},
2858 {"save", CmdSave
, 1, "<filename> -- Save trace (from graph window)"},
2859 {"scale", CmdScale
, 1, "<int> -- Set cursor display scale"},
2860 {"setlfdivisor", CmdSetDivisor
, 0, "<19 - 255> -- Drive LF antenna at 12Mhz/(divisor+1)"},
2861 {"setmux", CmdSetMux
, 0, "<loraw|hiraw|lopkd|hipkd> -- Set the ADC mux to a specific value"},
2862 {"sri512read", CmdSri512read
, 0, "<int> -- Read contents of a SRI512 tag"},
2863 {"srix4kread", CmdSrix4kread
, 0, "<int> -- Read contents of a SRIX4K tag"},
2864 {"tidemod", CmdTIDemod
, 1, "Demodulate raw bits for TI-type LF tag"},
2865 {"tiread", CmdTIRead
, 0, "Read and decode a TI 134 kHz tag"},
2866 {"tiwrite", CmdTIWrite
, 0, "Write new data to a r/w TI 134 kHz tag"},
2867 {"threshold", CmdThreshold
, 1, "Maximize/minimize every value in the graph window depending on threshold"},
2868 {"tune", CmdTune
, 0, "Measure antenna tuning"},
2869 {"vchdemod", CmdVchdemod
, 0, "['clone'] -- Demodulate samples for VeriChip"},
2870 {"version", CmdVersion
, 0, "Show version inforation about the connected Proxmark"},
2871 {"zerocrossings", CmdZerocrossings
, 1, "Count time between zero-crossings"},
2879 } CommandExtendedHelp
[]= {
2880 {"detectreader","'l'|'h'","'l' specifies LF antenna scan only, 'h' specifies HF antenna scan only.","Monitor antenna for changes in voltage. Output is in three fields: CHANGED, CURRENT, PERIOD,\nwhere CHANGED is the value just changed from, CURRENT is the current value and PERIOD is the\nnumber of program loops since the last change.\n\nThe RED LED indicates LF field detected, and the GREEN LED indicates HF field detected."},
2881 {"tune","","","Drive LF antenna at all divisor range values (19 - 255) and store the results in the output\nbuffer. Issuing 'losamples' and then 'plot' commands will display the resulting peak. 12MHz\ndivided by the peak's position plus one gives the antenna's resonant frequency. For convenience,\nthis value is also printed out by the command."},
2884 //-----------------------------------------------------------------------------
2885 // Entry point into our code: called whenever the user types a command and
2886 // then presses Enter, which the full command line that they typed.
2887 //-----------------------------------------------------------------------------
2888 void CommandReceived(char *cmd
)
2893 PrintToScrollback("> %s", cmd
);
2895 if(strcmp(cmd
, "help") == 0 || strncmp(cmd
,"help ",strlen("help ")) == 0) {
2896 // check if we're doing extended help
2897 if(strlen(cmd
) > strlen("help ")) {
2898 cmd
+= strlen("help ");
2899 for(i
= 0; i
< sizeof(CommandExtendedHelp
) / sizeof(CommandExtendedHelp
[0]); i
++) {
2900 if(strcmp(CommandExtendedHelp
[i
].name
,cmd
) == 0) {
2901 PrintToScrollback("\nExtended help for '%s':\n", cmd
);
2902 PrintToScrollback("Args: %s\t- %s\n",CommandExtendedHelp
[i
].args
,CommandExtendedHelp
[i
].argshelp
);
2903 PrintToScrollback(CommandExtendedHelp
[i
].description
);
2904 PrintToScrollback("");
2908 PrintToScrollback("No extended help available for '%s'", cmd
);
2911 if (offline
) PrintToScrollback("Operating in OFFLINE mode (no device connected)");
2912 PrintToScrollback("\r\nAvailable commands:");
2913 for(i
= 0; i
< sizeof(CommandTable
) / sizeof(CommandTable
[0]); i
++) {
2914 if (offline
&& (CommandTable
[i
].offline
==0)) continue;
2915 memset(line
, ' ', sizeof(line
));
2916 strcpy(line
+2, CommandTable
[i
].name
);
2917 line
[strlen(line
)] = ' ';
2918 sprintf(line
+15, " -- %s", CommandTable
[i
].docString
);
2919 PrintToScrollback("%s", line
);
2921 PrintToScrollback("");
2922 PrintToScrollback("'help <command>' for extended help on that command\n");
2926 for(i
= 0; i
< sizeof(CommandTable
) / sizeof(CommandTable
[0]); i
++) {
2927 char *name
= CommandTable
[i
].name
;
2928 if(memcmp(cmd
, name
, strlen(name
))==0 &&
2929 (cmd
[strlen(name
)] == ' ' || cmd
[strlen(name
)] == '\0'))
2931 cmd
+= strlen(name
);
2932 while(*cmd
== ' ') {
2935 if (offline
&& (CommandTable
[i
].offline
==0)) {
2936 PrintToScrollback("Offline mode, cannot use this command.");
2939 (CommandTable
[i
].handler
)(cmd
);
2943 PrintToScrollback(">> bad command '%s'", cmd
);
2946 //-----------------------------------------------------------------------------
2947 // Entry point into our code: called whenever we received a packet over USB
2948 // that we weren't necessarily expecting, for example a debug print.
2949 //-----------------------------------------------------------------------------
2950 void UsbCommandReceived(UsbCommand
*c
)
2952 // printf("%s(%x) current cmd = %x\n", __FUNCTION__, c->cmd, current_command);
2953 /* If we recognize a response, return to avoid further processing */
2955 case CMD_DEBUG_PRINT_STRING
: {
2957 if(c
->arg
[0] > 70 || c
->arg
[0] < 0) {
2960 memcpy(s
, c
->d
.asBytes
, c
->arg
[0]);
2961 s
[c
->arg
[0]] = '\0';
2962 PrintToScrollback("#db# %s", s
);
2966 case CMD_DEBUG_PRINT_INTEGERS
:
2967 PrintToScrollback("#db# %08x, %08x, %08x\r\n", c
->arg
[0], c
->arg
[1], c
->arg
[2]);
2970 case CMD_MEASURED_ANTENNA_TUNING
: {
2972 int vLf125
, vLf134
, vHf
;
2973 vLf125
= c
->arg
[0] & 0xffff;
2974 vLf134
= c
->arg
[0] >> 16;
2975 vHf
= c
->arg
[1] & 0xffff;;
2976 peakf
= c
->arg
[2] & 0xffff;
2977 peakv
= c
->arg
[2] >> 16;
2978 PrintToScrollback("");
2979 PrintToScrollback("");
2980 PrintToScrollback("# LF antenna: %5.2f V @ 125.00 kHz", vLf125
/1000.0);
2981 PrintToScrollback("# LF antenna: %5.2f V @ 134.00 kHz", vLf134
/1000.0);
2982 PrintToScrollback("# LF optimal: %5.2f V @%9.2f kHz", peakv
/1000.0, 12000.0/(peakf
+1));
2983 PrintToScrollback("# HF antenna: %5.2f V @ 13.56 MHz", vHf
/1000.0);
2985 PrintToScrollback("# Your LF antenna is unusable.");
2986 else if (peakv
<10000)
2987 PrintToScrollback("# Your LF antenna is marginal.");
2989 PrintToScrollback("# Your HF antenna is unusable.");
2991 PrintToScrollback("# Your HF antenna is marginal.");
2997 /* Maybe it's a response: */
2998 switch(current_command
) {
2999 case CMD_DOWNLOAD_RAW_ADC_SAMPLES_125K
:
3000 if (c
->cmd
!= CMD_DOWNLOADED_RAW_ADC_SAMPLES_125K
) goto unexpected_response
;
3002 for(i
=0; i
<48; i
++) sample_buf
[i
] = c
->d
.asBytes
[i
];
3003 received_command
= c
->cmd
;
3006 unexpected_response
:
3007 PrintToScrollback("unrecognized command %08x\n", c
->cmd
);