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
)
912 int requested
= atoi(str
);
922 for(i
= 0; i
< n
; i
+= 12) {
924 c
.cmd
= CMD_DOWNLOAD_RAW_ADC_SAMPLES_125K
;
926 SendCommand(&c
, FALSE
);
928 if(c
.cmd
!= CMD_DOWNLOADED_RAW_ADC_SAMPLES_125K
) {
929 PrintToScrollback("bad resp");
933 for(j
= 0; j
< 48; j
+= 8) {
934 PrintToScrollback("%02x %02x %02x %02x %02x %02x %02x %02x",
946 if(delivered
>= requested
)
949 if(delivered
>= requested
)
954 static void CmdHisampless(char *str
)
966 for(i
= 0; i
< n
; i
+= 12) {
968 c
.cmd
= CMD_DOWNLOAD_RAW_ADC_SAMPLES_125K
;
970 SendCommand(&c
, FALSE
);
972 if(c
.cmd
!= CMD_DOWNLOADED_RAW_ADC_SAMPLES_125K
) {
973 PrintToScrollback("bad resp");
977 for(j
= 0; j
< 48; j
++) {
978 GraphBuffer
[cnt
++] = (int)((signed char)c
.d
.asBytes
[j
]);
983 RepaintGraphWindow();
986 static WORD
Iso15693Crc(BYTE
*v
, int n
)
992 for(i
= 0; i
< n
; i
++) {
993 reg
= reg
^ ((DWORD
)v
[i
]);
994 for (j
= 0; j
< 8; j
++) {
996 reg
= (reg
>> 1) ^ 0x8408;
1006 static void CmdHi14bdemod(char *str
)
1011 BOOL negateI
, negateQ
;
1016 // As received, the samples are pairs, correlations against I and Q
1017 // square waves. So estimate angle of initial carrier (or just
1018 // quadrant, actually), and then do the demod.
1020 // First, estimate where the tag starts modulating.
1021 for(i
= 0; i
< GraphTraceLen
; i
+= 2) {
1022 if(abs(GraphBuffer
[i
]) + abs(GraphBuffer
[i
+1]) > 40) {
1026 if(i
>= GraphTraceLen
) {
1027 PrintToScrollback("too weak to sync");
1030 PrintToScrollback("out of weak at %d", i
);
1033 // Now, estimate the phase in the initial modulation of the tag
1036 for(; i
< (outOfWeakAt
+ 16); i
+= 2) {
1037 isum
+= GraphBuffer
[i
+0];
1038 qsum
+= GraphBuffer
[i
+1];
1040 negateI
= (isum
< 0);
1041 negateQ
= (qsum
< 0);
1043 // Turn the correlation pairs into soft decisions on the bit.
1045 for(i
= 0; i
< GraphTraceLen
/2; i
++) {
1046 int si
= GraphBuffer
[j
];
1047 int sq
= GraphBuffer
[j
+1];
1048 if(negateI
) si
= -si
;
1049 if(negateQ
) sq
= -sq
;
1050 GraphBuffer
[i
] = si
+ sq
;
1056 while(GraphBuffer
[i
] > 0 && i
< GraphTraceLen
)
1058 if(i
>= GraphTraceLen
) goto demodError
;
1061 while(GraphBuffer
[i
] < 0 && i
< GraphTraceLen
)
1063 if(i
>= GraphTraceLen
) goto demodError
;
1064 if((i
- iold
) > 23) goto demodError
;
1066 PrintToScrollback("make it to demod loop");
1070 while(GraphBuffer
[i
] >= 0 && i
< GraphTraceLen
)
1072 if(i
>= GraphTraceLen
) goto demodError
;
1073 if((i
- iold
) > 6) goto demodError
;
1076 if(i
+ 20 >= GraphTraceLen
) goto demodError
;
1078 for(j
= 0; j
< 10; j
++) {
1079 int soft
= GraphBuffer
[i
] + GraphBuffer
[i
+1];
1081 if(abs(soft
) < ((abs(isum
) + abs(qsum
))/20)) {
1082 PrintToScrollback("weak bit");
1086 if(GraphBuffer
[i
] + GraphBuffer
[i
+1] >= 0) {
1093 if( (shiftReg
& 0x200) &&
1094 !(shiftReg
& 0x001))
1096 // valid data byte, start and stop bits okay
1097 PrintToScrollback(" %02x", (shiftReg
>> 1) & 0xff);
1098 data
[dataLen
++] = (shiftReg
>> 1) & 0xff;
1099 if(dataLen
>= sizeof(data
)) {
1102 } else if(shiftReg
== 0x000) {
1111 ComputeCrc14443(CRC_14443_B
, data
, dataLen
-2, &first
, &second
);
1112 PrintToScrollback("CRC: %02x %02x (%s)\n", first
, second
,
1113 (first
== data
[dataLen
-2] && second
== data
[dataLen
-1]) ?
1114 "ok" : "****FAIL****");
1116 RepaintGraphWindow();
1120 PrintToScrollback("demod error");
1121 RepaintGraphWindow();
1124 static void CmdHi14list(char *str
)
1127 GetFromBigBuf(got
, sizeof(got
));
1129 PrintToScrollback("recorded activity:");
1130 PrintToScrollback(" time :rssi: who bytes");
1131 PrintToScrollback("---------+----+----+-----------");
1142 int timestamp
= *((DWORD
*)(got
+i
));
1143 if(timestamp
& 0x80000000) {
1144 timestamp
&= 0x7fffffff;
1149 int metric
= *((DWORD
*)(got
+i
+4));
1156 if(i
+ len
>= 900) {
1160 BYTE
*frame
= (got
+i
+9);
1162 char line
[1000] = "";
1164 for(j
= 0; j
< len
; j
++) {
1165 sprintf(line
+(j
*3), "%02x ", frame
[j
]);
1171 ComputeCrc14443(CRC_14443_B
, frame
, len
-2, &b1
, &b2
);
1172 if(b1
!= frame
[len
-2] || b2
!= frame
[len
-1]) {
1173 crc
= "**FAIL CRC**";
1181 char metricString
[100];
1183 sprintf(metricString
, "%3d", metric
);
1185 strcpy(metricString
, " ");
1188 PrintToScrollback(" +%7d: %s: %s %s %s",
1189 (prev
< 0 ? 0 : timestamp
- prev
),
1191 (isResponse
? "TAG" : " "), line
, crc
);
1198 static void CmdHi14alist(char *str
)
1201 GetFromBigBuf(got
, sizeof(got
));
1203 PrintToScrollback("recorded activity:");
1204 PrintToScrollback(" ETU :rssi: who bytes");
1205 PrintToScrollback("---------+----+----+-----------");
1216 int timestamp
= *((DWORD
*)(got
+i
));
1217 if(timestamp
& 0x80000000) {
1218 timestamp
&= 0x7fffffff;
1225 int parityBits
= *((DWORD
*)(got
+i
+4));
1226 // 4 bytes of additional information...
1227 // maximum of 32 additional parity bit information
1230 // at each quarter bit period we can send power level (16 levels)
1231 // or each half bit period in 256 levels.
1239 if(i
+ len
>= 1900) {
1243 BYTE
*frame
= (got
+i
+9);
1245 // Break and stick with current result if buffer was not completely full
1246 if(frame
[0] == 0x44 && frame
[1] == 0x44 && frame
[3] == 0x44) { break; }
1248 char line
[1000] = "";
1250 for(j
= 0; j
< len
; j
++) {
1251 int oddparity
= 0x01;
1255 oddparity
^= (((frame
[j
] & 0xFF) >> k
) & 0x01);
1258 //if((parityBits >> (len - j - 1)) & 0x01) {
1259 if(isResponse
&& (oddparity
!= ((parityBits
>> (len
- j
- 1)) & 0x01))) {
1260 sprintf(line
+(j
*4), "%02x! ", frame
[j
]);
1263 sprintf(line
+(j
*4), "%02x ", frame
[j
]);
1271 for(j
= 0; j
< (len
- 1); j
++) {
1272 // gives problems... search for the reason..
1273 /*if(frame[j] == 0xAA) {
1274 switch(frame[j+1]) {
1276 crc = "[1] Two drops close after each other";
1279 crc = "[2] Potential SOC with a drop in second half of bitperiod";
1282 crc = "[3] Segment Z after segment X is not possible";
1285 crc = "[4] Parity bit of a fully received byte was wrong";
1288 crc = "[?] Unknown error";
1295 if(strlen(crc
)==0) {
1296 ComputeCrc14443(CRC_14443_A
, frame
, len
-2, &b1
, &b2
);
1297 if(b1
!= frame
[len
-2] || b2
!= frame
[len
-1]) {
1298 crc
= (isResponse
& (len
< 6)) ? "" : " !crc";
1307 char metricString
[100];
1309 sprintf(metricString
, "%3d", metric
);
1311 strcpy(metricString
, " ");
1314 PrintToScrollback(" +%7d: %s: %s %s %s",
1315 (prev
< 0 ? 0 : (timestamp
- prev
)),
1317 (isResponse
? "TAG" : " "), line
, crc
);
1322 CommandFinished
= 1;
1325 static void CmdHi15demod(char *str
)
1327 // The sampling rate is 106.353 ksps/s, for T = 18.8 us
1330 // 1) Unmodulated time of 56.64us
1331 // 2) 24 pulses of 423.75khz
1332 // 3) logic '1' (unmodulated for 18.88us followed by 8 pulses of 423.75khz)
1334 static const int FrameSOF
[] = {
1335 -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
1336 -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
1337 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
1338 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
1344 static const int Logic0
[] = {
1350 static const int Logic1
[] = {
1358 // 1) logic '0' (8 pulses of 423.75khz followed by unmodulated for 18.88us)
1359 // 2) 24 pulses of 423.75khz
1360 // 3) Unmodulated time of 56.64us
1362 static const int FrameEOF
[] = {
1367 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
1368 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
1369 -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
1370 -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1
1374 int max
= 0, maxPos
;
1378 if(GraphTraceLen
< 1000) return;
1380 // First, correlate for SOF
1381 for(i
= 0; i
< 100; i
++) {
1383 for(j
= 0; j
< arraylen(FrameSOF
); j
+= skip
) {
1384 corr
+= FrameSOF
[j
]*GraphBuffer
[i
+(j
/skip
)];
1391 PrintToScrollback("SOF at %d, correlation %d", maxPos
,
1392 max
/(arraylen(FrameSOF
)/skip
));
1394 i
= maxPos
+ arraylen(FrameSOF
)/skip
;
1397 memset(outBuf
, 0, sizeof(outBuf
));
1400 int corr0
= 0, corr1
= 0, corrEOF
= 0;
1401 for(j
= 0; j
< arraylen(Logic0
); j
+= skip
) {
1402 corr0
+= Logic0
[j
]*GraphBuffer
[i
+(j
/skip
)];
1404 for(j
= 0; j
< arraylen(Logic1
); j
+= skip
) {
1405 corr1
+= Logic1
[j
]*GraphBuffer
[i
+(j
/skip
)];
1407 for(j
= 0; j
< arraylen(FrameEOF
); j
+= skip
) {
1408 corrEOF
+= FrameEOF
[j
]*GraphBuffer
[i
+(j
/skip
)];
1410 // Even things out by the length of the target waveform.
1414 if(corrEOF
> corr1
&& corrEOF
> corr0
) {
1415 PrintToScrollback("EOF at %d", i
);
1417 } else if(corr1
> corr0
) {
1418 i
+= arraylen(Logic1
)/skip
;
1421 i
+= arraylen(Logic0
)/skip
;
1428 if((i
+(int)arraylen(FrameEOF
)) >= GraphTraceLen
) {
1429 PrintToScrollback("ran off end!");
1434 PrintToScrollback("error, uneven octet! (discard extra bits!)");
1435 PrintToScrollback(" mask=%02x", mask
);
1437 PrintToScrollback("%d octets", k
);
1439 for(i
= 0; i
< k
; i
++) {
1440 PrintToScrollback("# %2d: %02x ", i
, outBuf
[i
]);
1442 PrintToScrollback("CRC=%04x", Iso15693Crc(outBuf
, k
-2));
1445 static void CmdFSKdemod(char *cmdline
)
1447 static const int LowTone
[] = {
1448 1, 1, 1, 1, 1, -1, -1, -1, -1, -1,
1449 1, 1, 1, 1, 1, -1, -1, -1, -1, -1,
1450 1, 1, 1, 1, 1, -1, -1, -1, -1, -1,
1451 1, 1, 1, 1, 1, -1, -1, -1, -1, -1,
1452 1, 1, 1, 1, 1, -1, -1, -1, -1, -1
1454 static const int HighTone
[] = {
1455 1, 1, 1, 1, 1, -1, -1, -1, -1,
1456 1, 1, 1, 1, -1, -1, -1, -1,
1457 1, 1, 1, 1, -1, -1, -1, -1,
1458 1, 1, 1, 1, -1, -1, -1, -1,
1459 1, 1, 1, 1, -1, -1, -1, -1,
1460 1, 1, 1, 1, -1, -1, -1, -1, -1,
1463 int lowLen
= sizeof(LowTone
)/sizeof(int);
1464 int highLen
= sizeof(HighTone
)/sizeof(int);
1465 int convLen
= (highLen
>lowLen
)?highLen
:lowLen
;
1466 DWORD hi
= 0, lo
= 0;
1469 int minMark
=0, maxMark
=0;
1471 for(i
= 0; i
< GraphTraceLen
- convLen
; i
++) {
1472 int lowSum
= 0, highSum
= 0;
1474 for(j
= 0; j
< lowLen
; j
++) {
1475 lowSum
+= LowTone
[j
]*GraphBuffer
[i
+j
];
1477 for(j
= 0; j
< highLen
; j
++) {
1478 highSum
+= HighTone
[j
]*GraphBuffer
[i
+j
];
1480 lowSum
= abs((100*lowSum
) / lowLen
);
1481 highSum
= abs((100*highSum
) / highLen
);
1482 GraphBuffer
[i
] = (highSum
<< 16) | lowSum
;
1485 for(i
= 0; i
< GraphTraceLen
- convLen
- 16; i
++) {
1487 int lowTot
= 0, highTot
= 0;
1488 // 10 and 8 are f_s divided by f_l and f_h, rounded
1489 for(j
= 0; j
< 10; j
++) {
1490 lowTot
+= (GraphBuffer
[i
+j
] & 0xffff);
1492 for(j
= 0; j
< 8; j
++) {
1493 highTot
+= (GraphBuffer
[i
+j
] >> 16);
1495 GraphBuffer
[i
] = lowTot
- highTot
;
1496 if (GraphBuffer
[i
]>maxMark
) maxMark
=GraphBuffer
[i
];
1497 if (GraphBuffer
[i
]<minMark
) minMark
=GraphBuffer
[i
];
1500 GraphTraceLen
-= (convLen
+ 16);
1502 RepaintGraphWindow();
1504 // Find bit-sync (3 lo followed by 3 high)
1505 int max
= 0, maxPos
= 0;
1506 for(i
= 0; i
< 6000; i
++) {
1508 for(j
= 0; j
< 3*lowLen
; j
++) {
1509 dec
-= GraphBuffer
[i
+j
];
1511 for(; j
< 3*(lowLen
+ highLen
); j
++) {
1512 dec
+= GraphBuffer
[i
+j
];
1520 // place start of bit sync marker in graph
1521 GraphBuffer
[maxPos
] = maxMark
;
1522 GraphBuffer
[maxPos
+1] = minMark
;
1526 // place end of bit sync marker in graph
1527 GraphBuffer
[maxPos
] = maxMark
;
1528 GraphBuffer
[maxPos
+1] = minMark
;
1530 PrintToScrollback("actual data bits start at sample %d", maxPos
);
1531 PrintToScrollback("length %d/%d", highLen
, lowLen
);
1534 bits
[sizeof(bits
)-1] = '\0';
1536 // find bit pairs and manchester decode them
1537 for(i
= 0; i
< arraylen(bits
)-1; i
++) {
1539 for(j
= 0; j
< lowLen
; j
++) {
1540 dec
-= GraphBuffer
[maxPos
+j
];
1542 for(; j
< lowLen
+ highLen
; j
++) {
1543 dec
+= GraphBuffer
[maxPos
+j
];
1546 // place inter bit marker in graph
1547 GraphBuffer
[maxPos
] = maxMark
;
1548 GraphBuffer
[maxPos
+1] = minMark
;
1550 // hi and lo form a 64 bit pair
1551 hi
= (hi
<<1)|(lo
>>31);
1553 // store decoded bit as binary (in hi/lo) and text (in bits[])
1561 PrintToScrollback("bits: '%s'", bits
);
1562 PrintToScrollback("hex: %08x %08x", hi
, lo
);
1565 // read a TI tag and return its ID
1566 static void CmdTIRead(char *str
)
1569 c
.cmd
= CMD_READ_TI_TYPE
;
1570 SendCommand(&c
, FALSE
);
1573 // write new data to a r/w TI tag
1574 static void CmdTIWrite(char *str
)
1579 c
.cmd
= CMD_WRITE_TI_TYPE
;
1580 res
= sscanf(str
, "0x%x 0x%x 0x%x ", &c
.ext1
, &c
.ext2
, &c
.ext3
);
1581 if (res
== 2) c
.ext3
=0;
1583 PrintToScrollback("Please specify the data as two hex strings, optionally the CRC as a third");
1585 SendCommand(&c
, FALSE
);
1588 static void CmdTIDemod(char *cmdline
)
1590 /* MATLAB as follows:
1591 f_s = 2000000; % sampling frequency
1592 f_l = 123200; % low FSK tone
1593 f_h = 134200; % high FSK tone
1595 T_l = 119e-6; % low bit duration
1596 T_h = 130e-6; % high bit duration
1598 l = 2*pi*ones(1, floor(f_s*T_l))*(f_l/f_s);
1599 h = 2*pi*ones(1, floor(f_s*T_h))*(f_h/f_s);
1601 l = sign(sin(cumsum(l)));
1602 h = sign(sin(cumsum(h)));
1605 // 2M*16/134.2k = 238
1606 static const int LowTone
[] = {
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, -1, -1, -1, -1, -1, -1,
1614 1, 1, 1, 1, 1, 1, 1, 1, -1, -1, -1, -1, -1, -1, -1, -1,
1615 1, 1, 1, 1, 1, 1, 1, 1, 1, -1, -1, -1, -1, -1, -1, -1, -1,
1616 1, 1, 1, 1, 1, 1, 1, 1, -1, -1, -1, -1, -1, -1, -1, -1,
1617 1, 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, -1,
1619 1, 1, 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, -1,
1621 1, 1, 1, 1, 1, 1, 1, 1, -1, -1
1623 // 2M*16/123.2k = 260
1624 static const int HighTone
[] = {
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, -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,
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, -1,
1634 1, 1, 1, 1, 1, 1, 1, -1, -1, -1, -1, -1, -1, -1, -1,
1635 1, 1, 1, 1, 1, 1, 1, -1, -1, -1, -1, -1, -1, -1,
1636 1, 1, 1, 1, 1, 1, 1, 1, -1, -1, -1, -1, -1, -1, -1,
1637 1, 1, 1, 1, 1, 1, 1, 1, -1, -1, -1, -1, -1, -1, -1,
1638 1, 1, 1, 1, 1, 1, 1, 1, -1, -1, -1, -1, -1, -1, -1,
1639 1, 1, 1, 1, 1, 1, 1, -1, -1, -1, -1, -1, -1, -1, -1,
1640 1, 1, 1, 1, 1, 1, 1, -1, -1, -1, -1, -1, -1, -1, -1,
1641 1, 1, 1, 1, 1, 1, 1, -1, -1, -1, -1, -1, -1, -1,
1642 1, 1, 1, 1, 1, 1, 1, 1
1644 int lowLen
= sizeof(LowTone
)/sizeof(int);
1645 int highLen
= sizeof(HighTone
)/sizeof(int);
1646 int convLen
= (highLen
>lowLen
)?highLen
:lowLen
;
1649 int lowSum
= 0, highSum
= 0;;
1650 int lowTot
= 0, highTot
= 0;
1652 for(i
= 0; i
< GraphTraceLen
- convLen
; i
++) {
1656 for(j
= 0; j
< lowLen
; j
++) {
1657 lowSum
+= LowTone
[j
]*GraphBuffer
[i
+j
];
1659 for(j
= 0; j
< highLen
; j
++) {
1660 highSum
+= HighTone
[j
]*GraphBuffer
[i
+j
];
1662 lowSum
= abs((100*lowSum
) / lowLen
);
1663 highSum
= abs((100*highSum
) / highLen
);
1664 lowSum
= (lowSum
<0)?-lowSum
:lowSum
;
1665 highSum
= (highSum
<0)?-highSum
:highSum
;
1667 GraphBuffer
[i
] = (highSum
<< 16) | lowSum
;
1670 for(i
= 0; i
< GraphTraceLen
- convLen
- 16; i
++) {
1673 // 16 and 15 are f_s divided by f_l and f_h, rounded
1674 for(j
= 0; j
< 16; j
++) {
1675 lowTot
+= (GraphBuffer
[i
+j
] & 0xffff);
1677 for(j
= 0; j
< 15; j
++) {
1678 highTot
+= (GraphBuffer
[i
+j
] >> 16);
1680 GraphBuffer
[i
] = lowTot
- highTot
;
1683 GraphTraceLen
-= (convLen
+ 16);
1685 RepaintGraphWindow();
1687 // TI tag data format is 16 prebits, 8 start bits, 64 data bits,
1688 // 16 crc CCITT bits, 8 stop bits, 15 end bits
1690 // the 16 prebits are always low
1691 // the 8 start and stop bits of a tag must match
1692 // the start/stop prebits of a ro tag are 01111110
1693 // the start/stop prebits of a rw tag are 11111110
1694 // the 15 end bits of a ro tag are all low
1695 // the 15 end bits of a rw tag match bits 15-1 of the data bits
1697 // Okay, so now we have unsliced soft decisions;
1698 // find bit-sync, and then get some bits.
1699 // look for 17 low bits followed by 6 highs (common pattern for ro and rw tags)
1700 int max
= 0, maxPos
= 0;
1701 for(i
= 0; i
< 6000; i
++) {
1704 // searching 17 consecutive lows
1705 for(j
= 0; j
< 17*lowLen
; j
++) {
1706 dec
-= GraphBuffer
[i
+j
];
1708 // searching 7 consecutive highs
1709 for(; j
< 17*lowLen
+ 6*highLen
; j
++) {
1710 dec
+= GraphBuffer
[i
+j
];
1718 // place a marker in the buffer to visually aid location
1719 // of the start of sync
1720 GraphBuffer
[maxPos
] = 800;
1721 GraphBuffer
[maxPos
+1] = -800;
1723 // advance pointer to start of actual data stream (after 16 pre and 8 start bits)
1724 maxPos
+= 17*lowLen
;
1725 maxPos
+= 6*highLen
;
1727 // place a marker in the buffer to visually aid location
1728 // of the end of sync
1729 GraphBuffer
[maxPos
] = 800;
1730 GraphBuffer
[maxPos
+1] = -800;
1732 PrintToScrollback("actual data bits start at sample %d", maxPos
);
1734 PrintToScrollback("length %d/%d", highLen
, lowLen
);
1736 BYTE bits
[1+64+16+8+16];
1737 bits
[sizeof(bits
)-1] = '\0';
1739 DWORD shift3
= 0x7e000000, shift2
= 0, shift1
= 0, shift0
= 0;
1741 for(i
= 0; i
< arraylen(bits
)-1; i
++) {
1745 for(j
= 0; j
< lowLen
; j
++) {
1746 low
-= GraphBuffer
[maxPos
+j
];
1748 for(j
= 0; j
< highLen
; j
++) {
1749 high
+= GraphBuffer
[maxPos
+j
];
1755 // bitstream arrives lsb first so shift right
1762 // 128 bit right shift register
1763 shift0
= (shift0
>>1) | (shift1
<< 31);
1764 shift1
= (shift1
>>1) | (shift2
<< 31);
1765 shift2
= (shift2
>>1) | (shift3
<< 31);
1768 // place a marker in the buffer between bits to visually aid location
1769 GraphBuffer
[maxPos
] = 800;
1770 GraphBuffer
[maxPos
+1] = -800;
1772 PrintToScrollback("Info: raw tag bits = %s", bits
);
1774 TagType
= (shift3
>>8)&0xff;
1775 if ( TagType
!= ((shift0
>>16)&0xff) ) {
1776 PrintToScrollback("Error: start and stop bits do not match!");
1779 else if (TagType
== 0x7e) {
1780 PrintToScrollback("Info: Readonly TI tag detected.");
1783 else if (TagType
== 0xfe) {
1784 PrintToScrollback("Info: Rewriteable TI tag detected.");
1786 // put 64 bit data into shift1 and shift0
1787 shift0
= (shift0
>>24) | (shift1
<< 8);
1788 shift1
= (shift1
>>24) | (shift2
<< 8);
1790 // align 16 bit crc into lower half of shift2
1791 shift2
= ((shift2
>>24) | (shift3
<< 8)) & 0x0ffff;
1793 // align 16 bit "end bits" or "ident" into lower half of shift3
1796 // only 15 bits compare, last bit of ident is not valid
1797 if ( (shift3
^shift0
)&0x7fff ) {
1798 PrintToScrollback("Error: Ident mismatch!");
1800 // WARNING the order of the bytes in which we calc crc below needs checking
1801 // i'm 99% sure the crc algorithm is correct, but it may need to eat the
1802 // bytes in reverse or something
1805 crc
= update_crc16(crc
, (shift0
)&0xff);
1806 crc
= update_crc16(crc
, (shift0
>>8)&0xff);
1807 crc
= update_crc16(crc
, (shift0
>>16)&0xff);
1808 crc
= update_crc16(crc
, (shift0
>>24)&0xff);
1809 crc
= update_crc16(crc
, (shift1
)&0xff);
1810 crc
= update_crc16(crc
, (shift1
>>8)&0xff);
1811 crc
= update_crc16(crc
, (shift1
>>16)&0xff);
1812 crc
= update_crc16(crc
, (shift1
>>24)&0xff);
1813 PrintToScrollback("Info: Tag data = %08X%08X", shift1
, shift0
);
1814 if (crc
!= (shift2
&0xffff)) {
1815 PrintToScrollback("Error: CRC mismatch, calculated %04X, got ^04X", crc
, shift2
&0xffff);
1817 PrintToScrollback("Info: CRC %04X is good", crc
);
1821 PrintToScrollback("Unknown tag type.");
1826 static void CmdNorm(char *str
)
1829 int max
= INT_MIN
, min
= INT_MAX
;
1830 for(i
= 10; i
< GraphTraceLen
; i
++) {
1831 if(GraphBuffer
[i
] > max
) {
1832 max
= GraphBuffer
[i
];
1834 if(GraphBuffer
[i
] < min
) {
1835 min
= GraphBuffer
[i
];
1839 for(i
= 0; i
< GraphTraceLen
; i
++) {
1840 GraphBuffer
[i
] = (GraphBuffer
[i
] - ((max
+ min
)/2))*1000/
1844 RepaintGraphWindow();
1847 static void CmdAmp(char *str
)
1849 int i
, rising
, falling
;
1850 int max
= INT_MIN
, min
= INT_MAX
;
1851 for(i
= 10; i
< GraphTraceLen
; i
++) {
1852 if(GraphBuffer
[i
] > max
) {
1853 max
= GraphBuffer
[i
];
1855 if(GraphBuffer
[i
] < min
) {
1856 min
= GraphBuffer
[i
];
1861 for(i
= 0; i
< GraphTraceLen
; i
++) {
1862 if(GraphBuffer
[i
+1] < GraphBuffer
[i
]) {
1864 GraphBuffer
[i
]= max
;
1869 if(GraphBuffer
[i
+1] > GraphBuffer
[i
]) {
1871 GraphBuffer
[i
]= min
;
1878 RepaintGraphWindow();
1881 static void CmdDec(char *str
)
1884 for(i
= 0; i
< (GraphTraceLen
/2); i
++) {
1885 GraphBuffer
[i
] = GraphBuffer
[i
*2];
1888 PrintToScrollback("decimated by 2");
1889 RepaintGraphWindow();
1892 static void CmdHpf(char *str
)
1896 for(i
= 10; i
< GraphTraceLen
; i
++) {
1897 accum
+= GraphBuffer
[i
];
1899 accum
/= (GraphTraceLen
- 10);
1900 for(i
= 0; i
< GraphTraceLen
; i
++) {
1901 GraphBuffer
[i
] -= accum
;
1904 RepaintGraphWindow();
1907 static void CmdZerocrossings(char *str
)
1910 // Zero-crossings aren't meaningful unless the signal is zero-mean.
1916 for(i
= 0; i
< GraphTraceLen
; i
++) {
1917 if(GraphBuffer
[i
]*sign
>= 0) {
1918 // No change in sign, reproduce the previous sample count.
1920 GraphBuffer
[i
] = lastZc
;
1922 // Change in sign, reset the sample count.
1924 GraphBuffer
[i
] = lastZc
;
1932 RepaintGraphWindow();
1935 static void CmdThreshold(char *str
)
1938 int threshold
= atoi(str
);
1940 for(i
= 0; i
< GraphTraceLen
; i
++) {
1941 if(GraphBuffer
[i
]>= threshold
)
1946 RepaintGraphWindow();
1949 static void CmdLtrim(char *str
)
1954 for(i
= ds
; i
< GraphTraceLen
; i
++) {
1955 GraphBuffer
[i
-ds
] = GraphBuffer
[i
];
1957 GraphTraceLen
-= ds
;
1959 RepaintGraphWindow();
1962 static void CmdAutoCorr(char *str
)
1964 static int CorrelBuffer
[MAX_GRAPH_TRACE_LEN
];
1966 int window
= atoi(str
);
1969 PrintToScrollback("needs a window");
1973 if(window
>= GraphTraceLen
) {
1974 PrintToScrollback("window must be smaller than trace (%d samples)",
1979 PrintToScrollback("performing %d correlations", GraphTraceLen
- window
);
1982 for(i
= 0; i
< GraphTraceLen
- window
; i
++) {
1985 for(j
= 0; j
< window
; j
++) {
1986 sum
+= (GraphBuffer
[j
]*GraphBuffer
[i
+j
]) / 256;
1988 CorrelBuffer
[i
] = sum
;
1990 GraphTraceLen
= GraphTraceLen
- window
;
1991 memcpy(GraphBuffer
, CorrelBuffer
, GraphTraceLen
*sizeof(int));
1993 RepaintGraphWindow();
1996 static void CmdVchdemod(char *str
)
1998 // Is this the entire sync pattern, or does this also include some
1999 // data bits that happen to be the same everywhere? That would be
2001 static const int SyncPattern
[] = {
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,
2004 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
2005 1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
2006 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
2007 1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
2008 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
2009 1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
2010 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
2011 1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
2014 // So first, we correlate for the sync pattern, and mark that.
2015 int bestCorrel
= 0, bestPos
= 0;
2017 // It does us no good to find the sync pattern, with fewer than
2018 // 2048 samples after it...
2019 for(i
= 0; i
< (GraphTraceLen
-2048); i
++) {
2022 for(j
= 0; j
< arraylen(SyncPattern
); j
++) {
2023 sum
+= GraphBuffer
[i
+j
]*SyncPattern
[j
];
2025 if(sum
> bestCorrel
) {
2030 PrintToScrollback("best sync at %d [metric %d]", bestPos
, bestCorrel
);
2035 int worst
= INT_MAX
;
2038 for(i
= 0; i
< 2048; i
+= 8) {
2041 for(j
= 0; j
< 8; j
++) {
2042 sum
+= GraphBuffer
[bestPos
+i
+j
];
2049 if(abs(sum
) < worst
) {
2054 PrintToScrollback("bits:");
2055 PrintToScrollback("%s", bits
);
2056 PrintToScrollback("worst metric: %d at pos %d", worst
, worstPos
);
2058 if(strcmp(str
, "clone")==0) {
2061 for(s
= bits
; *s
; s
++) {
2063 for(j
= 0; j
< 16; j
++) {
2064 GraphBuffer
[GraphTraceLen
++] = (*s
== '1') ? 1 : 0;
2067 RepaintGraphWindow();
2071 static void CmdIndalademod(char *str
)
2073 // Usage: recover 64bit UID by default, specify "224" as arg to recover a 224bit UID
2078 // worst case with GraphTraceLen=64000 is < 4096
2079 // under normal conditions it's < 2048
2082 int worst
= 0, worstPos
= 0;
2083 PrintToScrollback("Expecting a bit less than %d raw bits", GraphTraceLen
/32);
2084 for(i
= 0; i
< GraphTraceLen
-1; i
+= 2) {
2086 if((GraphBuffer
[i
] > GraphBuffer
[i
+ 1]) && (state
!= 1)) {
2088 for(j
= 0; j
< count
- 8; j
+= 16) {
2089 rawbits
[rawbit
++] = 0;
2091 if ((abs(count
- j
)) > worst
) {
2092 worst
= abs(count
- j
);
2098 } else if((GraphBuffer
[i
] < GraphBuffer
[i
+ 1]) && (state
!= 0)) {
2100 for(j
= 0; j
< count
- 8; j
+= 16) {
2101 rawbits
[rawbit
++] = 1;
2103 if ((abs(count
- j
)) > worst
) {
2104 worst
= abs(count
- j
);
2112 PrintToScrollback("Recovered %d raw bits", rawbit
);
2113 PrintToScrollback("worst metric (0=best..7=worst): %d at pos %d", worst
, worstPos
);
2115 // Finding the start of a UID
2116 int uidlen
, long_wait
;
2117 if(strcmp(str
, "224") == 0) {
2126 for(start
= 0; start
<= rawbit
- uidlen
; start
++) {
2127 first
= rawbits
[start
];
2128 for(i
= start
; i
< start
+ long_wait
; i
++) {
2129 if(rawbits
[i
] != first
) {
2133 if(i
== (start
+ long_wait
)) {
2137 if(start
== rawbit
- uidlen
+ 1) {
2138 PrintToScrollback("nothing to wait for");
2142 // Inverting signal if needed
2144 for(i
= start
; i
< rawbit
; i
++) {
2145 rawbits
[i
] = !rawbits
[i
];
2152 showbits
[uidlen
]='\0';
2156 if(uidlen
> rawbit
) {
2157 PrintToScrollback("Warning: not enough raw bits to get a full UID");
2158 for(bit
= 0; bit
< rawbit
; bit
++) {
2159 bits
[bit
] = rawbits
[i
++];
2160 // As we cannot know the parity, let's use "." and "/"
2161 showbits
[bit
] = '.' + bits
[bit
];
2163 showbits
[bit
+1]='\0';
2164 PrintToScrollback("Partial UID=%s", showbits
);
2167 for(bit
= 0; bit
< uidlen
; bit
++) {
2168 bits
[bit
] = rawbits
[i
++];
2169 showbits
[bit
] = '0' + bits
[bit
];
2173 PrintToScrollback("UID=%s", showbits
);
2175 // Checking UID against next occurences
2176 for(; i
+ uidlen
<= rawbit
;) {
2178 for(bit
= 0; bit
< uidlen
; bit
++) {
2179 if(bits
[bit
] != rawbits
[i
++]) {
2189 PrintToScrollback("Occurences: %d (expected %d)", times
, (rawbit
- start
) / uidlen
);
2191 // Remodulating for tag cloning
2192 GraphTraceLen
= 32*uidlen
;
2195 for(bit
= 0; bit
< uidlen
; bit
++) {
2196 if(bits
[bit
] == 0) {
2202 for(j
= 0; j
< 32; j
++) {
2203 GraphBuffer
[i
++] = phase
;
2208 RepaintGraphWindow();
2211 static void CmdFlexdemod(char *str
)
2214 for(i
= 0; i
< GraphTraceLen
; i
++) {
2215 if(GraphBuffer
[i
] < 0) {
2216 GraphBuffer
[i
] = -1;
2222 #define LONG_WAIT 100
2224 for(start
= 0; start
< GraphTraceLen
- LONG_WAIT
; start
++) {
2225 int first
= GraphBuffer
[start
];
2226 for(i
= start
; i
< start
+ LONG_WAIT
; i
++) {
2227 if(GraphBuffer
[i
] != first
) {
2231 if(i
== (start
+ LONG_WAIT
)) {
2235 if(start
== GraphTraceLen
- LONG_WAIT
) {
2236 PrintToScrollback("nothing to wait for");
2240 GraphBuffer
[start
] = 2;
2241 GraphBuffer
[start
+1] = -2;
2247 for(bit
= 0; bit
< 64; bit
++) {
2250 for(j
= 0; j
< 16; j
++) {
2251 sum
+= GraphBuffer
[i
++];
2258 PrintToScrollback("bit %d sum %d", bit
, sum
);
2261 for(bit
= 0; bit
< 64; bit
++) {
2264 for(j
= 0; j
< 16; j
++) {
2265 sum
+= GraphBuffer
[i
++];
2267 if(sum
> 0 && bits
[bit
] != 1) {
2268 PrintToScrollback("oops1 at %d", bit
);
2270 if(sum
< 0 && bits
[bit
] != 0) {
2271 PrintToScrollback("oops2 at %d", bit
);
2275 GraphTraceLen
= 32*64;
2278 for(bit
= 0; bit
< 64; bit
++) {
2279 if(bits
[bit
] == 0) {
2285 for(j
= 0; j
< 32; j
++) {
2286 GraphBuffer
[i
++] = phase
;
2291 RepaintGraphWindow();
2295 * Generic command to demodulate ASK.
2297 * Argument is convention: positive or negative (High mod means zero
2298 * or high mod means one)
2300 * Updates the Graph trace with 0/1 values
2306 static void Cmdaskdemod(char *str
) {
2308 int c
, high
= 0, low
= 0;
2310 // TODO: complain if we do not give 2 arguments here !
2311 // (AL - this doesn't make sense! we're only using one argument!!!)
2312 sscanf(str
, "%i", &c
);
2314 /* Detect high and lows and clock */
2316 for (i
= 0; i
< GraphTraceLen
; i
++)
2318 if (GraphBuffer
[i
] > high
)
2319 high
= GraphBuffer
[i
];
2320 else if (GraphBuffer
[i
] < low
)
2321 low
= GraphBuffer
[i
];
2323 if(c
!= 0 && c
!= 1) {
2324 PrintToScrollback("Invalid argument: %s",str
);
2328 if (GraphBuffer
[0] > 0) {
2329 GraphBuffer
[0] = 1-c
;
2333 for(i
=1;i
<GraphTraceLen
;i
++) {
2334 /* Transitions are detected at each peak
2335 * Transitions are either:
2336 * - we're low: transition if we hit a high
2337 * - we're high: transition if we hit a low
2338 * (we need to do it this way because some tags keep high or
2339 * low for long periods, others just reach the peak and go
2342 if ((GraphBuffer
[i
]==high
) && (GraphBuffer
[i
-1] == c
)) {
2344 } else if ((GraphBuffer
[i
]==low
) && (GraphBuffer
[i
-1] == (1-c
))){
2348 GraphBuffer
[i
] = GraphBuffer
[i
-1];
2351 RepaintGraphWindow();
2354 /* Print our clock rate */
2355 static void Cmddetectclockrate(char *str
)
2357 int clock
= detectclock(0);
2358 PrintToScrollback("Auto-detected clock rate: %d", clock
);
2364 int detectclock(int peak
)
2370 /* Detect peak if we don't have one */
2372 for (i
= 0; i
< GraphTraceLen
; i
++)
2373 if (GraphBuffer
[i
] > peak
)
2374 peak
= GraphBuffer
[i
];
2376 for (i
= 1; i
< GraphTraceLen
; i
++)
2378 /* If this is the beginning of a peak */
2379 if (GraphBuffer
[i
-1] != GraphBuffer
[i
] && GraphBuffer
[i
] == peak
)
2381 /* Find lowest difference between peaks */
2382 if (lastpeak
&& i
- lastpeak
< clock
)
2384 clock
= i
- lastpeak
;
2393 /* Get or auto-detect clock rate */
2394 int GetClock(char *str
, int peak
)
2398 sscanf(str
, "%i", &clock
);
2399 if (!strcmp(str
, ""))
2402 /* Auto-detect clock */
2405 clock
= detectclock(peak
);
2407 /* Only print this message if we're not looping something */
2409 PrintToScrollback("Auto-detected clock rate: %d", clock
);
2416 * Convert to a bitstream
2418 static void Cmdbitstream(char *str
) {
2425 int hithigh
, hitlow
, first
;
2427 /* Detect high and lows and clock */
2428 for (i
= 0; i
< GraphTraceLen
; i
++)
2430 if (GraphBuffer
[i
] > high
)
2431 high
= GraphBuffer
[i
];
2432 else if (GraphBuffer
[i
] < low
)
2433 low
= GraphBuffer
[i
];
2437 clock
= GetClock(str
, high
);
2439 gtl
= CmdClearGraph(0);
2442 for (i
= 0; i
< (int)(gtl
/ clock
); i
++)
2448 /* Find out if we hit both high and low peaks */
2449 for (j
= 0; j
< clock
; j
++)
2451 if (GraphBuffer
[(i
* clock
) + j
] == high
)
2453 else if (GraphBuffer
[(i
* clock
) + j
] == low
)
2456 /* it doesn't count if it's the first part of our read
2457 because it's really just trailing from the last sequence */
2458 if (first
&& (hithigh
|| hitlow
))
2459 hithigh
= hitlow
= 0;
2463 if (hithigh
&& hitlow
)
2467 /* If we didn't hit both high and low peaks, we had a bit transition */
2468 if (!hithigh
|| !hitlow
)
2471 CmdAppendGraph(0, clock
, bit
);
2472 // for (j = 0; j < (int)(clock/2); j++)
2473 // GraphBuffer[(i * clock) + j] = bit ^ 1;
2474 // for (j = (int)(clock/2); j < clock; j++)
2475 // GraphBuffer[(i * clock) + j] = bit;
2478 RepaintGraphWindow();
2481 /* Modulate our data into manchester */
2482 static void Cmdmanchestermod(char *str
)
2486 int bit
, lastbit
, wave
;
2489 clock
= GetClock(str
, 0);
2493 for (i
= 0; i
< (int)(GraphTraceLen
/ clock
); i
++)
2495 bit
= GraphBuffer
[i
* clock
] ^ 1;
2497 for (j
= 0; j
< (int)(clock
/2); j
++)
2498 GraphBuffer
[(i
* clock
) + j
] = bit
^ lastbit
^ wave
;
2499 for (j
= (int)(clock
/2); j
< clock
; j
++)
2500 GraphBuffer
[(i
* clock
) + j
] = bit
^ lastbit
^ wave
^ 1;
2502 /* Keep track of how we start our wave and if we changed or not this time */
2503 wave
^= bit
^ lastbit
;
2507 RepaintGraphWindow();
2511 * Manchester demodulate a bitstream. The bitstream needs to be already in
2512 * the GraphBuffer as 0 and 1 values
2514 * Give the clock rate as argument in order to help the sync - the algorithm
2515 * resyncs at each pulse anyway.
2517 * Not optimized by any means, this is the 1st time I'm writing this type of
2518 * routine, feel free to improve...
2520 * 1st argument: clock rate (as number of samples per clock rate)
2521 * Typical values can be 64, 32, 128...
2523 static void Cmdmanchesterdemod(char *str
) {
2524 int i
, j
, invert
= 0;
2530 int hithigh
, hitlow
, first
;
2536 /* check if we're inverting output */
2539 PrintToScrollback("Inverting output");
2543 while(*str
== ' '); // in case a 2nd argument was given
2546 /* Holds the decoded bitstream: each clock period contains 2 bits */
2547 /* later simplified to 1 bit after manchester decoding. */
2548 /* Add 10 bits to allow for noisy / uncertain traces without aborting */
2549 /* int BitStream[GraphTraceLen*2/clock+10]; */
2551 /* But it does not work if compiling on WIndows: therefore we just allocate a */
2553 int BitStream
[MAX_GRAPH_TRACE_LEN
];
2555 /* Detect high and lows */
2556 for (i
= 0; i
< GraphTraceLen
; i
++)
2558 if (GraphBuffer
[i
] > high
)
2559 high
= GraphBuffer
[i
];
2560 else if (GraphBuffer
[i
] < low
)
2561 low
= GraphBuffer
[i
];
2565 clock
= GetClock(str
, high
);
2567 int tolerance
= clock
/4;
2569 /* Detect first transition */
2570 /* Lo-Hi (arbitrary) */
2571 /* skip to the first high */
2572 for (i
= 0; i
< GraphTraceLen
; i
++)
2573 if(GraphBuffer
[i
] == high
)
2575 /* now look for the first low */
2576 for (; i
< GraphTraceLen
; i
++)
2578 if (GraphBuffer
[i
] == low
)
2585 /* If we're not working with 1/0s, demod based off clock */
2588 bit
= 0; /* We assume the 1st bit is zero, it may not be
2589 * the case: this routine (I think) has an init problem.
2592 for (; i
< (int)(GraphTraceLen
/ clock
); i
++)
2598 /* Find out if we hit both high and low peaks */
2599 for (j
= 0; j
< clock
; j
++)
2601 if (GraphBuffer
[(i
* clock
) + j
] == high
)
2603 else if (GraphBuffer
[(i
* clock
) + j
] == low
)
2606 /* it doesn't count if it's the first part of our read
2607 because it's really just trailing from the last sequence */
2608 if (first
&& (hithigh
|| hitlow
))
2609 hithigh
= hitlow
= 0;
2613 if (hithigh
&& hitlow
)
2617 /* If we didn't hit both high and low peaks, we had a bit transition */
2618 if (!hithigh
|| !hitlow
)
2621 BitStream
[bit2idx
++] = bit
^ invert
;
2625 /* standard 1/0 bitstream */
2629 /* Then detect duration between 2 successive transitions */
2630 for (bitidx
= 1; i
< GraphTraceLen
; i
++)
2632 if (GraphBuffer
[i
-1] != GraphBuffer
[i
])
2637 // Error check: if bitidx becomes too large, we do not
2638 // have a Manchester encoded bitstream or the clock is really
2640 if (bitidx
> (GraphTraceLen
*2/clock
+8) ) {
2641 PrintToScrollback("Error: the clock you gave is probably wrong, aborting.");
2644 // Then switch depending on lc length:
2645 // Tolerance is 1/4 of clock rate (arbitrary)
2646 if (abs(lc
-clock
/2) < tolerance
) {
2647 // Short pulse : either "1" or "0"
2648 BitStream
[bitidx
++]=GraphBuffer
[i
-1];
2649 } else if (abs(lc
-clock
) < tolerance
) {
2650 // Long pulse: either "11" or "00"
2651 BitStream
[bitidx
++]=GraphBuffer
[i
-1];
2652 BitStream
[bitidx
++]=GraphBuffer
[i
-1];
2656 PrintToScrollback("Warning: Manchester decode error for pulse width detection.");
2657 PrintToScrollback("(too many of those messages mean either the stream is not Manchester encoded, or clock is wrong)");
2661 PrintToScrollback("Error: too many detection errors, aborting.");
2668 // At this stage, we now have a bitstream of "01" ("1") or "10" ("0"), parse it into final decoded bitstream
2669 // Actually, we overwrite BitStream with the new decoded bitstream, we just need to be careful
2670 // to stop output at the final bitidx2 value, not bitidx
2671 for (i
= 0; i
< bitidx
; i
+= 2) {
2672 if ((BitStream
[i
] == 0) && (BitStream
[i
+1] == 1)) {
2673 BitStream
[bit2idx
++] = 1 ^ invert
;
2674 } else if ((BitStream
[i
] == 1) && (BitStream
[i
+1] == 0)) {
2675 BitStream
[bit2idx
++] = 0 ^ invert
;
2677 // We cannot end up in this state, this means we are unsynchronized,
2681 PrintToScrollback("Unsynchronized, resync...");
2682 PrintToScrollback("(too many of those messages mean the stream is not Manchester encoded)");
2686 PrintToScrollback("Error: too many decode errors, aborting.");
2693 PrintToScrollback("Manchester decoded bitstream");
2694 // Now output the bitstream to the scrollback by line of 16 bits
2695 for (i
= 0; i
< (bit2idx
-16); i
+=16) {
2696 PrintToScrollback("%i %i %i %i %i %i %i %i %i %i %i %i %i %i %i %i",
2719 static void CmdHiddemod(char *str
)
2721 if(GraphTraceLen
< 4800) {
2722 PrintToScrollback("too short; need at least 4800 samples");
2726 GraphTraceLen
= 4800;
2728 for(i
= 0; i
< GraphTraceLen
; i
++) {
2729 if(GraphBuffer
[i
] < 0) {
2735 RepaintGraphWindow();
2738 static void CmdPlot(char *str
)
2743 static void CmdGrid(char *str
)
2745 sscanf(str
, "%i %i", &PlotGridX
, &PlotGridY
);
2746 RepaintGraphWindow();
2749 static void CmdHide(char *str
)
2754 static void CmdScale(char *str
)
2756 CursorScaleFactor
= atoi(str
);
2757 if(CursorScaleFactor
== 0) {
2758 PrintToScrollback("bad, can't have zero scale");
2759 CursorScaleFactor
= 1;
2761 RepaintGraphWindow();
2764 static void CmdSave(char *str
)
2766 FILE *f
= fopen(str
, "w");
2768 PrintToScrollback("couldn't open '%s'", str
);
2772 for(i
= 0; i
< GraphTraceLen
; i
++) {
2773 fprintf(f
, "%d\n", GraphBuffer
[i
]);
2776 PrintToScrollback("saved to '%s'", str
);
2779 static void CmdLoad(char *str
)
2781 FILE *f
= fopen(str
, "r");
2783 PrintToScrollback("couldn't open '%s'", str
);
2789 while(fgets(line
, sizeof(line
), f
)) {
2790 GraphBuffer
[GraphTraceLen
] = atoi(line
);
2794 PrintToScrollback("loaded %d samples", GraphTraceLen
);
2795 RepaintGraphWindow();
2798 static void CmdHIDsimTAG(char *str
)
2800 unsigned int hi
=0, lo
=0;
2804 while (sscanf(&str
[i
++], "%1x", &n
) == 1) {
2805 hi
=(hi
<<4)|(lo
>>28);
2809 PrintToScrollback("Emulating tag with ID %x%16x", hi
, lo
);
2811 c
.cmd
= CMD_HID_SIM_TAG
;
2814 SendCommand(&c
, FALSE
);
2817 static void CmdReadmem(char *str
)
2820 c
.cmd
= CMD_READ_MEM
;
2822 SendCommand(&c
, FALSE
);
2825 static void CmdVersion(char *str
)
2828 c
.cmd
= CMD_VERSION
;
2829 SendCommand(&c
, FALSE
);
2832 static void CmdLcdReset(char *str
)
2835 c
.cmd
= CMD_LCD_RESET
;
2837 SendCommand(&c
, FALSE
);
2840 static void CmdLcd(char *str
)
2845 sscanf(str
, "%x %d", &i
, &j
);
2848 SendCommand(&c
, FALSE
);
2853 * Sets the divisor for LF frequency clock: lets the user choose any LF frequency below
2856 static void CmdSetDivisor(char *str
)
2859 c
.cmd
= CMD_SET_LF_DIVISOR
;
2861 if (( c
.ext1
<0) || (c
.ext1
>255)) {
2862 PrintToScrollback("divisor must be between 19 and 255");
2864 SendCommand(&c
, FALSE
);
2865 PrintToScrollback("Divisor set, expected freq=%dHz", 12000000/(c
.ext1
+1));
2869 static void CmdSetMux(char *str
)
2872 c
.cmd
= CMD_SET_ADC_MUX
;
2873 if(strcmp(str
, "lopkd") == 0) {
2875 } else if(strcmp(str
, "loraw") == 0) {
2877 } else if(strcmp(str
, "hipkd") == 0) {
2879 } else if(strcmp(str
, "hiraw") == 0) {
2882 SendCommand(&c
, FALSE
);
2885 typedef void HandlerFunction(char *cmdline
);
2887 /* in alphabetic order */
2890 HandlerFunction
*handler
;
2891 int offline
; // 1 if the command can be used when in offline mode
2893 } CommandTable
[] = {
2894 {"amp", CmdAmp
, 1, "Amplify peaks"},
2895 {"askdemod", Cmdaskdemod
, 1, "<0|1> -- Attempt to demodulate simple ASK tags"},
2896 {"autocorr", CmdAutoCorr
, 1, "<window length> -- Autocorrelation over window"},
2897 {"bitsamples", CmdBitsamples
, 0, "Get raw samples as bitstring"},
2898 {"bitstream", Cmdbitstream
, 1, "[clock rate] -- Convert waveform into a bitstream"},
2899 {"buffclear", CmdBuffClear
, 1, "Clear sample buffer and graph window"},
2900 {"dec", CmdDec
, 1, "Decimate samples"},
2901 {"detectclock", Cmddetectclockrate
, 1, "Detect clock rate"},
2902 {"detectreader", CmdDetectReader
, 0, "['l'|'h'] -- Detect external reader field (option 'l' or 'h' to limit to LF or HF)"},
2903 {"em410xsim", CmdEM410xsim
, 1, "<UID> -- Simulate EM410x tag"},
2904 {"em410xread", CmdEM410xread
, 1, "[clock rate] -- Extract ID from EM410x tag"},
2905 {"em410xwatch", CmdEM410xwatch
, 0, "Watches for EM410x tags"},
2906 {"em4x50read", CmdEM4x50read
, 1, "Extract data from EM4x50 tag"},
2907 {"exit", CmdQuit
, 1, "Exit program"},
2908 {"flexdemod", CmdFlexdemod
, 1, "Demodulate samples for FlexPass"},
2909 {"fpgaoff", CmdFPGAOff
, 0, "Set FPGA off"},
2910 {"fskdemod", CmdFSKdemod
, 1, "Demodulate graph window as a HID FSK"},
2911 {"grid", CmdGrid
, 1, "<x> <y> -- overlay grid on graph window, use zero value to turn off either"},
2912 {"hexsamples", CmdHexsamples
, 0, "<blocks> -- Dump big buffer as hex bytes"},
2913 {"hi14alist", CmdHi14alist
, 0, "List ISO 14443a history"},
2914 {"hi14areader", CmdHi14areader
, 0, "Act like an ISO14443 Type A reader"},
2915 {"hi14asim", CmdHi14asim
, 0, "<UID> -- Fake ISO 14443a tag"},
2916 {"hi14asnoop", CmdHi14asnoop
, 0, "Eavesdrop ISO 14443 Type A"},
2917 {"hi14bdemod", CmdHi14bdemod
, 1, "Demodulate ISO14443 Type B from tag"},
2918 {"hi14list", CmdHi14list
, 0, "List ISO 14443 history"},
2919 {"hi14read", CmdHi14read
, 0, "Read HF tag (ISO 14443)"},
2920 {"hi14sim", CmdHi14sim
, 0, "Fake ISO 14443 tag"},
2921 {"hi14snoop", CmdHi14snoop
, 0, "Eavesdrop ISO 14443"},
2922 {"hi15demod", CmdHi15demod
, 1, "Demodulate ISO15693 from tag"},
2923 {"hi15read", CmdHi15read
, 0, "Read HF tag (ISO 15693)"},
2924 {"hi15reader", CmdHi15reader
, 0, "Act like an ISO15693 reader"},
2925 {"hi15sim", CmdHi15tag
, 0, "Fake an ISO15693 tag"},
2926 {"hiddemod", CmdHiddemod
, 1, "Demodulate HID Prox Card II (not optimal)"},
2927 {"hide", CmdHide
, 1, "Hide graph window"},
2928 {"hidfskdemod", CmdHIDdemodFSK
, 0, "Realtime HID FSK demodulator"},
2929 {"hidsimtag", CmdHIDsimTAG
, 0, "<ID> -- HID tag simulator"},
2930 {"higet", CmdHi14read_sim
, 0, "<samples> -- Get samples HF, 'analog'"},
2931 {"hisamples", CmdHisamples
, 0, "Get raw samples for HF tag"},
2932 {"hisampless", CmdHisampless
, 0, "<samples> -- Get signed raw samples, HF tag"},
2933 {"hisamplest", CmdHi14readt
, 0, "Get samples HF, for testing"},
2934 {"hisimlisten", CmdHisimlisten
, 0, "Get HF samples as fake tag"},
2935 {"hpf", CmdHpf
, 1, "Remove DC offset from trace"},
2936 {"indalademod", CmdIndalademod
, 0, "['224'] -- Demodulate samples for Indala 64 bit UID (option '224' for 224 bit)"},
2937 {"lcd", CmdLcd
, 0, "<HEX command> <count> -- Send command/data to LCD"},
2938 {"lcdreset", CmdLcdReset
, 0, "Hardware reset LCD"},
2939 {"legicrfsim", CmdLegicRfSim
, 0, "Start the LEGIC RF tag simulator"},
2940 {"legicrfread", CmdLegicRfRead
, 0, "Start the LEGIC RF reader"},
2941 {"load", CmdLoad
, 1, "<filename> -- Load trace (to graph window"},
2942 {"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)"},
2943 {"loread", CmdLoread
, 0, "['h'] -- Read 125/134 kHz LF ID-only tag (option 'h' for 134)"},
2944 {"losamples", CmdLosamples
, 0, "[128 - 16000] -- Get raw samples for LF tag"},
2945 {"losim", CmdLosim
, 0, "Simulate LF tag"},
2946 {"losimbidir", CmdLosimBidir
, 0, "Simulate LF tag (with bidirectional data transmission between reader and tag)"},
2947 {"ltrim", CmdLtrim
, 1, "<samples> -- Trim samples from left of trace"},
2948 {"mandemod", Cmdmanchesterdemod
, 1, "[i] [clock rate] -- Manchester demodulate binary stream (option 'i' to invert output)"},
2949 {"manmod", Cmdmanchestermod
, 1, "[clock rate] -- Manchester modulate a binary stream"},
2950 {"norm", CmdNorm
, 1, "Normalize max/min to +/-500"},
2951 {"plot", CmdPlot
, 1, "Show graph window"},
2952 {"quit", CmdQuit
, 1, "Quit program"},
2953 {"readmem", CmdReadmem
, 0, "[address] -- Read memory at decimal address from flash"},
2954 {"reset", CmdReset
, 0, "Reset the Proxmark3"},
2955 {"save", CmdSave
, 1, "<filename> -- Save trace (from graph window)"},
2956 {"scale", CmdScale
, 1, "<int> -- Set cursor display scale"},
2957 {"setlfdivisor", CmdSetDivisor
, 0, "<19 - 255> -- Drive LF antenna at 12Mhz/(divisor+1)"},
2958 {"setmux", CmdSetMux
, 0, "<loraw|hiraw|lopkd|hipkd> -- Set the ADC mux to a specific value"},
2959 {"sri512read", CmdSri512read
, 0, "<int> -- Read contents of a SRI512 tag"},
2960 {"srix4kread", CmdSrix4kread
, 0, "<int> -- Read contents of a SRIX4K tag"},
2961 {"tidemod", CmdTIDemod
, 1, "Demodulate raw bits for TI-type LF tag"},
2962 {"tiread", CmdTIRead
, 0, "Read and decode a TI 134 kHz tag"},
2963 {"tiwrite", CmdTIWrite
, 0, "Write new data to a r/w TI 134 kHz tag"},
2964 {"threshold", CmdThreshold
, 1, "Maximize/minimize every value in the graph window depending on threshold"},
2965 {"tune", CmdTune
, 0, "Measure antenna tuning"},
2966 {"vchdemod", CmdVchdemod
, 0, "['clone'] -- Demodulate samples for VeriChip"},
2967 {"version", CmdVersion
, 0, "Show version inforation about the connected Proxmark"},
2968 {"zerocrossings", CmdZerocrossings
, 1, "Count time between zero-crossings"},
2976 } CommandExtendedHelp
[]= {
2977 {"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."},
2978 {"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."},
2981 //-----------------------------------------------------------------------------
2982 // Entry point into our code: called whenever the user types a command and
2983 // then presses Enter, which the full command line that they typed.
2984 //-----------------------------------------------------------------------------
2985 void CommandReceived(char *cmd
)
2990 PrintToScrollback("> %s", cmd
);
2992 if(strcmp(cmd
, "help") == 0 || strncmp(cmd
,"help ",strlen("help ")) == 0) {
2993 // check if we're doing extended help
2994 if(strlen(cmd
) > strlen("help ")) {
2995 cmd
+= strlen("help ");
2996 for(i
= 0; i
< sizeof(CommandExtendedHelp
) / sizeof(CommandExtendedHelp
[0]); i
++) {
2997 if(strcmp(CommandExtendedHelp
[i
].name
,cmd
) == 0) {
2998 PrintToScrollback("\nExtended help for '%s':\n", cmd
);
2999 PrintToScrollback("Args: %s\t- %s\n",CommandExtendedHelp
[i
].args
,CommandExtendedHelp
[i
].argshelp
);
3000 PrintToScrollback(CommandExtendedHelp
[i
].description
);
3001 PrintToScrollback("");
3005 PrintToScrollback("No extended help available for '%s'", cmd
);
3008 if (offline
) PrintToScrollback("Operating in OFFLINE mode (no device connected)");
3009 PrintToScrollback("\r\nAvailable commands:");
3010 for(i
= 0; i
< sizeof(CommandTable
) / sizeof(CommandTable
[0]); i
++) {
3011 if (offline
&& (CommandTable
[i
].offline
==0)) continue;
3012 memset(line
, ' ', sizeof(line
));
3013 strcpy(line
+2, CommandTable
[i
].name
);
3014 line
[strlen(line
)] = ' ';
3015 sprintf(line
+15, " -- %s", CommandTable
[i
].docString
);
3016 PrintToScrollback("%s", line
);
3018 PrintToScrollback("");
3019 PrintToScrollback("'help <command>' for extended help on that command\n");
3023 for(i
= 0; i
< sizeof(CommandTable
) / sizeof(CommandTable
[0]); i
++) {
3024 char *name
= CommandTable
[i
].name
;
3025 if(memcmp(cmd
, name
, strlen(name
))==0 &&
3026 (cmd
[strlen(name
)] == ' ' || cmd
[strlen(name
)] == '\0'))
3028 cmd
+= strlen(name
);
3029 while(*cmd
== ' ') {
3032 if (offline
&& (CommandTable
[i
].offline
==0)) {
3033 PrintToScrollback("Offline mode, cannot use this command.");
3036 (CommandTable
[i
].handler
)(cmd
);
3040 PrintToScrollback(">> bad command '%s'", cmd
);
3043 //-----------------------------------------------------------------------------
3044 // Entry point into our code: called whenever we received a packet over USB
3045 // that we weren't necessarily expecting, for example a debug print.
3046 //-----------------------------------------------------------------------------
3047 void UsbCommandReceived(UsbCommand
*c
)
3050 case CMD_DEBUG_PRINT_STRING
: {
3052 if(c
->ext1
> 70 || c
->ext1
< 0) {
3055 memcpy(s
, c
->d
.asBytes
, c
->ext1
);
3057 PrintToScrollback("#db# %s", s
);
3061 case CMD_DEBUG_PRINT_INTEGERS
:
3062 PrintToScrollback("#db# %08x, %08x, %08x\r\n", c
->ext1
, c
->ext2
, c
->ext3
);
3065 case CMD_MEASURED_ANTENNA_TUNING
: {
3067 int vLf125
, vLf134
, vHf
;
3068 vLf125
= c
->ext1
& 0xffff;
3069 vLf134
= c
->ext1
>> 16;
3070 vHf
= c
->ext2
& 0xffff;;
3071 peakf
= c
->ext3
& 0xffff;
3072 peakv
= c
->ext3
>> 16;
3073 PrintToScrollback("");
3074 PrintToScrollback("");
3075 PrintToScrollback("# LF antenna: %5.2f V @ 125.00 kHz", vLf125
/1000.0);
3076 PrintToScrollback("# LF antenna: %5.2f V @ 134.00 kHz", vLf134
/1000.0);
3077 PrintToScrollback("# LF optimal: %5.2f V @%9.2f kHz", peakv
/1000.0, 12000.0/(peakf
+1));
3078 PrintToScrollback("# HF antenna: %5.2f V @ 13.56 MHz", vHf
/1000.0);
3080 PrintToScrollback("# Your LF antenna is unusable.");
3081 else if (peakv
<10000)
3082 PrintToScrollback("# Your LF antenna is marginal.");
3084 PrintToScrollback("# Your HF antenna is unusable.");
3086 PrintToScrollback("# Your HF antenna is marginal.");
3090 PrintToScrollback("unrecognized command %08x\n", c
->cmd
);