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 CmdLosimBidir(char *str
)
669 c
.cmd
= CMD_LF_SIMULATE_BIDIR
;
670 c
.ext1
= 47; /* Set ADC to twice the carrier for a slight supersampling */
672 SendCommand(&c
, FALSE
);
675 static void CmdLoread(char *str
)
678 // 'h' means higher-low-frequency, 134 kHz
681 } else if (*str
== '\0') {
684 PrintToScrollback("use 'loread' or 'loread h'");
687 c
.cmd
= CMD_ACQUIRE_RAW_ADC_SAMPLES_125K
;
688 SendCommand(&c
, FALSE
);
691 static void CmdDetectReader(char *str
)
694 // 'l' means LF - 125/134 kHz
697 } else if (*str
== 'h') {
699 } else if (*str
!= '\0') {
700 PrintToScrollback("use 'detectreader' or 'detectreader l' or 'detectreader h'");
703 c
.cmd
= CMD_LISTEN_READER_FIELD
;
704 SendCommand(&c
, FALSE
);
707 /* send a command before reading */
708 static void CmdLoCommandRead(char *str
)
710 static char dummy
[3];
715 c
.cmd
= CMD_MOD_THEN_ACQUIRE_RAW_ADC_SAMPLES_125K
;
716 sscanf(str
, "%i %i %i %s %s", &c
.ext1
, &c
.ext2
, &c
.ext3
, (char *) &c
.d
.asBytes
,(char *) &dummy
+1);
717 // in case they specified 'h'
718 strcpy((char *)&c
.d
.asBytes
+ strlen((char *)c
.d
.asBytes
), dummy
);
719 SendCommand(&c
, FALSE
);
722 static void CmdLosamples(char *str
)
730 if (n
>16000) n
=16000;
732 for(i
= 0; i
< n
; i
+= 12) {
734 c
.cmd
= CMD_DOWNLOAD_RAW_ADC_SAMPLES_125K
;
736 SendCommand(&c
, FALSE
);
738 if(c
.cmd
!= CMD_DOWNLOADED_RAW_ADC_SAMPLES_125K
) {
740 PrintToScrollback("bad resp");
744 for(j
= 0; j
< 48; j
++) {
745 GraphBuffer
[cnt
++] = ((int)c
.d
.asBytes
[j
]) - 128;
749 RepaintGraphWindow();
752 static void CmdBitsamples(char *str
)
759 for(i
= 0; i
< n
; i
+= 12) {
761 c
.cmd
= CMD_DOWNLOAD_RAW_ADC_SAMPLES_125K
;
763 SendCommand(&c
, FALSE
);
765 if(c
.cmd
!= CMD_DOWNLOADED_RAW_ADC_SAMPLES_125K
) {
766 PrintToScrollback("bad resp");
770 for(j
= 0; j
< 48; j
++) {
771 for(k
= 0; k
< 8; k
++) {
772 if(c
.d
.asBytes
[j
] & (1 << (7 - k
))) {
773 GraphBuffer
[cnt
++] = 1;
775 GraphBuffer
[cnt
++] = 0;
781 RepaintGraphWindow();
784 static void CmdHisamples(char *str
)
790 for(i
= 0; i
< n
; i
+= 12) {
792 c
.cmd
= CMD_DOWNLOAD_RAW_ADC_SAMPLES_125K
;
794 SendCommand(&c
, FALSE
);
796 if(c
.cmd
!= CMD_DOWNLOADED_RAW_ADC_SAMPLES_125K
) {
797 PrintToScrollback("bad resp");
801 for(j
= 0; j
< 48; j
++) {
802 GraphBuffer
[cnt
++] = (int)((BYTE
)c
.d
.asBytes
[j
]);
807 RepaintGraphWindow();
810 static int CmdHisamplest(char *str
, int nrlow
)
822 for(i
= 0; i
< n
; i
+= 12) {
824 c
.cmd
= CMD_DOWNLOAD_RAW_ADC_SAMPLES_125K
;
826 SendCommand(&c
, FALSE
);
828 if(c
.cmd
!= CMD_DOWNLOADED_RAW_ADC_SAMPLES_125K
) {
829 PrintToScrollback("bad resp");
833 for(j
= 0; j
< 48; j
++) {
834 t2
= (int)((BYTE
)c
.d
.asBytes
[j
]);
835 if((t2
^ 0xC0) & 0xC0) { hasbeennull
++; }
841 t1
= (t2
& 0x80) ^ (t2
& 0x20);
842 t2
= ((t2
<< 1) & 0x80) ^ ((t2
<< 1) & 0x20);
848 t2
= ((t2
<< 1) & 0x80);
854 t2
= ((t2
<< 1) & 0x20);
858 // both, but tag with other algorithm
859 t1
= (t2
& 0x80) ^ (t2
& 0x08);
860 t2
= ((t2
<< 1) & 0x80) ^ ((t2
<< 1) & 0x08);
864 GraphBuffer
[cnt
++] = t1
;
865 GraphBuffer
[cnt
++] = t2
;
870 if(hasbeennull
>nrlow
|| nrlow
==0) {
871 PrintToScrollback("hasbeennull=%d", hasbeennull
);
880 static void CmdHexsamples(char *str
)
891 for(i
= 0; i
< n
; i
+= 12) {
893 c
.cmd
= CMD_DOWNLOAD_RAW_ADC_SAMPLES_125K
;
895 SendCommand(&c
, FALSE
);
897 if(c
.cmd
!= CMD_DOWNLOADED_RAW_ADC_SAMPLES_125K
) {
898 PrintToScrollback("bad resp");
902 for(j
= 0; j
< 48; j
+= 8) {
903 PrintToScrollback("%02x %02x %02x %02x %02x %02x %02x %02x",
918 static void CmdHisampless(char *str
)
930 for(i
= 0; i
< n
; i
+= 12) {
932 c
.cmd
= CMD_DOWNLOAD_RAW_ADC_SAMPLES_125K
;
934 SendCommand(&c
, FALSE
);
936 if(c
.cmd
!= CMD_DOWNLOADED_RAW_ADC_SAMPLES_125K
) {
937 PrintToScrollback("bad resp");
941 for(j
= 0; j
< 48; j
++) {
942 GraphBuffer
[cnt
++] = (int)((signed char)c
.d
.asBytes
[j
]);
947 RepaintGraphWindow();
950 static WORD
Iso15693Crc(BYTE
*v
, int n
)
956 for(i
= 0; i
< n
; i
++) {
957 reg
= reg
^ ((DWORD
)v
[i
]);
958 for (j
= 0; j
< 8; j
++) {
960 reg
= (reg
>> 1) ^ 0x8408;
970 static void CmdHi14bdemod(char *str
)
975 BOOL negateI
, negateQ
;
980 // As received, the samples are pairs, correlations against I and Q
981 // square waves. So estimate angle of initial carrier (or just
982 // quadrant, actually), and then do the demod.
984 // First, estimate where the tag starts modulating.
985 for(i
= 0; i
< GraphTraceLen
; i
+= 2) {
986 if(abs(GraphBuffer
[i
]) + abs(GraphBuffer
[i
+1]) > 40) {
990 if(i
>= GraphTraceLen
) {
991 PrintToScrollback("too weak to sync");
994 PrintToScrollback("out of weak at %d", i
);
997 // Now, estimate the phase in the initial modulation of the tag
1000 for(; i
< (outOfWeakAt
+ 16); i
+= 2) {
1001 isum
+= GraphBuffer
[i
+0];
1002 qsum
+= GraphBuffer
[i
+1];
1004 negateI
= (isum
< 0);
1005 negateQ
= (qsum
< 0);
1007 // Turn the correlation pairs into soft decisions on the bit.
1009 for(i
= 0; i
< GraphTraceLen
/2; i
++) {
1010 int si
= GraphBuffer
[j
];
1011 int sq
= GraphBuffer
[j
+1];
1012 if(negateI
) si
= -si
;
1013 if(negateQ
) sq
= -sq
;
1014 GraphBuffer
[i
] = si
+ sq
;
1020 while(GraphBuffer
[i
] > 0 && i
< GraphTraceLen
)
1022 if(i
>= GraphTraceLen
) goto demodError
;
1025 while(GraphBuffer
[i
] < 0 && i
< GraphTraceLen
)
1027 if(i
>= GraphTraceLen
) goto demodError
;
1028 if((i
- iold
) > 23) goto demodError
;
1030 PrintToScrollback("make it to demod loop");
1034 while(GraphBuffer
[i
] >= 0 && i
< GraphTraceLen
)
1036 if(i
>= GraphTraceLen
) goto demodError
;
1037 if((i
- iold
) > 6) goto demodError
;
1040 if(i
+ 20 >= GraphTraceLen
) goto demodError
;
1042 for(j
= 0; j
< 10; j
++) {
1043 int soft
= GraphBuffer
[i
] + GraphBuffer
[i
+1];
1045 if(abs(soft
) < ((abs(isum
) + abs(qsum
))/20)) {
1046 PrintToScrollback("weak bit");
1050 if(GraphBuffer
[i
] + GraphBuffer
[i
+1] >= 0) {
1057 if( (shiftReg
& 0x200) &&
1058 !(shiftReg
& 0x001))
1060 // valid data byte, start and stop bits okay
1061 PrintToScrollback(" %02x", (shiftReg
>> 1) & 0xff);
1062 data
[dataLen
++] = (shiftReg
>> 1) & 0xff;
1063 if(dataLen
>= sizeof(data
)) {
1066 } else if(shiftReg
== 0x000) {
1075 ComputeCrc14443(CRC_14443_B
, data
, dataLen
-2, &first
, &second
);
1076 PrintToScrollback("CRC: %02x %02x (%s)\n", first
, second
,
1077 (first
== data
[dataLen
-2] && second
== data
[dataLen
-1]) ?
1078 "ok" : "****FAIL****");
1080 RepaintGraphWindow();
1084 PrintToScrollback("demod error");
1085 RepaintGraphWindow();
1088 static void CmdHi14list(char *str
)
1091 GetFromBigBuf(got
, sizeof(got
));
1093 PrintToScrollback("recorded activity:");
1094 PrintToScrollback(" time :rssi: who bytes");
1095 PrintToScrollback("---------+----+----+-----------");
1106 int timestamp
= *((DWORD
*)(got
+i
));
1107 if(timestamp
& 0x80000000) {
1108 timestamp
&= 0x7fffffff;
1113 int metric
= *((DWORD
*)(got
+i
+4));
1120 if(i
+ len
>= 900) {
1124 BYTE
*frame
= (got
+i
+9);
1126 char line
[1000] = "";
1128 for(j
= 0; j
< len
; j
++) {
1129 sprintf(line
+(j
*3), "%02x ", frame
[j
]);
1135 ComputeCrc14443(CRC_14443_B
, frame
, len
-2, &b1
, &b2
);
1136 if(b1
!= frame
[len
-2] || b2
!= frame
[len
-1]) {
1137 crc
= "**FAIL CRC**";
1145 char metricString
[100];
1147 sprintf(metricString
, "%3d", metric
);
1149 strcpy(metricString
, " ");
1152 PrintToScrollback(" +%7d: %s: %s %s %s",
1153 (prev
< 0 ? 0 : timestamp
- prev
),
1155 (isResponse
? "TAG" : " "), line
, crc
);
1162 static void CmdHi14alist(char *str
)
1165 GetFromBigBuf(got
, sizeof(got
));
1167 PrintToScrollback("recorded activity:");
1168 PrintToScrollback(" ETU :rssi: who bytes");
1169 PrintToScrollback("---------+----+----+-----------");
1180 int timestamp
= *((DWORD
*)(got
+i
));
1181 if(timestamp
& 0x80000000) {
1182 timestamp
&= 0x7fffffff;
1189 int parityBits
= *((DWORD
*)(got
+i
+4));
1190 // 4 bytes of additional information...
1191 // maximum of 32 additional parity bit information
1194 // at each quarter bit period we can send power level (16 levels)
1195 // or each half bit period in 256 levels.
1203 if(i
+ len
>= 1900) {
1207 BYTE
*frame
= (got
+i
+9);
1209 // Break and stick with current result if buffer was not completely full
1210 if(frame
[0] == 0x44 && frame
[1] == 0x44 && frame
[3] == 0x44) { break; }
1212 char line
[1000] = "";
1214 for(j
= 0; j
< len
; j
++) {
1215 int oddparity
= 0x01;
1219 oddparity
^= (((frame
[j
] & 0xFF) >> k
) & 0x01);
1222 //if((parityBits >> (len - j - 1)) & 0x01) {
1223 if(isResponse
&& (oddparity
!= ((parityBits
>> (len
- j
- 1)) & 0x01))) {
1224 sprintf(line
+(j
*4), "%02x! ", frame
[j
]);
1227 sprintf(line
+(j
*4), "%02x ", frame
[j
]);
1235 for(j
= 0; j
< (len
- 1); j
++) {
1236 // gives problems... search for the reason..
1237 /*if(frame[j] == 0xAA) {
1238 switch(frame[j+1]) {
1240 crc = "[1] Two drops close after each other";
1243 crc = "[2] Potential SOC with a drop in second half of bitperiod";
1246 crc = "[3] Segment Z after segment X is not possible";
1249 crc = "[4] Parity bit of a fully received byte was wrong";
1252 crc = "[?] Unknown error";
1259 if(strlen(crc
)==0) {
1260 ComputeCrc14443(CRC_14443_A
, frame
, len
-2, &b1
, &b2
);
1261 if(b1
!= frame
[len
-2] || b2
!= frame
[len
-1]) {
1262 crc
= (isResponse
& (len
< 6)) ? "" : " !crc";
1271 char metricString
[100];
1273 sprintf(metricString
, "%3d", metric
);
1275 strcpy(metricString
, " ");
1278 PrintToScrollback(" +%7d: %s: %s %s %s",
1279 (prev
< 0 ? 0 : (timestamp
- prev
)),
1281 (isResponse
? "TAG" : " "), line
, crc
);
1286 CommandFinished
= 1;
1289 static void CmdHi15demod(char *str
)
1291 // The sampling rate is 106.353 ksps/s, for T = 18.8 us
1294 // 1) Unmodulated time of 56.64us
1295 // 2) 24 pulses of 423.75khz
1296 // 3) logic '1' (unmodulated for 18.88us followed by 8 pulses of 423.75khz)
1298 static const int FrameSOF
[] = {
1299 -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
1300 -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
1301 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
1302 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
1308 static const int Logic0
[] = {
1314 static const int Logic1
[] = {
1322 // 1) logic '0' (8 pulses of 423.75khz followed by unmodulated for 18.88us)
1323 // 2) 24 pulses of 423.75khz
1324 // 3) Unmodulated time of 56.64us
1326 static const int FrameEOF
[] = {
1331 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
1332 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
1333 -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
1334 -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1
1338 int max
= 0, maxPos
;
1342 if(GraphTraceLen
< 1000) return;
1344 // First, correlate for SOF
1345 for(i
= 0; i
< 100; i
++) {
1347 for(j
= 0; j
< arraylen(FrameSOF
); j
+= skip
) {
1348 corr
+= FrameSOF
[j
]*GraphBuffer
[i
+(j
/skip
)];
1355 PrintToScrollback("SOF at %d, correlation %d", maxPos
,
1356 max
/(arraylen(FrameSOF
)/skip
));
1358 i
= maxPos
+ arraylen(FrameSOF
)/skip
;
1361 memset(outBuf
, 0, sizeof(outBuf
));
1364 int corr0
= 0, corr1
= 0, corrEOF
= 0;
1365 for(j
= 0; j
< arraylen(Logic0
); j
+= skip
) {
1366 corr0
+= Logic0
[j
]*GraphBuffer
[i
+(j
/skip
)];
1368 for(j
= 0; j
< arraylen(Logic1
); j
+= skip
) {
1369 corr1
+= Logic1
[j
]*GraphBuffer
[i
+(j
/skip
)];
1371 for(j
= 0; j
< arraylen(FrameEOF
); j
+= skip
) {
1372 corrEOF
+= FrameEOF
[j
]*GraphBuffer
[i
+(j
/skip
)];
1374 // Even things out by the length of the target waveform.
1378 if(corrEOF
> corr1
&& corrEOF
> corr0
) {
1379 PrintToScrollback("EOF at %d", i
);
1381 } else if(corr1
> corr0
) {
1382 i
+= arraylen(Logic1
)/skip
;
1385 i
+= arraylen(Logic0
)/skip
;
1392 if((i
+(int)arraylen(FrameEOF
)) >= GraphTraceLen
) {
1393 PrintToScrollback("ran off end!");
1398 PrintToScrollback("error, uneven octet! (discard extra bits!)");
1399 PrintToScrollback(" mask=%02x", mask
);
1401 PrintToScrollback("%d octets", k
);
1403 for(i
= 0; i
< k
; i
++) {
1404 PrintToScrollback("# %2d: %02x ", i
, outBuf
[i
]);
1406 PrintToScrollback("CRC=%04x", Iso15693Crc(outBuf
, k
-2));
1409 static void CmdFSKdemod(char *cmdline
)
1411 static const int LowTone
[] = {
1412 1, 1, 1, 1, 1, -1, -1, -1, -1, -1,
1413 1, 1, 1, 1, 1, -1, -1, -1, -1, -1,
1414 1, 1, 1, 1, 1, -1, -1, -1, -1, -1,
1415 1, 1, 1, 1, 1, -1, -1, -1, -1, -1,
1416 1, 1, 1, 1, 1, -1, -1, -1, -1, -1
1418 static const int HighTone
[] = {
1419 1, 1, 1, 1, 1, -1, -1, -1, -1,
1420 1, 1, 1, 1, -1, -1, -1, -1,
1421 1, 1, 1, 1, -1, -1, -1, -1,
1422 1, 1, 1, 1, -1, -1, -1, -1,
1423 1, 1, 1, 1, -1, -1, -1, -1,
1424 1, 1, 1, 1, -1, -1, -1, -1, -1,
1427 int lowLen
= sizeof(LowTone
)/sizeof(int);
1428 int highLen
= sizeof(HighTone
)/sizeof(int);
1429 int convLen
= (highLen
>lowLen
)?highLen
:lowLen
;
1430 DWORD hi
= 0, lo
= 0;
1433 int minMark
=0, maxMark
=0;
1435 for(i
= 0; i
< GraphTraceLen
- convLen
; i
++) {
1436 int lowSum
= 0, highSum
= 0;
1438 for(j
= 0; j
< lowLen
; j
++) {
1439 lowSum
+= LowTone
[j
]*GraphBuffer
[i
+j
];
1441 for(j
= 0; j
< highLen
; j
++) {
1442 highSum
+= HighTone
[j
]*GraphBuffer
[i
+j
];
1444 lowSum
= abs((100*lowSum
) / lowLen
);
1445 highSum
= abs((100*highSum
) / highLen
);
1446 GraphBuffer
[i
] = (highSum
<< 16) | lowSum
;
1449 for(i
= 0; i
< GraphTraceLen
- convLen
- 16; i
++) {
1451 int lowTot
= 0, highTot
= 0;
1452 // 10 and 8 are f_s divided by f_l and f_h, rounded
1453 for(j
= 0; j
< 10; j
++) {
1454 lowTot
+= (GraphBuffer
[i
+j
] & 0xffff);
1456 for(j
= 0; j
< 8; j
++) {
1457 highTot
+= (GraphBuffer
[i
+j
] >> 16);
1459 GraphBuffer
[i
] = lowTot
- highTot
;
1460 if (GraphBuffer
[i
]>maxMark
) maxMark
=GraphBuffer
[i
];
1461 if (GraphBuffer
[i
]<minMark
) minMark
=GraphBuffer
[i
];
1464 GraphTraceLen
-= (convLen
+ 16);
1466 RepaintGraphWindow();
1468 // Find bit-sync (3 lo followed by 3 high)
1469 int max
= 0, maxPos
= 0;
1470 for(i
= 0; i
< 6000; i
++) {
1472 for(j
= 0; j
< 3*lowLen
; j
++) {
1473 dec
-= GraphBuffer
[i
+j
];
1475 for(; j
< 3*(lowLen
+ highLen
); j
++) {
1476 dec
+= GraphBuffer
[i
+j
];
1484 // place start of bit sync marker in graph
1485 GraphBuffer
[maxPos
] = maxMark
;
1486 GraphBuffer
[maxPos
+1] = minMark
;
1490 // place end of bit sync marker in graph
1491 GraphBuffer
[maxPos
] = maxMark
;
1492 GraphBuffer
[maxPos
+1] = minMark
;
1494 PrintToScrollback("actual data bits start at sample %d", maxPos
);
1495 PrintToScrollback("length %d/%d", highLen
, lowLen
);
1498 bits
[sizeof(bits
)-1] = '\0';
1500 // find bit pairs and manchester decode them
1501 for(i
= 0; i
< arraylen(bits
)-1; i
++) {
1503 for(j
= 0; j
< lowLen
; j
++) {
1504 dec
-= GraphBuffer
[maxPos
+j
];
1506 for(; j
< lowLen
+ highLen
; j
++) {
1507 dec
+= GraphBuffer
[maxPos
+j
];
1510 // place inter bit marker in graph
1511 GraphBuffer
[maxPos
] = maxMark
;
1512 GraphBuffer
[maxPos
+1] = minMark
;
1514 // hi and lo form a 64 bit pair
1515 hi
= (hi
<<1)|(lo
>>31);
1517 // store decoded bit as binary (in hi/lo) and text (in bits[])
1525 PrintToScrollback("bits: '%s'", bits
);
1526 PrintToScrollback("hex: %08x %08x", hi
, lo
);
1529 // read a TI tag and return its ID
1530 static void CmdTIRead(char *str
)
1533 c
.cmd
= CMD_READ_TI_TYPE
;
1534 SendCommand(&c
, FALSE
);
1537 // write new data to a r/w TI tag
1538 static void CmdTIWrite(char *str
)
1543 c
.cmd
= CMD_WRITE_TI_TYPE
;
1544 res
= sscanf(str
, "0x%x 0x%x 0x%x ", &c
.ext1
, &c
.ext2
, &c
.ext3
);
1545 if (res
== 2) c
.ext3
=0;
1547 PrintToScrollback("Please specify the data as two hex strings, optionally the CRC as a third");
1549 SendCommand(&c
, FALSE
);
1552 static void CmdTIDemod(char *cmdline
)
1554 /* MATLAB as follows:
1555 f_s = 2000000; % sampling frequency
1556 f_l = 123200; % low FSK tone
1557 f_h = 134200; % high FSK tone
1559 T_l = 119e-6; % low bit duration
1560 T_h = 130e-6; % high bit duration
1562 l = 2*pi*ones(1, floor(f_s*T_l))*(f_l/f_s);
1563 h = 2*pi*ones(1, floor(f_s*T_h))*(f_h/f_s);
1565 l = sign(sin(cumsum(l)));
1566 h = sign(sin(cumsum(h)));
1569 // 2M*16/134.2k = 238
1570 static const int LowTone
[] = {
1571 1, 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,
1575 1, 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, -1, -1, -1, -1, -1, -1,
1577 1, 1, 1, 1, 1, 1, 1, 1, -1, -1, -1, -1, -1, -1, -1, -1,
1578 1, 1, 1, 1, 1, 1, 1, 1, -1, -1, -1, -1, -1, -1, -1, -1,
1579 1, 1, 1, 1, 1, 1, 1, 1, 1, -1, -1, -1, -1, -1, -1, -1, -1,
1580 1, 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, -1,
1582 1, 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, -1, -1,
1584 1, 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
1587 // 2M*16/123.2k = 260
1588 static const int HighTone
[] = {
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, -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,
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, -1,
1597 1, 1, 1, 1, 1, 1, 1, -1, -1, -1, -1, -1, -1, -1, -1,
1598 1, 1, 1, 1, 1, 1, 1, -1, -1, -1, -1, -1, -1, -1, -1,
1599 1, 1, 1, 1, 1, 1, 1, -1, -1, -1, -1, -1, -1, -1,
1600 1, 1, 1, 1, 1, 1, 1, 1, -1, -1, -1, -1, -1, -1, -1,
1601 1, 1, 1, 1, 1, 1, 1, 1, -1, -1, -1, -1, -1, -1, -1,
1602 1, 1, 1, 1, 1, 1, 1, 1, -1, -1, -1, -1, -1, -1, -1,
1603 1, 1, 1, 1, 1, 1, 1, -1, -1, -1, -1, -1, -1, -1, -1,
1604 1, 1, 1, 1, 1, 1, 1, -1, -1, -1, -1, -1, -1, -1, -1,
1605 1, 1, 1, 1, 1, 1, 1, -1, -1, -1, -1, -1, -1, -1,
1606 1, 1, 1, 1, 1, 1, 1, 1
1608 int lowLen
= sizeof(LowTone
)/sizeof(int);
1609 int highLen
= sizeof(HighTone
)/sizeof(int);
1610 int convLen
= (highLen
>lowLen
)?highLen
:lowLen
;
1613 int lowSum
= 0, highSum
= 0;;
1614 int lowTot
= 0, highTot
= 0;
1616 for(i
= 0; i
< GraphTraceLen
- convLen
; i
++) {
1620 for(j
= 0; j
< lowLen
; j
++) {
1621 lowSum
+= LowTone
[j
]*GraphBuffer
[i
+j
];
1623 for(j
= 0; j
< highLen
; j
++) {
1624 highSum
+= HighTone
[j
]*GraphBuffer
[i
+j
];
1626 lowSum
= abs((100*lowSum
) / lowLen
);
1627 highSum
= abs((100*highSum
) / highLen
);
1628 lowSum
= (lowSum
<0)?-lowSum
:lowSum
;
1629 highSum
= (highSum
<0)?-highSum
:highSum
;
1631 GraphBuffer
[i
] = (highSum
<< 16) | lowSum
;
1634 for(i
= 0; i
< GraphTraceLen
- convLen
- 16; i
++) {
1637 // 16 and 15 are f_s divided by f_l and f_h, rounded
1638 for(j
= 0; j
< 16; j
++) {
1639 lowTot
+= (GraphBuffer
[i
+j
] & 0xffff);
1641 for(j
= 0; j
< 15; j
++) {
1642 highTot
+= (GraphBuffer
[i
+j
] >> 16);
1644 GraphBuffer
[i
] = lowTot
- highTot
;
1647 GraphTraceLen
-= (convLen
+ 16);
1649 RepaintGraphWindow();
1651 // TI tag data format is 16 prebits, 8 start bits, 64 data bits,
1652 // 16 crc CCITT bits, 8 stop bits, 15 end bits
1654 // the 16 prebits are always low
1655 // the 8 start and stop bits of a tag must match
1656 // the start/stop prebits of a ro tag are 01111110
1657 // the start/stop prebits of a rw tag are 11111110
1658 // the 15 end bits of a ro tag are all low
1659 // the 15 end bits of a rw tag match bits 15-1 of the data bits
1661 // Okay, so now we have unsliced soft decisions;
1662 // find bit-sync, and then get some bits.
1663 // look for 17 low bits followed by 6 highs (common pattern for ro and rw tags)
1664 int max
= 0, maxPos
= 0;
1665 for(i
= 0; i
< 6000; i
++) {
1668 // searching 17 consecutive lows
1669 for(j
= 0; j
< 17*lowLen
; j
++) {
1670 dec
-= GraphBuffer
[i
+j
];
1672 // searching 7 consecutive highs
1673 for(; j
< 17*lowLen
+ 6*highLen
; j
++) {
1674 dec
+= GraphBuffer
[i
+j
];
1682 // place a marker in the buffer to visually aid location
1683 // of the start of sync
1684 GraphBuffer
[maxPos
] = 800;
1685 GraphBuffer
[maxPos
+1] = -800;
1687 // advance pointer to start of actual data stream (after 16 pre and 8 start bits)
1688 maxPos
+= 17*lowLen
;
1689 maxPos
+= 6*highLen
;
1691 // place a marker in the buffer to visually aid location
1692 // of the end of sync
1693 GraphBuffer
[maxPos
] = 800;
1694 GraphBuffer
[maxPos
+1] = -800;
1696 PrintToScrollback("actual data bits start at sample %d", maxPos
);
1698 PrintToScrollback("length %d/%d", highLen
, lowLen
);
1700 BYTE bits
[1+64+16+8+16];
1701 bits
[sizeof(bits
)-1] = '\0';
1703 DWORD shift3
= 0x7e000000, shift2
= 0, shift1
= 0, shift0
= 0;
1705 for(i
= 0; i
< arraylen(bits
)-1; i
++) {
1709 for(j
= 0; j
< lowLen
; j
++) {
1710 low
-= GraphBuffer
[maxPos
+j
];
1712 for(j
= 0; j
< highLen
; j
++) {
1713 high
+= GraphBuffer
[maxPos
+j
];
1719 // bitstream arrives lsb first so shift right
1726 // 128 bit right shift register
1727 shift0
= (shift0
>>1) | (shift1
<< 31);
1728 shift1
= (shift1
>>1) | (shift2
<< 31);
1729 shift2
= (shift2
>>1) | (shift3
<< 31);
1732 // place a marker in the buffer between bits to visually aid location
1733 GraphBuffer
[maxPos
] = 800;
1734 GraphBuffer
[maxPos
+1] = -800;
1736 PrintToScrollback("Info: raw tag bits = %s", bits
);
1738 TagType
= (shift3
>>8)&0xff;
1739 if ( TagType
!= ((shift0
>>16)&0xff) ) {
1740 PrintToScrollback("Error: start and stop bits do not match!");
1743 else if (TagType
== 0x7e) {
1744 PrintToScrollback("Info: Readonly TI tag detected.");
1747 else if (TagType
== 0xfe) {
1748 PrintToScrollback("Info: Rewriteable TI tag detected.");
1750 // put 64 bit data into shift1 and shift0
1751 shift0
= (shift0
>>24) | (shift1
<< 8);
1752 shift1
= (shift1
>>24) | (shift2
<< 8);
1754 // align 16 bit crc into lower half of shift2
1755 shift2
= ((shift2
>>24) | (shift3
<< 8)) & 0x0ffff;
1757 // align 16 bit "end bits" or "ident" into lower half of shift3
1760 // only 15 bits compare, last bit of ident is not valid
1761 if ( (shift3
^shift0
)&0x7fff ) {
1762 PrintToScrollback("Error: Ident mismatch!");
1764 // WARNING the order of the bytes in which we calc crc below needs checking
1765 // i'm 99% sure the crc algorithm is correct, but it may need to eat the
1766 // bytes in reverse or something
1769 crc
= update_crc16(crc
, (shift0
)&0xff);
1770 crc
= update_crc16(crc
, (shift0
>>8)&0xff);
1771 crc
= update_crc16(crc
, (shift0
>>16)&0xff);
1772 crc
= update_crc16(crc
, (shift0
>>24)&0xff);
1773 crc
= update_crc16(crc
, (shift1
)&0xff);
1774 crc
= update_crc16(crc
, (shift1
>>8)&0xff);
1775 crc
= update_crc16(crc
, (shift1
>>16)&0xff);
1776 crc
= update_crc16(crc
, (shift1
>>24)&0xff);
1777 PrintToScrollback("Info: Tag data = %08X%08X", shift1
, shift0
);
1778 if (crc
!= (shift2
&0xffff)) {
1779 PrintToScrollback("Error: CRC mismatch, calculated %04X, got ^04X", crc
, shift2
&0xffff);
1781 PrintToScrollback("Info: CRC %04X is good", crc
);
1785 PrintToScrollback("Unknown tag type.");
1790 static void CmdNorm(char *str
)
1793 int max
= INT_MIN
, min
= INT_MAX
;
1794 for(i
= 10; i
< GraphTraceLen
; i
++) {
1795 if(GraphBuffer
[i
] > max
) {
1796 max
= GraphBuffer
[i
];
1798 if(GraphBuffer
[i
] < min
) {
1799 min
= GraphBuffer
[i
];
1803 for(i
= 0; i
< GraphTraceLen
; i
++) {
1804 GraphBuffer
[i
] = (GraphBuffer
[i
] - ((max
+ min
)/2))*1000/
1808 RepaintGraphWindow();
1811 static void CmdDec(char *str
)
1814 for(i
= 0; i
< (GraphTraceLen
/2); i
++) {
1815 GraphBuffer
[i
] = GraphBuffer
[i
*2];
1818 PrintToScrollback("decimated by 2");
1819 RepaintGraphWindow();
1822 static void CmdHpf(char *str
)
1826 for(i
= 10; i
< GraphTraceLen
; i
++) {
1827 accum
+= GraphBuffer
[i
];
1829 accum
/= (GraphTraceLen
- 10);
1830 for(i
= 0; i
< GraphTraceLen
; i
++) {
1831 GraphBuffer
[i
] -= accum
;
1834 RepaintGraphWindow();
1837 static void CmdZerocrossings(char *str
)
1840 // Zero-crossings aren't meaningful unless the signal is zero-mean.
1846 for(i
= 0; i
< GraphTraceLen
; i
++) {
1847 if(GraphBuffer
[i
]*sign
>= 0) {
1848 // No change in sign, reproduce the previous sample count.
1850 GraphBuffer
[i
] = lastZc
;
1852 // Change in sign, reset the sample count.
1854 GraphBuffer
[i
] = lastZc
;
1862 RepaintGraphWindow();
1865 static void CmdThreshold(char *str
)
1868 int threshold
= atoi(str
);
1870 for(i
= 0; i
< GraphTraceLen
; i
++) {
1871 if(GraphBuffer
[i
]>= threshold
)
1876 RepaintGraphWindow();
1879 static void CmdLtrim(char *str
)
1884 for(i
= ds
; i
< GraphTraceLen
; i
++) {
1885 GraphBuffer
[i
-ds
] = GraphBuffer
[i
];
1887 GraphTraceLen
-= ds
;
1889 RepaintGraphWindow();
1892 static void CmdAutoCorr(char *str
)
1894 static int CorrelBuffer
[MAX_GRAPH_TRACE_LEN
];
1896 int window
= atoi(str
);
1899 PrintToScrollback("needs a window");
1903 if(window
>= GraphTraceLen
) {
1904 PrintToScrollback("window must be smaller than trace (%d samples)",
1909 PrintToScrollback("performing %d correlations", GraphTraceLen
- window
);
1912 for(i
= 0; i
< GraphTraceLen
- window
; i
++) {
1915 for(j
= 0; j
< window
; j
++) {
1916 sum
+= (GraphBuffer
[j
]*GraphBuffer
[i
+j
]) / 256;
1918 CorrelBuffer
[i
] = sum
;
1920 GraphTraceLen
= GraphTraceLen
- window
;
1921 memcpy(GraphBuffer
, CorrelBuffer
, GraphTraceLen
*sizeof(int));
1923 RepaintGraphWindow();
1926 static void CmdVchdemod(char *str
)
1928 // Is this the entire sync pattern, or does this also include some
1929 // data bits that happen to be the same everywhere? That would be
1931 static const int SyncPattern
[] = {
1932 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
1933 1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
1934 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
1935 1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
1936 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
1937 1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
1938 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
1939 1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
1940 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
1941 1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
1944 // So first, we correlate for the sync pattern, and mark that.
1945 int bestCorrel
= 0, bestPos
= 0;
1947 // It does us no good to find the sync pattern, with fewer than
1948 // 2048 samples after it...
1949 for(i
= 0; i
< (GraphTraceLen
-2048); i
++) {
1952 for(j
= 0; j
< arraylen(SyncPattern
); j
++) {
1953 sum
+= GraphBuffer
[i
+j
]*SyncPattern
[j
];
1955 if(sum
> bestCorrel
) {
1960 PrintToScrollback("best sync at %d [metric %d]", bestPos
, bestCorrel
);
1965 int worst
= INT_MAX
;
1968 for(i
= 0; i
< 2048; i
+= 8) {
1971 for(j
= 0; j
< 8; j
++) {
1972 sum
+= GraphBuffer
[bestPos
+i
+j
];
1979 if(abs(sum
) < worst
) {
1984 PrintToScrollback("bits:");
1985 PrintToScrollback("%s", bits
);
1986 PrintToScrollback("worst metric: %d at pos %d", worst
, worstPos
);
1988 if(strcmp(str
, "clone")==0) {
1991 for(s
= bits
; *s
; s
++) {
1993 for(j
= 0; j
< 16; j
++) {
1994 GraphBuffer
[GraphTraceLen
++] = (*s
== '1') ? 1 : 0;
1997 RepaintGraphWindow();
2001 static void CmdIndalademod(char *str
)
2003 // Usage: recover 64bit UID by default, specify "224" as arg to recover a 224bit UID
2008 // worst case with GraphTraceLen=64000 is < 4096
2009 // under normal conditions it's < 2048
2012 int worst
= 0, worstPos
= 0;
2013 PrintToScrollback("Expecting a bit less than %d raw bits", GraphTraceLen
/32);
2014 for(i
= 0; i
< GraphTraceLen
-1; i
+= 2) {
2016 if((GraphBuffer
[i
] > GraphBuffer
[i
+ 1]) && (state
!= 1)) {
2018 for(j
= 0; j
< count
- 8; j
+= 16) {
2019 rawbits
[rawbit
++] = 0;
2021 if ((abs(count
- j
)) > worst
) {
2022 worst
= abs(count
- j
);
2028 } else if((GraphBuffer
[i
] < GraphBuffer
[i
+ 1]) && (state
!= 0)) {
2030 for(j
= 0; j
< count
- 8; j
+= 16) {
2031 rawbits
[rawbit
++] = 1;
2033 if ((abs(count
- j
)) > worst
) {
2034 worst
= abs(count
- j
);
2042 PrintToScrollback("Recovered %d raw bits", rawbit
);
2043 PrintToScrollback("worst metric (0=best..7=worst): %d at pos %d", worst
, worstPos
);
2045 // Finding the start of a UID
2046 int uidlen
, long_wait
;
2047 if(strcmp(str
, "224") == 0) {
2056 for(start
= 0; start
<= rawbit
- uidlen
; start
++) {
2057 first
= rawbits
[start
];
2058 for(i
= start
; i
< start
+ long_wait
; i
++) {
2059 if(rawbits
[i
] != first
) {
2063 if(i
== (start
+ long_wait
)) {
2067 if(start
== rawbit
- uidlen
+ 1) {
2068 PrintToScrollback("nothing to wait for");
2072 // Inverting signal if needed
2074 for(i
= start
; i
< rawbit
; i
++) {
2075 rawbits
[i
] = !rawbits
[i
];
2082 showbits
[uidlen
]='\0';
2086 if(uidlen
> rawbit
) {
2087 PrintToScrollback("Warning: not enough raw bits to get a full UID");
2088 for(bit
= 0; bit
< rawbit
; bit
++) {
2089 bits
[bit
] = rawbits
[i
++];
2090 // As we cannot know the parity, let's use "." and "/"
2091 showbits
[bit
] = '.' + bits
[bit
];
2093 showbits
[bit
+1]='\0';
2094 PrintToScrollback("Partial UID=%s", showbits
);
2097 for(bit
= 0; bit
< uidlen
; bit
++) {
2098 bits
[bit
] = rawbits
[i
++];
2099 showbits
[bit
] = '0' + bits
[bit
];
2103 PrintToScrollback("UID=%s", showbits
);
2105 // Checking UID against next occurences
2106 for(; i
+ uidlen
<= rawbit
;) {
2108 for(bit
= 0; bit
< uidlen
; bit
++) {
2109 if(bits
[bit
] != rawbits
[i
++]) {
2119 PrintToScrollback("Occurences: %d (expected %d)", times
, (rawbit
- start
) / uidlen
);
2121 // Remodulating for tag cloning
2122 GraphTraceLen
= 32*uidlen
;
2125 for(bit
= 0; bit
< uidlen
; bit
++) {
2126 if(bits
[bit
] == 0) {
2132 for(j
= 0; j
< 32; j
++) {
2133 GraphBuffer
[i
++] = phase
;
2138 RepaintGraphWindow();
2141 static void CmdFlexdemod(char *str
)
2144 for(i
= 0; i
< GraphTraceLen
; i
++) {
2145 if(GraphBuffer
[i
] < 0) {
2146 GraphBuffer
[i
] = -1;
2152 #define LONG_WAIT 100
2154 for(start
= 0; start
< GraphTraceLen
- LONG_WAIT
; start
++) {
2155 int first
= GraphBuffer
[start
];
2156 for(i
= start
; i
< start
+ LONG_WAIT
; i
++) {
2157 if(GraphBuffer
[i
] != first
) {
2161 if(i
== (start
+ LONG_WAIT
)) {
2165 if(start
== GraphTraceLen
- LONG_WAIT
) {
2166 PrintToScrollback("nothing to wait for");
2170 GraphBuffer
[start
] = 2;
2171 GraphBuffer
[start
+1] = -2;
2177 for(bit
= 0; bit
< 64; bit
++) {
2180 for(j
= 0; j
< 16; j
++) {
2181 sum
+= GraphBuffer
[i
++];
2188 PrintToScrollback("bit %d sum %d", bit
, sum
);
2191 for(bit
= 0; bit
< 64; bit
++) {
2194 for(j
= 0; j
< 16; j
++) {
2195 sum
+= GraphBuffer
[i
++];
2197 if(sum
> 0 && bits
[bit
] != 1) {
2198 PrintToScrollback("oops1 at %d", bit
);
2200 if(sum
< 0 && bits
[bit
] != 0) {
2201 PrintToScrollback("oops2 at %d", bit
);
2205 GraphTraceLen
= 32*64;
2208 for(bit
= 0; bit
< 64; bit
++) {
2209 if(bits
[bit
] == 0) {
2215 for(j
= 0; j
< 32; j
++) {
2216 GraphBuffer
[i
++] = phase
;
2221 RepaintGraphWindow();
2225 * Generic command to demodulate ASK.
2227 * Argument is convention: positive or negative (High mod means zero
2228 * or high mod means one)
2230 * Updates the Graph trace with 0/1 values
2236 static void Cmdaskdemod(char *str
) {
2238 int c
, high
= 0, low
= 0;
2240 // TODO: complain if we do not give 2 arguments here !
2241 sscanf(str
, "%i", &c
);
2243 /* Detect high and lows and clock */
2244 for (i
= 0; i
< GraphTraceLen
; i
++)
2246 if (GraphBuffer
[i
] > high
)
2247 high
= GraphBuffer
[i
];
2248 else if (GraphBuffer
[i
] < low
)
2249 low
= GraphBuffer
[i
];
2252 if (GraphBuffer
[0] > 0) {
2253 GraphBuffer
[0] = 1-c
;
2257 for(i
=1;i
<GraphTraceLen
;i
++) {
2258 /* Transitions are detected at each peak
2259 * Transitions are either:
2260 * - we're low: transition if we hit a high
2261 * - we're high: transition if we hit a low
2262 * (we need to do it this way because some tags keep high or
2263 * low for long periods, others just reach the peak and go
2266 if ((GraphBuffer
[i
]==high
) && (GraphBuffer
[i
-1] == c
)) {
2268 } else if ((GraphBuffer
[i
]==low
) && (GraphBuffer
[i
-1] == (1-c
))){
2272 GraphBuffer
[i
] = GraphBuffer
[i
-1];
2275 RepaintGraphWindow();
2278 /* Print our clock rate */
2279 static void Cmddetectclockrate(char *str
)
2281 int clock
= detectclock(0);
2282 PrintToScrollback("Auto-detected clock rate: %d", clock
);
2288 int detectclock(int peak
)
2294 /* Detect peak if we don't have one */
2296 for (i
= 0; i
< GraphTraceLen
; i
++)
2297 if (GraphBuffer
[i
] > peak
)
2298 peak
= GraphBuffer
[i
];
2300 for (i
= 1; i
< GraphTraceLen
; i
++)
2302 /* If this is the beginning of a peak */
2303 if (GraphBuffer
[i
-1] != GraphBuffer
[i
] && GraphBuffer
[i
] == peak
)
2305 /* Find lowest difference between peaks */
2306 if (lastpeak
&& i
- lastpeak
< clock
)
2308 clock
= i
- lastpeak
;
2317 /* Get or auto-detect clock rate */
2318 int GetClock(char *str
, int peak
)
2322 sscanf(str
, "%i", &clock
);
2323 if (!strcmp(str
, ""))
2326 /* Auto-detect clock */
2329 clock
= detectclock(peak
);
2331 /* Only print this message if we're not looping something */
2333 PrintToScrollback("Auto-detected clock rate: %d", clock
);
2340 * Convert to a bitstream
2342 static void Cmdbitstream(char *str
) {
2349 int hithigh
, hitlow
, first
;
2351 /* Detect high and lows and clock */
2352 for (i
= 0; i
< GraphTraceLen
; i
++)
2354 if (GraphBuffer
[i
] > high
)
2355 high
= GraphBuffer
[i
];
2356 else if (GraphBuffer
[i
] < low
)
2357 low
= GraphBuffer
[i
];
2361 clock
= GetClock(str
, high
);
2363 gtl
= CmdClearGraph(0);
2366 for (i
= 0; i
< (int)(gtl
/ clock
); i
++)
2372 /* Find out if we hit both high and low peaks */
2373 for (j
= 0; j
< clock
; j
++)
2375 if (GraphBuffer
[(i
* clock
) + j
] == high
)
2377 else if (GraphBuffer
[(i
* clock
) + j
] == low
)
2380 /* it doesn't count if it's the first part of our read
2381 because it's really just trailing from the last sequence */
2382 if (first
&& (hithigh
|| hitlow
))
2383 hithigh
= hitlow
= 0;
2387 if (hithigh
&& hitlow
)
2391 /* If we didn't hit both high and low peaks, we had a bit transition */
2392 if (!hithigh
|| !hitlow
)
2395 CmdAppendGraph(0, clock
, bit
);
2396 // for (j = 0; j < (int)(clock/2); j++)
2397 // GraphBuffer[(i * clock) + j] = bit ^ 1;
2398 // for (j = (int)(clock/2); j < clock; j++)
2399 // GraphBuffer[(i * clock) + j] = bit;
2402 RepaintGraphWindow();
2405 /* Modulate our data into manchester */
2406 static void Cmdmanchestermod(char *str
)
2410 int bit
, lastbit
, wave
;
2413 clock
= GetClock(str
, 0);
2417 for (i
= 0; i
< (int)(GraphTraceLen
/ clock
); i
++)
2419 bit
= GraphBuffer
[i
* clock
] ^ 1;
2421 for (j
= 0; j
< (int)(clock
/2); j
++)
2422 GraphBuffer
[(i
* clock
) + j
] = bit
^ lastbit
^ wave
;
2423 for (j
= (int)(clock
/2); j
< clock
; j
++)
2424 GraphBuffer
[(i
* clock
) + j
] = bit
^ lastbit
^ wave
^ 1;
2426 /* Keep track of how we start our wave and if we changed or not this time */
2427 wave
^= bit
^ lastbit
;
2431 RepaintGraphWindow();
2435 * Manchester demodulate a bitstream. The bitstream needs to be already in
2436 * the GraphBuffer as 0 and 1 values
2438 * Give the clock rate as argument in order to help the sync - the algorithm
2439 * resyncs at each pulse anyway.
2441 * Not optimized by any means, this is the 1st time I'm writing this type of
2442 * routine, feel free to improve...
2444 * 1st argument: clock rate (as number of samples per clock rate)
2445 * Typical values can be 64, 32, 128...
2447 static void Cmdmanchesterdemod(char *str
) {
2448 int i
, j
, invert
= 0;
2454 int hithigh
, hitlow
, first
;
2460 /* check if we're inverting output */
2463 PrintToScrollback("Inverting output");
2467 while(*str
== ' '); // in case a 2nd argument was given
2470 /* Holds the decoded bitstream: each clock period contains 2 bits */
2471 /* later simplified to 1 bit after manchester decoding. */
2472 /* Add 10 bits to allow for noisy / uncertain traces without aborting */
2473 /* int BitStream[GraphTraceLen*2/clock+10]; */
2475 /* But it does not work if compiling on WIndows: therefore we just allocate a */
2477 int BitStream
[MAX_GRAPH_TRACE_LEN
];
2479 /* Detect high and lows */
2480 for (i
= 0; i
< GraphTraceLen
; i
++)
2482 if (GraphBuffer
[i
] > high
)
2483 high
= GraphBuffer
[i
];
2484 else if (GraphBuffer
[i
] < low
)
2485 low
= GraphBuffer
[i
];
2489 clock
= GetClock(str
, high
);
2491 int tolerance
= clock
/4;
2493 /* Detect first transition */
2494 /* Lo-Hi (arbitrary) */
2495 for (i
= 0; i
< GraphTraceLen
; i
++)
2497 if (GraphBuffer
[i
] == low
)
2504 /* If we're not working with 1/0s, demod based off clock */
2507 bit
= 0; /* We assume the 1st bit is zero, it may not be
2508 * the case: this routine (I think) has an init problem.
2511 for (; i
< (int)(GraphTraceLen
/ clock
); i
++)
2517 /* Find out if we hit both high and low peaks */
2518 for (j
= 0; j
< clock
; j
++)
2520 if (GraphBuffer
[(i
* clock
) + j
] == high
)
2522 else if (GraphBuffer
[(i
* clock
) + j
] == low
)
2525 /* it doesn't count if it's the first part of our read
2526 because it's really just trailing from the last sequence */
2527 if (first
&& (hithigh
|| hitlow
))
2528 hithigh
= hitlow
= 0;
2532 if (hithigh
&& hitlow
)
2536 /* If we didn't hit both high and low peaks, we had a bit transition */
2537 if (!hithigh
|| !hitlow
)
2540 BitStream
[bit2idx
++] = bit
^ invert
;
2544 /* standard 1/0 bitstream */
2548 /* Then detect duration between 2 successive transitions */
2549 for (bitidx
= 1; i
< GraphTraceLen
; i
++)
2551 if (GraphBuffer
[i
-1] != GraphBuffer
[i
])
2556 // Error check: if bitidx becomes too large, we do not
2557 // have a Manchester encoded bitstream or the clock is really
2559 if (bitidx
> (GraphTraceLen
*2/clock
+8) ) {
2560 PrintToScrollback("Error: the clock you gave is probably wrong, aborting.");
2563 // Then switch depending on lc length:
2564 // Tolerance is 1/4 of clock rate (arbitrary)
2565 if (abs(lc
-clock
/2) < tolerance
) {
2566 // Short pulse : either "1" or "0"
2567 BitStream
[bitidx
++]=GraphBuffer
[i
-1];
2568 } else if (abs(lc
-clock
) < tolerance
) {
2569 // Long pulse: either "11" or "00"
2570 BitStream
[bitidx
++]=GraphBuffer
[i
-1];
2571 BitStream
[bitidx
++]=GraphBuffer
[i
-1];
2575 PrintToScrollback("Warning: Manchester decode error for pulse width detection.");
2576 PrintToScrollback("(too many of those messages mean either the stream is not Manchester encoded, or clock is wrong)");
2580 PrintToScrollback("Error: too many detection errors, aborting.");
2587 // At this stage, we now have a bitstream of "01" ("1") or "10" ("0"), parse it into final decoded bitstream
2588 // Actually, we overwrite BitStream with the new decoded bitstream, we just need to be careful
2589 // to stop output at the final bitidx2 value, not bitidx
2590 for (i
= 0; i
< bitidx
; i
+= 2) {
2591 if ((BitStream
[i
] == 0) && (BitStream
[i
+1] == 1)) {
2592 BitStream
[bit2idx
++] = 1 ^ invert
;
2593 } else if ((BitStream
[i
] == 1) && (BitStream
[i
+1] == 0)) {
2594 BitStream
[bit2idx
++] = 0 ^ invert
;
2596 // We cannot end up in this state, this means we are unsynchronized,
2600 PrintToScrollback("Unsynchronized, resync...");
2601 PrintToScrollback("(too many of those messages mean the stream is not Manchester encoded)");
2605 PrintToScrollback("Error: too many decode errors, aborting.");
2612 PrintToScrollback("Manchester decoded bitstream");
2613 // Now output the bitstream to the scrollback by line of 16 bits
2614 for (i
= 0; i
< (bit2idx
-16); i
+=16) {
2615 PrintToScrollback("%i %i %i %i %i %i %i %i %i %i %i %i %i %i %i %i",
2638 static void CmdHiddemod(char *str
)
2640 if(GraphTraceLen
< 4800) {
2641 PrintToScrollback("too short; need at least 4800 samples");
2645 GraphTraceLen
= 4800;
2647 for(i
= 0; i
< GraphTraceLen
; i
++) {
2648 if(GraphBuffer
[i
] < 0) {
2654 RepaintGraphWindow();
2657 static void CmdPlot(char *str
)
2662 static void CmdGrid(char *str
)
2664 sscanf(str
, "%i %i", &PlotGridX
, &PlotGridY
);
2665 RepaintGraphWindow();
2668 static void CmdHide(char *str
)
2673 static void CmdScale(char *str
)
2675 CursorScaleFactor
= atoi(str
);
2676 if(CursorScaleFactor
== 0) {
2677 PrintToScrollback("bad, can't have zero scale");
2678 CursorScaleFactor
= 1;
2680 RepaintGraphWindow();
2683 static void CmdSave(char *str
)
2685 FILE *f
= fopen(str
, "w");
2687 PrintToScrollback("couldn't open '%s'", str
);
2691 for(i
= 0; i
< GraphTraceLen
; i
++) {
2692 fprintf(f
, "%d\n", GraphBuffer
[i
]);
2695 PrintToScrollback("saved to '%s'", str
);
2698 static void CmdLoad(char *str
)
2700 FILE *f
= fopen(str
, "r");
2702 PrintToScrollback("couldn't open '%s'", str
);
2708 while(fgets(line
, sizeof(line
), f
)) {
2709 GraphBuffer
[GraphTraceLen
] = atoi(line
);
2713 PrintToScrollback("loaded %d samples", GraphTraceLen
);
2714 RepaintGraphWindow();
2717 static void CmdHIDsimTAG(char *str
)
2719 unsigned int hi
=0, lo
=0;
2723 while (sscanf(&str
[i
++], "%1x", &n
) == 1) {
2724 hi
=(hi
<<4)|(lo
>>28);
2728 PrintToScrollback("Emulating tag with ID %x%16x", hi
, lo
);
2730 c
.cmd
= CMD_HID_SIM_TAG
;
2733 SendCommand(&c
, FALSE
);
2736 static void CmdReadmem(char *str
)
2739 c
.cmd
= CMD_READ_MEM
;
2741 SendCommand(&c
, FALSE
);
2744 static void CmdVersion(char *str
)
2747 c
.cmd
= CMD_VERSION
;
2748 SendCommand(&c
, FALSE
);
2751 static void CmdLcdReset(char *str
)
2754 c
.cmd
= CMD_LCD_RESET
;
2756 SendCommand(&c
, FALSE
);
2759 static void CmdLcd(char *str
)
2764 sscanf(str
, "%x %d", &i
, &j
);
2767 SendCommand(&c
, FALSE
);
2772 * Sets the divisor for LF frequency clock: lets the user choose any LF frequency below
2775 static void CmdSetDivisor(char *str
)
2778 c
.cmd
= CMD_SET_LF_DIVISOR
;
2780 if (( c
.ext1
<0) || (c
.ext1
>255)) {
2781 PrintToScrollback("divisor must be between 19 and 255");
2783 SendCommand(&c
, FALSE
);
2784 PrintToScrollback("Divisor set, expected freq=%dHz", 12000000/(c
.ext1
+1));
2788 typedef void HandlerFunction(char *cmdline
);
2790 /* in alphabetic order */
2793 HandlerFunction
*handler
;
2794 int offline
; // 1 if the command can be used when in offline mode
2796 } CommandTable
[] = {
2797 {"askdemod", Cmdaskdemod
, 1, "<samples per bit> <0|1> -- Attempt to demodulate simple ASK tags"},
2798 {"autocorr", CmdAutoCorr
, 1, "<window length> -- Autocorrelation over window"},
2799 {"bitsamples", CmdBitsamples
, 0, "Get raw samples as bitstring"},
2800 {"bitstream", Cmdbitstream
, 1, "[clock rate] -- Convert waveform into a bitstream"},
2801 {"buffclear", CmdBuffClear
, 1, "Clear sample buffer and graph window"},
2802 {"dec", CmdDec
, 1, "Decimate samples"},
2803 {"detectclock", Cmddetectclockrate
, 1, "Detect clock rate"},
2804 {"detectreader", CmdDetectReader
, 0, "['l'|'h'] -- Detect external reader field (option 'l' or 'h' to limit to LF or HF)"},
2805 {"em410xsim", CmdEM410xsim
, 1, "<UID> -- Simulate EM410x tag"},
2806 {"em410xread", CmdEM410xread
, 1, "[clock rate] -- Extract ID from EM410x tag"},
2807 {"em410xwatch", CmdEM410xwatch
, 0, "Watches for EM410x tags"},
2808 {"em4x50read", CmdEM4x50read
, 1, "Extract data from EM4x50 tag"},
2809 {"exit", CmdQuit
, 1, "Exit program"},
2810 {"flexdemod", CmdFlexdemod
, 1, "Demodulate samples for FlexPass"},
2811 {"fpgaoff", CmdFPGAOff
, 0, "Set FPGA off"},
2812 {"fskdemod", CmdFSKdemod
, 1, "Demodulate graph window as a HID FSK"},
2813 {"grid", CmdGrid
, 1, "<x> <y> -- overlay grid on graph window, use zero value to turn off either"},
2814 {"hexsamples", CmdHexsamples
, 0, "<blocks> -- Dump big buffer as hex bytes"},
2815 {"hi14alist", CmdHi14alist
, 0, "List ISO 14443a history"},
2816 {"hi14areader", CmdHi14areader
, 0, "Act like an ISO14443 Type A reader"},
2817 {"hi14asim", CmdHi14asim
, 0, "<UID> -- Fake ISO 14443a tag"},
2818 {"hi14asnoop", CmdHi14asnoop
, 0, "Eavesdrop ISO 14443 Type A"},
2819 {"hi14bdemod", CmdHi14bdemod
, 1, "Demodulate ISO14443 Type B from tag"},
2820 {"hi14list", CmdHi14list
, 0, "List ISO 14443 history"},
2821 {"hi14read", CmdHi14read
, 0, "Read HF tag (ISO 14443)"},
2822 {"hi14sim", CmdHi14sim
, 0, "Fake ISO 14443 tag"},
2823 {"hi14snoop", CmdHi14snoop
, 0, "Eavesdrop ISO 14443"},
2824 {"hi15demod", CmdHi15demod
, 1, "Demodulate ISO15693 from tag"},
2825 {"hi15read", CmdHi15read
, 0, "Read HF tag (ISO 15693)"},
2826 {"hi15reader", CmdHi15reader
, 0, "Act like an ISO15693 reader"},
2827 {"hi15sim", CmdHi15tag
, 0, "Fake an ISO15693 tag"},
2828 {"hiddemod", CmdHiddemod
, 1, "Demodulate HID Prox Card II (not optimal)"},
2829 {"hide", CmdHide
, 1, "Hide graph window"},
2830 {"hidfskdemod", CmdHIDdemodFSK
, 0, "Realtime HID FSK demodulator"},
2831 {"hidsimtag", CmdHIDsimTAG
, 0, "<ID> -- HID tag simulator"},
2832 {"higet", CmdHi14read_sim
, 0, "<samples> -- Get samples HF, 'analog'"},
2833 {"hisamples", CmdHisamples
, 0, "Get raw samples for HF tag"},
2834 {"hisampless", CmdHisampless
, 0, "<samples> -- Get signed raw samples, HF tag"},
2835 {"hisamplest", CmdHi14readt
, 0, "Get samples HF, for testing"},
2836 {"hisimlisten", CmdHisimlisten
, 0, "Get HF samples as fake tag"},
2837 {"hpf", CmdHpf
, 1, "Remove DC offset from trace"},
2838 {"indalademod", CmdIndalademod
, 0, "['224'] -- Demodulate samples for Indala 64 bit UID (option '224' for 224 bit)"},
2839 {"lcd", CmdLcd
, 0, "<HEX command> <count> -- Send command/data to LCD"},
2840 {"lcdreset", CmdLcdReset
, 0, "Hardware reset LCD"},
2841 {"load", CmdLoad
, 1, "<filename> -- Load trace (to graph window"},
2842 {"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)"},
2843 {"loread", CmdLoread
, 0, "['h'] -- Read 125/134 kHz LF ID-only tag (option 'h' for 134)"},
2844 {"losamples", CmdLosamples
, 0, "[128 - 16000] -- Get raw samples for LF tag"},
2845 {"losim", CmdLosim
, 0, "Simulate LF tag"},
2846 {"losimbidir", CmdLosimBidir
, 0, "Simulate LF tag (with bidirectional data transmission between reader and tag)"},
2847 {"ltrim", CmdLtrim
, 1, "<samples> -- Trim samples from left of trace"},
2848 {"mandemod", Cmdmanchesterdemod
, 1, "[i] [clock rate] -- Manchester demodulate binary stream (option 'i' to invert output)"},
2849 {"manmod", Cmdmanchestermod
, 1, "[clock rate] -- Manchester modulate a binary stream"},
2850 {"norm", CmdNorm
, 1, "Normalize max/min to +/-500"},
2851 {"plot", CmdPlot
, 1, "Show graph window"},
2852 {"quit", CmdQuit
, 1, "Quit program"},
2853 {"readmem", CmdReadmem
, 0, "[address] -- Read memory at decimal address from flash"},
2854 {"reset", CmdReset
, 0, "Reset the Proxmark3"},
2855 {"save", CmdSave
, 1, "<filename> -- Save trace (from graph window)"},
2856 {"scale", CmdScale
, 1, "<int> -- Set cursor display scale"},
2857 {"setlfdivisor", CmdSetDivisor
, 0, "<19 - 255> -- Drive LF antenna at 12Mhz/(divisor+1)"},
2858 {"sri512read", CmdSri512read
, 0, "<int> -- Read contents of a SRI512 tag"},
2859 {"tidemod", CmdTIDemod
, 1, "Demodulate raw bits for TI-type LF tag"},
2860 {"tiread", CmdTIRead
, 0, "Read and decode a TI 134 kHz tag"},
2861 {"tiwrite", CmdTIWrite
, 0, "Write new data to a r/w TI 134 kHz tag"},
2862 {"threshold", CmdThreshold
, 1, "Maximize/minimize every value in the graph window depending on threshold"},
2863 {"tune", CmdTune
, 0, "Measure antenna tuning"},
2864 {"vchdemod", CmdVchdemod
, 0, "['clone'] -- Demodulate samples for VeriChip"},
2865 {"version", CmdVersion
, 0, "Show version inforation about the connected Proxmark"},
2866 {"zerocrossings", CmdZerocrossings
, 1, "Count time between zero-crossings"},
2874 } CommandExtendedHelp
[]= {
2875 {"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."},
2876 {"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."},
2879 //-----------------------------------------------------------------------------
2880 // Entry point into our code: called whenever the user types a command and
2881 // then presses Enter, which the full command line that they typed.
2882 //-----------------------------------------------------------------------------
2883 void CommandReceived(char *cmd
)
2888 PrintToScrollback("> %s", cmd
);
2890 if(strcmp(cmd
, "help") == 0 || strncmp(cmd
,"help ",strlen("help ")) == 0) {
2891 // check if we're doing extended help
2892 if(strlen(cmd
) > strlen("help ")) {
2893 cmd
+= strlen("help ");
2894 for(i
= 0; i
< sizeof(CommandExtendedHelp
) / sizeof(CommandExtendedHelp
[0]); i
++) {
2895 if(strcmp(CommandExtendedHelp
[i
].name
,cmd
) == 0) {
2896 PrintToScrollback("\nExtended help for '%s':\n", cmd
);
2897 PrintToScrollback("Args: %s\t- %s\n",CommandExtendedHelp
[i
].args
,CommandExtendedHelp
[i
].argshelp
);
2898 PrintToScrollback(CommandExtendedHelp
[i
].description
);
2899 PrintToScrollback("");
2903 PrintToScrollback("No extended help available for '%s'", cmd
);
2906 if (offline
) PrintToScrollback("Operating in OFFLINE mode (no device connected)");
2907 PrintToScrollback("\r\nAvailable commands:");
2908 for(i
= 0; i
< sizeof(CommandTable
) / sizeof(CommandTable
[0]); i
++) {
2909 if (offline
&& (CommandTable
[i
].offline
==0)) continue;
2910 memset(line
, ' ', sizeof(line
));
2911 strcpy(line
+2, CommandTable
[i
].name
);
2912 line
[strlen(line
)] = ' ';
2913 sprintf(line
+15, " -- %s", CommandTable
[i
].docString
);
2914 PrintToScrollback("%s", line
);
2916 PrintToScrollback("");
2917 PrintToScrollback("'help <command>' for extended help on that command\n");
2921 for(i
= 0; i
< sizeof(CommandTable
) / sizeof(CommandTable
[0]); i
++) {
2922 char *name
= CommandTable
[i
].name
;
2923 if(memcmp(cmd
, name
, strlen(name
))==0 &&
2924 (cmd
[strlen(name
)] == ' ' || cmd
[strlen(name
)] == '\0'))
2926 cmd
+= strlen(name
);
2927 while(*cmd
== ' ') {
2930 if (offline
&& (CommandTable
[i
].offline
==0)) {
2931 PrintToScrollback("Offline mode, cannot use this command.");
2934 (CommandTable
[i
].handler
)(cmd
);
2938 PrintToScrollback(">> bad command '%s'", cmd
);
2941 //-----------------------------------------------------------------------------
2942 // Entry point into our code: called whenever we received a packet over USB
2943 // that we weren't necessarily expecting, for example a debug print.
2944 //-----------------------------------------------------------------------------
2945 void UsbCommandReceived(UsbCommand
*c
)
2948 case CMD_DEBUG_PRINT_STRING
: {
2950 if(c
->ext1
> 70 || c
->ext1
< 0) {
2953 memcpy(s
, c
->d
.asBytes
, c
->ext1
);
2955 PrintToScrollback("#db# %s", s
);
2959 case CMD_DEBUG_PRINT_INTEGERS
:
2960 PrintToScrollback("#db# %08x, %08x, %08x\r\n", c
->ext1
, c
->ext2
, c
->ext3
);
2963 case CMD_MEASURED_ANTENNA_TUNING
: {
2965 int vLf125
, vLf134
, vHf
;
2966 vLf125
= c
->ext1
& 0xffff;
2967 vLf134
= c
->ext1
>> 16;
2968 vHf
= c
->ext2
& 0xffff;;
2969 peakf
= c
->ext3
& 0xffff;
2970 peakv
= c
->ext3
>> 16;
2971 PrintToScrollback("");
2972 PrintToScrollback("");
2973 PrintToScrollback("# LF antenna: %5.2f V @ 125.00 kHz", vLf125
/1000.0);
2974 PrintToScrollback("# LF antenna: %5.2f V @ 134.00 kHz", vLf134
/1000.0);
2975 PrintToScrollback("# LF optimal: %5.2f V @%9.2f kHz", peakv
/1000.0, 12000.0/(peakf
+1));
2976 PrintToScrollback("# HF antenna: %5.2f V @ 13.56 MHz", vHf
/1000.0);
2978 PrintToScrollback("# Your LF antenna is unusable.");
2979 else if (peakv
<10000)
2980 PrintToScrollback("# Your LF antenna is marginal.");
2982 PrintToScrollback("# Your HF antenna is unusable.");
2984 PrintToScrollback("# Your HF antenna is marginal.");
2988 PrintToScrollback("unrecognized command %08x\n", c
->cmd
);