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
);
111 /* New command to read the contents of a SRIX4K tag
112 * SRIX4K tags are ISO14443-B modulated memory tags,
113 * this command just dumps the contents of the memory/
115 static void CmdSrix4kread(char *str
)
118 c
.cmd
= CMD_READ_SRIX4K_TAG
;
120 SendCommand(&c
, FALSE
);
126 static void CmdHi14areader(char *str
)
129 c
.cmd
= CMD_READER_ISO_14443a
;
131 SendCommand(&c
, FALSE
);
135 static void CmdHi15reader(char *str
)
138 c
.cmd
= CMD_READER_ISO_15693
;
140 SendCommand(&c
, FALSE
);
144 static void CmdHi15tag(char *str
)
147 c
.cmd
= CMD_SIMTAG_ISO_15693
;
149 SendCommand(&c
, FALSE
);
152 static void CmdHi14read_sim(char *str
)
155 c
.cmd
= CMD_ACQUIRE_RAW_ADC_SAMPLES_ISO_14443_SIM
;
157 SendCommand(&c
, FALSE
);
160 static void CmdHi14readt(char *str
)
163 c
.cmd
= CMD_ACQUIRE_RAW_ADC_SAMPLES_ISO_14443
;
165 SendCommand(&c
, FALSE
);
167 //CmdHisamplest(str);
168 while(CmdHisamplest(str
,atoi(str
))==0) {
169 c
.cmd
= CMD_ACQUIRE_RAW_ADC_SAMPLES_ISO_14443
;
171 SendCommand(&c
, FALSE
);
173 RepaintGraphWindow();
176 static void CmdHisimlisten(char *str
)
179 c
.cmd
= CMD_SIMULATE_TAG_HF_LISTEN
;
180 SendCommand(&c
, FALSE
);
183 static void CmdHi14sim(char *str
)
186 c
.cmd
= CMD_SIMULATE_TAG_ISO_14443
;
187 SendCommand(&c
, FALSE
);
190 static void CmdHi14asim(char *str
) // ## simulate iso14443a tag
191 { // ## greg - added ability to specify tag UID
193 unsigned int hi
=0, lo
=0;
197 while (sscanf(&str
[i
++], "%1x", &n
) == 1) {
202 c
.cmd
= CMD_SIMULATE_TAG_ISO_14443a
;
203 // c.ext should be set to *str or convert *str to the correct format for a uid
206 PrintToScrollback("Emulating 14443A TAG with UID %x%16x", hi
, lo
);
207 SendCommand(&c
, FALSE
);
210 static void CmdHi14snoop(char *str
)
213 c
.cmd
= CMD_SNOOP_ISO_14443
;
214 SendCommand(&c
, FALSE
);
217 static void CmdHi14asnoop(char *str
)
220 c
.cmd
= CMD_SNOOP_ISO_14443a
;
221 SendCommand(&c
, FALSE
);
224 static void CmdLegicRfSim(char *str
)
227 c
.cmd
= CMD_SIMULATE_TAG_LEGIC_RF
;
228 SendCommand(&c
, FALSE
);
231 static void CmdLegicRfRead(char *str
)
234 c
.cmd
= CMD_READER_LEGIC_RF
;
235 SendCommand(&c
, FALSE
);
238 static void CmdFPGAOff(char *str
) // ## FPGA Control
241 c
.cmd
= CMD_FPGA_MAJOR_MODE_OFF
;
242 SendCommand(&c
, FALSE
);
245 /* clear out our graph window */
246 int CmdClearGraph(int redraw
)
248 int gtl
= GraphTraceLen
;
252 RepaintGraphWindow();
257 /* write a bit to the graph */
258 static void CmdAppendGraph(int redraw
, int clock
, int bit
)
262 for (i
= 0; i
< (int)(clock
/2); i
++)
263 GraphBuffer
[GraphTraceLen
++] = bit
^ 1;
265 for (i
= (int)(clock
/2); i
< clock
; i
++)
266 GraphBuffer
[GraphTraceLen
++] = bit
;
269 RepaintGraphWindow();
272 /* Function is equivalent of loread + losamples + em410xread
273 * looped until an EM410x tag is detected */
274 static void CmdEM410xwatch(char *str
)
288 /* Read the transmitted data of an EM4x50 tag
291 * XXXXXXXX [row parity bit (even)] <- 8 bits plus parity
292 * XXXXXXXX [row parity bit (even)] <- 8 bits plus parity
293 * XXXXXXXX [row parity bit (even)] <- 8 bits plus parity
294 * XXXXXXXX [row parity bit (even)] <- 8 bits plus parity
295 * CCCCCCCC <- column parity bits
297 * LW <- Listen Window
299 * This pattern repeats for every block of data being transmitted.
300 * Transmission starts with two Listen Windows (LW - a modulated
301 * pattern of 320 cycles each (32/32/128/64/64)).
303 * Note that this data may or may not be the UID. It is whatever data
304 * is stored in the blocks defined in the control word First and Last
305 * Word Read values. UID is stored in block 32.
307 static void CmdEM4x50read(char *str
)
309 int i
, j
, startblock
, clock
, skip
, block
, start
, end
, low
, high
;
310 BOOL complete
= FALSE
;
311 int tmpbuff
[MAX_GRAPH_TRACE_LEN
/ 64];
317 /* first get high and low values */
318 for (i
= 0; i
< GraphTraceLen
; i
++)
320 if (GraphBuffer
[i
] > high
)
321 high
= GraphBuffer
[i
];
322 else if (GraphBuffer
[i
] < low
)
323 low
= GraphBuffer
[i
];
326 /* populate a buffer with pulse lengths */
329 while(i
< GraphTraceLen
)
331 // measure from low to low
332 while((GraphBuffer
[i
] > low
) && (i
<GraphTraceLen
))
335 while((GraphBuffer
[i
] < high
) && (i
<GraphTraceLen
))
337 while((GraphBuffer
[i
] > low
) && (i
<GraphTraceLen
))
339 if (j
>(MAX_GRAPH_TRACE_LEN
/64)) {
342 tmpbuff
[j
++]= i
- start
;
345 /* look for data start - should be 2 pairs of LW (pulses of 192,128) */
348 for (i
= 0; i
< j
- 4 ; ++i
)
351 if (tmpbuff
[i
] >= 190 && tmpbuff
[i
] <= 194)
352 if (tmpbuff
[i
+1] >= 126 && tmpbuff
[i
+1] <= 130)
353 if (tmpbuff
[i
+2] >= 190 && tmpbuff
[i
+2] <= 194)
354 if (tmpbuff
[i
+3] >= 126 && tmpbuff
[i
+3] <= 130)
362 /* skip over the remainder of the LW */
363 skip
+= tmpbuff
[i
+1]+tmpbuff
[i
+2];
364 while(skip
< MAX_GRAPH_TRACE_LEN
&& GraphBuffer
[skip
] > low
)
368 /* now do it again to find the end */
370 for (i
+= 3; i
< j
- 4 ; ++i
)
373 if (tmpbuff
[i
] >= 190 && tmpbuff
[i
] <= 194)
374 if (tmpbuff
[i
+1] >= 126 && tmpbuff
[i
+1] <= 130)
375 if (tmpbuff
[i
+2] >= 190 && tmpbuff
[i
+2] <= 194)
376 if (tmpbuff
[i
+3] >= 126 && tmpbuff
[i
+3] <= 130)
384 PrintToScrollback("Found data at sample: %i",skip
);
387 PrintToScrollback("No data found!");
388 PrintToScrollback("Try again with more samples.");
394 PrintToScrollback("*** Warning!");
395 PrintToScrollback("Partial data - no end found!");
396 PrintToScrollback("Try again with more samples.");
399 /* get rid of leading crap */
400 sprintf(tmp
,"%i",skip
);
403 /* now work through remaining buffer printing out data blocks */
408 PrintToScrollback("Block %i:", block
);
409 // mandemod routine needs to be split so we can call it for data
410 // just print for now for debugging
411 Cmdmanchesterdemod("i 64");
413 /* look for LW before start of next block */
414 for ( ; i
< j
- 4 ; ++i
)
417 if (tmpbuff
[i
] >= 190 && tmpbuff
[i
] <= 194)
418 if (tmpbuff
[i
+1] >= 126 && tmpbuff
[i
+1] <= 130)
421 while(GraphBuffer
[skip
] > low
)
424 sprintf(tmp
,"%i",skip
);
432 /* Read the ID of an EM410x tag.
434 * 1111 1111 1 <-- standard non-repeatable header
435 * XXXX [row parity bit] <-- 10 rows of 5 bits for our 40 bit tag ID
437 * CCCC <-- each bit here is parity for the 10 bits above in corresponding column
438 * 0 <-- stop bit, end of tag
440 static void CmdEM410xread(char *str
)
442 int i
, j
, clock
, header
, rows
, bit
, hithigh
, hitlow
, first
, bit2idx
, high
, low
;
446 int BitStream
[MAX_GRAPH_TRACE_LEN
];
449 /* Detect high and lows and clock */
450 for (i
= 0; i
< GraphTraceLen
; i
++)
452 if (GraphBuffer
[i
] > high
)
453 high
= GraphBuffer
[i
];
454 else if (GraphBuffer
[i
] < low
)
455 low
= GraphBuffer
[i
];
459 clock
= GetClock(str
, high
);
461 /* parity for our 4 columns */
462 parity
[0] = parity
[1] = parity
[2] = parity
[3] = 0;
465 /* manchester demodulate */
467 for (i
= 0; i
< (int)(GraphTraceLen
/ clock
); i
++)
473 /* Find out if we hit both high and low peaks */
474 for (j
= 0; j
< clock
; j
++)
476 if (GraphBuffer
[(i
* clock
) + j
] == high
)
478 else if (GraphBuffer
[(i
* clock
) + j
] == low
)
481 /* it doesn't count if it's the first part of our read
482 because it's really just trailing from the last sequence */
483 if (first
&& (hithigh
|| hitlow
))
484 hithigh
= hitlow
= 0;
488 if (hithigh
&& hitlow
)
492 /* If we didn't hit both high and low peaks, we had a bit transition */
493 if (!hithigh
|| !hitlow
)
496 BitStream
[bit2idx
++] = bit
;
500 /* We go till 5 before the graph ends because we'll get that far below */
501 for (i
= 1; i
< bit2idx
- 5; i
++)
503 /* Step 2: We have our header but need our tag ID */
504 if (header
== 9 && rows
< 10)
506 /* Confirm parity is correct */
507 if ((BitStream
[i
] ^ BitStream
[i
+1] ^ BitStream
[i
+2] ^ BitStream
[i
+3]) == BitStream
[i
+4])
509 /* Read another byte! */
510 sprintf(id
+rows
, "%x", (8 * BitStream
[i
]) + (4 * BitStream
[i
+1]) + (2 * BitStream
[i
+2]) + (1 * BitStream
[i
+3]));
513 /* Keep parity info */
514 parity
[0] ^= BitStream
[i
];
515 parity
[1] ^= BitStream
[i
+1];
516 parity
[2] ^= BitStream
[i
+2];
517 parity
[3] ^= BitStream
[i
+3];
519 /* Move 4 bits ahead */
523 /* Damn, something wrong! reset */
526 PrintToScrollback("Thought we had a valid tag but failed at word %d (i=%d)", rows
+ 1, i
);
528 /* Start back rows * 5 + 9 header bits, -1 to not start at same place */
529 i
-= 9 + (5 * rows
) - 5;
535 /* Step 3: Got our 40 bits! confirm column parity */
538 /* We need to make sure our 4 bits of parity are correct and we have a stop bit */
539 if (BitStream
[i
] == parity
[0] && BitStream
[i
+1] == parity
[1] &&
540 BitStream
[i
+2] == parity
[2] && BitStream
[i
+3] == parity
[3] &&
544 PrintToScrollback("EM410x Tag ID: %s", id
);
551 /* Crap! Incorrect parity or no stop bit, start all over */
556 /* Go back 59 bits (9 header bits + 10 rows at 4+1 parity) */
561 /* Step 1: get our header */
564 /* Need 9 consecutive 1's */
565 if (BitStream
[i
] == 1)
568 /* We don't have a header, not enough consecutive 1 bits */
574 /* if we've already retested after flipping bits, return */
578 /* if this didn't work, try flipping bits */
579 for (i
= 0; i
< bit2idx
; i
++)
585 /* emulate an EM410X tag
587 * 1111 1111 1 <-- standard non-repeatable header
588 * XXXX [row parity bit] <-- 10 rows of 5 bits for our 40 bit tag ID
590 * CCCC <-- each bit here is parity for the 10 bits above in corresponding column
591 * 0 <-- stop bit, end of tag
593 static void CmdEM410xsim(char *str
)
595 int i
, n
, j
, h
, binary
[4], parity
[4];
598 /* clock is 64 in EM410x tags */
601 /* clear our graph */
604 /* write it out a few times */
605 for (h
= 0; h
< 4; h
++)
607 /* write 9 start bits */
608 for (i
= 0; i
< 9; i
++)
609 CmdAppendGraph(0, clock
, 1);
611 /* for each hex char */
612 parity
[0] = parity
[1] = parity
[2] = parity
[3] = 0;
613 for (i
= 0; i
< 10; i
++)
615 /* read each hex char */
616 sscanf(&str
[i
], "%1x", &n
);
617 for (j
= 3; j
>= 0; j
--, n
/= 2)
620 /* append each bit */
621 CmdAppendGraph(0, clock
, binary
[0]);
622 CmdAppendGraph(0, clock
, binary
[1]);
623 CmdAppendGraph(0, clock
, binary
[2]);
624 CmdAppendGraph(0, clock
, binary
[3]);
626 /* append parity bit */
627 CmdAppendGraph(0, clock
, binary
[0] ^ binary
[1] ^ binary
[2] ^ binary
[3]);
629 /* keep track of column parity */
630 parity
[0] ^= binary
[0];
631 parity
[1] ^= binary
[1];
632 parity
[2] ^= binary
[2];
633 parity
[3] ^= binary
[3];
637 CmdAppendGraph(0, clock
, parity
[0]);
638 CmdAppendGraph(0, clock
, parity
[1]);
639 CmdAppendGraph(0, clock
, parity
[2]);
640 CmdAppendGraph(0, clock
, parity
[3]);
643 CmdAppendGraph(0, clock
, 0);
646 /* modulate that biatch */
650 RepaintGraphWindow();
655 static void ChkBitstream(char *str
)
659 /* convert to bitstream if necessary */
660 for (i
= 0; i
< (int)(GraphTraceLen
/ 2); i
++)
662 if (GraphBuffer
[i
] > 1 || GraphBuffer
[i
] < 0)
670 static void CmdLosim(char *str
)
674 /* convert to bitstream if necessary */
677 for (i
= 0; i
< GraphTraceLen
; i
+= 48) {
680 for(j
= 0; j
< 48; j
++) {
681 c
.d
.asBytes
[j
] = GraphBuffer
[i
+j
];
683 c
.cmd
= CMD_DOWNLOADED_SIM_SAMPLES_125K
;
685 SendCommand(&c
, FALSE
);
689 c
.cmd
= CMD_SIMULATE_TAG_125K
;
690 c
.ext1
= GraphTraceLen
;
691 SendCommand(&c
, FALSE
);
694 static void CmdLosimBidir(char *str
)
697 c
.cmd
= CMD_LF_SIMULATE_BIDIR
;
698 c
.ext1
= 47; /* Set ADC to twice the carrier for a slight supersampling */
700 SendCommand(&c
, FALSE
);
703 static void CmdLoread(char *str
)
706 // 'h' means higher-low-frequency, 134 kHz
709 } else if (*str
== '\0') {
712 PrintToScrollback("use 'loread' or 'loread h'");
715 c
.cmd
= CMD_ACQUIRE_RAW_ADC_SAMPLES_125K
;
716 SendCommand(&c
, FALSE
);
719 static void CmdDetectReader(char *str
)
722 // 'l' means LF - 125/134 kHz
725 } else if (*str
== 'h') {
727 } else if (*str
!= '\0') {
728 PrintToScrollback("use 'detectreader' or 'detectreader l' or 'detectreader h'");
731 c
.cmd
= CMD_LISTEN_READER_FIELD
;
732 SendCommand(&c
, FALSE
);
735 /* send a command before reading */
736 static void CmdLoCommandRead(char *str
)
738 static char dummy
[3];
743 c
.cmd
= CMD_MOD_THEN_ACQUIRE_RAW_ADC_SAMPLES_125K
;
744 sscanf(str
, "%i %i %i %s %s", &c
.ext1
, &c
.ext2
, &c
.ext3
, (char *) &c
.d
.asBytes
,(char *) &dummy
+1);
745 // in case they specified 'h'
746 strcpy((char *)&c
.d
.asBytes
+ strlen((char *)c
.d
.asBytes
), dummy
);
747 SendCommand(&c
, FALSE
);
750 static void CmdLosamples(char *str
)
758 if (n
>16000) n
=16000;
760 for(i
= 0; i
< n
; i
+= 12) {
762 c
.cmd
= CMD_DOWNLOAD_RAW_ADC_SAMPLES_125K
;
764 SendCommand(&c
, FALSE
);
766 if(c
.cmd
!= CMD_DOWNLOADED_RAW_ADC_SAMPLES_125K
) {
768 PrintToScrollback("bad resp");
772 for(j
= 0; j
< 48; j
++) {
773 GraphBuffer
[cnt
++] = ((int)c
.d
.asBytes
[j
]) - 128;
777 RepaintGraphWindow();
780 static void CmdBitsamples(char *str
)
787 for(i
= 0; i
< n
; i
+= 12) {
789 c
.cmd
= CMD_DOWNLOAD_RAW_ADC_SAMPLES_125K
;
791 SendCommand(&c
, FALSE
);
793 if(c
.cmd
!= CMD_DOWNLOADED_RAW_ADC_SAMPLES_125K
) {
794 PrintToScrollback("bad resp");
798 for(j
= 0; j
< 48; j
++) {
799 for(k
= 0; k
< 8; k
++) {
800 if(c
.d
.asBytes
[j
] & (1 << (7 - k
))) {
801 GraphBuffer
[cnt
++] = 1;
803 GraphBuffer
[cnt
++] = 0;
809 RepaintGraphWindow();
812 static void CmdHisamples(char *str
)
818 for(i
= 0; i
< n
; i
+= 12) {
820 c
.cmd
= CMD_DOWNLOAD_RAW_ADC_SAMPLES_125K
;
822 SendCommand(&c
, FALSE
);
824 if(c
.cmd
!= CMD_DOWNLOADED_RAW_ADC_SAMPLES_125K
) {
825 PrintToScrollback("bad resp");
829 for(j
= 0; j
< 48; j
++) {
830 GraphBuffer
[cnt
++] = (int)((BYTE
)c
.d
.asBytes
[j
]);
835 RepaintGraphWindow();
838 static int CmdHisamplest(char *str
, int nrlow
)
850 for(i
= 0; i
< n
; i
+= 12) {
852 c
.cmd
= CMD_DOWNLOAD_RAW_ADC_SAMPLES_125K
;
854 SendCommand(&c
, FALSE
);
856 if(c
.cmd
!= CMD_DOWNLOADED_RAW_ADC_SAMPLES_125K
) {
857 PrintToScrollback("bad resp");
861 for(j
= 0; j
< 48; j
++) {
862 t2
= (int)((BYTE
)c
.d
.asBytes
[j
]);
863 if((t2
^ 0xC0) & 0xC0) { hasbeennull
++; }
869 t1
= (t2
& 0x80) ^ (t2
& 0x20);
870 t2
= ((t2
<< 1) & 0x80) ^ ((t2
<< 1) & 0x20);
876 t2
= ((t2
<< 1) & 0x80);
882 t2
= ((t2
<< 1) & 0x20);
886 // both, but tag with other algorithm
887 t1
= (t2
& 0x80) ^ (t2
& 0x08);
888 t2
= ((t2
<< 1) & 0x80) ^ ((t2
<< 1) & 0x08);
892 GraphBuffer
[cnt
++] = t1
;
893 GraphBuffer
[cnt
++] = t2
;
898 if(hasbeennull
>nrlow
|| nrlow
==0) {
899 PrintToScrollback("hasbeennull=%d", hasbeennull
);
908 static void CmdHexsamples(char *str
)
919 for(i
= 0; i
< n
; i
+= 12) {
921 c
.cmd
= CMD_DOWNLOAD_RAW_ADC_SAMPLES_125K
;
923 SendCommand(&c
, FALSE
);
925 if(c
.cmd
!= CMD_DOWNLOADED_RAW_ADC_SAMPLES_125K
) {
926 PrintToScrollback("bad resp");
930 for(j
= 0; j
< 48; j
+= 8) {
931 PrintToScrollback("%02x %02x %02x %02x %02x %02x %02x %02x",
946 static void CmdHisampless(char *str
)
958 for(i
= 0; i
< n
; i
+= 12) {
960 c
.cmd
= CMD_DOWNLOAD_RAW_ADC_SAMPLES_125K
;
962 SendCommand(&c
, FALSE
);
964 if(c
.cmd
!= CMD_DOWNLOADED_RAW_ADC_SAMPLES_125K
) {
965 PrintToScrollback("bad resp");
969 for(j
= 0; j
< 48; j
++) {
970 GraphBuffer
[cnt
++] = (int)((signed char)c
.d
.asBytes
[j
]);
975 RepaintGraphWindow();
978 static WORD
Iso15693Crc(BYTE
*v
, int n
)
984 for(i
= 0; i
< n
; i
++) {
985 reg
= reg
^ ((DWORD
)v
[i
]);
986 for (j
= 0; j
< 8; j
++) {
988 reg
= (reg
>> 1) ^ 0x8408;
998 static void CmdHi14bdemod(char *str
)
1003 BOOL negateI
, negateQ
;
1008 // As received, the samples are pairs, correlations against I and Q
1009 // square waves. So estimate angle of initial carrier (or just
1010 // quadrant, actually), and then do the demod.
1012 // First, estimate where the tag starts modulating.
1013 for(i
= 0; i
< GraphTraceLen
; i
+= 2) {
1014 if(abs(GraphBuffer
[i
]) + abs(GraphBuffer
[i
+1]) > 40) {
1018 if(i
>= GraphTraceLen
) {
1019 PrintToScrollback("too weak to sync");
1022 PrintToScrollback("out of weak at %d", i
);
1025 // Now, estimate the phase in the initial modulation of the tag
1028 for(; i
< (outOfWeakAt
+ 16); i
+= 2) {
1029 isum
+= GraphBuffer
[i
+0];
1030 qsum
+= GraphBuffer
[i
+1];
1032 negateI
= (isum
< 0);
1033 negateQ
= (qsum
< 0);
1035 // Turn the correlation pairs into soft decisions on the bit.
1037 for(i
= 0; i
< GraphTraceLen
/2; i
++) {
1038 int si
= GraphBuffer
[j
];
1039 int sq
= GraphBuffer
[j
+1];
1040 if(negateI
) si
= -si
;
1041 if(negateQ
) sq
= -sq
;
1042 GraphBuffer
[i
] = si
+ sq
;
1048 while(GraphBuffer
[i
] > 0 && i
< GraphTraceLen
)
1050 if(i
>= GraphTraceLen
) goto demodError
;
1053 while(GraphBuffer
[i
] < 0 && i
< GraphTraceLen
)
1055 if(i
>= GraphTraceLen
) goto demodError
;
1056 if((i
- iold
) > 23) goto demodError
;
1058 PrintToScrollback("make it to demod loop");
1062 while(GraphBuffer
[i
] >= 0 && i
< GraphTraceLen
)
1064 if(i
>= GraphTraceLen
) goto demodError
;
1065 if((i
- iold
) > 6) goto demodError
;
1068 if(i
+ 20 >= GraphTraceLen
) goto demodError
;
1070 for(j
= 0; j
< 10; j
++) {
1071 int soft
= GraphBuffer
[i
] + GraphBuffer
[i
+1];
1073 if(abs(soft
) < ((abs(isum
) + abs(qsum
))/20)) {
1074 PrintToScrollback("weak bit");
1078 if(GraphBuffer
[i
] + GraphBuffer
[i
+1] >= 0) {
1085 if( (shiftReg
& 0x200) &&
1086 !(shiftReg
& 0x001))
1088 // valid data byte, start and stop bits okay
1089 PrintToScrollback(" %02x", (shiftReg
>> 1) & 0xff);
1090 data
[dataLen
++] = (shiftReg
>> 1) & 0xff;
1091 if(dataLen
>= sizeof(data
)) {
1094 } else if(shiftReg
== 0x000) {
1103 ComputeCrc14443(CRC_14443_B
, data
, dataLen
-2, &first
, &second
);
1104 PrintToScrollback("CRC: %02x %02x (%s)\n", first
, second
,
1105 (first
== data
[dataLen
-2] && second
== data
[dataLen
-1]) ?
1106 "ok" : "****FAIL****");
1108 RepaintGraphWindow();
1112 PrintToScrollback("demod error");
1113 RepaintGraphWindow();
1116 static void CmdHi14list(char *str
)
1119 GetFromBigBuf(got
, sizeof(got
));
1121 PrintToScrollback("recorded activity:");
1122 PrintToScrollback(" time :rssi: who bytes");
1123 PrintToScrollback("---------+----+----+-----------");
1134 int timestamp
= *((DWORD
*)(got
+i
));
1135 if(timestamp
& 0x80000000) {
1136 timestamp
&= 0x7fffffff;
1141 int metric
= *((DWORD
*)(got
+i
+4));
1148 if(i
+ len
>= 900) {
1152 BYTE
*frame
= (got
+i
+9);
1154 char line
[1000] = "";
1156 for(j
= 0; j
< len
; j
++) {
1157 sprintf(line
+(j
*3), "%02x ", frame
[j
]);
1163 ComputeCrc14443(CRC_14443_B
, frame
, len
-2, &b1
, &b2
);
1164 if(b1
!= frame
[len
-2] || b2
!= frame
[len
-1]) {
1165 crc
= "**FAIL CRC**";
1173 char metricString
[100];
1175 sprintf(metricString
, "%3d", metric
);
1177 strcpy(metricString
, " ");
1180 PrintToScrollback(" +%7d: %s: %s %s %s",
1181 (prev
< 0 ? 0 : timestamp
- prev
),
1183 (isResponse
? "TAG" : " "), line
, crc
);
1190 static void CmdHi14alist(char *str
)
1193 GetFromBigBuf(got
, sizeof(got
));
1195 PrintToScrollback("recorded activity:");
1196 PrintToScrollback(" ETU :rssi: who bytes");
1197 PrintToScrollback("---------+----+----+-----------");
1208 int timestamp
= *((DWORD
*)(got
+i
));
1209 if(timestamp
& 0x80000000) {
1210 timestamp
&= 0x7fffffff;
1217 int parityBits
= *((DWORD
*)(got
+i
+4));
1218 // 4 bytes of additional information...
1219 // maximum of 32 additional parity bit information
1222 // at each quarter bit period we can send power level (16 levels)
1223 // or each half bit period in 256 levels.
1231 if(i
+ len
>= 1900) {
1235 BYTE
*frame
= (got
+i
+9);
1237 // Break and stick with current result if buffer was not completely full
1238 if(frame
[0] == 0x44 && frame
[1] == 0x44 && frame
[3] == 0x44) { break; }
1240 char line
[1000] = "";
1242 for(j
= 0; j
< len
; j
++) {
1243 int oddparity
= 0x01;
1247 oddparity
^= (((frame
[j
] & 0xFF) >> k
) & 0x01);
1250 //if((parityBits >> (len - j - 1)) & 0x01) {
1251 if(isResponse
&& (oddparity
!= ((parityBits
>> (len
- j
- 1)) & 0x01))) {
1252 sprintf(line
+(j
*4), "%02x! ", frame
[j
]);
1255 sprintf(line
+(j
*4), "%02x ", frame
[j
]);
1263 for(j
= 0; j
< (len
- 1); j
++) {
1264 // gives problems... search for the reason..
1265 /*if(frame[j] == 0xAA) {
1266 switch(frame[j+1]) {
1268 crc = "[1] Two drops close after each other";
1271 crc = "[2] Potential SOC with a drop in second half of bitperiod";
1274 crc = "[3] Segment Z after segment X is not possible";
1277 crc = "[4] Parity bit of a fully received byte was wrong";
1280 crc = "[?] Unknown error";
1287 if(strlen(crc
)==0) {
1288 ComputeCrc14443(CRC_14443_A
, frame
, len
-2, &b1
, &b2
);
1289 if(b1
!= frame
[len
-2] || b2
!= frame
[len
-1]) {
1290 crc
= (isResponse
& (len
< 6)) ? "" : " !crc";
1299 char metricString
[100];
1301 sprintf(metricString
, "%3d", metric
);
1303 strcpy(metricString
, " ");
1306 PrintToScrollback(" +%7d: %s: %s %s %s",
1307 (prev
< 0 ? 0 : (timestamp
- prev
)),
1309 (isResponse
? "TAG" : " "), line
, crc
);
1314 CommandFinished
= 1;
1317 static void CmdHi15demod(char *str
)
1319 // The sampling rate is 106.353 ksps/s, for T = 18.8 us
1322 // 1) Unmodulated time of 56.64us
1323 // 2) 24 pulses of 423.75khz
1324 // 3) logic '1' (unmodulated for 18.88us followed by 8 pulses of 423.75khz)
1326 static const int FrameSOF
[] = {
1327 -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
1328 -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
1329 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
1330 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
1336 static const int Logic0
[] = {
1342 static const int Logic1
[] = {
1350 // 1) logic '0' (8 pulses of 423.75khz followed by unmodulated for 18.88us)
1351 // 2) 24 pulses of 423.75khz
1352 // 3) Unmodulated time of 56.64us
1354 static const int FrameEOF
[] = {
1359 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
1360 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
1361 -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
1362 -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1
1366 int max
= 0, maxPos
;
1370 if(GraphTraceLen
< 1000) return;
1372 // First, correlate for SOF
1373 for(i
= 0; i
< 100; i
++) {
1375 for(j
= 0; j
< arraylen(FrameSOF
); j
+= skip
) {
1376 corr
+= FrameSOF
[j
]*GraphBuffer
[i
+(j
/skip
)];
1383 PrintToScrollback("SOF at %d, correlation %d", maxPos
,
1384 max
/(arraylen(FrameSOF
)/skip
));
1386 i
= maxPos
+ arraylen(FrameSOF
)/skip
;
1389 memset(outBuf
, 0, sizeof(outBuf
));
1392 int corr0
= 0, corr1
= 0, corrEOF
= 0;
1393 for(j
= 0; j
< arraylen(Logic0
); j
+= skip
) {
1394 corr0
+= Logic0
[j
]*GraphBuffer
[i
+(j
/skip
)];
1396 for(j
= 0; j
< arraylen(Logic1
); j
+= skip
) {
1397 corr1
+= Logic1
[j
]*GraphBuffer
[i
+(j
/skip
)];
1399 for(j
= 0; j
< arraylen(FrameEOF
); j
+= skip
) {
1400 corrEOF
+= FrameEOF
[j
]*GraphBuffer
[i
+(j
/skip
)];
1402 // Even things out by the length of the target waveform.
1406 if(corrEOF
> corr1
&& corrEOF
> corr0
) {
1407 PrintToScrollback("EOF at %d", i
);
1409 } else if(corr1
> corr0
) {
1410 i
+= arraylen(Logic1
)/skip
;
1413 i
+= arraylen(Logic0
)/skip
;
1420 if((i
+(int)arraylen(FrameEOF
)) >= GraphTraceLen
) {
1421 PrintToScrollback("ran off end!");
1426 PrintToScrollback("error, uneven octet! (discard extra bits!)");
1427 PrintToScrollback(" mask=%02x", mask
);
1429 PrintToScrollback("%d octets", k
);
1431 for(i
= 0; i
< k
; i
++) {
1432 PrintToScrollback("# %2d: %02x ", i
, outBuf
[i
]);
1434 PrintToScrollback("CRC=%04x", Iso15693Crc(outBuf
, k
-2));
1437 static void CmdFSKdemod(char *cmdline
)
1439 static const int LowTone
[] = {
1440 1, 1, 1, 1, 1, -1, -1, -1, -1, -1,
1441 1, 1, 1, 1, 1, -1, -1, -1, -1, -1,
1442 1, 1, 1, 1, 1, -1, -1, -1, -1, -1,
1443 1, 1, 1, 1, 1, -1, -1, -1, -1, -1,
1444 1, 1, 1, 1, 1, -1, -1, -1, -1, -1
1446 static const int HighTone
[] = {
1447 1, 1, 1, 1, 1, -1, -1, -1, -1,
1448 1, 1, 1, 1, -1, -1, -1, -1,
1449 1, 1, 1, 1, -1, -1, -1, -1,
1450 1, 1, 1, 1, -1, -1, -1, -1,
1451 1, 1, 1, 1, -1, -1, -1, -1,
1452 1, 1, 1, 1, -1, -1, -1, -1, -1,
1455 int lowLen
= sizeof(LowTone
)/sizeof(int);
1456 int highLen
= sizeof(HighTone
)/sizeof(int);
1457 int convLen
= (highLen
>lowLen
)?highLen
:lowLen
;
1458 DWORD hi
= 0, lo
= 0;
1461 int minMark
=0, maxMark
=0;
1463 for(i
= 0; i
< GraphTraceLen
- convLen
; i
++) {
1464 int lowSum
= 0, highSum
= 0;
1466 for(j
= 0; j
< lowLen
; j
++) {
1467 lowSum
+= LowTone
[j
]*GraphBuffer
[i
+j
];
1469 for(j
= 0; j
< highLen
; j
++) {
1470 highSum
+= HighTone
[j
]*GraphBuffer
[i
+j
];
1472 lowSum
= abs((100*lowSum
) / lowLen
);
1473 highSum
= abs((100*highSum
) / highLen
);
1474 GraphBuffer
[i
] = (highSum
<< 16) | lowSum
;
1477 for(i
= 0; i
< GraphTraceLen
- convLen
- 16; i
++) {
1479 int lowTot
= 0, highTot
= 0;
1480 // 10 and 8 are f_s divided by f_l and f_h, rounded
1481 for(j
= 0; j
< 10; j
++) {
1482 lowTot
+= (GraphBuffer
[i
+j
] & 0xffff);
1484 for(j
= 0; j
< 8; j
++) {
1485 highTot
+= (GraphBuffer
[i
+j
] >> 16);
1487 GraphBuffer
[i
] = lowTot
- highTot
;
1488 if (GraphBuffer
[i
]>maxMark
) maxMark
=GraphBuffer
[i
];
1489 if (GraphBuffer
[i
]<minMark
) minMark
=GraphBuffer
[i
];
1492 GraphTraceLen
-= (convLen
+ 16);
1494 RepaintGraphWindow();
1496 // Find bit-sync (3 lo followed by 3 high)
1497 int max
= 0, maxPos
= 0;
1498 for(i
= 0; i
< 6000; i
++) {
1500 for(j
= 0; j
< 3*lowLen
; j
++) {
1501 dec
-= GraphBuffer
[i
+j
];
1503 for(; j
< 3*(lowLen
+ highLen
); j
++) {
1504 dec
+= GraphBuffer
[i
+j
];
1512 // place start of bit sync marker in graph
1513 GraphBuffer
[maxPos
] = maxMark
;
1514 GraphBuffer
[maxPos
+1] = minMark
;
1518 // place end of bit sync marker in graph
1519 GraphBuffer
[maxPos
] = maxMark
;
1520 GraphBuffer
[maxPos
+1] = minMark
;
1522 PrintToScrollback("actual data bits start at sample %d", maxPos
);
1523 PrintToScrollback("length %d/%d", highLen
, lowLen
);
1526 bits
[sizeof(bits
)-1] = '\0';
1528 // find bit pairs and manchester decode them
1529 for(i
= 0; i
< arraylen(bits
)-1; i
++) {
1531 for(j
= 0; j
< lowLen
; j
++) {
1532 dec
-= GraphBuffer
[maxPos
+j
];
1534 for(; j
< lowLen
+ highLen
; j
++) {
1535 dec
+= GraphBuffer
[maxPos
+j
];
1538 // place inter bit marker in graph
1539 GraphBuffer
[maxPos
] = maxMark
;
1540 GraphBuffer
[maxPos
+1] = minMark
;
1542 // hi and lo form a 64 bit pair
1543 hi
= (hi
<<1)|(lo
>>31);
1545 // store decoded bit as binary (in hi/lo) and text (in bits[])
1553 PrintToScrollback("bits: '%s'", bits
);
1554 PrintToScrollback("hex: %08x %08x", hi
, lo
);
1557 // read a TI tag and return its ID
1558 static void CmdTIRead(char *str
)
1561 c
.cmd
= CMD_READ_TI_TYPE
;
1562 SendCommand(&c
, FALSE
);
1565 // write new data to a r/w TI tag
1566 static void CmdTIWrite(char *str
)
1571 c
.cmd
= CMD_WRITE_TI_TYPE
;
1572 res
= sscanf(str
, "0x%x 0x%x 0x%x ", &c
.ext1
, &c
.ext2
, &c
.ext3
);
1573 if (res
== 2) c
.ext3
=0;
1575 PrintToScrollback("Please specify the data as two hex strings, optionally the CRC as a third");
1577 SendCommand(&c
, FALSE
);
1580 static void CmdTIDemod(char *cmdline
)
1582 /* MATLAB as follows:
1583 f_s = 2000000; % sampling frequency
1584 f_l = 123200; % low FSK tone
1585 f_h = 134200; % high FSK tone
1587 T_l = 119e-6; % low bit duration
1588 T_h = 130e-6; % high bit duration
1590 l = 2*pi*ones(1, floor(f_s*T_l))*(f_l/f_s);
1591 h = 2*pi*ones(1, floor(f_s*T_h))*(f_h/f_s);
1593 l = sign(sin(cumsum(l)));
1594 h = sign(sin(cumsum(h)));
1597 // 2M*16/134.2k = 238
1598 static const int LowTone
[] = {
1599 1, 1, 1, 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, -1,
1601 1, 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, -1,
1603 1, 1, 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, -1,
1605 1, 1, 1, 1, 1, 1, 1, 1, -1, -1, -1, -1, -1, -1, -1, -1,
1606 1, 1, 1, 1, 1, 1, 1, 1, -1, -1, -1, -1, -1, -1, -1, -1,
1607 1, 1, 1, 1, 1, 1, 1, 1, 1, -1, -1, -1, -1, -1, -1, -1, -1,
1608 1, 1, 1, 1, 1, 1, 1, 1, -1, -1, -1, -1, -1, -1, -1, -1,
1609 1, 1, 1, 1, 1, 1, 1, 1, -1, -1, -1, -1, -1, -1, -1, -1,
1610 1, 1, 1, 1, 1, 1, 1, 1, -1, -1, -1, -1, -1, -1, -1, -1,
1611 1, 1, 1, 1, 1, 1, 1, 1, 1, -1, -1, -1, -1, -1, -1, -1, -1,
1612 1, 1, 1, 1, 1, 1, 1, 1, -1, -1, -1, -1, -1, -1, -1, -1,
1613 1, 1, 1, 1, 1, 1, 1, 1, -1, -1
1615 // 2M*16/123.2k = 260
1616 static const int HighTone
[] = {
1617 1, 1, 1, 1, 1, 1, 1, 1, -1, -1, -1, -1, -1, -1, -1,
1618 1, 1, 1, 1, 1, 1, 1, 1, -1, -1, -1, -1, -1, -1, -1,
1619 1, 1, 1, 1, 1, 1, 1, -1, -1, -1, -1, -1, -1, -1, -1,
1620 1, 1, 1, 1, 1, 1, 1, -1, -1, -1, -1, -1, -1, -1, -1,
1621 1, 1, 1, 1, 1, 1, 1, -1, -1, -1, -1, -1, -1, -1, -1,
1622 1, 1, 1, 1, 1, 1, 1, -1, -1, -1, -1, -1, -1, -1,
1623 1, 1, 1, 1, 1, 1, 1, 1, -1, -1, -1, -1, -1, -1, -1,
1624 1, 1, 1, 1, 1, 1, 1, 1, -1, -1, -1, -1, -1, -1, -1,
1625 1, 1, 1, 1, 1, 1, 1, -1, -1, -1, -1, -1, -1, -1, -1,
1626 1, 1, 1, 1, 1, 1, 1, -1, -1, -1, -1, -1, -1, -1, -1,
1627 1, 1, 1, 1, 1, 1, 1, -1, -1, -1, -1, -1, -1, -1,
1628 1, 1, 1, 1, 1, 1, 1, 1, -1, -1, -1, -1, -1, -1, -1,
1629 1, 1, 1, 1, 1, 1, 1, 1, -1, -1, -1, -1, -1, -1, -1,
1630 1, 1, 1, 1, 1, 1, 1, 1, -1, -1, -1, -1, -1, -1, -1,
1631 1, 1, 1, 1, 1, 1, 1, -1, -1, -1, -1, -1, -1, -1, -1,
1632 1, 1, 1, 1, 1, 1, 1, -1, -1, -1, -1, -1, -1, -1, -1,
1633 1, 1, 1, 1, 1, 1, 1, -1, -1, -1, -1, -1, -1, -1,
1634 1, 1, 1, 1, 1, 1, 1, 1
1636 int lowLen
= sizeof(LowTone
)/sizeof(int);
1637 int highLen
= sizeof(HighTone
)/sizeof(int);
1638 int convLen
= (highLen
>lowLen
)?highLen
:lowLen
;
1641 int lowSum
= 0, highSum
= 0;;
1642 int lowTot
= 0, highTot
= 0;
1644 for(i
= 0; i
< GraphTraceLen
- convLen
; i
++) {
1648 for(j
= 0; j
< lowLen
; j
++) {
1649 lowSum
+= LowTone
[j
]*GraphBuffer
[i
+j
];
1651 for(j
= 0; j
< highLen
; j
++) {
1652 highSum
+= HighTone
[j
]*GraphBuffer
[i
+j
];
1654 lowSum
= abs((100*lowSum
) / lowLen
);
1655 highSum
= abs((100*highSum
) / highLen
);
1656 lowSum
= (lowSum
<0)?-lowSum
:lowSum
;
1657 highSum
= (highSum
<0)?-highSum
:highSum
;
1659 GraphBuffer
[i
] = (highSum
<< 16) | lowSum
;
1662 for(i
= 0; i
< GraphTraceLen
- convLen
- 16; i
++) {
1665 // 16 and 15 are f_s divided by f_l and f_h, rounded
1666 for(j
= 0; j
< 16; j
++) {
1667 lowTot
+= (GraphBuffer
[i
+j
] & 0xffff);
1669 for(j
= 0; j
< 15; j
++) {
1670 highTot
+= (GraphBuffer
[i
+j
] >> 16);
1672 GraphBuffer
[i
] = lowTot
- highTot
;
1675 GraphTraceLen
-= (convLen
+ 16);
1677 RepaintGraphWindow();
1679 // TI tag data format is 16 prebits, 8 start bits, 64 data bits,
1680 // 16 crc CCITT bits, 8 stop bits, 15 end bits
1682 // the 16 prebits are always low
1683 // the 8 start and stop bits of a tag must match
1684 // the start/stop prebits of a ro tag are 01111110
1685 // the start/stop prebits of a rw tag are 11111110
1686 // the 15 end bits of a ro tag are all low
1687 // the 15 end bits of a rw tag match bits 15-1 of the data bits
1689 // Okay, so now we have unsliced soft decisions;
1690 // find bit-sync, and then get some bits.
1691 // look for 17 low bits followed by 6 highs (common pattern for ro and rw tags)
1692 int max
= 0, maxPos
= 0;
1693 for(i
= 0; i
< 6000; i
++) {
1696 // searching 17 consecutive lows
1697 for(j
= 0; j
< 17*lowLen
; j
++) {
1698 dec
-= GraphBuffer
[i
+j
];
1700 // searching 7 consecutive highs
1701 for(; j
< 17*lowLen
+ 6*highLen
; j
++) {
1702 dec
+= GraphBuffer
[i
+j
];
1710 // place a marker in the buffer to visually aid location
1711 // of the start of sync
1712 GraphBuffer
[maxPos
] = 800;
1713 GraphBuffer
[maxPos
+1] = -800;
1715 // advance pointer to start of actual data stream (after 16 pre and 8 start bits)
1716 maxPos
+= 17*lowLen
;
1717 maxPos
+= 6*highLen
;
1719 // place a marker in the buffer to visually aid location
1720 // of the end of sync
1721 GraphBuffer
[maxPos
] = 800;
1722 GraphBuffer
[maxPos
+1] = -800;
1724 PrintToScrollback("actual data bits start at sample %d", maxPos
);
1726 PrintToScrollback("length %d/%d", highLen
, lowLen
);
1728 BYTE bits
[1+64+16+8+16];
1729 bits
[sizeof(bits
)-1] = '\0';
1731 DWORD shift3
= 0x7e000000, shift2
= 0, shift1
= 0, shift0
= 0;
1733 for(i
= 0; i
< arraylen(bits
)-1; i
++) {
1737 for(j
= 0; j
< lowLen
; j
++) {
1738 low
-= GraphBuffer
[maxPos
+j
];
1740 for(j
= 0; j
< highLen
; j
++) {
1741 high
+= GraphBuffer
[maxPos
+j
];
1747 // bitstream arrives lsb first so shift right
1754 // 128 bit right shift register
1755 shift0
= (shift0
>>1) | (shift1
<< 31);
1756 shift1
= (shift1
>>1) | (shift2
<< 31);
1757 shift2
= (shift2
>>1) | (shift3
<< 31);
1760 // place a marker in the buffer between bits to visually aid location
1761 GraphBuffer
[maxPos
] = 800;
1762 GraphBuffer
[maxPos
+1] = -800;
1764 PrintToScrollback("Info: raw tag bits = %s", bits
);
1766 TagType
= (shift3
>>8)&0xff;
1767 if ( TagType
!= ((shift0
>>16)&0xff) ) {
1768 PrintToScrollback("Error: start and stop bits do not match!");
1771 else if (TagType
== 0x7e) {
1772 PrintToScrollback("Info: Readonly TI tag detected.");
1775 else if (TagType
== 0xfe) {
1776 PrintToScrollback("Info: Rewriteable TI tag detected.");
1778 // put 64 bit data into shift1 and shift0
1779 shift0
= (shift0
>>24) | (shift1
<< 8);
1780 shift1
= (shift1
>>24) | (shift2
<< 8);
1782 // align 16 bit crc into lower half of shift2
1783 shift2
= ((shift2
>>24) | (shift3
<< 8)) & 0x0ffff;
1785 // align 16 bit "end bits" or "ident" into lower half of shift3
1788 // only 15 bits compare, last bit of ident is not valid
1789 if ( (shift3
^shift0
)&0x7fff ) {
1790 PrintToScrollback("Error: Ident mismatch!");
1792 // WARNING the order of the bytes in which we calc crc below needs checking
1793 // i'm 99% sure the crc algorithm is correct, but it may need to eat the
1794 // bytes in reverse or something
1797 crc
= update_crc16(crc
, (shift0
)&0xff);
1798 crc
= update_crc16(crc
, (shift0
>>8)&0xff);
1799 crc
= update_crc16(crc
, (shift0
>>16)&0xff);
1800 crc
= update_crc16(crc
, (shift0
>>24)&0xff);
1801 crc
= update_crc16(crc
, (shift1
)&0xff);
1802 crc
= update_crc16(crc
, (shift1
>>8)&0xff);
1803 crc
= update_crc16(crc
, (shift1
>>16)&0xff);
1804 crc
= update_crc16(crc
, (shift1
>>24)&0xff);
1805 PrintToScrollback("Info: Tag data = %08X%08X", shift1
, shift0
);
1806 if (crc
!= (shift2
&0xffff)) {
1807 PrintToScrollback("Error: CRC mismatch, calculated %04X, got ^04X", crc
, shift2
&0xffff);
1809 PrintToScrollback("Info: CRC %04X is good", crc
);
1813 PrintToScrollback("Unknown tag type.");
1818 static void CmdNorm(char *str
)
1821 int max
= INT_MIN
, min
= INT_MAX
;
1822 for(i
= 10; i
< GraphTraceLen
; i
++) {
1823 if(GraphBuffer
[i
] > max
) {
1824 max
= GraphBuffer
[i
];
1826 if(GraphBuffer
[i
] < min
) {
1827 min
= GraphBuffer
[i
];
1831 for(i
= 0; i
< GraphTraceLen
; i
++) {
1832 GraphBuffer
[i
] = (GraphBuffer
[i
] - ((max
+ min
)/2))*1000/
1836 RepaintGraphWindow();
1839 static void CmdAmp(char *str
)
1841 int i
, rising
, falling
;
1842 int max
= INT_MIN
, min
= INT_MAX
;
1843 for(i
= 10; i
< GraphTraceLen
; i
++) {
1844 if(GraphBuffer
[i
] > max
) {
1845 max
= GraphBuffer
[i
];
1847 if(GraphBuffer
[i
] < min
) {
1848 min
= GraphBuffer
[i
];
1853 for(i
= 0; i
< GraphTraceLen
; i
++) {
1854 if(GraphBuffer
[i
+1] < GraphBuffer
[i
]) {
1856 GraphBuffer
[i
]= max
;
1861 if(GraphBuffer
[i
+1] > GraphBuffer
[i
]) {
1863 GraphBuffer
[i
]= min
;
1870 RepaintGraphWindow();
1873 static void CmdDec(char *str
)
1876 for(i
= 0; i
< (GraphTraceLen
/2); i
++) {
1877 GraphBuffer
[i
] = GraphBuffer
[i
*2];
1880 PrintToScrollback("decimated by 2");
1881 RepaintGraphWindow();
1884 static void CmdHpf(char *str
)
1888 for(i
= 10; i
< GraphTraceLen
; i
++) {
1889 accum
+= GraphBuffer
[i
];
1891 accum
/= (GraphTraceLen
- 10);
1892 for(i
= 0; i
< GraphTraceLen
; i
++) {
1893 GraphBuffer
[i
] -= accum
;
1896 RepaintGraphWindow();
1899 static void CmdZerocrossings(char *str
)
1902 // Zero-crossings aren't meaningful unless the signal is zero-mean.
1908 for(i
= 0; i
< GraphTraceLen
; i
++) {
1909 if(GraphBuffer
[i
]*sign
>= 0) {
1910 // No change in sign, reproduce the previous sample count.
1912 GraphBuffer
[i
] = lastZc
;
1914 // Change in sign, reset the sample count.
1916 GraphBuffer
[i
] = lastZc
;
1924 RepaintGraphWindow();
1927 static void CmdThreshold(char *str
)
1930 int threshold
= atoi(str
);
1932 for(i
= 0; i
< GraphTraceLen
; i
++) {
1933 if(GraphBuffer
[i
]>= threshold
)
1938 RepaintGraphWindow();
1941 static void CmdLtrim(char *str
)
1946 for(i
= ds
; i
< GraphTraceLen
; i
++) {
1947 GraphBuffer
[i
-ds
] = GraphBuffer
[i
];
1949 GraphTraceLen
-= ds
;
1951 RepaintGraphWindow();
1954 static void CmdAutoCorr(char *str
)
1956 static int CorrelBuffer
[MAX_GRAPH_TRACE_LEN
];
1958 int window
= atoi(str
);
1961 PrintToScrollback("needs a window");
1965 if(window
>= GraphTraceLen
) {
1966 PrintToScrollback("window must be smaller than trace (%d samples)",
1971 PrintToScrollback("performing %d correlations", GraphTraceLen
- window
);
1974 for(i
= 0; i
< GraphTraceLen
- window
; i
++) {
1977 for(j
= 0; j
< window
; j
++) {
1978 sum
+= (GraphBuffer
[j
]*GraphBuffer
[i
+j
]) / 256;
1980 CorrelBuffer
[i
] = sum
;
1982 GraphTraceLen
= GraphTraceLen
- window
;
1983 memcpy(GraphBuffer
, CorrelBuffer
, GraphTraceLen
*sizeof(int));
1985 RepaintGraphWindow();
1988 static void CmdVchdemod(char *str
)
1990 // Is this the entire sync pattern, or does this also include some
1991 // data bits that happen to be the same everywhere? That would be
1993 static const int SyncPattern
[] = {
1994 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
1995 1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
1996 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
1997 1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
1998 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
1999 1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
2000 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
2001 1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
2002 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
2003 1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
2006 // So first, we correlate for the sync pattern, and mark that.
2007 int bestCorrel
= 0, bestPos
= 0;
2009 // It does us no good to find the sync pattern, with fewer than
2010 // 2048 samples after it...
2011 for(i
= 0; i
< (GraphTraceLen
-2048); i
++) {
2014 for(j
= 0; j
< arraylen(SyncPattern
); j
++) {
2015 sum
+= GraphBuffer
[i
+j
]*SyncPattern
[j
];
2017 if(sum
> bestCorrel
) {
2022 PrintToScrollback("best sync at %d [metric %d]", bestPos
, bestCorrel
);
2027 int worst
= INT_MAX
;
2030 for(i
= 0; i
< 2048; i
+= 8) {
2033 for(j
= 0; j
< 8; j
++) {
2034 sum
+= GraphBuffer
[bestPos
+i
+j
];
2041 if(abs(sum
) < worst
) {
2046 PrintToScrollback("bits:");
2047 PrintToScrollback("%s", bits
);
2048 PrintToScrollback("worst metric: %d at pos %d", worst
, worstPos
);
2050 if(strcmp(str
, "clone")==0) {
2053 for(s
= bits
; *s
; s
++) {
2055 for(j
= 0; j
< 16; j
++) {
2056 GraphBuffer
[GraphTraceLen
++] = (*s
== '1') ? 1 : 0;
2059 RepaintGraphWindow();
2063 static void CmdIndalademod(char *str
)
2065 // Usage: recover 64bit UID by default, specify "224" as arg to recover a 224bit UID
2070 // worst case with GraphTraceLen=64000 is < 4096
2071 // under normal conditions it's < 2048
2074 int worst
= 0, worstPos
= 0;
2075 PrintToScrollback("Expecting a bit less than %d raw bits", GraphTraceLen
/32);
2076 for(i
= 0; i
< GraphTraceLen
-1; i
+= 2) {
2078 if((GraphBuffer
[i
] > GraphBuffer
[i
+ 1]) && (state
!= 1)) {
2080 for(j
= 0; j
< count
- 8; j
+= 16) {
2081 rawbits
[rawbit
++] = 0;
2083 if ((abs(count
- j
)) > worst
) {
2084 worst
= abs(count
- j
);
2090 } else if((GraphBuffer
[i
] < GraphBuffer
[i
+ 1]) && (state
!= 0)) {
2092 for(j
= 0; j
< count
- 8; j
+= 16) {
2093 rawbits
[rawbit
++] = 1;
2095 if ((abs(count
- j
)) > worst
) {
2096 worst
= abs(count
- j
);
2104 PrintToScrollback("Recovered %d raw bits", rawbit
);
2105 PrintToScrollback("worst metric (0=best..7=worst): %d at pos %d", worst
, worstPos
);
2107 // Finding the start of a UID
2108 int uidlen
, long_wait
;
2109 if(strcmp(str
, "224") == 0) {
2118 for(start
= 0; start
<= rawbit
- uidlen
; start
++) {
2119 first
= rawbits
[start
];
2120 for(i
= start
; i
< start
+ long_wait
; i
++) {
2121 if(rawbits
[i
] != first
) {
2125 if(i
== (start
+ long_wait
)) {
2129 if(start
== rawbit
- uidlen
+ 1) {
2130 PrintToScrollback("nothing to wait for");
2134 // Inverting signal if needed
2136 for(i
= start
; i
< rawbit
; i
++) {
2137 rawbits
[i
] = !rawbits
[i
];
2144 showbits
[uidlen
]='\0';
2148 if(uidlen
> rawbit
) {
2149 PrintToScrollback("Warning: not enough raw bits to get a full UID");
2150 for(bit
= 0; bit
< rawbit
; bit
++) {
2151 bits
[bit
] = rawbits
[i
++];
2152 // As we cannot know the parity, let's use "." and "/"
2153 showbits
[bit
] = '.' + bits
[bit
];
2155 showbits
[bit
+1]='\0';
2156 PrintToScrollback("Partial UID=%s", showbits
);
2159 for(bit
= 0; bit
< uidlen
; bit
++) {
2160 bits
[bit
] = rawbits
[i
++];
2161 showbits
[bit
] = '0' + bits
[bit
];
2165 PrintToScrollback("UID=%s", showbits
);
2167 // Checking UID against next occurences
2168 for(; i
+ uidlen
<= rawbit
;) {
2170 for(bit
= 0; bit
< uidlen
; bit
++) {
2171 if(bits
[bit
] != rawbits
[i
++]) {
2181 PrintToScrollback("Occurences: %d (expected %d)", times
, (rawbit
- start
) / uidlen
);
2183 // Remodulating for tag cloning
2184 GraphTraceLen
= 32*uidlen
;
2187 for(bit
= 0; bit
< uidlen
; bit
++) {
2188 if(bits
[bit
] == 0) {
2194 for(j
= 0; j
< 32; j
++) {
2195 GraphBuffer
[i
++] = phase
;
2200 RepaintGraphWindow();
2203 static void CmdFlexdemod(char *str
)
2206 for(i
= 0; i
< GraphTraceLen
; i
++) {
2207 if(GraphBuffer
[i
] < 0) {
2208 GraphBuffer
[i
] = -1;
2214 #define LONG_WAIT 100
2216 for(start
= 0; start
< GraphTraceLen
- LONG_WAIT
; start
++) {
2217 int first
= GraphBuffer
[start
];
2218 for(i
= start
; i
< start
+ LONG_WAIT
; i
++) {
2219 if(GraphBuffer
[i
] != first
) {
2223 if(i
== (start
+ LONG_WAIT
)) {
2227 if(start
== GraphTraceLen
- LONG_WAIT
) {
2228 PrintToScrollback("nothing to wait for");
2232 GraphBuffer
[start
] = 2;
2233 GraphBuffer
[start
+1] = -2;
2239 for(bit
= 0; bit
< 64; bit
++) {
2242 for(j
= 0; j
< 16; j
++) {
2243 sum
+= GraphBuffer
[i
++];
2250 PrintToScrollback("bit %d sum %d", bit
, sum
);
2253 for(bit
= 0; bit
< 64; bit
++) {
2256 for(j
= 0; j
< 16; j
++) {
2257 sum
+= GraphBuffer
[i
++];
2259 if(sum
> 0 && bits
[bit
] != 1) {
2260 PrintToScrollback("oops1 at %d", bit
);
2262 if(sum
< 0 && bits
[bit
] != 0) {
2263 PrintToScrollback("oops2 at %d", bit
);
2267 GraphTraceLen
= 32*64;
2270 for(bit
= 0; bit
< 64; bit
++) {
2271 if(bits
[bit
] == 0) {
2277 for(j
= 0; j
< 32; j
++) {
2278 GraphBuffer
[i
++] = phase
;
2283 RepaintGraphWindow();
2287 * Generic command to demodulate ASK.
2289 * Argument is convention: positive or negative (High mod means zero
2290 * or high mod means one)
2292 * Updates the Graph trace with 0/1 values
2298 static void Cmdaskdemod(char *str
) {
2300 int c
, high
= 0, low
= 0;
2302 // TODO: complain if we do not give 2 arguments here !
2303 // (AL - this doesn't make sense! we're only using one argument!!!)
2304 sscanf(str
, "%i", &c
);
2306 /* Detect high and lows and clock */
2308 for (i
= 0; i
< GraphTraceLen
; i
++)
2310 if (GraphBuffer
[i
] > high
)
2311 high
= GraphBuffer
[i
];
2312 else if (GraphBuffer
[i
] < low
)
2313 low
= GraphBuffer
[i
];
2315 if(c
!= 0 && c
!= 1) {
2316 PrintToScrollback("Invalid argument: %s",str
);
2320 if (GraphBuffer
[0] > 0) {
2321 GraphBuffer
[0] = 1-c
;
2325 for(i
=1;i
<GraphTraceLen
;i
++) {
2326 /* Transitions are detected at each peak
2327 * Transitions are either:
2328 * - we're low: transition if we hit a high
2329 * - we're high: transition if we hit a low
2330 * (we need to do it this way because some tags keep high or
2331 * low for long periods, others just reach the peak and go
2334 if ((GraphBuffer
[i
]==high
) && (GraphBuffer
[i
-1] == c
)) {
2336 } else if ((GraphBuffer
[i
]==low
) && (GraphBuffer
[i
-1] == (1-c
))){
2340 GraphBuffer
[i
] = GraphBuffer
[i
-1];
2343 RepaintGraphWindow();
2346 /* Print our clock rate */
2347 static void Cmddetectclockrate(char *str
)
2349 int clock
= detectclock(0);
2350 PrintToScrollback("Auto-detected clock rate: %d", clock
);
2356 int detectclock(int peak
)
2362 /* Detect peak if we don't have one */
2364 for (i
= 0; i
< GraphTraceLen
; i
++)
2365 if (GraphBuffer
[i
] > peak
)
2366 peak
= GraphBuffer
[i
];
2368 for (i
= 1; i
< GraphTraceLen
; i
++)
2370 /* If this is the beginning of a peak */
2371 if (GraphBuffer
[i
-1] != GraphBuffer
[i
] && GraphBuffer
[i
] == peak
)
2373 /* Find lowest difference between peaks */
2374 if (lastpeak
&& i
- lastpeak
< clock
)
2376 clock
= i
- lastpeak
;
2385 /* Get or auto-detect clock rate */
2386 int GetClock(char *str
, int peak
)
2390 sscanf(str
, "%i", &clock
);
2391 if (!strcmp(str
, ""))
2394 /* Auto-detect clock */
2397 clock
= detectclock(peak
);
2399 /* Only print this message if we're not looping something */
2401 PrintToScrollback("Auto-detected clock rate: %d", clock
);
2408 * Convert to a bitstream
2410 static void Cmdbitstream(char *str
) {
2417 int hithigh
, hitlow
, first
;
2419 /* Detect high and lows and clock */
2420 for (i
= 0; i
< GraphTraceLen
; i
++)
2422 if (GraphBuffer
[i
] > high
)
2423 high
= GraphBuffer
[i
];
2424 else if (GraphBuffer
[i
] < low
)
2425 low
= GraphBuffer
[i
];
2429 clock
= GetClock(str
, high
);
2431 gtl
= CmdClearGraph(0);
2434 for (i
= 0; i
< (int)(gtl
/ clock
); i
++)
2440 /* Find out if we hit both high and low peaks */
2441 for (j
= 0; j
< clock
; j
++)
2443 if (GraphBuffer
[(i
* clock
) + j
] == high
)
2445 else if (GraphBuffer
[(i
* clock
) + j
] == low
)
2448 /* it doesn't count if it's the first part of our read
2449 because it's really just trailing from the last sequence */
2450 if (first
&& (hithigh
|| hitlow
))
2451 hithigh
= hitlow
= 0;
2455 if (hithigh
&& hitlow
)
2459 /* If we didn't hit both high and low peaks, we had a bit transition */
2460 if (!hithigh
|| !hitlow
)
2463 CmdAppendGraph(0, clock
, bit
);
2464 // for (j = 0; j < (int)(clock/2); j++)
2465 // GraphBuffer[(i * clock) + j] = bit ^ 1;
2466 // for (j = (int)(clock/2); j < clock; j++)
2467 // GraphBuffer[(i * clock) + j] = bit;
2470 RepaintGraphWindow();
2473 /* Modulate our data into manchester */
2474 static void Cmdmanchestermod(char *str
)
2478 int bit
, lastbit
, wave
;
2481 clock
= GetClock(str
, 0);
2485 for (i
= 0; i
< (int)(GraphTraceLen
/ clock
); i
++)
2487 bit
= GraphBuffer
[i
* clock
] ^ 1;
2489 for (j
= 0; j
< (int)(clock
/2); j
++)
2490 GraphBuffer
[(i
* clock
) + j
] = bit
^ lastbit
^ wave
;
2491 for (j
= (int)(clock
/2); j
< clock
; j
++)
2492 GraphBuffer
[(i
* clock
) + j
] = bit
^ lastbit
^ wave
^ 1;
2494 /* Keep track of how we start our wave and if we changed or not this time */
2495 wave
^= bit
^ lastbit
;
2499 RepaintGraphWindow();
2503 * Manchester demodulate a bitstream. The bitstream needs to be already in
2504 * the GraphBuffer as 0 and 1 values
2506 * Give the clock rate as argument in order to help the sync - the algorithm
2507 * resyncs at each pulse anyway.
2509 * Not optimized by any means, this is the 1st time I'm writing this type of
2510 * routine, feel free to improve...
2512 * 1st argument: clock rate (as number of samples per clock rate)
2513 * Typical values can be 64, 32, 128...
2515 static void Cmdmanchesterdemod(char *str
) {
2516 int i
, j
, invert
= 0;
2522 int hithigh
, hitlow
, first
;
2528 /* check if we're inverting output */
2531 PrintToScrollback("Inverting output");
2535 while(*str
== ' '); // in case a 2nd argument was given
2538 /* Holds the decoded bitstream: each clock period contains 2 bits */
2539 /* later simplified to 1 bit after manchester decoding. */
2540 /* Add 10 bits to allow for noisy / uncertain traces without aborting */
2541 /* int BitStream[GraphTraceLen*2/clock+10]; */
2543 /* But it does not work if compiling on WIndows: therefore we just allocate a */
2545 int BitStream
[MAX_GRAPH_TRACE_LEN
];
2547 /* Detect high and lows */
2548 for (i
= 0; i
< GraphTraceLen
; i
++)
2550 if (GraphBuffer
[i
] > high
)
2551 high
= GraphBuffer
[i
];
2552 else if (GraphBuffer
[i
] < low
)
2553 low
= GraphBuffer
[i
];
2557 clock
= GetClock(str
, high
);
2559 int tolerance
= clock
/4;
2561 /* Detect first transition */
2562 /* Lo-Hi (arbitrary) */
2563 /* skip to the first high */
2564 for (i
= 0; i
< GraphTraceLen
; i
++)
2565 if(GraphBuffer
[i
] == high
)
2567 /* now look for the first low */
2568 for (; i
< GraphTraceLen
; i
++)
2570 if (GraphBuffer
[i
] == low
)
2577 /* If we're not working with 1/0s, demod based off clock */
2580 bit
= 0; /* We assume the 1st bit is zero, it may not be
2581 * the case: this routine (I think) has an init problem.
2584 for (; i
< (int)(GraphTraceLen
/ clock
); i
++)
2590 /* Find out if we hit both high and low peaks */
2591 for (j
= 0; j
< clock
; j
++)
2593 if (GraphBuffer
[(i
* clock
) + j
] == high
)
2595 else if (GraphBuffer
[(i
* clock
) + j
] == low
)
2598 /* it doesn't count if it's the first part of our read
2599 because it's really just trailing from the last sequence */
2600 if (first
&& (hithigh
|| hitlow
))
2601 hithigh
= hitlow
= 0;
2605 if (hithigh
&& hitlow
)
2609 /* If we didn't hit both high and low peaks, we had a bit transition */
2610 if (!hithigh
|| !hitlow
)
2613 BitStream
[bit2idx
++] = bit
^ invert
;
2617 /* standard 1/0 bitstream */
2621 /* Then detect duration between 2 successive transitions */
2622 for (bitidx
= 1; i
< GraphTraceLen
; i
++)
2624 if (GraphBuffer
[i
-1] != GraphBuffer
[i
])
2629 // Error check: if bitidx becomes too large, we do not
2630 // have a Manchester encoded bitstream or the clock is really
2632 if (bitidx
> (GraphTraceLen
*2/clock
+8) ) {
2633 PrintToScrollback("Error: the clock you gave is probably wrong, aborting.");
2636 // Then switch depending on lc length:
2637 // Tolerance is 1/4 of clock rate (arbitrary)
2638 if (abs(lc
-clock
/2) < tolerance
) {
2639 // Short pulse : either "1" or "0"
2640 BitStream
[bitidx
++]=GraphBuffer
[i
-1];
2641 } else if (abs(lc
-clock
) < tolerance
) {
2642 // Long pulse: either "11" or "00"
2643 BitStream
[bitidx
++]=GraphBuffer
[i
-1];
2644 BitStream
[bitidx
++]=GraphBuffer
[i
-1];
2648 PrintToScrollback("Warning: Manchester decode error for pulse width detection.");
2649 PrintToScrollback("(too many of those messages mean either the stream is not Manchester encoded, or clock is wrong)");
2653 PrintToScrollback("Error: too many detection errors, aborting.");
2660 // At this stage, we now have a bitstream of "01" ("1") or "10" ("0"), parse it into final decoded bitstream
2661 // Actually, we overwrite BitStream with the new decoded bitstream, we just need to be careful
2662 // to stop output at the final bitidx2 value, not bitidx
2663 for (i
= 0; i
< bitidx
; i
+= 2) {
2664 if ((BitStream
[i
] == 0) && (BitStream
[i
+1] == 1)) {
2665 BitStream
[bit2idx
++] = 1 ^ invert
;
2666 } else if ((BitStream
[i
] == 1) && (BitStream
[i
+1] == 0)) {
2667 BitStream
[bit2idx
++] = 0 ^ invert
;
2669 // We cannot end up in this state, this means we are unsynchronized,
2673 PrintToScrollback("Unsynchronized, resync...");
2674 PrintToScrollback("(too many of those messages mean the stream is not Manchester encoded)");
2678 PrintToScrollback("Error: too many decode errors, aborting.");
2685 PrintToScrollback("Manchester decoded bitstream");
2686 // Now output the bitstream to the scrollback by line of 16 bits
2687 for (i
= 0; i
< (bit2idx
-16); i
+=16) {
2688 PrintToScrollback("%i %i %i %i %i %i %i %i %i %i %i %i %i %i %i %i",
2711 static void CmdHiddemod(char *str
)
2713 if(GraphTraceLen
< 4800) {
2714 PrintToScrollback("too short; need at least 4800 samples");
2718 GraphTraceLen
= 4800;
2720 for(i
= 0; i
< GraphTraceLen
; i
++) {
2721 if(GraphBuffer
[i
] < 0) {
2727 RepaintGraphWindow();
2730 static void CmdPlot(char *str
)
2735 static void CmdGrid(char *str
)
2737 sscanf(str
, "%i %i", &PlotGridX
, &PlotGridY
);
2738 RepaintGraphWindow();
2741 static void CmdHide(char *str
)
2746 static void CmdScale(char *str
)
2748 CursorScaleFactor
= atoi(str
);
2749 if(CursorScaleFactor
== 0) {
2750 PrintToScrollback("bad, can't have zero scale");
2751 CursorScaleFactor
= 1;
2753 RepaintGraphWindow();
2756 static void CmdSave(char *str
)
2758 FILE *f
= fopen(str
, "w");
2760 PrintToScrollback("couldn't open '%s'", str
);
2764 for(i
= 0; i
< GraphTraceLen
; i
++) {
2765 fprintf(f
, "%d\n", GraphBuffer
[i
]);
2768 PrintToScrollback("saved to '%s'", str
);
2771 static void CmdLoad(char *str
)
2773 FILE *f
= fopen(str
, "r");
2775 PrintToScrollback("couldn't open '%s'", str
);
2781 while(fgets(line
, sizeof(line
), f
)) {
2782 GraphBuffer
[GraphTraceLen
] = atoi(line
);
2786 PrintToScrollback("loaded %d samples", GraphTraceLen
);
2787 RepaintGraphWindow();
2790 static void CmdHIDsimTAG(char *str
)
2792 unsigned int hi
=0, lo
=0;
2796 while (sscanf(&str
[i
++], "%1x", &n
) == 1) {
2797 hi
=(hi
<<4)|(lo
>>28);
2801 PrintToScrollback("Emulating tag with ID %x%16x", hi
, lo
);
2803 c
.cmd
= CMD_HID_SIM_TAG
;
2806 SendCommand(&c
, FALSE
);
2809 static void CmdReadmem(char *str
)
2812 c
.cmd
= CMD_READ_MEM
;
2814 SendCommand(&c
, FALSE
);
2817 static void CmdVersion(char *str
)
2820 c
.cmd
= CMD_VERSION
;
2821 SendCommand(&c
, FALSE
);
2824 static void CmdLcdReset(char *str
)
2827 c
.cmd
= CMD_LCD_RESET
;
2829 SendCommand(&c
, FALSE
);
2832 static void CmdLcd(char *str
)
2837 sscanf(str
, "%x %d", &i
, &j
);
2840 SendCommand(&c
, FALSE
);
2845 * Sets the divisor for LF frequency clock: lets the user choose any LF frequency below
2848 static void CmdSetDivisor(char *str
)
2851 c
.cmd
= CMD_SET_LF_DIVISOR
;
2853 if (( c
.ext1
<0) || (c
.ext1
>255)) {
2854 PrintToScrollback("divisor must be between 19 and 255");
2856 SendCommand(&c
, FALSE
);
2857 PrintToScrollback("Divisor set, expected freq=%dHz", 12000000/(c
.ext1
+1));
2861 static void CmdSetMux(char *str
)
2864 c
.cmd
= CMD_SET_ADC_MUX
;
2865 if(strcmp(str
, "lopkd") == 0) {
2867 } else if(strcmp(str
, "loraw") == 0) {
2869 } else if(strcmp(str
, "hipkd") == 0) {
2871 } else if(strcmp(str
, "hiraw") == 0) {
2874 SendCommand(&c
, FALSE
);
2877 typedef void HandlerFunction(char *cmdline
);
2879 /* in alphabetic order */
2882 HandlerFunction
*handler
;
2883 int offline
; // 1 if the command can be used when in offline mode
2885 } CommandTable
[] = {
2886 {"amp", CmdAmp
, 1, "Amplify peaks"},
2887 {"askdemod", Cmdaskdemod
, 1, "<0|1> -- Attempt to demodulate simple ASK tags"},
2888 {"autocorr", CmdAutoCorr
, 1, "<window length> -- Autocorrelation over window"},
2889 {"bitsamples", CmdBitsamples
, 0, "Get raw samples as bitstring"},
2890 {"bitstream", Cmdbitstream
, 1, "[clock rate] -- Convert waveform into a bitstream"},
2891 {"buffclear", CmdBuffClear
, 1, "Clear sample buffer and graph window"},
2892 {"dec", CmdDec
, 1, "Decimate samples"},
2893 {"detectclock", Cmddetectclockrate
, 1, "Detect clock rate"},
2894 {"detectreader", CmdDetectReader
, 0, "['l'|'h'] -- Detect external reader field (option 'l' or 'h' to limit to LF or HF)"},
2895 {"em410xsim", CmdEM410xsim
, 1, "<UID> -- Simulate EM410x tag"},
2896 {"em410xread", CmdEM410xread
, 1, "[clock rate] -- Extract ID from EM410x tag"},
2897 {"em410xwatch", CmdEM410xwatch
, 0, "Watches for EM410x tags"},
2898 {"em4x50read", CmdEM4x50read
, 1, "Extract data from EM4x50 tag"},
2899 {"exit", CmdQuit
, 1, "Exit program"},
2900 {"flexdemod", CmdFlexdemod
, 1, "Demodulate samples for FlexPass"},
2901 {"fpgaoff", CmdFPGAOff
, 0, "Set FPGA off"},
2902 {"fskdemod", CmdFSKdemod
, 1, "Demodulate graph window as a HID FSK"},
2903 {"grid", CmdGrid
, 1, "<x> <y> -- overlay grid on graph window, use zero value to turn off either"},
2904 {"hexsamples", CmdHexsamples
, 0, "<blocks> -- Dump big buffer as hex bytes"},
2905 {"hi14alist", CmdHi14alist
, 0, "List ISO 14443a history"},
2906 {"hi14areader", CmdHi14areader
, 0, "Act like an ISO14443 Type A reader"},
2907 {"hi14asim", CmdHi14asim
, 0, "<UID> -- Fake ISO 14443a tag"},
2908 {"hi14asnoop", CmdHi14asnoop
, 0, "Eavesdrop ISO 14443 Type A"},
2909 {"hi14bdemod", CmdHi14bdemod
, 1, "Demodulate ISO14443 Type B from tag"},
2910 {"hi14list", CmdHi14list
, 0, "List ISO 14443 history"},
2911 {"hi14read", CmdHi14read
, 0, "Read HF tag (ISO 14443)"},
2912 {"hi14sim", CmdHi14sim
, 0, "Fake ISO 14443 tag"},
2913 {"hi14snoop", CmdHi14snoop
, 0, "Eavesdrop ISO 14443"},
2914 {"hi15demod", CmdHi15demod
, 1, "Demodulate ISO15693 from tag"},
2915 {"hi15read", CmdHi15read
, 0, "Read HF tag (ISO 15693)"},
2916 {"hi15reader", CmdHi15reader
, 0, "Act like an ISO15693 reader"},
2917 {"hi15sim", CmdHi15tag
, 0, "Fake an ISO15693 tag"},
2918 {"hiddemod", CmdHiddemod
, 1, "Demodulate HID Prox Card II (not optimal)"},
2919 {"hide", CmdHide
, 1, "Hide graph window"},
2920 {"hidfskdemod", CmdHIDdemodFSK
, 0, "Realtime HID FSK demodulator"},
2921 {"hidsimtag", CmdHIDsimTAG
, 0, "<ID> -- HID tag simulator"},
2922 {"higet", CmdHi14read_sim
, 0, "<samples> -- Get samples HF, 'analog'"},
2923 {"hisamples", CmdHisamples
, 0, "Get raw samples for HF tag"},
2924 {"hisampless", CmdHisampless
, 0, "<samples> -- Get signed raw samples, HF tag"},
2925 {"hisamplest", CmdHi14readt
, 0, "Get samples HF, for testing"},
2926 {"hisimlisten", CmdHisimlisten
, 0, "Get HF samples as fake tag"},
2927 {"hpf", CmdHpf
, 1, "Remove DC offset from trace"},
2928 {"indalademod", CmdIndalademod
, 0, "['224'] -- Demodulate samples for Indala 64 bit UID (option '224' for 224 bit)"},
2929 {"lcd", CmdLcd
, 0, "<HEX command> <count> -- Send command/data to LCD"},
2930 {"lcdreset", CmdLcdReset
, 0, "Hardware reset LCD"},
2931 {"legicrfsim", CmdLegicRfSim
, 0, "Start the LEGIC RF tag simulator"},
2932 {"legicrfread", CmdLegicRfRead
, 0, "Start the LEGIC RF reader"},
2933 {"load", CmdLoad
, 1, "<filename> -- Load trace (to graph window"},
2934 {"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)"},
2935 {"loread", CmdLoread
, 0, "['h'] -- Read 125/134 kHz LF ID-only tag (option 'h' for 134)"},
2936 {"losamples", CmdLosamples
, 0, "[128 - 16000] -- Get raw samples for LF tag"},
2937 {"losim", CmdLosim
, 0, "Simulate LF tag"},
2938 {"losimbidir", CmdLosimBidir
, 0, "Simulate LF tag (with bidirectional data transmission between reader and tag)"},
2939 {"ltrim", CmdLtrim
, 1, "<samples> -- Trim samples from left of trace"},
2940 {"mandemod", Cmdmanchesterdemod
, 1, "[i] [clock rate] -- Manchester demodulate binary stream (option 'i' to invert output)"},
2941 {"manmod", Cmdmanchestermod
, 1, "[clock rate] -- Manchester modulate a binary stream"},
2942 {"norm", CmdNorm
, 1, "Normalize max/min to +/-500"},
2943 {"plot", CmdPlot
, 1, "Show graph window"},
2944 {"quit", CmdQuit
, 1, "Quit program"},
2945 {"readmem", CmdReadmem
, 0, "[address] -- Read memory at decimal address from flash"},
2946 {"reset", CmdReset
, 0, "Reset the Proxmark3"},
2947 {"save", CmdSave
, 1, "<filename> -- Save trace (from graph window)"},
2948 {"scale", CmdScale
, 1, "<int> -- Set cursor display scale"},
2949 {"setlfdivisor", CmdSetDivisor
, 0, "<19 - 255> -- Drive LF antenna at 12Mhz/(divisor+1)"},
2950 {"setmux", CmdSetMux
, 0, "<loraw|hiraw|lopkd|hipkd> -- Set the ADC mux to a specific value"},
2951 {"sri512read", CmdSri512read
, 0, "<int> -- Read contents of a SRI512 tag"},
2952 {"srix4kread", CmdSrix4kread
, 0, "<int> -- Read contents of a SRIX4K tag"},
2953 {"tidemod", CmdTIDemod
, 1, "Demodulate raw bits for TI-type LF tag"},
2954 {"tiread", CmdTIRead
, 0, "Read and decode a TI 134 kHz tag"},
2955 {"tiwrite", CmdTIWrite
, 0, "Write new data to a r/w TI 134 kHz tag"},
2956 {"threshold", CmdThreshold
, 1, "Maximize/minimize every value in the graph window depending on threshold"},
2957 {"tune", CmdTune
, 0, "Measure antenna tuning"},
2958 {"vchdemod", CmdVchdemod
, 0, "['clone'] -- Demodulate samples for VeriChip"},
2959 {"version", CmdVersion
, 0, "Show version inforation about the connected Proxmark"},
2960 {"zerocrossings", CmdZerocrossings
, 1, "Count time between zero-crossings"},
2968 } CommandExtendedHelp
[]= {
2969 {"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."},
2970 {"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."},
2973 //-----------------------------------------------------------------------------
2974 // Entry point into our code: called whenever the user types a command and
2975 // then presses Enter, which the full command line that they typed.
2976 //-----------------------------------------------------------------------------
2977 void CommandReceived(char *cmd
)
2982 PrintToScrollback("> %s", cmd
);
2984 if(strcmp(cmd
, "help") == 0 || strncmp(cmd
,"help ",strlen("help ")) == 0) {
2985 // check if we're doing extended help
2986 if(strlen(cmd
) > strlen("help ")) {
2987 cmd
+= strlen("help ");
2988 for(i
= 0; i
< sizeof(CommandExtendedHelp
) / sizeof(CommandExtendedHelp
[0]); i
++) {
2989 if(strcmp(CommandExtendedHelp
[i
].name
,cmd
) == 0) {
2990 PrintToScrollback("\nExtended help for '%s':\n", cmd
);
2991 PrintToScrollback("Args: %s\t- %s\n",CommandExtendedHelp
[i
].args
,CommandExtendedHelp
[i
].argshelp
);
2992 PrintToScrollback(CommandExtendedHelp
[i
].description
);
2993 PrintToScrollback("");
2997 PrintToScrollback("No extended help available for '%s'", cmd
);
3000 if (offline
) PrintToScrollback("Operating in OFFLINE mode (no device connected)");
3001 PrintToScrollback("\r\nAvailable commands:");
3002 for(i
= 0; i
< sizeof(CommandTable
) / sizeof(CommandTable
[0]); i
++) {
3003 if (offline
&& (CommandTable
[i
].offline
==0)) continue;
3004 memset(line
, ' ', sizeof(line
));
3005 strcpy(line
+2, CommandTable
[i
].name
);
3006 line
[strlen(line
)] = ' ';
3007 sprintf(line
+15, " -- %s", CommandTable
[i
].docString
);
3008 PrintToScrollback("%s", line
);
3010 PrintToScrollback("");
3011 PrintToScrollback("'help <command>' for extended help on that command\n");
3015 for(i
= 0; i
< sizeof(CommandTable
) / sizeof(CommandTable
[0]); i
++) {
3016 char *name
= CommandTable
[i
].name
;
3017 if(memcmp(cmd
, name
, strlen(name
))==0 &&
3018 (cmd
[strlen(name
)] == ' ' || cmd
[strlen(name
)] == '\0'))
3020 cmd
+= strlen(name
);
3021 while(*cmd
== ' ') {
3024 if (offline
&& (CommandTable
[i
].offline
==0)) {
3025 PrintToScrollback("Offline mode, cannot use this command.");
3028 (CommandTable
[i
].handler
)(cmd
);
3032 PrintToScrollback(">> bad command '%s'", cmd
);
3035 //-----------------------------------------------------------------------------
3036 // Entry point into our code: called whenever we received a packet over USB
3037 // that we weren't necessarily expecting, for example a debug print.
3038 //-----------------------------------------------------------------------------
3039 void UsbCommandReceived(UsbCommand
*c
)
3042 case CMD_DEBUG_PRINT_STRING
: {
3044 if(c
->ext1
> 70 || c
->ext1
< 0) {
3047 memcpy(s
, c
->d
.asBytes
, c
->ext1
);
3049 PrintToScrollback("#db# %s", s
);
3053 case CMD_DEBUG_PRINT_INTEGERS
:
3054 PrintToScrollback("#db# %08x, %08x, %08x\r\n", c
->ext1
, c
->ext2
, c
->ext3
);
3057 case CMD_MEASURED_ANTENNA_TUNING
: {
3059 int vLf125
, vLf134
, vHf
;
3060 vLf125
= c
->ext1
& 0xffff;
3061 vLf134
= c
->ext1
>> 16;
3062 vHf
= c
->ext2
& 0xffff;;
3063 peakf
= c
->ext3
& 0xffff;
3064 peakv
= c
->ext3
>> 16;
3065 PrintToScrollback("");
3066 PrintToScrollback("");
3067 PrintToScrollback("# LF antenna: %5.2f V @ 125.00 kHz", vLf125
/1000.0);
3068 PrintToScrollback("# LF antenna: %5.2f V @ 134.00 kHz", vLf134
/1000.0);
3069 PrintToScrollback("# LF optimal: %5.2f V @%9.2f kHz", peakv
/1000.0, 12000.0/(peakf
+1));
3070 PrintToScrollback("# HF antenna: %5.2f V @ 13.56 MHz", vHf
/1000.0);
3072 PrintToScrollback("# Your LF antenna is unusable.");
3073 else if (peakv
<10000)
3074 PrintToScrollback("# Your LF antenna is marginal.");
3076 PrintToScrollback("# Your HF antenna is unusable.");
3078 PrintToScrollback("# Your HF antenna is marginal.");
3082 PrintToScrollback("unrecognized command %08x\n", c
->cmd
);