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"
15 #include "../common/crc16.c"
17 #define arraylen(x) (sizeof(x)/sizeof((x)[0]))
18 #define BIT(x) GraphBuffer[x * clock]
19 #define BITS (GraphTraceLen / clock)
22 static int CmdHisamplest(char *str
, int nrlow
);
24 static void GetFromBigBuf(BYTE
*dest
, int bytes
)
29 PrintToScrollback("bad len in GetFromBigBuf");
34 for(i
= 0; i
< n
; i
+= 12) {
36 c
.cmd
= CMD_DOWNLOAD_RAW_ADC_SAMPLES_125K
;
38 SendCommand(&c
, FALSE
);
40 if(c
.cmd
!= CMD_DOWNLOADED_RAW_ADC_SAMPLES_125K
) {
41 PrintToScrollback("bad resp");
45 memcpy(dest
+(i
*4), c
.d
.asBytes
, 48);
49 static void CmdReset(char *str
)
52 c
.cmd
= CMD_HARDWARE_RESET
;
53 SendCommand(&c
, FALSE
);
56 static void CmdBuffClear(char *str
)
59 c
.cmd
= CMD_BUFF_CLEAR
;
60 SendCommand(&c
, FALSE
);
64 static void CmdQuit(char *str
)
69 static void CmdHIDdemodFSK(char *str
)
72 c
.cmd
= CMD_HID_DEMOD_FSK
;
73 SendCommand(&c
, FALSE
);
76 static void CmdTune(char *str
)
79 c
.cmd
= CMD_MEASURE_ANTENNA_TUNING
;
80 SendCommand(&c
, FALSE
);
83 static void CmdHi15read(char *str
)
86 c
.cmd
= CMD_ACQUIRE_RAW_ADC_SAMPLES_ISO_15693
;
87 SendCommand(&c
, FALSE
);
90 static void CmdHi14read(char *str
)
93 c
.cmd
= CMD_ACQUIRE_RAW_ADC_SAMPLES_ISO_14443
;
95 SendCommand(&c
, FALSE
);
99 /* New command to read the contents of a SRI512 tag
100 * SRI512 tags are ISO14443-B modulated memory tags,
101 * this command just dumps the contents of the memory/
103 static void CmdSri512read(char *str
)
106 c
.cmd
= CMD_READ_SRI512_TAG
;
108 SendCommand(&c
, FALSE
);
112 static void CmdHi14areader(char *str
)
115 c
.cmd
= CMD_READER_ISO_14443a
;
117 SendCommand(&c
, FALSE
);
121 static void CmdHi15reader(char *str
)
124 c
.cmd
= CMD_READER_ISO_15693
;
126 SendCommand(&c
, FALSE
);
130 static void CmdHi15tag(char *str
)
133 c
.cmd
= CMD_SIMTAG_ISO_15693
;
135 SendCommand(&c
, FALSE
);
138 static void CmdHi14read_sim(char *str
)
141 c
.cmd
= CMD_ACQUIRE_RAW_ADC_SAMPLES_ISO_14443_SIM
;
143 SendCommand(&c
, FALSE
);
146 static void CmdHi14readt(char *str
)
149 c
.cmd
= CMD_ACQUIRE_RAW_ADC_SAMPLES_ISO_14443
;
151 SendCommand(&c
, FALSE
);
153 //CmdHisamplest(str);
154 while(CmdHisamplest(str
,atoi(str
))==0) {
155 c
.cmd
= CMD_ACQUIRE_RAW_ADC_SAMPLES_ISO_14443
;
157 SendCommand(&c
, FALSE
);
159 RepaintGraphWindow();
162 static void CmdHisimlisten(char *str
)
165 c
.cmd
= CMD_SIMULATE_TAG_HF_LISTEN
;
166 SendCommand(&c
, FALSE
);
169 static void CmdHi14sim(char *str
)
172 c
.cmd
= CMD_SIMULATE_TAG_ISO_14443
;
173 SendCommand(&c
, FALSE
);
176 static void CmdHi14asim(char *str
) // ## simulate iso14443a tag
177 { // ## greg - added ability to specify tag UID
179 unsigned int hi
=0, lo
=0;
183 while (sscanf(&str
[i
++], "%1x", &n
) == 1) {
188 c
.cmd
= CMD_SIMULATE_TAG_ISO_14443a
;
189 // c.ext should be set to *str or convert *str to the correct format for a uid
192 PrintToScrollback("Emulating 14443A TAG with UID %x%16x", hi
, lo
);
193 SendCommand(&c
, FALSE
);
196 static void CmdHi14snoop(char *str
)
199 c
.cmd
= CMD_SNOOP_ISO_14443
;
200 SendCommand(&c
, FALSE
);
203 static void CmdHi14asnoop(char *str
)
206 c
.cmd
= CMD_SNOOP_ISO_14443a
;
207 SendCommand(&c
, FALSE
);
210 static void CmdFPGAOff(char *str
) // ## FPGA Control
213 c
.cmd
= CMD_FPGA_MAJOR_MODE_OFF
;
214 SendCommand(&c
, FALSE
);
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) {
652 for(j
= 0; j
< 48; j
++) {
653 c
.d
.asBytes
[j
] = GraphBuffer
[i
+j
];
655 c
.cmd
= CMD_DOWNLOADED_SIM_SAMPLES_125K
;
657 SendCommand(&c
, FALSE
);
661 c
.cmd
= CMD_SIMULATE_TAG_125K
;
662 c
.ext1
= GraphTraceLen
;
663 SendCommand(&c
, FALSE
);
666 static void CmdLoread(char *str
)
669 // 'h' means higher-low-frequency, 134 kHz
672 } else if (*str
== '\0') {
675 PrintToScrollback("use 'loread' or 'loread h'");
678 c
.cmd
= CMD_ACQUIRE_RAW_ADC_SAMPLES_125K
;
679 SendCommand(&c
, FALSE
);
682 static void CmdDetectReader(char *str
)
685 // 'l' means LF - 125/134 kHz
688 } else if (*str
== 'h') {
690 } else if (*str
!= '\0') {
691 PrintToScrollback("use 'detectreader' or 'detectreader l' or 'detectreader h'");
694 c
.cmd
= CMD_LISTEN_READER_FIELD
;
695 SendCommand(&c
, FALSE
);
698 /* send a command before reading */
699 static void CmdLoCommandRead(char *str
)
701 static char dummy
[3];
706 c
.cmd
= CMD_MOD_THEN_ACQUIRE_RAW_ADC_SAMPLES_125K
;
707 sscanf(str
, "%i %i %i %s %s", &c
.ext1
, &c
.ext2
, &c
.ext3
, (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
);
710 SendCommand(&c
, FALSE
);
713 static void CmdLosamples(char *str
)
721 if (n
>16000) n
=16000;
723 for(i
= 0; i
< n
; i
+= 12) {
725 c
.cmd
= CMD_DOWNLOAD_RAW_ADC_SAMPLES_125K
;
727 SendCommand(&c
, FALSE
);
729 if(c
.cmd
!= CMD_DOWNLOADED_RAW_ADC_SAMPLES_125K
) {
731 PrintToScrollback("bad resp");
735 for(j
= 0; j
< 48; j
++) {
736 GraphBuffer
[cnt
++] = ((int)c
.d
.asBytes
[j
]) - 128;
740 RepaintGraphWindow();
743 static void CmdBitsamples(char *str
)
750 for(i
= 0; i
< n
; i
+= 12) {
752 c
.cmd
= CMD_DOWNLOAD_RAW_ADC_SAMPLES_125K
;
754 SendCommand(&c
, FALSE
);
756 if(c
.cmd
!= CMD_DOWNLOADED_RAW_ADC_SAMPLES_125K
) {
757 PrintToScrollback("bad resp");
761 for(j
= 0; j
< 48; j
++) {
762 for(k
= 0; k
< 8; k
++) {
763 if(c
.d
.asBytes
[j
] & (1 << (7 - k
))) {
764 GraphBuffer
[cnt
++] = 1;
766 GraphBuffer
[cnt
++] = 0;
772 RepaintGraphWindow();
775 static void CmdHisamples(char *str
)
781 for(i
= 0; i
< n
; i
+= 12) {
783 c
.cmd
= CMD_DOWNLOAD_RAW_ADC_SAMPLES_125K
;
785 SendCommand(&c
, FALSE
);
787 if(c
.cmd
!= CMD_DOWNLOADED_RAW_ADC_SAMPLES_125K
) {
788 PrintToScrollback("bad resp");
792 for(j
= 0; j
< 48; j
++) {
793 GraphBuffer
[cnt
++] = (int)((BYTE
)c
.d
.asBytes
[j
]);
798 RepaintGraphWindow();
801 static int CmdHisamplest(char *str
, int nrlow
)
813 for(i
= 0; i
< n
; i
+= 12) {
815 c
.cmd
= CMD_DOWNLOAD_RAW_ADC_SAMPLES_125K
;
817 SendCommand(&c
, FALSE
);
819 if(c
.cmd
!= CMD_DOWNLOADED_RAW_ADC_SAMPLES_125K
) {
820 PrintToScrollback("bad resp");
824 for(j
= 0; j
< 48; j
++) {
825 t2
= (int)((BYTE
)c
.d
.asBytes
[j
]);
826 if((t2
^ 0xC0) & 0xC0) { hasbeennull
++; }
832 t1
= (t2
& 0x80) ^ (t2
& 0x20);
833 t2
= ((t2
<< 1) & 0x80) ^ ((t2
<< 1) & 0x20);
839 t2
= ((t2
<< 1) & 0x80);
845 t2
= ((t2
<< 1) & 0x20);
849 // both, but tag with other algorithm
850 t1
= (t2
& 0x80) ^ (t2
& 0x08);
851 t2
= ((t2
<< 1) & 0x80) ^ ((t2
<< 1) & 0x08);
855 GraphBuffer
[cnt
++] = t1
;
856 GraphBuffer
[cnt
++] = t2
;
861 if(hasbeennull
>nrlow
|| nrlow
==0) {
862 PrintToScrollback("hasbeennull=%d", hasbeennull
);
871 static void CmdHexsamples(char *str
)
882 for(i
= 0; i
< n
; i
+= 12) {
884 c
.cmd
= CMD_DOWNLOAD_RAW_ADC_SAMPLES_125K
;
886 SendCommand(&c
, FALSE
);
888 if(c
.cmd
!= CMD_DOWNLOADED_RAW_ADC_SAMPLES_125K
) {
889 PrintToScrollback("bad resp");
893 for(j
= 0; j
< 48; j
+= 8) {
894 PrintToScrollback("%02x %02x %02x %02x %02x %02x %02x %02x",
909 static void CmdHisampless(char *str
)
921 for(i
= 0; i
< n
; i
+= 12) {
923 c
.cmd
= CMD_DOWNLOAD_RAW_ADC_SAMPLES_125K
;
925 SendCommand(&c
, FALSE
);
927 if(c
.cmd
!= CMD_DOWNLOADED_RAW_ADC_SAMPLES_125K
) {
928 PrintToScrollback("bad resp");
932 for(j
= 0; j
< 48; j
++) {
933 GraphBuffer
[cnt
++] = (int)((signed char)c
.d
.asBytes
[j
]);
938 RepaintGraphWindow();
941 static WORD
Iso15693Crc(BYTE
*v
, int n
)
947 for(i
= 0; i
< n
; i
++) {
948 reg
= reg
^ ((DWORD
)v
[i
]);
949 for (j
= 0; j
< 8; j
++) {
951 reg
= (reg
>> 1) ^ 0x8408;
961 static void CmdHi14bdemod(char *str
)
966 BOOL negateI
, negateQ
;
971 // As received, the samples are pairs, correlations against I and Q
972 // square waves. So estimate angle of initial carrier (or just
973 // quadrant, actually), and then do the demod.
975 // First, estimate where the tag starts modulating.
976 for(i
= 0; i
< GraphTraceLen
; i
+= 2) {
977 if(abs(GraphBuffer
[i
]) + abs(GraphBuffer
[i
+1]) > 40) {
981 if(i
>= GraphTraceLen
) {
982 PrintToScrollback("too weak to sync");
985 PrintToScrollback("out of weak at %d", i
);
988 // Now, estimate the phase in the initial modulation of the tag
991 for(; i
< (outOfWeakAt
+ 16); i
+= 2) {
992 isum
+= GraphBuffer
[i
+0];
993 qsum
+= GraphBuffer
[i
+1];
995 negateI
= (isum
< 0);
996 negateQ
= (qsum
< 0);
998 // Turn the correlation pairs into soft decisions on the bit.
1000 for(i
= 0; i
< GraphTraceLen
/2; i
++) {
1001 int si
= GraphBuffer
[j
];
1002 int sq
= GraphBuffer
[j
+1];
1003 if(negateI
) si
= -si
;
1004 if(negateQ
) sq
= -sq
;
1005 GraphBuffer
[i
] = si
+ sq
;
1011 while(GraphBuffer
[i
] > 0 && i
< GraphTraceLen
)
1013 if(i
>= GraphTraceLen
) goto demodError
;
1016 while(GraphBuffer
[i
] < 0 && i
< GraphTraceLen
)
1018 if(i
>= GraphTraceLen
) goto demodError
;
1019 if((i
- iold
) > 23) goto demodError
;
1021 PrintToScrollback("make it to demod loop");
1025 while(GraphBuffer
[i
] >= 0 && i
< GraphTraceLen
)
1027 if(i
>= GraphTraceLen
) goto demodError
;
1028 if((i
- iold
) > 6) goto demodError
;
1031 if(i
+ 20 >= GraphTraceLen
) goto demodError
;
1033 for(j
= 0; j
< 10; j
++) {
1034 int soft
= GraphBuffer
[i
] + GraphBuffer
[i
+1];
1036 if(abs(soft
) < ((abs(isum
) + abs(qsum
))/20)) {
1037 PrintToScrollback("weak bit");
1041 if(GraphBuffer
[i
] + GraphBuffer
[i
+1] >= 0) {
1048 if( (shiftReg
& 0x200) &&
1049 !(shiftReg
& 0x001))
1051 // valid data byte, start and stop bits okay
1052 PrintToScrollback(" %02x", (shiftReg
>> 1) & 0xff);
1053 data
[dataLen
++] = (shiftReg
>> 1) & 0xff;
1054 if(dataLen
>= sizeof(data
)) {
1057 } else if(shiftReg
== 0x000) {
1066 ComputeCrc14443(CRC_14443_B
, data
, dataLen
-2, &first
, &second
);
1067 PrintToScrollback("CRC: %02x %02x (%s)\n", first
, second
,
1068 (first
== data
[dataLen
-2] && second
== data
[dataLen
-1]) ?
1069 "ok" : "****FAIL****");
1071 RepaintGraphWindow();
1075 PrintToScrollback("demod error");
1076 RepaintGraphWindow();
1079 static void CmdHi14list(char *str
)
1082 GetFromBigBuf(got
, sizeof(got
));
1084 PrintToScrollback("recorded activity:");
1085 PrintToScrollback(" time :rssi: who bytes");
1086 PrintToScrollback("---------+----+----+-----------");
1097 int timestamp
= *((DWORD
*)(got
+i
));
1098 if(timestamp
& 0x80000000) {
1099 timestamp
&= 0x7fffffff;
1104 int metric
= *((DWORD
*)(got
+i
+4));
1111 if(i
+ len
>= 900) {
1115 BYTE
*frame
= (got
+i
+9);
1117 char line
[1000] = "";
1119 for(j
= 0; j
< len
; j
++) {
1120 sprintf(line
+(j
*3), "%02x ", frame
[j
]);
1126 ComputeCrc14443(CRC_14443_B
, frame
, len
-2, &b1
, &b2
);
1127 if(b1
!= frame
[len
-2] || b2
!= frame
[len
-1]) {
1128 crc
= "**FAIL CRC**";
1136 char metricString
[100];
1138 sprintf(metricString
, "%3d", metric
);
1140 strcpy(metricString
, " ");
1143 PrintToScrollback(" +%7d: %s: %s %s %s",
1144 (prev
< 0 ? 0 : timestamp
- prev
),
1146 (isResponse
? "TAG" : " "), line
, crc
);
1153 static void CmdHi14alist(char *str
)
1156 GetFromBigBuf(got
, sizeof(got
));
1158 PrintToScrollback("recorded activity:");
1159 PrintToScrollback(" ETU :rssi: who bytes");
1160 PrintToScrollback("---------+----+----+-----------");
1171 int timestamp
= *((DWORD
*)(got
+i
));
1172 if(timestamp
& 0x80000000) {
1173 timestamp
&= 0x7fffffff;
1180 int parityBits
= *((DWORD
*)(got
+i
+4));
1181 // 4 bytes of additional information...
1182 // maximum of 32 additional parity bit information
1185 // at each quarter bit period we can send power level (16 levels)
1186 // or each half bit period in 256 levels.
1194 if(i
+ len
>= 1900) {
1198 BYTE
*frame
= (got
+i
+9);
1200 // Break and stick with current result if buffer was not completely full
1201 if(frame
[0] == 0x44 && frame
[1] == 0x44 && frame
[3] == 0x44) { break; }
1203 char line
[1000] = "";
1205 for(j
= 0; j
< len
; j
++) {
1206 int oddparity
= 0x01;
1210 oddparity
^= (((frame
[j
] & 0xFF) >> k
) & 0x01);
1213 //if((parityBits >> (len - j - 1)) & 0x01) {
1214 if(isResponse
&& (oddparity
!= ((parityBits
>> (len
- j
- 1)) & 0x01))) {
1215 sprintf(line
+(j
*4), "%02x! ", frame
[j
]);
1218 sprintf(line
+(j
*4), "%02x ", frame
[j
]);
1226 for(j
= 0; j
< (len
- 1); j
++) {
1227 // gives problems... search for the reason..
1228 /*if(frame[j] == 0xAA) {
1229 switch(frame[j+1]) {
1231 crc = "[1] Two drops close after each other";
1234 crc = "[2] Potential SOC with a drop in second half of bitperiod";
1237 crc = "[3] Segment Z after segment X is not possible";
1240 crc = "[4] Parity bit of a fully received byte was wrong";
1243 crc = "[?] Unknown error";
1250 if(strlen(crc
)==0) {
1251 ComputeCrc14443(CRC_14443_A
, frame
, len
-2, &b1
, &b2
);
1252 if(b1
!= frame
[len
-2] || b2
!= frame
[len
-1]) {
1253 crc
= (isResponse
& (len
< 6)) ? "" : " !crc";
1262 char metricString
[100];
1264 sprintf(metricString
, "%3d", metric
);
1266 strcpy(metricString
, " ");
1269 PrintToScrollback(" +%7d: %s: %s %s %s",
1270 (prev
< 0 ? 0 : (timestamp
- prev
)),
1272 (isResponse
? "TAG" : " "), line
, crc
);
1277 CommandFinished
= 1;
1280 static void CmdHi15demod(char *str
)
1282 // The sampling rate is 106.353 ksps/s, for T = 18.8 us
1285 // 1) Unmodulated time of 56.64us
1286 // 2) 24 pulses of 423.75khz
1287 // 3) logic '1' (unmodulated for 18.88us followed by 8 pulses of 423.75khz)
1289 static const int FrameSOF
[] = {
1290 -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
1291 -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
1292 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
1293 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
1299 static const int Logic0
[] = {
1305 static const int Logic1
[] = {
1313 // 1) logic '0' (8 pulses of 423.75khz followed by unmodulated for 18.88us)
1314 // 2) 24 pulses of 423.75khz
1315 // 3) Unmodulated time of 56.64us
1317 static const int FrameEOF
[] = {
1322 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
1323 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
1324 -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
1325 -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1
1329 int max
= 0, maxPos
;
1333 if(GraphTraceLen
< 1000) return;
1335 // First, correlate for SOF
1336 for(i
= 0; i
< 100; i
++) {
1338 for(j
= 0; j
< arraylen(FrameSOF
); j
+= skip
) {
1339 corr
+= FrameSOF
[j
]*GraphBuffer
[i
+(j
/skip
)];
1346 PrintToScrollback("SOF at %d, correlation %d", maxPos
,
1347 max
/(arraylen(FrameSOF
)/skip
));
1349 i
= maxPos
+ arraylen(FrameSOF
)/skip
;
1352 memset(outBuf
, 0, sizeof(outBuf
));
1355 int corr0
= 0, corr1
= 0, corrEOF
= 0;
1356 for(j
= 0; j
< arraylen(Logic0
); j
+= skip
) {
1357 corr0
+= Logic0
[j
]*GraphBuffer
[i
+(j
/skip
)];
1359 for(j
= 0; j
< arraylen(Logic1
); j
+= skip
) {
1360 corr1
+= Logic1
[j
]*GraphBuffer
[i
+(j
/skip
)];
1362 for(j
= 0; j
< arraylen(FrameEOF
); j
+= skip
) {
1363 corrEOF
+= FrameEOF
[j
]*GraphBuffer
[i
+(j
/skip
)];
1365 // Even things out by the length of the target waveform.
1369 if(corrEOF
> corr1
&& corrEOF
> corr0
) {
1370 PrintToScrollback("EOF at %d", i
);
1372 } else if(corr1
> corr0
) {
1373 i
+= arraylen(Logic1
)/skip
;
1376 i
+= arraylen(Logic0
)/skip
;
1383 if((i
+(int)arraylen(FrameEOF
)) >= GraphTraceLen
) {
1384 PrintToScrollback("ran off end!");
1389 PrintToScrollback("error, uneven octet! (discard extra bits!)");
1390 PrintToScrollback(" mask=%02x", mask
);
1392 PrintToScrollback("%d octets", k
);
1394 for(i
= 0; i
< k
; i
++) {
1395 PrintToScrollback("# %2d: %02x ", i
, outBuf
[i
]);
1397 PrintToScrollback("CRC=%04x", Iso15693Crc(outBuf
, k
-2));
1400 static void CmdFSKdemod(char *cmdline
)
1402 static const int LowTone
[] = {
1403 1, 1, 1, 1, 1, -1, -1, -1, -1, -1,
1404 1, 1, 1, 1, 1, -1, -1, -1, -1, -1,
1405 1, 1, 1, 1, 1, -1, -1, -1, -1, -1,
1406 1, 1, 1, 1, 1, -1, -1, -1, -1, -1,
1407 1, 1, 1, 1, 1, -1, -1, -1, -1, -1
1409 static const int HighTone
[] = {
1410 1, 1, 1, 1, 1, -1, -1, -1, -1,
1411 1, 1, 1, 1, -1, -1, -1, -1,
1412 1, 1, 1, 1, -1, -1, -1, -1,
1413 1, 1, 1, 1, -1, -1, -1, -1,
1414 1, 1, 1, 1, -1, -1, -1, -1,
1415 1, 1, 1, 1, -1, -1, -1, -1, -1,
1418 int lowLen
= sizeof(LowTone
)/sizeof(int);
1419 int highLen
= sizeof(HighTone
)/sizeof(int);
1420 int convLen
= (highLen
>lowLen
)?highLen
:lowLen
;
1421 DWORD hi
= 0, lo
= 0;
1424 int minMark
=0, maxMark
=0;
1426 for(i
= 0; i
< GraphTraceLen
- convLen
; i
++) {
1427 int lowSum
= 0, highSum
= 0;
1429 for(j
= 0; j
< lowLen
; j
++) {
1430 lowSum
+= LowTone
[j
]*GraphBuffer
[i
+j
];
1432 for(j
= 0; j
< highLen
; j
++) {
1433 highSum
+= HighTone
[j
]*GraphBuffer
[i
+j
];
1435 lowSum
= abs((100*lowSum
) / lowLen
);
1436 highSum
= abs((100*highSum
) / highLen
);
1437 GraphBuffer
[i
] = (highSum
<< 16) | lowSum
;
1440 for(i
= 0; i
< GraphTraceLen
- convLen
- 16; i
++) {
1442 int lowTot
= 0, highTot
= 0;
1443 // 10 and 8 are f_s divided by f_l and f_h, rounded
1444 for(j
= 0; j
< 10; j
++) {
1445 lowTot
+= (GraphBuffer
[i
+j
] & 0xffff);
1447 for(j
= 0; j
< 8; j
++) {
1448 highTot
+= (GraphBuffer
[i
+j
] >> 16);
1450 GraphBuffer
[i
] = lowTot
- highTot
;
1451 if (GraphBuffer
[i
]>maxMark
) maxMark
=GraphBuffer
[i
];
1452 if (GraphBuffer
[i
]<minMark
) minMark
=GraphBuffer
[i
];
1455 GraphTraceLen
-= (convLen
+ 16);
1457 RepaintGraphWindow();
1459 // Find bit-sync (3 lo followed by 3 high)
1460 int max
= 0, maxPos
= 0;
1461 for(i
= 0; i
< 6000; i
++) {
1463 for(j
= 0; j
< 3*lowLen
; j
++) {
1464 dec
-= GraphBuffer
[i
+j
];
1466 for(; j
< 3*(lowLen
+ highLen
); j
++) {
1467 dec
+= GraphBuffer
[i
+j
];
1475 // place start of bit sync marker in graph
1476 GraphBuffer
[maxPos
] = maxMark
;
1477 GraphBuffer
[maxPos
+1] = minMark
;
1481 // place end of bit sync marker in graph
1482 GraphBuffer
[maxPos
] = maxMark
;
1483 GraphBuffer
[maxPos
+1] = minMark
;
1485 PrintToScrollback("actual data bits start at sample %d", maxPos
);
1486 PrintToScrollback("length %d/%d", highLen
, lowLen
);
1489 bits
[sizeof(bits
)-1] = '\0';
1491 // find bit pairs and manchester decode them
1492 for(i
= 0; i
< arraylen(bits
)-1; i
++) {
1494 for(j
= 0; j
< lowLen
; j
++) {
1495 dec
-= GraphBuffer
[maxPos
+j
];
1497 for(; j
< lowLen
+ highLen
; j
++) {
1498 dec
+= GraphBuffer
[maxPos
+j
];
1501 // place inter bit marker in graph
1502 GraphBuffer
[maxPos
] = maxMark
;
1503 GraphBuffer
[maxPos
+1] = minMark
;
1505 // hi and lo form a 64 bit pair
1506 hi
= (hi
<<1)|(lo
>>31);
1508 // store decoded bit as binary (in hi/lo) and text (in bits[])
1516 PrintToScrollback("bits: '%s'", bits
);
1517 PrintToScrollback("hex: %08x %08x", hi
, lo
);
1520 // read a TI tag and return its ID
1521 static void CmdTIRead(char *str
)
1524 c
.cmd
= CMD_READ_TI_TYPE
;
1525 SendCommand(&c
, FALSE
);
1528 // write new data to a r/w TI tag
1529 static void CmdTIWrite(char *str
)
1534 c
.cmd
= CMD_WRITE_TI_TYPE
;
1535 res
= sscanf(str
, "0x%x 0x%x 0x%x ", &c
.ext1
, &c
.ext2
, &c
.ext3
);
1536 if (res
== 2) c
.ext3
=0;
1538 PrintToScrollback("Please specify the data as two hex strings, optionally the CRC as a third");
1540 SendCommand(&c
, FALSE
);
1543 static void CmdTIDemod(char *cmdline
)
1545 /* MATLAB as follows:
1546 f_s = 2000000; % sampling frequency
1547 f_l = 123200; % low FSK tone
1548 f_h = 134200; % high FSK tone
1550 T_l = 119e-6; % low bit duration
1551 T_h = 130e-6; % high bit duration
1553 l = 2*pi*ones(1, floor(f_s*T_l))*(f_l/f_s);
1554 h = 2*pi*ones(1, floor(f_s*T_h))*(f_h/f_s);
1556 l = sign(sin(cumsum(l)));
1557 h = sign(sin(cumsum(h)));
1560 // 2M*16/134.2k = 238
1561 static const int LowTone
[] = {
1562 1, 1, 1, 1, 1, 1, 1, 1, 1, -1, -1, -1, -1, -1, -1, -1, -1,
1563 1, 1, 1, 1, 1, 1, 1, 1, -1, -1, -1, -1, -1, -1, -1, -1,
1564 1, 1, 1, 1, 1, 1, 1, 1, -1, -1, -1, -1, -1, -1, -1, -1,
1565 1, 1, 1, 1, 1, 1, 1, 1, -1, -1, -1, -1, -1, -1, -1, -1,
1566 1, 1, 1, 1, 1, 1, 1, 1, 1, -1, -1, -1, -1, -1, -1, -1, -1,
1567 1, 1, 1, 1, 1, 1, 1, 1, -1, -1, -1, -1, -1, -1, -1, -1,
1568 1, 1, 1, 1, 1, 1, 1, 1, -1, -1, -1, -1, -1, -1, -1, -1,
1569 1, 1, 1, 1, 1, 1, 1, 1, -1, -1, -1, -1, -1, -1, -1, -1,
1570 1, 1, 1, 1, 1, 1, 1, 1, 1, -1, -1, -1, -1, -1, -1, -1, -1,
1571 1, 1, 1, 1, 1, 1, 1, 1, -1, -1, -1, -1, -1, -1, -1, -1,
1572 1, 1, 1, 1, 1, 1, 1, 1, -1, -1, -1, -1, -1, -1, -1, -1,
1573 1, 1, 1, 1, 1, 1, 1, 1, -1, -1, -1, -1, -1, -1, -1, -1,
1574 1, 1, 1, 1, 1, 1, 1, 1, 1, -1, -1, -1, -1, -1, -1, -1, -1,
1575 1, 1, 1, 1, 1, 1, 1, 1, -1, -1, -1, -1, -1, -1, -1, -1,
1576 1, 1, 1, 1, 1, 1, 1, 1, -1, -1
1578 // 2M*16/123.2k = 260
1579 static const int HighTone
[] = {
1580 1, 1, 1, 1, 1, 1, 1, 1, -1, -1, -1, -1, -1, -1, -1,
1581 1, 1, 1, 1, 1, 1, 1, 1, -1, -1, -1, -1, -1, -1, -1,
1582 1, 1, 1, 1, 1, 1, 1, -1, -1, -1, -1, -1, -1, -1, -1,
1583 1, 1, 1, 1, 1, 1, 1, -1, -1, -1, -1, -1, -1, -1, -1,
1584 1, 1, 1, 1, 1, 1, 1, -1, -1, -1, -1, -1, -1, -1, -1,
1585 1, 1, 1, 1, 1, 1, 1, -1, -1, -1, -1, -1, -1, -1,
1586 1, 1, 1, 1, 1, 1, 1, 1, -1, -1, -1, -1, -1, -1, -1,
1587 1, 1, 1, 1, 1, 1, 1, 1, -1, -1, -1, -1, -1, -1, -1,
1588 1, 1, 1, 1, 1, 1, 1, -1, -1, -1, -1, -1, -1, -1, -1,
1589 1, 1, 1, 1, 1, 1, 1, -1, -1, -1, -1, -1, -1, -1, -1,
1590 1, 1, 1, 1, 1, 1, 1, -1, -1, -1, -1, -1, -1, -1,
1591 1, 1, 1, 1, 1, 1, 1, 1, -1, -1, -1, -1, -1, -1, -1,
1592 1, 1, 1, 1, 1, 1, 1, 1, -1, -1, -1, -1, -1, -1, -1,
1593 1, 1, 1, 1, 1, 1, 1, 1, -1, -1, -1, -1, -1, -1, -1,
1594 1, 1, 1, 1, 1, 1, 1, -1, -1, -1, -1, -1, -1, -1, -1,
1595 1, 1, 1, 1, 1, 1, 1, -1, -1, -1, -1, -1, -1, -1, -1,
1596 1, 1, 1, 1, 1, 1, 1, -1, -1, -1, -1, -1, -1, -1,
1597 1, 1, 1, 1, 1, 1, 1, 1
1599 int lowLen
= sizeof(LowTone
)/sizeof(int);
1600 int highLen
= sizeof(HighTone
)/sizeof(int);
1601 int convLen
= (highLen
>lowLen
)?highLen
:lowLen
;
1604 int lowSum
= 0, highSum
= 0;;
1605 int lowTot
= 0, highTot
= 0;
1607 for(i
= 0; i
< GraphTraceLen
- convLen
; i
++) {
1611 for(j
= 0; j
< lowLen
; j
++) {
1612 lowSum
+= LowTone
[j
]*GraphBuffer
[i
+j
];
1614 for(j
= 0; j
< highLen
; j
++) {
1615 highSum
+= HighTone
[j
]*GraphBuffer
[i
+j
];
1617 lowSum
= abs((100*lowSum
) / lowLen
);
1618 highSum
= abs((100*highSum
) / highLen
);
1619 lowSum
= (lowSum
<0)?-lowSum
:lowSum
;
1620 highSum
= (highSum
<0)?-highSum
:highSum
;
1622 GraphBuffer
[i
] = (highSum
<< 16) | lowSum
;
1625 for(i
= 0; i
< GraphTraceLen
- convLen
- 16; i
++) {
1628 // 16 and 15 are f_s divided by f_l and f_h, rounded
1629 for(j
= 0; j
< 16; j
++) {
1630 lowTot
+= (GraphBuffer
[i
+j
] & 0xffff);
1632 for(j
= 0; j
< 15; j
++) {
1633 highTot
+= (GraphBuffer
[i
+j
] >> 16);
1635 GraphBuffer
[i
] = lowTot
- highTot
;
1638 GraphTraceLen
-= (convLen
+ 16);
1640 RepaintGraphWindow();
1642 // TI tag data format is 16 prebits, 8 start bits, 64 data bits,
1643 // 16 crc CCITT bits, 8 stop bits, 15 end bits
1645 // the 16 prebits are always low
1646 // the 8 start and stop bits of a tag must match
1647 // the start/stop prebits of a ro tag are 01111110
1648 // the start/stop prebits of a rw tag are 11111110
1649 // the 15 end bits of a ro tag are all low
1650 // the 15 end bits of a rw tag match bits 15-1 of the data bits
1652 // Okay, so now we have unsliced soft decisions;
1653 // find bit-sync, and then get some bits.
1654 // look for 17 low bits followed by 6 highs (common pattern for ro and rw tags)
1655 int max
= 0, maxPos
= 0;
1656 for(i
= 0; i
< 6000; i
++) {
1659 // searching 17 consecutive lows
1660 for(j
= 0; j
< 17*lowLen
; j
++) {
1661 dec
-= GraphBuffer
[i
+j
];
1663 // searching 7 consecutive highs
1664 for(; j
< 17*lowLen
+ 6*highLen
; j
++) {
1665 dec
+= GraphBuffer
[i
+j
];
1673 // place a marker in the buffer to visually aid location
1674 // of the start of sync
1675 GraphBuffer
[maxPos
] = 800;
1676 GraphBuffer
[maxPos
+1] = -800;
1678 // advance pointer to start of actual data stream (after 16 pre and 8 start bits)
1679 maxPos
+= 17*lowLen
;
1680 maxPos
+= 6*highLen
;
1682 // place a marker in the buffer to visually aid location
1683 // of the end of sync
1684 GraphBuffer
[maxPos
] = 800;
1685 GraphBuffer
[maxPos
+1] = -800;
1687 PrintToScrollback("actual data bits start at sample %d", maxPos
);
1689 PrintToScrollback("length %d/%d", highLen
, lowLen
);
1691 BYTE bits
[1+64+16+8+16];
1692 bits
[sizeof(bits
)-1] = '\0';
1694 DWORD shift3
= 0x7e000000, shift2
= 0, shift1
= 0, shift0
= 0;
1696 for(i
= 0; i
< arraylen(bits
)-1; i
++) {
1700 for(j
= 0; j
< lowLen
; j
++) {
1701 low
-= GraphBuffer
[maxPos
+j
];
1703 for(j
= 0; j
< highLen
; j
++) {
1704 high
+= GraphBuffer
[maxPos
+j
];
1710 // bitstream arrives lsb first so shift right
1717 // 128 bit right shift register
1718 shift0
= (shift0
>>1) | (shift1
<< 31);
1719 shift1
= (shift1
>>1) | (shift2
<< 31);
1720 shift2
= (shift2
>>1) | (shift3
<< 31);
1723 // place a marker in the buffer between bits to visually aid location
1724 GraphBuffer
[maxPos
] = 800;
1725 GraphBuffer
[maxPos
+1] = -800;
1727 PrintToScrollback("Info: raw tag bits = %s", bits
);
1729 TagType
= (shift3
>>8)&0xff;
1730 if ( TagType
!= ((shift0
>>16)&0xff) ) {
1731 PrintToScrollback("Error: start and stop bits do not match!");
1734 else if (TagType
== 0x7e) {
1735 PrintToScrollback("Info: Readonly TI tag detected.");
1738 else if (TagType
== 0xfe) {
1739 PrintToScrollback("Info: Rewriteable TI tag detected.");
1741 // put 64 bit data into shift1 and shift0
1742 shift0
= (shift0
>>24) | (shift1
<< 8);
1743 shift1
= (shift1
>>24) | (shift2
<< 8);
1745 // align 16 bit crc into lower half of shift2
1746 shift2
= ((shift2
>>24) | (shift3
<< 8)) & 0x0ffff;
1748 // align 16 bit "end bits" or "ident" into lower half of shift3
1751 // only 15 bits compare, last bit of ident is not valid
1752 if ( (shift3
^shift0
)&0x7fff ) {
1753 PrintToScrollback("Error: Ident mismatch!");
1755 // WARNING the order of the bytes in which we calc crc below needs checking
1756 // i'm 99% sure the crc algorithm is correct, but it may need to eat the
1757 // bytes in reverse or something
1760 crc
= update_crc16(crc
, (shift0
)&0xff);
1761 crc
= update_crc16(crc
, (shift0
>>8)&0xff);
1762 crc
= update_crc16(crc
, (shift0
>>16)&0xff);
1763 crc
= update_crc16(crc
, (shift0
>>24)&0xff);
1764 crc
= update_crc16(crc
, (shift1
)&0xff);
1765 crc
= update_crc16(crc
, (shift1
>>8)&0xff);
1766 crc
= update_crc16(crc
, (shift1
>>16)&0xff);
1767 crc
= update_crc16(crc
, (shift1
>>24)&0xff);
1768 PrintToScrollback("Info: Tag data = %08X%08X", shift1
, shift0
);
1769 if (crc
!= (shift2
&0xffff)) {
1770 PrintToScrollback("Error: CRC mismatch, calculated %04X, got ^04X", crc
, shift2
&0xffff);
1772 PrintToScrollback("Info: CRC %04X is good", crc
);
1776 PrintToScrollback("Unknown tag type.");
1781 static void CmdNorm(char *str
)
1784 int max
= INT_MIN
, min
= INT_MAX
;
1785 for(i
= 10; i
< GraphTraceLen
; i
++) {
1786 if(GraphBuffer
[i
] > max
) {
1787 max
= GraphBuffer
[i
];
1789 if(GraphBuffer
[i
] < min
) {
1790 min
= GraphBuffer
[i
];
1794 for(i
= 0; i
< GraphTraceLen
; i
++) {
1795 GraphBuffer
[i
] = (GraphBuffer
[i
] - ((max
+ min
)/2))*1000/
1799 RepaintGraphWindow();
1802 static void CmdDec(char *str
)
1805 for(i
= 0; i
< (GraphTraceLen
/2); i
++) {
1806 GraphBuffer
[i
] = GraphBuffer
[i
*2];
1809 PrintToScrollback("decimated by 2");
1810 RepaintGraphWindow();
1813 static void CmdHpf(char *str
)
1817 for(i
= 10; i
< GraphTraceLen
; i
++) {
1818 accum
+= GraphBuffer
[i
];
1820 accum
/= (GraphTraceLen
- 10);
1821 for(i
= 0; i
< GraphTraceLen
; i
++) {
1822 GraphBuffer
[i
] -= accum
;
1825 RepaintGraphWindow();
1828 static void CmdZerocrossings(char *str
)
1831 // Zero-crossings aren't meaningful unless the signal is zero-mean.
1837 for(i
= 0; i
< GraphTraceLen
; i
++) {
1838 if(GraphBuffer
[i
]*sign
>= 0) {
1839 // No change in sign, reproduce the previous sample count.
1841 GraphBuffer
[i
] = lastZc
;
1843 // Change in sign, reset the sample count.
1845 GraphBuffer
[i
] = lastZc
;
1853 RepaintGraphWindow();
1856 static void CmdThreshold(char *str
)
1859 int threshold
= atoi(str
);
1861 for(i
= 0; i
< GraphTraceLen
; i
++) {
1862 if(GraphBuffer
[i
]>= threshold
)
1867 RepaintGraphWindow();
1870 static void CmdLtrim(char *str
)
1875 for(i
= ds
; i
< GraphTraceLen
; i
++) {
1876 GraphBuffer
[i
-ds
] = GraphBuffer
[i
];
1878 GraphTraceLen
-= ds
;
1880 RepaintGraphWindow();
1883 static void CmdAutoCorr(char *str
)
1885 static int CorrelBuffer
[MAX_GRAPH_TRACE_LEN
];
1887 int window
= atoi(str
);
1890 PrintToScrollback("needs a window");
1894 if(window
>= GraphTraceLen
) {
1895 PrintToScrollback("window must be smaller than trace (%d samples)",
1900 PrintToScrollback("performing %d correlations", GraphTraceLen
- window
);
1903 for(i
= 0; i
< GraphTraceLen
- window
; i
++) {
1906 for(j
= 0; j
< window
; j
++) {
1907 sum
+= (GraphBuffer
[j
]*GraphBuffer
[i
+j
]) / 256;
1909 CorrelBuffer
[i
] = sum
;
1911 GraphTraceLen
= GraphTraceLen
- window
;
1912 memcpy(GraphBuffer
, CorrelBuffer
, GraphTraceLen
*sizeof(int));
1914 RepaintGraphWindow();
1917 static void CmdVchdemod(char *str
)
1919 // Is this the entire sync pattern, or does this also include some
1920 // data bits that happen to be the same everywhere? That would be
1922 static const int SyncPattern
[] = {
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,
1928 1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
1929 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
1930 1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
1931 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
1932 1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
1935 // So first, we correlate for the sync pattern, and mark that.
1936 int bestCorrel
= 0, bestPos
= 0;
1938 // It does us no good to find the sync pattern, with fewer than
1939 // 2048 samples after it...
1940 for(i
= 0; i
< (GraphTraceLen
-2048); i
++) {
1943 for(j
= 0; j
< arraylen(SyncPattern
); j
++) {
1944 sum
+= GraphBuffer
[i
+j
]*SyncPattern
[j
];
1946 if(sum
> bestCorrel
) {
1951 PrintToScrollback("best sync at %d [metric %d]", bestPos
, bestCorrel
);
1956 int worst
= INT_MAX
;
1959 for(i
= 0; i
< 2048; i
+= 8) {
1962 for(j
= 0; j
< 8; j
++) {
1963 sum
+= GraphBuffer
[bestPos
+i
+j
];
1970 if(abs(sum
) < worst
) {
1975 PrintToScrollback("bits:");
1976 PrintToScrollback("%s", bits
);
1977 PrintToScrollback("worst metric: %d at pos %d", worst
, worstPos
);
1979 if(strcmp(str
, "clone")==0) {
1982 for(s
= bits
; *s
; s
++) {
1984 for(j
= 0; j
< 16; j
++) {
1985 GraphBuffer
[GraphTraceLen
++] = (*s
== '1') ? 1 : 0;
1988 RepaintGraphWindow();
1992 static void CmdIndalademod(char *str
)
1994 // Usage: recover 64bit UID by default, specify "224" as arg to recover a 224bit UID
1999 // worst case with GraphTraceLen=64000 is < 4096
2000 // under normal conditions it's < 2048
2003 int worst
= 0, worstPos
= 0;
2004 PrintToScrollback("Expecting a bit less than %d raw bits", GraphTraceLen
/32);
2005 for(i
= 0; i
< GraphTraceLen
-1; i
+= 2) {
2007 if((GraphBuffer
[i
] > GraphBuffer
[i
+ 1]) && (state
!= 1)) {
2009 for(j
= 0; j
< count
- 8; j
+= 16) {
2010 rawbits
[rawbit
++] = 0;
2012 if ((abs(count
- j
)) > worst
) {
2013 worst
= abs(count
- j
);
2019 } else if((GraphBuffer
[i
] < GraphBuffer
[i
+ 1]) && (state
!= 0)) {
2021 for(j
= 0; j
< count
- 8; j
+= 16) {
2022 rawbits
[rawbit
++] = 1;
2024 if ((abs(count
- j
)) > worst
) {
2025 worst
= abs(count
- j
);
2033 PrintToScrollback("Recovered %d raw bits", rawbit
);
2034 PrintToScrollback("worst metric (0=best..7=worst): %d at pos %d", worst
, worstPos
);
2036 // Finding the start of a UID
2037 int uidlen
, long_wait
;
2038 if(strcmp(str
, "224") == 0) {
2047 for(start
= 0; start
<= rawbit
- uidlen
; start
++) {
2048 first
= rawbits
[start
];
2049 for(i
= start
; i
< start
+ long_wait
; i
++) {
2050 if(rawbits
[i
] != first
) {
2054 if(i
== (start
+ long_wait
)) {
2058 if(start
== rawbit
- uidlen
+ 1) {
2059 PrintToScrollback("nothing to wait for");
2063 // Inverting signal if needed
2065 for(i
= start
; i
< rawbit
; i
++) {
2066 rawbits
[i
] = !rawbits
[i
];
2073 showbits
[uidlen
]='\0';
2077 if(uidlen
> rawbit
) {
2078 PrintToScrollback("Warning: not enough raw bits to get a full UID");
2079 for(bit
= 0; bit
< rawbit
; bit
++) {
2080 bits
[bit
] = rawbits
[i
++];
2081 // As we cannot know the parity, let's use "." and "/"
2082 showbits
[bit
] = '.' + bits
[bit
];
2084 showbits
[bit
+1]='\0';
2085 PrintToScrollback("Partial UID=%s", showbits
);
2088 for(bit
= 0; bit
< uidlen
; bit
++) {
2089 bits
[bit
] = rawbits
[i
++];
2090 showbits
[bit
] = '0' + bits
[bit
];
2094 PrintToScrollback("UID=%s", showbits
);
2096 // Checking UID against next occurences
2097 for(; i
+ uidlen
<= rawbit
;) {
2099 for(bit
= 0; bit
< uidlen
; bit
++) {
2100 if(bits
[bit
] != rawbits
[i
++]) {
2110 PrintToScrollback("Occurences: %d (expected %d)", times
, (rawbit
- start
) / uidlen
);
2112 // Remodulating for tag cloning
2113 GraphTraceLen
= 32*uidlen
;
2116 for(bit
= 0; bit
< uidlen
; bit
++) {
2117 if(bits
[bit
] == 0) {
2123 for(j
= 0; j
< 32; j
++) {
2124 GraphBuffer
[i
++] = phase
;
2129 RepaintGraphWindow();
2132 static void CmdFlexdemod(char *str
)
2135 for(i
= 0; i
< GraphTraceLen
; i
++) {
2136 if(GraphBuffer
[i
] < 0) {
2137 GraphBuffer
[i
] = -1;
2143 #define LONG_WAIT 100
2145 for(start
= 0; start
< GraphTraceLen
- LONG_WAIT
; start
++) {
2146 int first
= GraphBuffer
[start
];
2147 for(i
= start
; i
< start
+ LONG_WAIT
; i
++) {
2148 if(GraphBuffer
[i
] != first
) {
2152 if(i
== (start
+ LONG_WAIT
)) {
2156 if(start
== GraphTraceLen
- LONG_WAIT
) {
2157 PrintToScrollback("nothing to wait for");
2161 GraphBuffer
[start
] = 2;
2162 GraphBuffer
[start
+1] = -2;
2168 for(bit
= 0; bit
< 64; bit
++) {
2171 for(j
= 0; j
< 16; j
++) {
2172 sum
+= GraphBuffer
[i
++];
2179 PrintToScrollback("bit %d sum %d", bit
, sum
);
2182 for(bit
= 0; bit
< 64; bit
++) {
2185 for(j
= 0; j
< 16; j
++) {
2186 sum
+= GraphBuffer
[i
++];
2188 if(sum
> 0 && bits
[bit
] != 1) {
2189 PrintToScrollback("oops1 at %d", bit
);
2191 if(sum
< 0 && bits
[bit
] != 0) {
2192 PrintToScrollback("oops2 at %d", bit
);
2196 GraphTraceLen
= 32*64;
2199 for(bit
= 0; bit
< 64; bit
++) {
2200 if(bits
[bit
] == 0) {
2206 for(j
= 0; j
< 32; j
++) {
2207 GraphBuffer
[i
++] = phase
;
2212 RepaintGraphWindow();
2216 * Generic command to demodulate ASK.
2218 * Argument is convention: positive or negative (High mod means zero
2219 * or high mod means one)
2221 * Updates the Graph trace with 0/1 values
2227 static void Cmdaskdemod(char *str
) {
2229 int c
, high
= 0, low
= 0;
2231 // TODO: complain if we do not give 2 arguments here !
2232 sscanf(str
, "%i", &c
);
2234 /* Detect high and lows and clock */
2235 for (i
= 0; i
< GraphTraceLen
; i
++)
2237 if (GraphBuffer
[i
] > high
)
2238 high
= GraphBuffer
[i
];
2239 else if (GraphBuffer
[i
] < low
)
2240 low
= GraphBuffer
[i
];
2243 if (GraphBuffer
[0] > 0) {
2244 GraphBuffer
[0] = 1-c
;
2248 for(i
=1;i
<GraphTraceLen
;i
++) {
2249 /* Transitions are detected at each peak
2250 * Transitions are either:
2251 * - we're low: transition if we hit a high
2252 * - we're high: transition if we hit a low
2253 * (we need to do it this way because some tags keep high or
2254 * low for long periods, others just reach the peak and go
2257 if ((GraphBuffer
[i
]==high
) && (GraphBuffer
[i
-1] == c
)) {
2259 } else if ((GraphBuffer
[i
]==low
) && (GraphBuffer
[i
-1] == (1-c
))){
2263 GraphBuffer
[i
] = GraphBuffer
[i
-1];
2266 RepaintGraphWindow();
2269 /* Print our clock rate */
2270 static void Cmddetectclockrate(char *str
)
2272 int clock
= detectclock(0);
2273 PrintToScrollback("Auto-detected clock rate: %d", clock
);
2279 int detectclock(int peak
)
2285 /* Detect peak if we don't have one */
2287 for (i
= 0; i
< GraphTraceLen
; i
++)
2288 if (GraphBuffer
[i
] > peak
)
2289 peak
= GraphBuffer
[i
];
2291 for (i
= 1; i
< GraphTraceLen
; i
++)
2293 /* If this is the beginning of a peak */
2294 if (GraphBuffer
[i
-1] != GraphBuffer
[i
] && GraphBuffer
[i
] == peak
)
2296 /* Find lowest difference between peaks */
2297 if (lastpeak
&& i
- lastpeak
< clock
)
2299 clock
= i
- lastpeak
;
2308 /* Get or auto-detect clock rate */
2309 int GetClock(char *str
, int peak
)
2313 sscanf(str
, "%i", &clock
);
2314 if (!strcmp(str
, ""))
2317 /* Auto-detect clock */
2320 clock
= detectclock(peak
);
2322 /* Only print this message if we're not looping something */
2324 PrintToScrollback("Auto-detected clock rate: %d", clock
);
2331 * Convert to a bitstream
2333 static void Cmdbitstream(char *str
) {
2340 int hithigh
, hitlow
, first
;
2342 /* Detect high and lows and clock */
2343 for (i
= 0; i
< GraphTraceLen
; i
++)
2345 if (GraphBuffer
[i
] > high
)
2346 high
= GraphBuffer
[i
];
2347 else if (GraphBuffer
[i
] < low
)
2348 low
= GraphBuffer
[i
];
2352 clock
= GetClock(str
, high
);
2354 gtl
= CmdClearGraph(0);
2357 for (i
= 0; i
< (int)(gtl
/ clock
); i
++)
2363 /* Find out if we hit both high and low peaks */
2364 for (j
= 0; j
< clock
; j
++)
2366 if (GraphBuffer
[(i
* clock
) + j
] == high
)
2368 else if (GraphBuffer
[(i
* clock
) + j
] == low
)
2371 /* it doesn't count if it's the first part of our read
2372 because it's really just trailing from the last sequence */
2373 if (first
&& (hithigh
|| hitlow
))
2374 hithigh
= hitlow
= 0;
2378 if (hithigh
&& hitlow
)
2382 /* If we didn't hit both high and low peaks, we had a bit transition */
2383 if (!hithigh
|| !hitlow
)
2386 CmdAppendGraph(0, clock
, bit
);
2387 // for (j = 0; j < (int)(clock/2); j++)
2388 // GraphBuffer[(i * clock) + j] = bit ^ 1;
2389 // for (j = (int)(clock/2); j < clock; j++)
2390 // GraphBuffer[(i * clock) + j] = bit;
2393 RepaintGraphWindow();
2396 /* Modulate our data into manchester */
2397 static void Cmdmanchestermod(char *str
)
2401 int bit
, lastbit
, wave
;
2404 clock
= GetClock(str
, 0);
2408 for (i
= 0; i
< (int)(GraphTraceLen
/ clock
); i
++)
2410 bit
= GraphBuffer
[i
* clock
] ^ 1;
2412 for (j
= 0; j
< (int)(clock
/2); j
++)
2413 GraphBuffer
[(i
* clock
) + j
] = bit
^ lastbit
^ wave
;
2414 for (j
= (int)(clock
/2); j
< clock
; j
++)
2415 GraphBuffer
[(i
* clock
) + j
] = bit
^ lastbit
^ wave
^ 1;
2417 /* Keep track of how we start our wave and if we changed or not this time */
2418 wave
^= bit
^ lastbit
;
2422 RepaintGraphWindow();
2426 * Manchester demodulate a bitstream. The bitstream needs to be already in
2427 * the GraphBuffer as 0 and 1 values
2429 * Give the clock rate as argument in order to help the sync - the algorithm
2430 * resyncs at each pulse anyway.
2432 * Not optimized by any means, this is the 1st time I'm writing this type of
2433 * routine, feel free to improve...
2435 * 1st argument: clock rate (as number of samples per clock rate)
2436 * Typical values can be 64, 32, 128...
2438 static void Cmdmanchesterdemod(char *str
) {
2439 int i
, j
, invert
= 0;
2445 int hithigh
, hitlow
, first
;
2451 /* check if we're inverting output */
2454 PrintToScrollback("Inverting output");
2458 while(*str
== ' '); // in case a 2nd argument was given
2461 /* Holds the decoded bitstream: each clock period contains 2 bits */
2462 /* later simplified to 1 bit after manchester decoding. */
2463 /* Add 10 bits to allow for noisy / uncertain traces without aborting */
2464 /* int BitStream[GraphTraceLen*2/clock+10]; */
2466 /* But it does not work if compiling on WIndows: therefore we just allocate a */
2468 int BitStream
[MAX_GRAPH_TRACE_LEN
];
2470 /* Detect high and lows */
2471 for (i
= 0; i
< GraphTraceLen
; i
++)
2473 if (GraphBuffer
[i
] > high
)
2474 high
= GraphBuffer
[i
];
2475 else if (GraphBuffer
[i
] < low
)
2476 low
= GraphBuffer
[i
];
2480 clock
= GetClock(str
, high
);
2482 int tolerance
= clock
/4;
2484 /* Detect first transition */
2485 /* Lo-Hi (arbitrary) */
2486 for (i
= 0; i
< GraphTraceLen
; i
++)
2488 if (GraphBuffer
[i
] == low
)
2495 /* If we're not working with 1/0s, demod based off clock */
2498 bit
= 0; /* We assume the 1st bit is zero, it may not be
2499 * the case: this routine (I think) has an init problem.
2502 for (; i
< (int)(GraphTraceLen
/ clock
); i
++)
2508 /* Find out if we hit both high and low peaks */
2509 for (j
= 0; j
< clock
; j
++)
2511 if (GraphBuffer
[(i
* clock
) + j
] == high
)
2513 else if (GraphBuffer
[(i
* clock
) + j
] == low
)
2516 /* it doesn't count if it's the first part of our read
2517 because it's really just trailing from the last sequence */
2518 if (first
&& (hithigh
|| hitlow
))
2519 hithigh
= hitlow
= 0;
2523 if (hithigh
&& hitlow
)
2527 /* If we didn't hit both high and low peaks, we had a bit transition */
2528 if (!hithigh
|| !hitlow
)
2531 BitStream
[bit2idx
++] = bit
^ invert
;
2535 /* standard 1/0 bitstream */
2539 /* Then detect duration between 2 successive transitions */
2540 for (bitidx
= 1; i
< GraphTraceLen
; i
++)
2542 if (GraphBuffer
[i
-1] != GraphBuffer
[i
])
2547 // Error check: if bitidx becomes too large, we do not
2548 // have a Manchester encoded bitstream or the clock is really
2550 if (bitidx
> (GraphTraceLen
*2/clock
+8) ) {
2551 PrintToScrollback("Error: the clock you gave is probably wrong, aborting.");
2554 // Then switch depending on lc length:
2555 // Tolerance is 1/4 of clock rate (arbitrary)
2556 if (abs(lc
-clock
/2) < tolerance
) {
2557 // Short pulse : either "1" or "0"
2558 BitStream
[bitidx
++]=GraphBuffer
[i
-1];
2559 } else if (abs(lc
-clock
) < tolerance
) {
2560 // Long pulse: either "11" or "00"
2561 BitStream
[bitidx
++]=GraphBuffer
[i
-1];
2562 BitStream
[bitidx
++]=GraphBuffer
[i
-1];
2566 PrintToScrollback("Warning: Manchester decode error for pulse width detection.");
2567 PrintToScrollback("(too many of those messages mean either the stream is not Manchester encoded, or clock is wrong)");
2571 PrintToScrollback("Error: too many detection errors, aborting.");
2578 // At this stage, we now have a bitstream of "01" ("1") or "10" ("0"), parse it into final decoded bitstream
2579 // Actually, we overwrite BitStream with the new decoded bitstream, we just need to be careful
2580 // to stop output at the final bitidx2 value, not bitidx
2581 for (i
= 0; i
< bitidx
; i
+= 2) {
2582 if ((BitStream
[i
] == 0) && (BitStream
[i
+1] == 1)) {
2583 BitStream
[bit2idx
++] = 1 ^ invert
;
2584 } else if ((BitStream
[i
] == 1) && (BitStream
[i
+1] == 0)) {
2585 BitStream
[bit2idx
++] = 0 ^ invert
;
2587 // We cannot end up in this state, this means we are unsynchronized,
2591 PrintToScrollback("Unsynchronized, resync...");
2592 PrintToScrollback("(too many of those messages mean the stream is not Manchester encoded)");
2596 PrintToScrollback("Error: too many decode errors, aborting.");
2603 PrintToScrollback("Manchester decoded bitstream");
2604 // Now output the bitstream to the scrollback by line of 16 bits
2605 for (i
= 0; i
< (bit2idx
-16); i
+=16) {
2606 PrintToScrollback("%i %i %i %i %i %i %i %i %i %i %i %i %i %i %i %i",
2629 static void CmdHiddemod(char *str
)
2631 if(GraphTraceLen
< 4800) {
2632 PrintToScrollback("too short; need at least 4800 samples");
2636 GraphTraceLen
= 4800;
2638 for(i
= 0; i
< GraphTraceLen
; i
++) {
2639 if(GraphBuffer
[i
] < 0) {
2645 RepaintGraphWindow();
2648 static void CmdPlot(char *str
)
2653 static void CmdGrid(char *str
)
2655 sscanf(str
, "%i %i", &PlotGridX
, &PlotGridY
);
2656 RepaintGraphWindow();
2659 static void CmdHide(char *str
)
2664 static void CmdScale(char *str
)
2666 CursorScaleFactor
= atoi(str
);
2667 if(CursorScaleFactor
== 0) {
2668 PrintToScrollback("bad, can't have zero scale");
2669 CursorScaleFactor
= 1;
2671 RepaintGraphWindow();
2674 static void CmdSave(char *str
)
2676 FILE *f
= fopen(str
, "w");
2678 PrintToScrollback("couldn't open '%s'", str
);
2682 for(i
= 0; i
< GraphTraceLen
; i
++) {
2683 fprintf(f
, "%d\n", GraphBuffer
[i
]);
2686 PrintToScrollback("saved to '%s'", str
);
2689 static void CmdLoad(char *str
)
2691 FILE *f
= fopen(str
, "r");
2693 PrintToScrollback("couldn't open '%s'", str
);
2699 while(fgets(line
, sizeof(line
), f
)) {
2700 GraphBuffer
[GraphTraceLen
] = atoi(line
);
2704 PrintToScrollback("loaded %d samples", GraphTraceLen
);
2705 RepaintGraphWindow();
2708 static void CmdHIDsimTAG(char *str
)
2710 unsigned int hi
=0, lo
=0;
2714 while (sscanf(&str
[i
++], "%1x", &n
) == 1) {
2715 hi
=(hi
<<4)|(lo
>>28);
2719 PrintToScrollback("Emulating tag with ID %x%16x", hi
, lo
);
2721 c
.cmd
= CMD_HID_SIM_TAG
;
2724 SendCommand(&c
, FALSE
);
2727 static void CmdReadmem(char *str
)
2730 c
.cmd
= CMD_READ_MEM
;
2732 SendCommand(&c
, FALSE
);
2735 static void CmdLcdReset(char *str
)
2738 c
.cmd
= CMD_LCD_RESET
;
2740 SendCommand(&c
, FALSE
);
2743 static void CmdLcd(char *str
)
2748 sscanf(str
, "%x %d", &i
, &j
);
2751 SendCommand(&c
, FALSE
);
2756 * Sets the divisor for LF frequency clock: lets the user choose any LF frequency below
2759 static void CmdSetDivisor(char *str
)
2762 c
.cmd
= CMD_SET_LF_DIVISOR
;
2764 if (( c
.ext1
<0) || (c
.ext1
>255)) {
2765 PrintToScrollback("divisor must be between 19 and 255");
2767 SendCommand(&c
, FALSE
);
2768 PrintToScrollback("Divisor set, expected freq=%dHz", 12000000/(c
.ext1
+1));
2772 typedef void HandlerFunction(char *cmdline
);
2774 /* in alphabetic order */
2777 HandlerFunction
*handler
;
2778 int offline
; // 1 if the command can be used when in offline mode
2780 } CommandTable
[] = {
2781 {"askdemod", Cmdaskdemod
, 1, "<samples per bit> <0|1> -- Attempt to demodulate simple ASK tags"},
2782 {"autocorr", CmdAutoCorr
, 1, "<window length> -- Autocorrelation over window"},
2783 {"bitsamples", CmdBitsamples
, 0, "Get raw samples as bitstring"},
2784 {"bitstream", Cmdbitstream
, 1, "[clock rate] -- Convert waveform into a bitstream"},
2785 {"buffclear", CmdBuffClear
, 1, "Clear sample buffer and graph window"},
2786 {"dec", CmdDec
, 1, "Decimate samples"},
2787 {"detectclock", Cmddetectclockrate
, 1, "Detect clock rate"},
2788 {"detectreader", CmdDetectReader
, 0, "['l'|'h'] -- Detect external reader field (option 'l' or 'h' to limit to LF or HF)"},
2789 {"em410xsim", CmdEM410xsim
, 1, "<UID> -- Simulate EM410x tag"},
2790 {"em410xread", CmdEM410xread
, 1, "[clock rate] -- Extract ID from EM410x tag"},
2791 {"em410xwatch", CmdEM410xwatch
, 0, "Watches for EM410x tags"},
2792 {"em4x50read", CmdEM4x50read
, 1, "Extract data from EM4x50 tag"},
2793 {"exit", CmdQuit
, 1, "Exit program"},
2794 {"flexdemod", CmdFlexdemod
, 1, "Demodulate samples for FlexPass"},
2795 {"fpgaoff", CmdFPGAOff
, 0, "Set FPGA off"},
2796 {"fskdemod", CmdFSKdemod
, 1, "Demodulate graph window as a HID FSK"},
2797 {"grid", CmdGrid
, 1, "<x> <y> -- overlay grid on graph window, use zero value to turn off either"},
2798 {"hexsamples", CmdHexsamples
, 0, "<blocks> -- Dump big buffer as hex bytes"},
2799 {"hi14alist", CmdHi14alist
, 0, "List ISO 14443a history"},
2800 {"hi14areader", CmdHi14areader
, 0, "Act like an ISO14443 Type A reader"},
2801 {"hi14asim", CmdHi14asim
, 0, "<UID> -- Fake ISO 14443a tag"},
2802 {"hi14asnoop", CmdHi14asnoop
, 0, "Eavesdrop ISO 14443 Type A"},
2803 {"hi14bdemod", CmdHi14bdemod
, 1, "Demodulate ISO14443 Type B from tag"},
2804 {"hi14list", CmdHi14list
, 0, "List ISO 14443 history"},
2805 {"hi14read", CmdHi14read
, 0, "Read HF tag (ISO 14443)"},
2806 {"hi14sim", CmdHi14sim
, 0, "Fake ISO 14443 tag"},
2807 {"hi14snoop", CmdHi14snoop
, 0, "Eavesdrop ISO 14443"},
2808 {"hi15demod", CmdHi15demod
, 1, "Demodulate ISO15693 from tag"},
2809 {"hi15read", CmdHi15read
, 0, "Read HF tag (ISO 15693)"},
2810 {"hi15reader", CmdHi15reader
, 0, "Act like an ISO15693 reader"},
2811 {"hi15sim", CmdHi15tag
, 0, "Fake an ISO15693 tag"},
2812 {"hiddemod", CmdHiddemod
, 1, "Demodulate HID Prox Card II (not optimal)"},
2813 {"hide", CmdHide
, 1, "Hide graph window"},
2814 {"hidfskdemod", CmdHIDdemodFSK
, 0, "Realtime HID FSK demodulator"},
2815 {"hidsimtag", CmdHIDsimTAG
, 0, "<ID> -- HID tag simulator"},
2816 {"higet", CmdHi14read_sim
, 0, "<samples> -- Get samples HF, 'analog'"},
2817 {"hisamples", CmdHisamples
, 0, "Get raw samples for HF tag"},
2818 {"hisampless", CmdHisampless
, 0, "<samples> -- Get signed raw samples, HF tag"},
2819 {"hisamplest", CmdHi14readt
, 0, "Get samples HF, for testing"},
2820 {"hisimlisten", CmdHisimlisten
, 0, "Get HF samples as fake tag"},
2821 {"hpf", CmdHpf
, 1, "Remove DC offset from trace"},
2822 {"indalademod", CmdIndalademod
, 0, "['224'] -- Demodulate samples for Indala 64 bit UID (option '224' for 224 bit)"},
2823 {"lcd", CmdLcd
, 0, "<HEX command> <count> -- Send command/data to LCD"},
2824 {"lcdreset", CmdLcdReset
, 0, "Hardware reset LCD"},
2825 {"load", CmdLoad
, 1, "<filename> -- Load trace (to graph window"},
2826 {"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)"},
2827 {"loread", CmdLoread
, 0, "['h'] -- Read 125/134 kHz LF ID-only tag (option 'h' for 134)"},
2828 {"losamples", CmdLosamples
, 0, "[128 - 16000] -- Get raw samples for LF tag"},
2829 {"losim", CmdLosim
, 0, "Simulate LF tag"},
2830 {"ltrim", CmdLtrim
, 1, "<samples> -- Trim samples from left of trace"},
2831 {"mandemod", Cmdmanchesterdemod
, 1, "[i] [clock rate] -- Manchester demodulate binary stream (option 'i' to invert output)"},
2832 {"manmod", Cmdmanchestermod
, 1, "[clock rate] -- Manchester modulate a binary stream"},
2833 {"norm", CmdNorm
, 1, "Normalize max/min to +/-500"},
2834 {"plot", CmdPlot
, 1, "Show graph window"},
2835 {"quit", CmdQuit
, 1, "Quit program"},
2836 {"readmem", CmdReadmem
, 0, "[address] -- Read memory at decimal address from flash"},
2837 {"reset", CmdReset
, 0, "Reset the Proxmark3"},
2838 {"save", CmdSave
, 1, "<filename> -- Save trace (from graph window)"},
2839 {"scale", CmdScale
, 1, "<int> -- Set cursor display scale"},
2840 {"setlfdivisor", CmdSetDivisor
, 0, "<19 - 255> -- Drive LF antenna at 12Mhz/(divisor+1)"},
2841 {"sri512read", CmdSri512read
, 0, "<int> -- Read contents of a SRI512 tag"},
2842 {"tidemod", CmdTIDemod
, 1, "Demodulate raw bits for TI-type LF tag"},
2843 {"tiread", CmdTIRead
, 0, "Read and decode a TI 134 kHz tag"},
2844 {"tiwrite", CmdTIWrite
, 0, "Write new data to a r/w TI 134 kHz tag"},
2845 {"threshold", CmdThreshold
, 1, "Maximize/minimize every value in the graph window depending on threshold"},
2846 {"tune", CmdTune
, 0, "Measure antenna tuning"},
2847 {"vchdemod", CmdVchdemod
, 0, "['clone'] -- Demodulate samples for VeriChip"},
2848 {"zerocrossings", CmdZerocrossings
, 1, "Count time between zero-crossings"},
2856 } CommandExtendedHelp
[]= {
2857 {"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."},
2858 {"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."},
2861 //-----------------------------------------------------------------------------
2862 // Entry point into our code: called whenever the user types a command and
2863 // then presses Enter, which the full command line that they typed.
2864 //-----------------------------------------------------------------------------
2865 void CommandReceived(char *cmd
)
2870 PrintToScrollback("> %s", cmd
);
2872 if(strcmp(cmd
, "help") == 0 || strncmp(cmd
,"help ",strlen("help ")) == 0) {
2873 // check if we're doing extended help
2874 if(strlen(cmd
) > strlen("help ")) {
2875 cmd
+= strlen("help ");
2876 for(i
= 0; i
< sizeof(CommandExtendedHelp
) / sizeof(CommandExtendedHelp
[0]); i
++) {
2877 if(strcmp(CommandExtendedHelp
[i
].name
,cmd
) == 0) {
2878 PrintToScrollback("\nExtended help for '%s':\n", cmd
);
2879 PrintToScrollback("Args: %s\t- %s\n",CommandExtendedHelp
[i
].args
,CommandExtendedHelp
[i
].argshelp
);
2880 PrintToScrollback(CommandExtendedHelp
[i
].description
);
2881 PrintToScrollback("");
2885 PrintToScrollback("No extended help available for '%s'", cmd
);
2888 if (offline
) PrintToScrollback("Operating in OFFLINE mode (no device connected)");
2889 PrintToScrollback("\r\nAvailable commands:");
2890 for(i
= 0; i
< sizeof(CommandTable
) / sizeof(CommandTable
[0]); i
++) {
2891 if (offline
&& (CommandTable
[i
].offline
==0)) continue;
2892 memset(line
, ' ', sizeof(line
));
2893 strcpy(line
+2, CommandTable
[i
].name
);
2894 line
[strlen(line
)] = ' ';
2895 sprintf(line
+15, " -- %s", CommandTable
[i
].docString
);
2896 PrintToScrollback("%s", line
);
2898 PrintToScrollback("");
2899 PrintToScrollback("'help <command>' for extended help on that command\n");
2903 for(i
= 0; i
< sizeof(CommandTable
) / sizeof(CommandTable
[0]); i
++) {
2904 char *name
= CommandTable
[i
].name
;
2905 if(memcmp(cmd
, name
, strlen(name
))==0 &&
2906 (cmd
[strlen(name
)] == ' ' || cmd
[strlen(name
)] == '\0'))
2908 cmd
+= strlen(name
);
2909 while(*cmd
== ' ') {
2912 if (offline
&& (CommandTable
[i
].offline
==0)) {
2913 PrintToScrollback("Offline mode, cannot use this command.");
2916 (CommandTable
[i
].handler
)(cmd
);
2920 PrintToScrollback(">> bad command '%s'", cmd
);
2923 //-----------------------------------------------------------------------------
2924 // Entry point into our code: called whenever we received a packet over USB
2925 // that we weren't necessarily expecting, for example a debug print.
2926 //-----------------------------------------------------------------------------
2927 void UsbCommandReceived(UsbCommand
*c
)
2930 case CMD_DEBUG_PRINT_STRING
: {
2932 if(c
->ext1
> 70 || c
->ext1
< 0) {
2935 memcpy(s
, c
->d
.asBytes
, c
->ext1
);
2937 PrintToScrollback("#db# %s", s
);
2941 case CMD_DEBUG_PRINT_INTEGERS
:
2942 PrintToScrollback("#db# %08x, %08x, %08x\r\n", c
->ext1
, c
->ext2
, c
->ext3
);
2945 case CMD_MEASURED_ANTENNA_TUNING
: {
2947 int vLf125
, vLf134
, vHf
;
2948 vLf125
= c
->ext1
& 0xffff;
2949 vLf134
= c
->ext1
>> 16;
2950 vHf
= c
->ext2
& 0xffff;;
2951 peakf
= c
->ext3
& 0xffff;
2952 peakv
= c
->ext3
>> 16;
2953 PrintToScrollback("");
2954 PrintToScrollback("");
2955 PrintToScrollback("# LF antenna: %5.2f V @ 125.00 kHz", vLf125
/1000.0);
2956 PrintToScrollback("# LF antenna: %5.2f V @ 134.00 kHz", vLf134
/1000.0);
2957 PrintToScrollback("# LF optimal: %5.2f V @%9.2f kHz", peakv
/1000.0, 12000.0/(peakf
+1));
2958 PrintToScrollback("# HF antenna: %5.2f V @ 13.56 MHz", vHf
/1000.0);
2960 PrintToScrollback("# Your LF antenna is unusable.");
2961 else if (peakv
<10000)
2962 PrintToScrollback("# Your LF antenna is marginal.");
2964 PrintToScrollback("# Your HF antenna is unusable.");
2966 PrintToScrollback("# Your HF antenna is marginal.");
2970 PrintToScrollback("unrecognized command %08x\n", c
->cmd
);