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 //-----------------------------------------------------------------------------
15 typedef DWORD
uint32_t;
17 typedef WORD
uint16_t;
27 #include "../common/iso14443_crc.c"
28 #include "../common/crc16.c"
30 #define arraylen(x) (sizeof(x)/sizeof((x)[0]))
31 #define BIT(x) GraphBuffer[x * clock]
32 #define BITS (GraphTraceLen / clock)
35 static int CmdHisamplest(char *str
, int nrlow
);
37 static void GetFromBigBuf(uint8_t *dest
, int bytes
)
43 PrintToScrollback("bad len in GetFromBigBuf");
47 for(i
= 0; i
< n
; i
+= 12) {
49 c
.cmd
= CMD_DOWNLOAD_RAW_ADC_SAMPLES_125K
;
51 SendCommand(&c
, false);
53 if(c
.cmd
!= CMD_DOWNLOADED_RAW_ADC_SAMPLES_125K
) {
54 PrintToScrollback("bad resp");
58 memcpy(dest
+(i
*4), c
.d
.asBytes
, 48);
62 static void CmdReset(char *str
)
65 c
.cmd
= CMD_HARDWARE_RESET
;
66 SendCommand(&c
, false);
69 static void CmdBuffClear(char *str
)
72 c
.cmd
= CMD_BUFF_CLEAR
;
73 SendCommand(&c
, false);
77 static void CmdQuit(char *str
)
82 static void CmdHIDdemodFSK(char *str
)
85 c
.cmd
= CMD_HID_DEMOD_FSK
;
86 SendCommand(&c
, false);
89 static void CmdTune(char *str
)
92 c
.cmd
= CMD_MEASURE_ANTENNA_TUNING
;
93 SendCommand(&c
, false);
96 static void CmdHi15read(char *str
)
99 c
.cmd
= CMD_ACQUIRE_RAW_ADC_SAMPLES_ISO_15693
;
100 SendCommand(&c
, false);
103 static void CmdHi14read(char *str
)
106 c
.cmd
= CMD_ACQUIRE_RAW_ADC_SAMPLES_ISO_14443
;
107 c
.arg
[0] = atoi(str
);
108 SendCommand(&c
, false);
112 /* New command to read the contents of a SRI512 tag
113 * SRI512 tags are ISO14443-B modulated memory tags,
114 * this command just dumps the contents of the memory/
116 static void CmdSri512read(char *str
)
119 c
.cmd
= CMD_READ_SRI512_TAG
;
120 c
.arg
[0] = atoi(str
);
121 SendCommand(&c
, false);
124 /* New command to read the contents of a SRIX4K tag
125 * SRIX4K tags are ISO14443-B modulated memory tags,
126 * this command just dumps the contents of the memory/
128 static void CmdSrix4kread(char *str
)
131 c
.cmd
= CMD_READ_SRIX4K_TAG
;
132 c
.arg
[0] = atoi(str
);
133 SendCommand(&c
, false);
139 static void CmdHi14areader(char *str
)
142 c
.cmd
= CMD_READER_ISO_14443a
;
143 c
.arg
[0] = atoi(str
);
144 SendCommand(&c
, false);
148 static void CmdHi15reader(char *str
)
151 c
.cmd
= CMD_READER_ISO_15693
;
152 c
.arg
[0] = atoi(str
);
153 SendCommand(&c
, false);
157 static void CmdHi15tag(char *str
)
160 c
.cmd
= CMD_SIMTAG_ISO_15693
;
161 c
.arg
[0] = atoi(str
);
162 SendCommand(&c
, false);
165 static void CmdHi14read_sim(char *str
)
168 c
.cmd
= CMD_ACQUIRE_RAW_ADC_SAMPLES_ISO_14443_SIM
;
169 c
.arg
[0] = atoi(str
);
170 SendCommand(&c
, false);
173 static void CmdHi14readt(char *str
)
176 c
.cmd
= CMD_ACQUIRE_RAW_ADC_SAMPLES_ISO_14443
;
177 c
.arg
[0] = atoi(str
);
178 SendCommand(&c
, false);
180 //CmdHisamplest(str);
181 while(CmdHisamplest(str
,atoi(str
))==0) {
182 c
.cmd
= CMD_ACQUIRE_RAW_ADC_SAMPLES_ISO_14443
;
183 c
.arg
[0] = atoi(str
);
184 SendCommand(&c
, false);
186 RepaintGraphWindow();
189 static void CmdHisimlisten(char *str
)
192 c
.cmd
= CMD_SIMULATE_TAG_HF_LISTEN
;
193 SendCommand(&c
, false);
196 static void CmdHi14sim(char *str
)
199 c
.cmd
= CMD_SIMULATE_TAG_ISO_14443
;
200 SendCommand(&c
, false);
203 static void CmdHi14asim(char *str
) // ## simulate iso14443a tag
204 { // ## greg - added ability to specify tag UID
206 unsigned int hi
=0, lo
=0;
210 while (sscanf(&str
[i
++], "%1x", &n
) == 1) {
215 c
.cmd
= CMD_SIMULATE_TAG_ISO_14443a
;
216 // c.ext should be set to *str or convert *str to the correct format for a uid
219 PrintToScrollback("Emulating 14443A TAG with UID %x%16x", hi
, lo
);
220 SendCommand(&c
, false);
223 static void CmdHi14snoop(char *str
)
226 c
.cmd
= CMD_SNOOP_ISO_14443
;
227 SendCommand(&c
, false);
230 static void CmdHi14asnoop(char *str
)
233 c
.cmd
= CMD_SNOOP_ISO_14443a
;
234 SendCommand(&c
, false);
237 static void CmdLegicRfSim(char *str
)
240 c
.cmd
= CMD_SIMULATE_TAG_LEGIC_RF
;
241 SendCommand(&c
, false);
244 static void CmdLegicRfRead(char *str
)
247 c
.cmd
= CMD_READER_LEGIC_RF
;
248 SendCommand(&c
, false);
251 static void CmdFPGAOff(char *str
) // ## FPGA Control
254 c
.cmd
= CMD_FPGA_MAJOR_MODE_OFF
;
255 SendCommand(&c
, false);
258 /* clear out our graph window */
259 int CmdClearGraph(int redraw
)
261 int gtl
= GraphTraceLen
;
265 RepaintGraphWindow();
270 /* write a bit to the graph */
271 static void CmdAppendGraph(int redraw
, int clock
, int bit
)
275 for (i
= 0; i
< (int)(clock
/2); i
++)
276 GraphBuffer
[GraphTraceLen
++] = bit
^ 1;
278 for (i
= (int)(clock
/2); i
< clock
; i
++)
279 GraphBuffer
[GraphTraceLen
++] = bit
;
282 RepaintGraphWindow();
285 /* Function is equivalent of loread + losamples + em410xread
286 * looped until an EM410x tag is detected */
287 static void CmdEM410xwatch(char *str
)
301 /* Read the transmitted data of an EM4x50 tag
304 * XXXXXXXX [row parity bit (even)] <- 8 bits plus parity
305 * XXXXXXXX [row parity bit (even)] <- 8 bits plus parity
306 * XXXXXXXX [row parity bit (even)] <- 8 bits plus parity
307 * XXXXXXXX [row parity bit (even)] <- 8 bits plus parity
308 * CCCCCCCC <- column parity bits
310 * LW <- Listen Window
312 * This pattern repeats for every block of data being transmitted.
313 * Transmission starts with two Listen Windows (LW - a modulated
314 * pattern of 320 cycles each (32/32/128/64/64)).
316 * Note that this data may or may not be the UID. It is whatever data
317 * is stored in the blocks defined in the control word First and Last
318 * Word Read values. UID is stored in block 32.
320 static void CmdEM4x50read(char *str
)
322 int i
, j
, startblock
, clock
, skip
, block
, start
, end
, low
, high
;
323 bool complete
= false;
324 int tmpbuff
[MAX_GRAPH_TRACE_LEN
/ 64];
330 /* first get high and low values */
331 for (i
= 0; i
< GraphTraceLen
; i
++)
333 if (GraphBuffer
[i
] > high
)
334 high
= GraphBuffer
[i
];
335 else if (GraphBuffer
[i
] < low
)
336 low
= GraphBuffer
[i
];
339 /* populate a buffer with pulse lengths */
342 while(i
< GraphTraceLen
)
344 // measure from low to low
345 while((GraphBuffer
[i
] > low
) && (i
<GraphTraceLen
))
348 while((GraphBuffer
[i
] < high
) && (i
<GraphTraceLen
))
350 while((GraphBuffer
[i
] > low
) && (i
<GraphTraceLen
))
352 if (j
>(MAX_GRAPH_TRACE_LEN
/64)) {
355 tmpbuff
[j
++]= i
- start
;
358 /* look for data start - should be 2 pairs of LW (pulses of 192,128) */
361 for (i
= 0; i
< j
- 4 ; ++i
)
364 if (tmpbuff
[i
] >= 190 && tmpbuff
[i
] <= 194)
365 if (tmpbuff
[i
+1] >= 126 && tmpbuff
[i
+1] <= 130)
366 if (tmpbuff
[i
+2] >= 190 && tmpbuff
[i
+2] <= 194)
367 if (tmpbuff
[i
+3] >= 126 && tmpbuff
[i
+3] <= 130)
375 /* skip over the remainder of the LW */
376 skip
+= tmpbuff
[i
+1]+tmpbuff
[i
+2];
377 while(skip
< MAX_GRAPH_TRACE_LEN
&& GraphBuffer
[skip
] > low
)
381 /* now do it again to find the end */
383 for (i
+= 3; i
< j
- 4 ; ++i
)
386 if (tmpbuff
[i
] >= 190 && tmpbuff
[i
] <= 194)
387 if (tmpbuff
[i
+1] >= 126 && tmpbuff
[i
+1] <= 130)
388 if (tmpbuff
[i
+2] >= 190 && tmpbuff
[i
+2] <= 194)
389 if (tmpbuff
[i
+3] >= 126 && tmpbuff
[i
+3] <= 130)
397 PrintToScrollback("Found data at sample: %i",skip
);
400 PrintToScrollback("No data found!");
401 PrintToScrollback("Try again with more samples.");
407 PrintToScrollback("*** Warning!");
408 PrintToScrollback("Partial data - no end found!");
409 PrintToScrollback("Try again with more samples.");
412 /* get rid of leading crap */
413 sprintf(tmp
,"%i",skip
);
416 /* now work through remaining buffer printing out data blocks */
421 PrintToScrollback("Block %i:", block
);
422 // mandemod routine needs to be split so we can call it for data
423 // just print for now for debugging
424 Cmdmanchesterdemod("i 64");
426 /* look for LW before start of next block */
427 for ( ; i
< j
- 4 ; ++i
)
430 if (tmpbuff
[i
] >= 190 && tmpbuff
[i
] <= 194)
431 if (tmpbuff
[i
+1] >= 126 && tmpbuff
[i
+1] <= 130)
434 while(GraphBuffer
[skip
] > low
)
437 sprintf(tmp
,"%i",skip
);
445 /* Read the ID of an EM410x tag.
447 * 1111 1111 1 <-- standard non-repeatable header
448 * XXXX [row parity bit] <-- 10 rows of 5 bits for our 40 bit tag ID
450 * CCCC <-- each bit here is parity for the 10 bits above in corresponding column
451 * 0 <-- stop bit, end of tag
453 static void CmdEM410xread(char *str
)
455 int i
, j
, clock
, header
, rows
, bit
, hithigh
, hitlow
, first
, bit2idx
, high
, low
;
459 int BitStream
[MAX_GRAPH_TRACE_LEN
];
462 /* Detect high and lows and clock */
463 for (i
= 0; i
< GraphTraceLen
; i
++)
465 if (GraphBuffer
[i
] > high
)
466 high
= GraphBuffer
[i
];
467 else if (GraphBuffer
[i
] < low
)
468 low
= GraphBuffer
[i
];
472 clock
= GetClock(str
, high
);
474 /* parity for our 4 columns */
475 parity
[0] = parity
[1] = parity
[2] = parity
[3] = 0;
478 /* manchester demodulate */
480 for (i
= 0; i
< (int)(GraphTraceLen
/ clock
); i
++)
486 /* Find out if we hit both high and low peaks */
487 for (j
= 0; j
< clock
; j
++)
489 if (GraphBuffer
[(i
* clock
) + j
] == high
)
491 else if (GraphBuffer
[(i
* clock
) + j
] == low
)
494 /* it doesn't count if it's the first part of our read
495 because it's really just trailing from the last sequence */
496 if (first
&& (hithigh
|| hitlow
))
497 hithigh
= hitlow
= 0;
501 if (hithigh
&& hitlow
)
505 /* If we didn't hit both high and low peaks, we had a bit transition */
506 if (!hithigh
|| !hitlow
)
509 BitStream
[bit2idx
++] = bit
;
513 /* We go till 5 before the graph ends because we'll get that far below */
514 for (i
= 1; i
< bit2idx
- 5; i
++)
516 /* Step 2: We have our header but need our tag ID */
517 if (header
== 9 && rows
< 10)
519 /* Confirm parity is correct */
520 if ((BitStream
[i
] ^ BitStream
[i
+1] ^ BitStream
[i
+2] ^ BitStream
[i
+3]) == BitStream
[i
+4])
522 /* Read another byte! */
523 sprintf(id
+rows
, "%x", (8 * BitStream
[i
]) + (4 * BitStream
[i
+1]) + (2 * BitStream
[i
+2]) + (1 * BitStream
[i
+3]));
526 /* Keep parity info */
527 parity
[0] ^= BitStream
[i
];
528 parity
[1] ^= BitStream
[i
+1];
529 parity
[2] ^= BitStream
[i
+2];
530 parity
[3] ^= BitStream
[i
+3];
532 /* Move 4 bits ahead */
536 /* Damn, something wrong! reset */
539 PrintToScrollback("Thought we had a valid tag but failed at word %d (i=%d)", rows
+ 1, i
);
541 /* Start back rows * 5 + 9 header bits, -1 to not start at same place */
542 i
-= 9 + (5 * rows
) - 5;
548 /* Step 3: Got our 40 bits! confirm column parity */
551 /* We need to make sure our 4 bits of parity are correct and we have a stop bit */
552 if (BitStream
[i
] == parity
[0] && BitStream
[i
+1] == parity
[1] &&
553 BitStream
[i
+2] == parity
[2] && BitStream
[i
+3] == parity
[3] &&
557 PrintToScrollback("EM410x Tag ID: %s", id
);
564 /* Crap! Incorrect parity or no stop bit, start all over */
569 /* Go back 59 bits (9 header bits + 10 rows at 4+1 parity) */
574 /* Step 1: get our header */
577 /* Need 9 consecutive 1's */
578 if (BitStream
[i
] == 1)
581 /* We don't have a header, not enough consecutive 1 bits */
587 /* if we've already retested after flipping bits, return */
591 /* if this didn't work, try flipping bits */
592 for (i
= 0; i
< bit2idx
; i
++)
598 /* emulate an EM410X tag
600 * 1111 1111 1 <-- standard non-repeatable header
601 * XXXX [row parity bit] <-- 10 rows of 5 bits for our 40 bit tag ID
603 * CCCC <-- each bit here is parity for the 10 bits above in corresponding column
604 * 0 <-- stop bit, end of tag
606 static void CmdEM410xsim(char *str
)
608 int i
, n
, j
, h
, binary
[4], parity
[4];
611 /* clock is 64 in EM410x tags */
614 /* clear our graph */
617 /* write it out a few times */
618 for (h
= 0; h
< 4; h
++)
620 /* write 9 start bits */
621 for (i
= 0; i
< 9; i
++)
622 CmdAppendGraph(0, clock
, 1);
624 /* for each hex char */
625 parity
[0] = parity
[1] = parity
[2] = parity
[3] = 0;
626 for (i
= 0; i
< 10; i
++)
628 /* read each hex char */
629 sscanf(&str
[i
], "%1x", &n
);
630 for (j
= 3; j
>= 0; j
--, n
/= 2)
633 /* append each bit */
634 CmdAppendGraph(0, clock
, binary
[0]);
635 CmdAppendGraph(0, clock
, binary
[1]);
636 CmdAppendGraph(0, clock
, binary
[2]);
637 CmdAppendGraph(0, clock
, binary
[3]);
639 /* append parity bit */
640 CmdAppendGraph(0, clock
, binary
[0] ^ binary
[1] ^ binary
[2] ^ binary
[3]);
642 /* keep track of column parity */
643 parity
[0] ^= binary
[0];
644 parity
[1] ^= binary
[1];
645 parity
[2] ^= binary
[2];
646 parity
[3] ^= binary
[3];
650 CmdAppendGraph(0, clock
, parity
[0]);
651 CmdAppendGraph(0, clock
, parity
[1]);
652 CmdAppendGraph(0, clock
, parity
[2]);
653 CmdAppendGraph(0, clock
, parity
[3]);
656 CmdAppendGraph(0, clock
, 0);
659 /* modulate that biatch */
663 RepaintGraphWindow();
668 static void ChkBitstream(char *str
)
672 /* convert to bitstream if necessary */
673 for (i
= 0; i
< (int)(GraphTraceLen
/ 2); i
++)
675 if (GraphBuffer
[i
] > 1 || GraphBuffer
[i
] < 0)
683 static void CmdLosim(char *str
)
688 /* convert to bitstream if necessary */
691 for (i
= 0; i
< GraphTraceLen
; i
+= 48) {
694 for(j
= 0; j
< 48; j
++) {
695 c
.d
.asBytes
[j
] = GraphBuffer
[i
+j
];
697 c
.cmd
= CMD_DOWNLOADED_SIM_SAMPLES_125K
;
699 SendCommand(&c
, false);
702 c
.cmd
= CMD_SIMULATE_TAG_125K
;
703 c
.arg
[0] = GraphTraceLen
;
704 SendCommand(&c
, false);
707 static void CmdLosimBidir(char *str
)
710 c
.cmd
= CMD_LF_SIMULATE_BIDIR
;
711 c
.arg
[0] = 47; /* Set ADC to twice the carrier for a slight supersampling */
713 SendCommand(&c
, false);
716 static void CmdLoread(char *str
)
719 // 'h' means higher-low-frequency, 134 kHz
722 } else if (*str
== '\0') {
725 PrintToScrollback("use 'loread' or 'loread h'");
728 c
.cmd
= CMD_ACQUIRE_RAW_ADC_SAMPLES_125K
;
729 SendCommand(&c
, false);
732 static void CmdDetectReader(char *str
)
735 // 'l' means LF - 125/134 kHz
738 } else if (*str
== 'h') {
740 } else if (*str
!= '\0') {
741 PrintToScrollback("use 'detectreader' or 'detectreader l' or 'detectreader h'");
744 c
.cmd
= CMD_LISTEN_READER_FIELD
;
745 SendCommand(&c
, false);
748 /* send a command before reading */
749 static void CmdLoCommandRead(char *str
)
751 static char dummy
[3];
756 c
.cmd
= CMD_MOD_THEN_ACQUIRE_RAW_ADC_SAMPLES_125K
;
757 sscanf(str
, "%i %i %i %s %s", &c
.arg
[0], &c
.arg
[1], &c
.arg
[2], (char *) &c
.d
.asBytes
,(char *) &dummy
+1);
758 // in case they specified 'h'
759 strcpy((char *)&c
.d
.asBytes
+ strlen((char *)c
.d
.asBytes
), dummy
);
760 SendCommand(&c
, false);
763 static void CmdLosamples(char *str
)
772 if (n
>16000) n
=16000;
774 for(i
= 0; i
< n
; i
+= 12) {
776 c
.cmd
= CMD_DOWNLOAD_RAW_ADC_SAMPLES_125K
;
778 SendCommand(&c
, false);
780 if(c
.cmd
!= CMD_DOWNLOADED_RAW_ADC_SAMPLES_125K
) {
782 PrintToScrollback("bad resp");
785 for(j
= 0; j
< 48; j
++) {
786 GraphBuffer
[cnt
++] = ((int)c
.d
.asBytes
[j
]) - 128;
790 RepaintGraphWindow();
793 static void CmdBitsamples(char *str
)
801 for(i
= 0; i
< n
; i
+= 12) {
803 c
.cmd
= CMD_DOWNLOAD_RAW_ADC_SAMPLES_125K
;
805 SendCommand(&c
, false);
807 if(c
.cmd
!= CMD_DOWNLOADED_RAW_ADC_SAMPLES_125K
) {
808 PrintToScrollback("bad resp");
811 for(j
= 0; j
< 48; j
++) {
812 for(k
= 0; k
< 8; k
++) {
813 if(c
.d
.asBytes
[j
] & (1 << (7 - k
))) {
814 GraphBuffer
[cnt
++] = 1;
816 GraphBuffer
[cnt
++] = 0;
822 RepaintGraphWindow();
825 static void CmdHisamples(char *str
)
832 for(i
= 0; i
< n
; i
+= 12) {
834 c
.cmd
= CMD_DOWNLOAD_RAW_ADC_SAMPLES_125K
;
836 SendCommand(&c
, false);
838 if(c
.cmd
!= CMD_DOWNLOADED_RAW_ADC_SAMPLES_125K
) {
839 PrintToScrollback("bad resp");
842 for(j
= 0; j
< 48; j
++) {
843 GraphBuffer
[cnt
++] = (int)((uint8_t)c
.d
.asBytes
[j
]);
848 RepaintGraphWindow();
851 static int CmdHisamplest(char *str
, int nrlow
)
864 for(i
= 0; i
< n
; i
+= 12) {
866 c
.cmd
= CMD_DOWNLOAD_RAW_ADC_SAMPLES_125K
;
868 SendCommand(&c
, false);
870 if(c
.cmd
!= CMD_DOWNLOADED_RAW_ADC_SAMPLES_125K
) {
871 PrintToScrollback("bad resp");
874 for(j
= 0; j
< 48; j
++) {
875 t2
= (int)((uint8_t)c
.d
.asBytes
[j
]);
876 if((t2
^ 0xC0) & 0xC0) { hasbeennull
++; }
882 t1
= (t2
& 0x80) ^ (t2
& 0x20);
883 t2
= ((t2
<< 1) & 0x80) ^ ((t2
<< 1) & 0x20);
889 t2
= ((t2
<< 1) & 0x80);
895 t2
= ((t2
<< 1) & 0x20);
899 // both, but tag with other algorithm
900 t1
= (t2
& 0x80) ^ (t2
& 0x08);
901 t2
= ((t2
<< 1) & 0x80) ^ ((t2
<< 1) & 0x08);
905 GraphBuffer
[cnt
++] = t1
;
906 GraphBuffer
[cnt
++] = t2
;
911 if(hasbeennull
>nrlow
|| nrlow
==0) {
912 PrintToScrollback("hasbeennull=%d", hasbeennull
);
921 static void CmdHexsamples(char *str
)
925 int requested
= atoi(str
);
936 for(i
= 0; i
< n
; i
+= 12) {
938 c
.cmd
= CMD_DOWNLOAD_RAW_ADC_SAMPLES_125K
;
940 SendCommand(&c
, false);
942 if(c
.cmd
!= CMD_DOWNLOADED_RAW_ADC_SAMPLES_125K
) {
943 PrintToScrollback("bad resp");
946 for(j
= 0; j
< 48; j
+= 8) {
947 PrintToScrollback("%02x %02x %02x %02x %02x %02x %02x %02x",
959 if(delivered
>= requested
)
962 if(delivered
>= requested
)
967 static void CmdHisampless(char *str
)
980 for(i
= 0; i
< n
; i
+= 12) {
982 c
.cmd
= CMD_DOWNLOAD_RAW_ADC_SAMPLES_125K
;
984 SendCommand(&c
, false);
986 if(c
.cmd
!= CMD_DOWNLOADED_RAW_ADC_SAMPLES_125K
) {
987 PrintToScrollback("bad resp");
990 for(j
= 0; j
< 48; j
++) {
991 GraphBuffer
[cnt
++] = (int)((signed char)c
.d
.asBytes
[j
]);
996 RepaintGraphWindow();
999 static uint16_t Iso15693Crc(uint8_t *v
, int n
)
1005 for(i
= 0; i
< n
; i
++) {
1006 reg
= reg
^ ((uint32_t)v
[i
]);
1007 for (j
= 0; j
< 8; j
++) {
1009 reg
= (reg
>> 1) ^ 0x8408;
1016 return (uint16_t)~reg
;
1019 static void CmdHi14bdemod(char *str
)
1024 bool negateI
, negateQ
;
1025 uint8_t first
, second
;
1030 // As received, the samples are pairs, correlations against I and Q
1031 // square waves. So estimate angle of initial carrier (or just
1032 // quadrant, actually), and then do the demod.
1034 // First, estimate where the tag starts modulating.
1035 for(i
= 0; i
< GraphTraceLen
; i
+= 2) {
1036 if(abs(GraphBuffer
[i
]) + abs(GraphBuffer
[i
+1]) > 40) {
1040 if(i
>= GraphTraceLen
) {
1041 PrintToScrollback("too weak to sync");
1044 PrintToScrollback("out of weak at %d", i
);
1047 // Now, estimate the phase in the initial modulation of the tag
1050 for(; i
< (outOfWeakAt
+ 16); i
+= 2) {
1051 isum
+= GraphBuffer
[i
+0];
1052 qsum
+= GraphBuffer
[i
+1];
1054 negateI
= (isum
< 0);
1055 negateQ
= (qsum
< 0);
1057 // Turn the correlation pairs into soft decisions on the bit.
1059 for(i
= 0; i
< GraphTraceLen
/2; i
++) {
1060 int si
= GraphBuffer
[j
];
1061 int sq
= GraphBuffer
[j
+1];
1062 if(negateI
) si
= -si
;
1063 if(negateQ
) sq
= -sq
;
1064 GraphBuffer
[i
] = si
+ sq
;
1070 while(GraphBuffer
[i
] > 0 && i
< GraphTraceLen
)
1072 if(i
>= GraphTraceLen
) goto demodError
;
1075 while(GraphBuffer
[i
] < 0 && i
< GraphTraceLen
)
1077 if(i
>= GraphTraceLen
) goto demodError
;
1078 if((i
- iold
) > 23) goto demodError
;
1080 PrintToScrollback("make it to demod loop");
1083 uint16_t shiftReg
= 0;
1085 while(GraphBuffer
[i
] >= 0 && i
< GraphTraceLen
)
1087 if(i
>= GraphTraceLen
) goto demodError
;
1088 if((i
- iold
) > 6) goto demodError
;
1090 if(i
+ 20 >= GraphTraceLen
) goto demodError
;
1092 for(j
= 0; j
< 10; j
++) {
1093 int soft
= GraphBuffer
[i
] + GraphBuffer
[i
+1];
1095 if(abs(soft
) < ((abs(isum
) + abs(qsum
))/20)) {
1096 PrintToScrollback("weak bit");
1100 if(GraphBuffer
[i
] + GraphBuffer
[i
+1] >= 0) {
1107 if( (shiftReg
& 0x200) &&
1108 !(shiftReg
& 0x001))
1110 // valid data byte, start and stop bits okay
1111 PrintToScrollback(" %02x", (shiftReg
>> 1) & 0xff);
1112 data
[dataLen
++] = (shiftReg
>> 1) & 0xff;
1113 if(dataLen
>= sizeof(data
)) {
1116 } else if(shiftReg
== 0x000) {
1124 ComputeCrc14443(CRC_14443_B
, data
, dataLen
-2, &first
, &second
);
1125 PrintToScrollback("CRC: %02x %02x (%s)\n", first
, second
,
1126 (first
== data
[dataLen
-2] && second
== data
[dataLen
-1]) ?
1127 "ok" : "****FAIL****");
1129 RepaintGraphWindow();
1133 PrintToScrollback("demod error");
1134 RepaintGraphWindow();
1137 static void CmdHi14list(char *str
)
1142 GetFromBigBuf(got
, sizeof(got
));
1144 PrintToScrollback("recorded activity:");
1145 PrintToScrollback(" time :rssi: who bytes");
1146 PrintToScrollback("---------+----+----+-----------");
1151 int metric
= *((uint32_t *)(got
+i
+4));
1153 int timestamp
= *((uint32_t *)(got
+i
));
1154 uint8_t *frame
= (got
+i
+9);
1156 char metricString
[100];
1158 char line
[1000] = "";
1161 if(timestamp
& 0x80000000) {
1162 timestamp
&= 0x7fffffff;
1171 if(i
+ len
>= 900) {
1175 for(j
= 0; j
< len
; j
++) {
1176 sprintf(line
+(j
*3), "%02x ", frame
[j
]);
1181 ComputeCrc14443(CRC_14443_B
, frame
, len
-2, &b1
, &b2
);
1182 if(b1
!= frame
[len
-2] || b2
!= frame
[len
-1]) {
1183 crc
= "**FAIL CRC**";
1192 sprintf(metricString
, "%3d", metric
);
1194 strcpy(metricString
, " ");
1197 PrintToScrollback(" +%7d: %s: %s %s %s",
1198 (prev
< 0 ? 0 : timestamp
- prev
),
1200 (isResponse
? "TAG" : " "), line
, crc
);
1207 static void CmdHi14alist(char *str
)
1213 GetFromBigBuf(got
, sizeof(got
));
1215 PrintToScrollback("recorded activity:");
1216 PrintToScrollback(" ETU :rssi: who bytes");
1217 PrintToScrollback("---------+----+----+-----------");
1221 int timestamp
= *((uint32_t *)(got
+i
));
1223 int parityBits
= *((uint32_t *)(got
+i
+4));
1225 char line
[1000] = "";
1227 uint8_t *frame
= (got
+i
+9);
1229 char metricString
[100];
1231 if(timestamp
& 0x80000000) {
1232 timestamp
&= 0x7fffffff;
1238 // 4 bytes of additional information...
1239 // maximum of 32 additional parity bit information
1242 // at each quarter bit period we can send power level (16 levels)
1243 // or each half bit period in 256 levels.
1249 if(i
+ len
>= 1900) {
1253 // Break and stick with current result if buffer was not completely full
1254 if(frame
[0] == 0x44 && frame
[1] == 0x44 && frame
[3] == 0x44) { break; }
1256 for(j
= 0; j
< len
; j
++) {
1257 int oddparity
= 0x01;
1261 oddparity
^= (((frame
[j
] & 0xFF) >> k
) & 0x01);
1264 //if((parityBits >> (len - j - 1)) & 0x01) {
1265 if(isResponse
&& (oddparity
!= ((parityBits
>> (len
- j
- 1)) & 0x01))) {
1266 sprintf(line
+(j
*4), "%02x! ", frame
[j
]);
1269 sprintf(line
+(j
*4), "%02x ", frame
[j
]);
1276 for(j
= 0; j
< (len
- 1); j
++) {
1277 // gives problems... search for the reason..
1278 /*if(frame[j] == 0xAA) {
1279 switch(frame[j+1]) {
1281 crc = "[1] Two drops close after each other";
1284 crc = "[2] Potential SOC with a drop in second half of bitperiod";
1287 crc = "[3] Segment Z after segment X is not possible";
1290 crc = "[4] Parity bit of a fully received byte was wrong";
1293 crc = "[?] Unknown error";
1300 if(strlen(crc
)==0) {
1301 ComputeCrc14443(CRC_14443_A
, frame
, len
-2, &b1
, &b2
);
1302 if(b1
!= frame
[len
-2] || b2
!= frame
[len
-1]) {
1303 crc
= (isResponse
& (len
< 6)) ? "" : " !crc";
1313 sprintf(metricString
, "%3d", metric
);
1315 strcpy(metricString
, " ");
1318 PrintToScrollback(" +%7d: %s: %s %s %s",
1319 (prev
< 0 ? 0 : (timestamp
- prev
)),
1321 (isResponse
? "TAG" : " "), line
, crc
);
1326 CommandFinished
= 1;
1329 static void CmdHi15demod(char *str
)
1331 // The sampling rate is 106.353 ksps/s, for T = 18.8 us
1334 // 1) Unmodulated time of 56.64us
1335 // 2) 24 pulses of 423.75khz
1336 // 3) logic '1' (unmodulated for 18.88us followed by 8 pulses of 423.75khz)
1338 static const int FrameSOF
[] = {
1339 -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
1340 -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
1341 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
1342 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
1348 static const int Logic0
[] = {
1354 static const int Logic1
[] = {
1362 // 1) logic '0' (8 pulses of 423.75khz followed by unmodulated for 18.88us)
1363 // 2) 24 pulses of 423.75khz
1364 // 3) Unmodulated time of 56.64us
1366 static const int FrameEOF
[] = {
1371 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
1372 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
1373 -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
1374 -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1
1378 int max
= 0, maxPos
;
1383 uint8_t mask
= 0x01;
1385 if(GraphTraceLen
< 1000) return;
1387 // First, correlate for SOF
1388 for(i
= 0; i
< 100; i
++) {
1390 for(j
= 0; j
< arraylen(FrameSOF
); j
+= skip
) {
1391 corr
+= FrameSOF
[j
]*GraphBuffer
[i
+(j
/skip
)];
1398 PrintToScrollback("SOF at %d, correlation %d", maxPos
,
1399 max
/(arraylen(FrameSOF
)/skip
));
1401 i
= maxPos
+ arraylen(FrameSOF
)/skip
;
1402 memset(outBuf
, 0, sizeof(outBuf
));
1404 int corr0
= 0, corr1
= 0, corrEOF
= 0;
1405 for(j
= 0; j
< arraylen(Logic0
); j
+= skip
) {
1406 corr0
+= Logic0
[j
]*GraphBuffer
[i
+(j
/skip
)];
1408 for(j
= 0; j
< arraylen(Logic1
); j
+= skip
) {
1409 corr1
+= Logic1
[j
]*GraphBuffer
[i
+(j
/skip
)];
1411 for(j
= 0; j
< arraylen(FrameEOF
); j
+= skip
) {
1412 corrEOF
+= FrameEOF
[j
]*GraphBuffer
[i
+(j
/skip
)];
1414 // Even things out by the length of the target waveform.
1418 if(corrEOF
> corr1
&& corrEOF
> corr0
) {
1419 PrintToScrollback("EOF at %d", i
);
1421 } else if(corr1
> corr0
) {
1422 i
+= arraylen(Logic1
)/skip
;
1425 i
+= arraylen(Logic0
)/skip
;
1432 if((i
+(int)arraylen(FrameEOF
)) >= GraphTraceLen
) {
1433 PrintToScrollback("ran off end!");
1438 PrintToScrollback("error, uneven octet! (discard extra bits!)");
1439 PrintToScrollback(" mask=%02x", mask
);
1441 PrintToScrollback("%d octets", k
);
1443 for(i
= 0; i
< k
; i
++) {
1444 PrintToScrollback("# %2d: %02x ", i
, outBuf
[i
]);
1446 PrintToScrollback("CRC=%04x", Iso15693Crc(outBuf
, k
-2));
1449 static void CmdFSKdemod(char *cmdline
)
1451 static const int LowTone
[] = {
1452 1, 1, 1, 1, 1, -1, -1, -1, -1, -1,
1453 1, 1, 1, 1, 1, -1, -1, -1, -1, -1,
1454 1, 1, 1, 1, 1, -1, -1, -1, -1, -1,
1455 1, 1, 1, 1, 1, -1, -1, -1, -1, -1,
1456 1, 1, 1, 1, 1, -1, -1, -1, -1, -1
1458 static const int HighTone
[] = {
1459 1, 1, 1, 1, 1, -1, -1, -1, -1,
1460 1, 1, 1, 1, -1, -1, -1, -1,
1461 1, 1, 1, 1, -1, -1, -1, -1,
1462 1, 1, 1, 1, -1, -1, -1, -1,
1463 1, 1, 1, 1, -1, -1, -1, -1,
1464 1, 1, 1, 1, -1, -1, -1, -1, -1,
1467 int lowLen
= sizeof(LowTone
)/sizeof(int);
1468 int highLen
= sizeof(HighTone
)/sizeof(int);
1469 int convLen
= (highLen
>lowLen
)?highLen
:lowLen
;
1470 uint32_t hi
= 0, lo
= 0;
1473 int minMark
=0, maxMark
=0;
1474 int max
= 0, maxPos
= 0;
1477 for(i
= 0; i
< GraphTraceLen
- convLen
; i
++) {
1478 int lowSum
= 0, highSum
= 0;
1480 for(j
= 0; j
< lowLen
; j
++) {
1481 lowSum
+= LowTone
[j
]*GraphBuffer
[i
+j
];
1483 for(j
= 0; j
< highLen
; j
++) {
1484 highSum
+= HighTone
[j
]*GraphBuffer
[i
+j
];
1486 lowSum
= abs((100*lowSum
) / lowLen
);
1487 highSum
= abs((100*highSum
) / highLen
);
1488 GraphBuffer
[i
] = (highSum
<< 16) | lowSum
;
1491 for(i
= 0; i
< GraphTraceLen
- convLen
- 16; i
++) {
1493 int lowTot
= 0, highTot
= 0;
1494 // 10 and 8 are f_s divided by f_l and f_h, rounded
1495 for(j
= 0; j
< 10; j
++) {
1496 lowTot
+= (GraphBuffer
[i
+j
] & 0xffff);
1498 for(j
= 0; j
< 8; j
++) {
1499 highTot
+= (GraphBuffer
[i
+j
] >> 16);
1501 GraphBuffer
[i
] = lowTot
- highTot
;
1502 if (GraphBuffer
[i
]>maxMark
) maxMark
=GraphBuffer
[i
];
1503 if (GraphBuffer
[i
]<minMark
) minMark
=GraphBuffer
[i
];
1506 GraphTraceLen
-= (convLen
+ 16);
1508 RepaintGraphWindow();
1510 // Find bit-sync (3 lo followed by 3 high)
1511 for(i
= 0; i
< 6000; i
++) {
1513 for(j
= 0; j
< 3*lowLen
; j
++) {
1514 dec
-= GraphBuffer
[i
+j
];
1516 for(; j
< 3*(lowLen
+ highLen
); j
++) {
1517 dec
+= GraphBuffer
[i
+j
];
1525 // place start of bit sync marker in graph
1526 GraphBuffer
[maxPos
] = maxMark
;
1527 GraphBuffer
[maxPos
+1] = minMark
;
1531 // place end of bit sync marker in graph
1532 GraphBuffer
[maxPos
] = maxMark
;
1533 GraphBuffer
[maxPos
+1] = minMark
;
1535 PrintToScrollback("actual data bits start at sample %d", maxPos
);
1536 PrintToScrollback("length %d/%d", highLen
, lowLen
);
1538 bits
[sizeof(bits
)-1] = '\0';
1540 // find bit pairs and manchester decode them
1541 for(i
= 0; i
< arraylen(bits
)-1; i
++) {
1543 for(j
= 0; j
< lowLen
; j
++) {
1544 dec
-= GraphBuffer
[maxPos
+j
];
1546 for(; j
< lowLen
+ highLen
; j
++) {
1547 dec
+= GraphBuffer
[maxPos
+j
];
1550 // place inter bit marker in graph
1551 GraphBuffer
[maxPos
] = maxMark
;
1552 GraphBuffer
[maxPos
+1] = minMark
;
1554 // hi and lo form a 64 bit pair
1555 hi
= (hi
<<1)|(lo
>>31);
1557 // store decoded bit as binary (in hi/lo) and text (in bits[])
1565 PrintToScrollback("bits: '%s'", bits
);
1566 PrintToScrollback("hex: %08x %08x", hi
, lo
);
1569 // read a TI tag and return its ID
1570 static void CmdTIRead(char *str
)
1573 c
.cmd
= CMD_READ_TI_TYPE
;
1574 SendCommand(&c
, false);
1577 // write new data to a r/w TI tag
1578 static void CmdTIWrite(char *str
)
1583 c
.cmd
= CMD_WRITE_TI_TYPE
;
1584 res
= sscanf(str
, "0x%x 0x%x 0x%x ", &c
.arg
[0], &c
.arg
[1], &c
.arg
[2]);
1585 if (res
== 2) c
.arg
[2]=0;
1587 PrintToScrollback("Please specify the data as two hex strings, optionally the CRC as a third");
1589 SendCommand(&c
, false);
1592 static void CmdTIDemod(char *cmdline
)
1594 /* MATLAB as follows:
1595 f_s = 2000000; % sampling frequency
1596 f_l = 123200; % low FSK tone
1597 f_h = 134200; % high FSK tone
1599 T_l = 119e-6; % low bit duration
1600 T_h = 130e-6; % high bit duration
1602 l = 2*pi*ones(1, floor(f_s*T_l))*(f_l/f_s);
1603 h = 2*pi*ones(1, floor(f_s*T_h))*(f_h/f_s);
1605 l = sign(sin(cumsum(l)));
1606 h = sign(sin(cumsum(h)));
1609 // 2M*16/134.2k = 238
1610 static const int LowTone
[] = {
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, -1, -1, -1, -1, -1, -1,
1622 1, 1, 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, -1, -1,
1624 1, 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
1627 // 2M*16/123.2k = 260
1628 static const int HighTone
[] = {
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, -1,
1634 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, -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,
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, -1,
1642 1, 1, 1, 1, 1, 1, 1, 1, -1, -1, -1, -1, -1, -1, -1,
1643 1, 1, 1, 1, 1, 1, 1, -1, -1, -1, -1, -1, -1, -1, -1,
1644 1, 1, 1, 1, 1, 1, 1, -1, -1, -1, -1, -1, -1, -1, -1,
1645 1, 1, 1, 1, 1, 1, 1, -1, -1, -1, -1, -1, -1, -1,
1646 1, 1, 1, 1, 1, 1, 1, 1
1648 int lowLen
= sizeof(LowTone
)/sizeof(int);
1649 int highLen
= sizeof(HighTone
)/sizeof(int);
1650 int convLen
= (highLen
>lowLen
)?highLen
:lowLen
;
1653 int lowSum
= 0, highSum
= 0;
1654 int lowTot
= 0, highTot
= 0;
1655 int max
= 0, maxPos
= 0;
1656 uint8_t bits
[1+64+16+8+16];
1657 uint32_t shift3
= 0x7e000000, shift2
= 0, shift1
= 0, shift0
= 0;
1660 for(i
= 0; i
< GraphTraceLen
- convLen
; i
++) {
1664 for(j
= 0; j
< lowLen
; j
++) {
1665 lowSum
+= LowTone
[j
]*GraphBuffer
[i
+j
];
1667 for(j
= 0; j
< highLen
; j
++) {
1668 highSum
+= HighTone
[j
]*GraphBuffer
[i
+j
];
1670 lowSum
= abs((100*lowSum
) / lowLen
);
1671 highSum
= abs((100*highSum
) / highLen
);
1672 lowSum
= (lowSum
<0)?-lowSum
:lowSum
;
1673 highSum
= (highSum
<0)?-highSum
:highSum
;
1675 GraphBuffer
[i
] = (highSum
<< 16) | lowSum
;
1678 for(i
= 0; i
< GraphTraceLen
- convLen
- 16; i
++) {
1681 // 16 and 15 are f_s divided by f_l and f_h, rounded
1682 for(j
= 0; j
< 16; j
++) {
1683 lowTot
+= (GraphBuffer
[i
+j
] & 0xffff);
1685 for(j
= 0; j
< 15; j
++) {
1686 highTot
+= (GraphBuffer
[i
+j
] >> 16);
1688 GraphBuffer
[i
] = lowTot
- highTot
;
1691 GraphTraceLen
-= (convLen
+ 16);
1693 RepaintGraphWindow();
1695 // TI tag data format is 16 prebits, 8 start bits, 64 data bits,
1696 // 16 crc CCITT bits, 8 stop bits, 15 end bits
1698 // the 16 prebits are always low
1699 // the 8 start and stop bits of a tag must match
1700 // the start/stop prebits of a ro tag are 01111110
1701 // the start/stop prebits of a rw tag are 11111110
1702 // the 15 end bits of a ro tag are all low
1703 // the 15 end bits of a rw tag match bits 15-1 of the data bits
1705 // Okay, so now we have unsliced soft decisions;
1706 // find bit-sync, and then get some bits.
1707 // look for 17 low bits followed by 6 highs (common pattern for ro and rw tags)
1708 for(i
= 0; i
< 6000; i
++) {
1711 // searching 17 consecutive lows
1712 for(j
= 0; j
< 17*lowLen
; j
++) {
1713 dec
-= GraphBuffer
[i
+j
];
1715 // searching 7 consecutive highs
1716 for(; j
< 17*lowLen
+ 6*highLen
; j
++) {
1717 dec
+= GraphBuffer
[i
+j
];
1725 // place a marker in the buffer to visually aid location
1726 // of the start of sync
1727 GraphBuffer
[maxPos
] = 800;
1728 GraphBuffer
[maxPos
+1] = -800;
1730 // advance pointer to start of actual data stream (after 16 pre and 8 start bits)
1731 maxPos
+= 17*lowLen
;
1732 maxPos
+= 6*highLen
;
1734 // place a marker in the buffer to visually aid location
1735 // of the end of sync
1736 GraphBuffer
[maxPos
] = 800;
1737 GraphBuffer
[maxPos
+1] = -800;
1739 PrintToScrollback("actual data bits start at sample %d", maxPos
);
1741 PrintToScrollback("length %d/%d", highLen
, lowLen
);
1743 bits
[sizeof(bits
)-1] = '\0';
1745 for(i
= 0; i
< arraylen(bits
)-1; i
++) {
1749 for(j
= 0; j
< lowLen
; j
++) {
1750 low
-= GraphBuffer
[maxPos
+j
];
1752 for(j
= 0; j
< highLen
; j
++) {
1753 high
+= GraphBuffer
[maxPos
+j
];
1759 // bitstream arrives lsb first so shift right
1766 // 128 bit right shift register
1767 shift0
= (shift0
>>1) | (shift1
<< 31);
1768 shift1
= (shift1
>>1) | (shift2
<< 31);
1769 shift2
= (shift2
>>1) | (shift3
<< 31);
1772 // place a marker in the buffer between bits to visually aid location
1773 GraphBuffer
[maxPos
] = 800;
1774 GraphBuffer
[maxPos
+1] = -800;
1776 PrintToScrollback("Info: raw tag bits = %s", bits
);
1778 TagType
= (shift3
>>8)&0xff;
1779 if ( TagType
!= ((shift0
>>16)&0xff) ) {
1780 PrintToScrollback("Error: start and stop bits do not match!");
1783 else if (TagType
== 0x7e) {
1784 PrintToScrollback("Info: Readonly TI tag detected.");
1787 else if (TagType
== 0xfe) {
1788 PrintToScrollback("Info: Rewriteable TI tag detected.");
1790 // put 64 bit data into shift1 and shift0
1791 shift0
= (shift0
>>24) | (shift1
<< 8);
1792 shift1
= (shift1
>>24) | (shift2
<< 8);
1794 // align 16 bit crc into lower half of shift2
1795 shift2
= ((shift2
>>24) | (shift3
<< 8)) & 0x0ffff;
1797 // align 16 bit "end bits" or "ident" into lower half of shift3
1800 // only 15 bits compare, last bit of ident is not valid
1801 if ( (shift3
^shift0
)&0x7fff ) {
1802 PrintToScrollback("Error: Ident mismatch!");
1804 // WARNING the order of the bytes in which we calc crc below needs checking
1805 // i'm 99% sure the crc algorithm is correct, but it may need to eat the
1806 // bytes in reverse or something
1809 crc
= update_crc16(crc
, (shift0
)&0xff);
1810 crc
= update_crc16(crc
, (shift0
>>8)&0xff);
1811 crc
= update_crc16(crc
, (shift0
>>16)&0xff);
1812 crc
= update_crc16(crc
, (shift0
>>24)&0xff);
1813 crc
= update_crc16(crc
, (shift1
)&0xff);
1814 crc
= update_crc16(crc
, (shift1
>>8)&0xff);
1815 crc
= update_crc16(crc
, (shift1
>>16)&0xff);
1816 crc
= update_crc16(crc
, (shift1
>>24)&0xff);
1817 PrintToScrollback("Info: Tag data = %08X%08X", shift1
, shift0
);
1818 if (crc
!= (shift2
&0xffff)) {
1819 PrintToScrollback("Error: CRC mismatch, calculated %04X, got ^04X", crc
, shift2
&0xffff);
1821 PrintToScrollback("Info: CRC %04X is good", crc
);
1825 PrintToScrollback("Unknown tag type.");
1830 static void CmdNorm(char *str
)
1833 int max
= INT_MIN
, min
= INT_MAX
;
1834 for(i
= 10; i
< GraphTraceLen
; i
++) {
1835 if(GraphBuffer
[i
] > max
) {
1836 max
= GraphBuffer
[i
];
1838 if(GraphBuffer
[i
] < min
) {
1839 min
= GraphBuffer
[i
];
1843 for(i
= 0; i
< GraphTraceLen
; i
++) {
1844 GraphBuffer
[i
] = (GraphBuffer
[i
] - ((max
+ min
)/2))*1000/
1848 RepaintGraphWindow();
1851 static void CmdAmp(char *str
)
1853 int i
, rising
, falling
;
1854 int max
= INT_MIN
, min
= INT_MAX
;
1855 for(i
= 10; i
< GraphTraceLen
; i
++) {
1856 if(GraphBuffer
[i
] > max
) {
1857 max
= GraphBuffer
[i
];
1859 if(GraphBuffer
[i
] < min
) {
1860 min
= GraphBuffer
[i
];
1865 for(i
= 0; i
< GraphTraceLen
; i
++) {
1866 if(GraphBuffer
[i
+1] < GraphBuffer
[i
]) {
1868 GraphBuffer
[i
]= max
;
1873 if(GraphBuffer
[i
+1] > GraphBuffer
[i
]) {
1875 GraphBuffer
[i
]= min
;
1882 RepaintGraphWindow();
1885 static void CmdDec(char *str
)
1888 for(i
= 0; i
< (GraphTraceLen
/2); i
++) {
1889 GraphBuffer
[i
] = GraphBuffer
[i
*2];
1892 PrintToScrollback("decimated by 2");
1893 RepaintGraphWindow();
1896 static void CmdHpf(char *str
)
1900 for(i
= 10; i
< GraphTraceLen
; i
++) {
1901 accum
+= GraphBuffer
[i
];
1903 accum
/= (GraphTraceLen
- 10);
1904 for(i
= 0; i
< GraphTraceLen
; i
++) {
1905 GraphBuffer
[i
] -= accum
;
1908 RepaintGraphWindow();
1911 static void CmdZerocrossings(char *str
)
1917 // Zero-crossings aren't meaningful unless the signal is zero-mean.
1920 for(i
= 0; i
< GraphTraceLen
; i
++) {
1921 if(GraphBuffer
[i
]*sign
>= 0) {
1922 // No change in sign, reproduce the previous sample count.
1924 GraphBuffer
[i
] = lastZc
;
1926 // Change in sign, reset the sample count.
1928 GraphBuffer
[i
] = lastZc
;
1936 RepaintGraphWindow();
1939 static void CmdThreshold(char *str
)
1942 int threshold
= atoi(str
);
1944 for(i
= 0; i
< GraphTraceLen
; i
++) {
1945 if(GraphBuffer
[i
]>= threshold
)
1950 RepaintGraphWindow();
1953 static void CmdLtrim(char *str
)
1958 for(i
= ds
; i
< GraphTraceLen
; i
++) {
1959 GraphBuffer
[i
-ds
] = GraphBuffer
[i
];
1961 GraphTraceLen
-= ds
;
1963 RepaintGraphWindow();
1966 static void CmdAutoCorr(char *str
)
1968 static int CorrelBuffer
[MAX_GRAPH_TRACE_LEN
];
1971 int window
= atoi(str
);
1974 PrintToScrollback("needs a window");
1978 if(window
>= GraphTraceLen
) {
1979 PrintToScrollback("window must be smaller than trace (%d samples)",
1984 PrintToScrollback("performing %d correlations", GraphTraceLen
- window
);
1986 for(i
= 0; i
< GraphTraceLen
- window
; i
++) {
1989 for(j
= 0; j
< window
; j
++) {
1990 sum
+= (GraphBuffer
[j
]*GraphBuffer
[i
+j
]) / 256;
1992 CorrelBuffer
[i
] = sum
;
1994 GraphTraceLen
= GraphTraceLen
- window
;
1995 memcpy(GraphBuffer
, CorrelBuffer
, GraphTraceLen
*sizeof(int));
1997 RepaintGraphWindow();
2000 static void CmdVchdemod(char *str
)
2002 // Is this the entire sync pattern, or does this also include some
2003 // data bits that happen to be the same everywhere? That would be
2005 static const int SyncPattern
[] = {
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,
2012 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
2013 1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
2014 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
2015 1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
2018 // So first, we correlate for the sync pattern, and mark that.
2019 int bestCorrel
= 0, bestPos
= 0;
2022 int worst
= INT_MAX
;
2025 // It does us no good to find the sync pattern, with fewer than
2026 // 2048 samples after it...
2027 for(i
= 0; i
< (GraphTraceLen
-2048); i
++) {
2030 for(j
= 0; j
< arraylen(SyncPattern
); j
++) {
2031 sum
+= GraphBuffer
[i
+j
]*SyncPattern
[j
];
2033 if(sum
> bestCorrel
) {
2038 PrintToScrollback("best sync at %d [metric %d]", bestPos
, bestCorrel
);
2042 for(i
= 0; i
< 2048; i
+= 8) {
2045 for(j
= 0; j
< 8; j
++) {
2046 sum
+= GraphBuffer
[bestPos
+i
+j
];
2053 if(abs(sum
) < worst
) {
2058 PrintToScrollback("bits:");
2059 PrintToScrollback("%s", bits
);
2060 PrintToScrollback("worst metric: %d at pos %d", worst
, worstPos
);
2062 if(strcmp(str
, "clone")==0) {
2065 for(s
= bits
; *s
; s
++) {
2067 for(j
= 0; j
< 16; j
++) {
2068 GraphBuffer
[GraphTraceLen
++] = (*s
== '1') ? 1 : 0;
2071 RepaintGraphWindow();
2075 static void CmdIndalademod(char *str
)
2077 // Usage: recover 64bit UID by default, specify "224" as arg to recover a 224bit UID
2082 int uidlen
, long_wait
;
2083 // worst case with GraphTraceLen=64000 is < 4096
2084 // under normal conditions it's < 2048
2085 uint8_t rawbits
[4096];
2087 int worst
= 0, worstPos
= 0;
2096 PrintToScrollback("Expecting a bit less than %d raw bits", GraphTraceLen
/32);
2097 for(i
= 0; i
< GraphTraceLen
-1; i
+= 2) {
2099 if((GraphBuffer
[i
] > GraphBuffer
[i
+ 1]) && (state
!= 1)) {
2101 for(j
= 0; j
< count
- 8; j
+= 16) {
2102 rawbits
[rawbit
++] = 0;
2104 if ((abs(count
- j
)) > worst
) {
2105 worst
= abs(count
- j
);
2111 } else if((GraphBuffer
[i
] < GraphBuffer
[i
+ 1]) && (state
!= 0)) {
2113 for(j
= 0; j
< count
- 8; j
+= 16) {
2114 rawbits
[rawbit
++] = 1;
2116 if ((abs(count
- j
)) > worst
) {
2117 worst
= abs(count
- j
);
2125 PrintToScrollback("Recovered %d raw bits", rawbit
);
2126 PrintToScrollback("worst metric (0=best..7=worst): %d at pos %d", worst
, worstPos
);
2128 // Finding the start of a UID
2129 if(strcmp(str
, "224") == 0) {
2136 for(start
= 0; start
<= rawbit
- uidlen
; start
++) {
2137 first
= rawbits
[start
];
2138 for(i
= start
; i
< start
+ long_wait
; i
++) {
2139 if(rawbits
[i
] != first
) {
2143 if(i
== (start
+ long_wait
)) {
2147 if(start
== rawbit
- uidlen
+ 1) {
2148 PrintToScrollback("nothing to wait for");
2152 // Inverting signal if needed
2154 for(i
= start
; i
< rawbit
; i
++) {
2155 rawbits
[i
] = !rawbits
[i
];
2160 showbits
[uidlen
]='\0';
2162 if(uidlen
> rawbit
) {
2163 PrintToScrollback("Warning: not enough raw bits to get a full UID");
2164 for(bit
= 0; bit
< rawbit
; bit
++) {
2165 bits
[bit
] = rawbits
[i
++];
2166 // As we cannot know the parity, let's use "." and "/"
2167 showbits
[bit
] = '.' + bits
[bit
];
2169 showbits
[bit
+1]='\0';
2170 PrintToScrollback("Partial UID=%s", showbits
);
2173 for(bit
= 0; bit
< uidlen
; bit
++) {
2174 bits
[bit
] = rawbits
[i
++];
2175 showbits
[bit
] = '0' + bits
[bit
];
2179 PrintToScrollback("UID=%s", showbits
);
2181 // Checking UID against next occurences
2182 for(; i
+ uidlen
<= rawbit
;) {
2184 for(bit
= 0; bit
< uidlen
; bit
++) {
2185 if(bits
[bit
] != rawbits
[i
++]) {
2195 PrintToScrollback("Occurences: %d (expected %d)", times
, (rawbit
- start
) / uidlen
);
2197 // Remodulating for tag cloning
2198 GraphTraceLen
= 32*uidlen
;
2200 for(bit
= 0; bit
< uidlen
; bit
++) {
2202 if(bits
[bit
] == 0) {
2207 for(j
= 0; j
< 32; j
++) {
2208 GraphBuffer
[i
++] = phase
;
2213 RepaintGraphWindow();
2216 static void CmdFlexdemod(char *str
)
2225 for(i
= 0; i
< GraphTraceLen
; i
++) {
2226 if(GraphBuffer
[i
] < 0) {
2227 GraphBuffer
[i
] = -1;
2233 #define LONG_WAIT 100
2234 for(start
= 0; start
< GraphTraceLen
- LONG_WAIT
; start
++) {
2235 int first
= GraphBuffer
[start
];
2236 for(i
= start
; i
< start
+ LONG_WAIT
; i
++) {
2237 if(GraphBuffer
[i
] != first
) {
2241 if(i
== (start
+ LONG_WAIT
)) {
2245 if(start
== GraphTraceLen
- LONG_WAIT
) {
2246 PrintToScrollback("nothing to wait for");
2250 GraphBuffer
[start
] = 2;
2251 GraphBuffer
[start
+1] = -2;
2254 for(bit
= 0; bit
< 64; bit
++) {
2257 for(j
= 0; j
< 16; j
++) {
2258 sum
+= GraphBuffer
[i
++];
2265 PrintToScrollback("bit %d sum %d", bit
, sum
);
2268 for(bit
= 0; bit
< 64; bit
++) {
2271 for(j
= 0; j
< 16; j
++) {
2272 sum
+= GraphBuffer
[i
++];
2274 if(sum
> 0 && bits
[bit
] != 1) {
2275 PrintToScrollback("oops1 at %d", bit
);
2277 if(sum
< 0 && bits
[bit
] != 0) {
2278 PrintToScrollback("oops2 at %d", bit
);
2282 GraphTraceLen
= 32*64;
2284 for(bit
= 0; bit
< 64; bit
++) {
2286 if(bits
[bit
] == 0) {
2291 for(j
= 0; j
< 32; j
++) {
2292 GraphBuffer
[i
++] = phase
;
2297 RepaintGraphWindow();
2301 * Generic command to demodulate ASK.
2303 * Argument is convention: positive or negative (High mod means zero
2304 * or high mod means one)
2306 * Updates the Graph trace with 0/1 values
2312 static void Cmdaskdemod(char *str
) {
2314 int c
, high
= 0, low
= 0;
2316 // TODO: complain if we do not give 2 arguments here !
2317 // (AL - this doesn't make sense! we're only using one argument!!!)
2318 sscanf(str
, "%i", &c
);
2320 /* Detect high and lows and clock */
2322 for (i
= 0; i
< GraphTraceLen
; i
++)
2324 if (GraphBuffer
[i
] > high
)
2325 high
= GraphBuffer
[i
];
2326 else if (GraphBuffer
[i
] < low
)
2327 low
= GraphBuffer
[i
];
2329 if(c
!= 0 && c
!= 1) {
2330 PrintToScrollback("Invalid argument: %s",str
);
2334 if (GraphBuffer
[0] > 0) {
2335 GraphBuffer
[0] = 1-c
;
2339 for(i
=1;i
<GraphTraceLen
;i
++) {
2340 /* Transitions are detected at each peak
2341 * Transitions are either:
2342 * - we're low: transition if we hit a high
2343 * - we're high: transition if we hit a low
2344 * (we need to do it this way because some tags keep high or
2345 * low for long periods, others just reach the peak and go
2348 if ((GraphBuffer
[i
]==high
) && (GraphBuffer
[i
-1] == c
)) {
2350 } else if ((GraphBuffer
[i
]==low
) && (GraphBuffer
[i
-1] == (1-c
))){
2354 GraphBuffer
[i
] = GraphBuffer
[i
-1];
2357 RepaintGraphWindow();
2360 /* Print our clock rate */
2361 static void Cmddetectclockrate(char *str
)
2363 int clock
= detectclock(0);
2364 PrintToScrollback("Auto-detected clock rate: %d", clock
);
2370 int detectclock(int peak
)
2376 /* Detect peak if we don't have one */
2378 for (i
= 0; i
< GraphTraceLen
; i
++)
2379 if (GraphBuffer
[i
] > peak
)
2380 peak
= GraphBuffer
[i
];
2382 for (i
= 1; i
< GraphTraceLen
; i
++)
2384 /* If this is the beginning of a peak */
2385 if (GraphBuffer
[i
-1] != GraphBuffer
[i
] && GraphBuffer
[i
] == peak
)
2387 /* Find lowest difference between peaks */
2388 if (lastpeak
&& i
- lastpeak
< clock
)
2390 clock
= i
- lastpeak
;
2399 /* Get or auto-detect clock rate */
2400 int GetClock(char *str
, int peak
)
2404 sscanf(str
, "%i", &clock
);
2405 if (!strcmp(str
, ""))
2408 /* Auto-detect clock */
2411 clock
= detectclock(peak
);
2413 /* Only print this message if we're not looping something */
2415 PrintToScrollback("Auto-detected clock rate: %d", clock
);
2422 * Convert to a bitstream
2424 static void Cmdbitstream(char *str
) {
2431 int hithigh
, hitlow
, first
;
2433 /* Detect high and lows and clock */
2434 for (i
= 0; i
< GraphTraceLen
; i
++)
2436 if (GraphBuffer
[i
] > high
)
2437 high
= GraphBuffer
[i
];
2438 else if (GraphBuffer
[i
] < low
)
2439 low
= GraphBuffer
[i
];
2443 clock
= GetClock(str
, high
);
2445 gtl
= CmdClearGraph(0);
2448 for (i
= 0; i
< (int)(gtl
/ clock
); i
++)
2454 /* Find out if we hit both high and low peaks */
2455 for (j
= 0; j
< clock
; j
++)
2457 if (GraphBuffer
[(i
* clock
) + j
] == high
)
2459 else if (GraphBuffer
[(i
* clock
) + j
] == low
)
2462 /* it doesn't count if it's the first part of our read
2463 because it's really just trailing from the last sequence */
2464 if (first
&& (hithigh
|| hitlow
))
2465 hithigh
= hitlow
= 0;
2469 if (hithigh
&& hitlow
)
2473 /* If we didn't hit both high and low peaks, we had a bit transition */
2474 if (!hithigh
|| !hitlow
)
2477 CmdAppendGraph(0, clock
, bit
);
2478 // for (j = 0; j < (int)(clock/2); j++)
2479 // GraphBuffer[(i * clock) + j] = bit ^ 1;
2480 // for (j = (int)(clock/2); j < clock; j++)
2481 // GraphBuffer[(i * clock) + j] = bit;
2484 RepaintGraphWindow();
2487 /* Modulate our data into manchester */
2488 static void Cmdmanchestermod(char *str
)
2492 int bit
, lastbit
, wave
;
2495 clock
= GetClock(str
, 0);
2499 for (i
= 0; i
< (int)(GraphTraceLen
/ clock
); i
++)
2501 bit
= GraphBuffer
[i
* clock
] ^ 1;
2503 for (j
= 0; j
< (int)(clock
/2); j
++)
2504 GraphBuffer
[(i
* clock
) + j
] = bit
^ lastbit
^ wave
;
2505 for (j
= (int)(clock
/2); j
< clock
; j
++)
2506 GraphBuffer
[(i
* clock
) + j
] = bit
^ lastbit
^ wave
^ 1;
2508 /* Keep track of how we start our wave and if we changed or not this time */
2509 wave
^= bit
^ lastbit
;
2513 RepaintGraphWindow();
2517 * Manchester demodulate a bitstream. The bitstream needs to be already in
2518 * the GraphBuffer as 0 and 1 values
2520 * Give the clock rate as argument in order to help the sync - the algorithm
2521 * resyncs at each pulse anyway.
2523 * Not optimized by any means, this is the 1st time I'm writing this type of
2524 * routine, feel free to improve...
2526 * 1st argument: clock rate (as number of samples per clock rate)
2527 * Typical values can be 64, 32, 128...
2529 static void Cmdmanchesterdemod(char *str
) {
2530 int i
, j
, invert
= 0;
2536 int hithigh
, hitlow
, first
;
2542 /* Holds the decoded bitstream: each clock period contains 2 bits */
2543 /* later simplified to 1 bit after manchester decoding. */
2544 /* Add 10 bits to allow for noisy / uncertain traces without aborting */
2545 /* int BitStream[GraphTraceLen*2/clock+10]; */
2547 /* But it does not work if compiling on WIndows: therefore we just allocate a */
2549 int BitStream
[MAX_GRAPH_TRACE_LEN
];
2552 /* check if we're inverting output */
2555 PrintToScrollback("Inverting output");
2559 while(*str
== ' '); // in case a 2nd argument was given
2562 /* Detect high and lows */
2563 for (i
= 0; i
< GraphTraceLen
; i
++)
2565 if (GraphBuffer
[i
] > high
)
2566 high
= GraphBuffer
[i
];
2567 else if (GraphBuffer
[i
] < low
)
2568 low
= GraphBuffer
[i
];
2572 clock
= GetClock(str
, high
);
2574 tolerance
= clock
/4;
2576 /* Detect first transition */
2577 /* Lo-Hi (arbitrary) */
2578 /* skip to the first high */
2579 for (i
= 0; i
< GraphTraceLen
; i
++)
2580 if(GraphBuffer
[i
] == high
)
2582 /* now look for the first low */
2583 for (; i
< GraphTraceLen
; i
++)
2585 if (GraphBuffer
[i
] == low
)
2592 /* If we're not working with 1/0s, demod based off clock */
2595 bit
= 0; /* We assume the 1st bit is zero, it may not be
2596 * the case: this routine (I think) has an init problem.
2599 for (; i
< (int)(GraphTraceLen
/ clock
); i
++)
2605 /* Find out if we hit both high and low peaks */
2606 for (j
= 0; j
< clock
; j
++)
2608 if (GraphBuffer
[(i
* clock
) + j
] == high
)
2610 else if (GraphBuffer
[(i
* clock
) + j
] == low
)
2613 /* it doesn't count if it's the first part of our read
2614 because it's really just trailing from the last sequence */
2615 if (first
&& (hithigh
|| hitlow
))
2616 hithigh
= hitlow
= 0;
2620 if (hithigh
&& hitlow
)
2624 /* If we didn't hit both high and low peaks, we had a bit transition */
2625 if (!hithigh
|| !hitlow
)
2628 BitStream
[bit2idx
++] = bit
^ invert
;
2632 /* standard 1/0 bitstream */
2636 /* Then detect duration between 2 successive transitions */
2637 for (bitidx
= 1; i
< GraphTraceLen
; i
++)
2639 if (GraphBuffer
[i
-1] != GraphBuffer
[i
])
2644 // Error check: if bitidx becomes too large, we do not
2645 // have a Manchester encoded bitstream or the clock is really
2647 if (bitidx
> (GraphTraceLen
*2/clock
+8) ) {
2648 PrintToScrollback("Error: the clock you gave is probably wrong, aborting.");
2651 // Then switch depending on lc length:
2652 // Tolerance is 1/4 of clock rate (arbitrary)
2653 if (abs(lc
-clock
/2) < tolerance
) {
2654 // Short pulse : either "1" or "0"
2655 BitStream
[bitidx
++]=GraphBuffer
[i
-1];
2656 } else if (abs(lc
-clock
) < tolerance
) {
2657 // Long pulse: either "11" or "00"
2658 BitStream
[bitidx
++]=GraphBuffer
[i
-1];
2659 BitStream
[bitidx
++]=GraphBuffer
[i
-1];
2663 PrintToScrollback("Warning: Manchester decode error for pulse width detection.");
2664 PrintToScrollback("(too many of those messages mean either the stream is not Manchester encoded, or clock is wrong)");
2668 PrintToScrollback("Error: too many detection errors, aborting.");
2675 // At this stage, we now have a bitstream of "01" ("1") or "10" ("0"), parse it into final decoded bitstream
2676 // Actually, we overwrite BitStream with the new decoded bitstream, we just need to be careful
2677 // to stop output at the final bitidx2 value, not bitidx
2678 for (i
= 0; i
< bitidx
; i
+= 2) {
2679 if ((BitStream
[i
] == 0) && (BitStream
[i
+1] == 1)) {
2680 BitStream
[bit2idx
++] = 1 ^ invert
;
2681 } else if ((BitStream
[i
] == 1) && (BitStream
[i
+1] == 0)) {
2682 BitStream
[bit2idx
++] = 0 ^ invert
;
2684 // We cannot end up in this state, this means we are unsynchronized,
2688 PrintToScrollback("Unsynchronized, resync...");
2689 PrintToScrollback("(too many of those messages mean the stream is not Manchester encoded)");
2693 PrintToScrollback("Error: too many decode errors, aborting.");
2700 PrintToScrollback("Manchester decoded bitstream");
2701 // Now output the bitstream to the scrollback by line of 16 bits
2702 for (i
= 0; i
< (bit2idx
-16); i
+=16) {
2703 PrintToScrollback("%i %i %i %i %i %i %i %i %i %i %i %i %i %i %i %i",
2726 static void CmdHiddemod(char *str
)
2729 if(GraphTraceLen
< 4800) {
2730 PrintToScrollback("too short; need at least 4800 samples");
2734 GraphTraceLen
= 4800;
2735 for(i
= 0; i
< GraphTraceLen
; i
++) {
2736 if(GraphBuffer
[i
] < 0) {
2742 RepaintGraphWindow();
2745 static void CmdPlot(char *str
)
2750 static void CmdGrid(char *str
)
2752 sscanf(str
, "%i %i", &PlotGridX
, &PlotGridY
);
2753 RepaintGraphWindow();
2756 static void CmdHide(char *str
)
2761 static void CmdScale(char *str
)
2763 CursorScaleFactor
= atoi(str
);
2764 if(CursorScaleFactor
== 0) {
2765 PrintToScrollback("bad, can't have zero scale");
2766 CursorScaleFactor
= 1;
2768 RepaintGraphWindow();
2771 static void CmdSave(char *str
)
2774 FILE *f
= fopen(str
, "w");
2776 PrintToScrollback("couldn't open '%s'", str
);
2779 for(i
= 0; i
< GraphTraceLen
; i
++) {
2780 fprintf(f
, "%d\n", GraphBuffer
[i
]);
2783 PrintToScrollback("saved to '%s'", str
);
2786 static void CmdLoad(char *str
)
2789 FILE *f
= fopen(str
, "r");
2791 PrintToScrollback("couldn't open '%s'", str
);
2796 while(fgets(line
, sizeof(line
), f
)) {
2797 GraphBuffer
[GraphTraceLen
] = atoi(line
);
2801 PrintToScrollback("loaded %d samples", GraphTraceLen
);
2802 RepaintGraphWindow();
2805 static void CmdHIDsimTAG(char *str
)
2807 unsigned int hi
=0, lo
=0;
2811 while (sscanf(&str
[i
++], "%1x", &n
) == 1) {
2812 hi
=(hi
<<4)|(lo
>>28);
2816 PrintToScrollback("Emulating tag with ID %x%16x", hi
, lo
);
2818 c
.cmd
= CMD_HID_SIM_TAG
;
2821 SendCommand(&c
, false);
2824 static void CmdReadmem(char *str
)
2827 c
.cmd
= CMD_READ_MEM
;
2828 c
.arg
[0] = atoi(str
);
2829 SendCommand(&c
, false);
2832 static void CmdVersion(char *str
)
2835 c
.cmd
= CMD_VERSION
;
2836 SendCommand(&c
, false);
2839 static void CmdLcdReset(char *str
)
2842 c
.cmd
= CMD_LCD_RESET
;
2843 c
.arg
[0] = atoi(str
);
2844 SendCommand(&c
, false);
2847 static void CmdLcd(char *str
)
2852 sscanf(str
, "%x %d", &i
, &j
);
2855 SendCommand(&c
, false);
2860 * Sets the divisor for LF frequency clock: lets the user choose any LF frequency below
2863 static void CmdSetDivisor(char *str
)
2866 c
.cmd
= CMD_SET_LF_DIVISOR
;
2867 c
.arg
[0] = atoi(str
);
2868 if (( c
.arg
[0]<0) || (c
.arg
[0]>255)) {
2869 PrintToScrollback("divisor must be between 19 and 255");
2871 SendCommand(&c
, false);
2872 PrintToScrollback("Divisor set, expected freq=%dHz", 12000000/(c
.arg
[0]+1));
2876 static void CmdSetMux(char *str
)
2879 c
.cmd
= CMD_SET_ADC_MUX
;
2880 if(strcmp(str
, "lopkd") == 0) {
2882 } else if(strcmp(str
, "loraw") == 0) {
2884 } else if(strcmp(str
, "hipkd") == 0) {
2886 } else if(strcmp(str
, "hiraw") == 0) {
2889 SendCommand(&c
, false);
2892 typedef void HandlerFunction(char *cmdline
);
2894 /* in alphabetic order */
2897 HandlerFunction
*handler
;
2898 int offline
; // 1 if the command can be used when in offline mode
2900 } CommandTable
[] = {
2901 {"amp", CmdAmp
, 1, "Amplify peaks"},
2902 {"askdemod", Cmdaskdemod
, 1, "<0|1> -- Attempt to demodulate simple ASK tags"},
2903 {"autocorr", CmdAutoCorr
, 1, "<window length> -- Autocorrelation over window"},
2904 {"bitsamples", CmdBitsamples
, 0, "Get raw samples as bitstring"},
2905 {"bitstream", Cmdbitstream
, 1, "[clock rate] -- Convert waveform into a bitstream"},
2906 {"buffclear", CmdBuffClear
, 1, "Clear sample buffer and graph window"},
2907 {"dec", CmdDec
, 1, "Decimate samples"},
2908 {"detectclock", Cmddetectclockrate
, 1, "Detect clock rate"},
2909 {"detectreader", CmdDetectReader
, 0, "['l'|'h'] -- Detect external reader field (option 'l' or 'h' to limit to LF or HF)"},
2910 {"em410xsim", CmdEM410xsim
, 1, "<UID> -- Simulate EM410x tag"},
2911 {"em410xread", CmdEM410xread
, 1, "[clock rate] -- Extract ID from EM410x tag"},
2912 {"em410xwatch", CmdEM410xwatch
, 0, "Watches for EM410x tags"},
2913 {"em4x50read", CmdEM4x50read
, 1, "Extract data from EM4x50 tag"},
2914 {"exit", CmdQuit
, 1, "Exit program"},
2915 {"flexdemod", CmdFlexdemod
, 1, "Demodulate samples for FlexPass"},
2916 {"fpgaoff", CmdFPGAOff
, 0, "Set FPGA off"},
2917 {"fskdemod", CmdFSKdemod
, 1, "Demodulate graph window as a HID FSK"},
2918 {"grid", CmdGrid
, 1, "<x> <y> -- overlay grid on graph window, use zero value to turn off either"},
2919 {"hexsamples", CmdHexsamples
, 0, "<blocks> -- Dump big buffer as hex bytes"},
2920 {"hi14alist", CmdHi14alist
, 0, "List ISO 14443a history"},
2921 {"hi14areader", CmdHi14areader
, 0, "Act like an ISO14443 Type A reader"},
2922 {"hi14asim", CmdHi14asim
, 0, "<UID> -- Fake ISO 14443a tag"},
2923 {"hi14asnoop", CmdHi14asnoop
, 0, "Eavesdrop ISO 14443 Type A"},
2924 {"hi14bdemod", CmdHi14bdemod
, 1, "Demodulate ISO14443 Type B from tag"},
2925 {"hi14list", CmdHi14list
, 0, "List ISO 14443 history"},
2926 {"hi14read", CmdHi14read
, 0, "Read HF tag (ISO 14443)"},
2927 {"hi14sim", CmdHi14sim
, 0, "Fake ISO 14443 tag"},
2928 {"hi14snoop", CmdHi14snoop
, 0, "Eavesdrop ISO 14443"},
2929 {"hi15demod", CmdHi15demod
, 1, "Demodulate ISO15693 from tag"},
2930 {"hi15read", CmdHi15read
, 0, "Read HF tag (ISO 15693)"},
2931 {"hi15reader", CmdHi15reader
, 0, "Act like an ISO15693 reader"},
2932 {"hi15sim", CmdHi15tag
, 0, "Fake an ISO15693 tag"},
2933 {"hiddemod", CmdHiddemod
, 1, "Demodulate HID Prox Card II (not optimal)"},
2934 {"hide", CmdHide
, 1, "Hide graph window"},
2935 {"hidfskdemod", CmdHIDdemodFSK
, 0, "Realtime HID FSK demodulator"},
2936 {"hidsimtag", CmdHIDsimTAG
, 0, "<ID> -- HID tag simulator"},
2937 {"higet", CmdHi14read_sim
, 0, "<samples> -- Get samples HF, 'analog'"},
2938 {"hisamples", CmdHisamples
, 0, "Get raw samples for HF tag"},
2939 {"hisampless", CmdHisampless
, 0, "<samples> -- Get signed raw samples, HF tag"},
2940 {"hisamplest", CmdHi14readt
, 0, "Get samples HF, for testing"},
2941 {"hisimlisten", CmdHisimlisten
, 0, "Get HF samples as fake tag"},
2942 {"hpf", CmdHpf
, 1, "Remove DC offset from trace"},
2943 {"indalademod", CmdIndalademod
, 0, "['224'] -- Demodulate samples for Indala 64 bit UID (option '224' for 224 bit)"},
2944 {"lcd", CmdLcd
, 0, "<HEX command> <count> -- Send command/data to LCD"},
2945 {"lcdreset", CmdLcdReset
, 0, "Hardware reset LCD"},
2946 {"legicrfsim", CmdLegicRfSim
, 0, "Start the LEGIC RF tag simulator"},
2947 {"legicrfread", CmdLegicRfRead
, 0, "Start the LEGIC RF reader"},
2948 {"load", CmdLoad
, 1, "<filename> -- Load trace (to graph window"},
2949 {"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)"},
2950 {"loread", CmdLoread
, 0, "['h'] -- Read 125/134 kHz LF ID-only tag (option 'h' for 134)"},
2951 {"losamples", CmdLosamples
, 0, "[128 - 16000] -- Get raw samples for LF tag"},
2952 {"losim", CmdLosim
, 0, "Simulate LF tag"},
2953 {"losimbidir", CmdLosimBidir
, 0, "Simulate LF tag (with bidirectional data transmission between reader and tag)"},
2954 {"ltrim", CmdLtrim
, 1, "<samples> -- Trim samples from left of trace"},
2955 {"mandemod", Cmdmanchesterdemod
, 1, "[i] [clock rate] -- Manchester demodulate binary stream (option 'i' to invert output)"},
2956 {"manmod", Cmdmanchestermod
, 1, "[clock rate] -- Manchester modulate a binary stream"},
2957 {"norm", CmdNorm
, 1, "Normalize max/min to +/-500"},
2958 {"plot", CmdPlot
, 1, "Show graph window"},
2959 {"quit", CmdQuit
, 1, "Quit program"},
2960 {"readmem", CmdReadmem
, 0, "[address] -- Read memory at decimal address from flash"},
2961 {"reset", CmdReset
, 0, "Reset the Proxmark3"},
2962 {"save", CmdSave
, 1, "<filename> -- Save trace (from graph window)"},
2963 {"scale", CmdScale
, 1, "<int> -- Set cursor display scale"},
2964 {"setlfdivisor", CmdSetDivisor
, 0, "<19 - 255> -- Drive LF antenna at 12Mhz/(divisor+1)"},
2965 {"setmux", CmdSetMux
, 0, "<loraw|hiraw|lopkd|hipkd> -- Set the ADC mux to a specific value"},
2966 {"sri512read", CmdSri512read
, 0, "<int> -- Read contents of a SRI512 tag"},
2967 {"srix4kread", CmdSrix4kread
, 0, "<int> -- Read contents of a SRIX4K tag"},
2968 {"tidemod", CmdTIDemod
, 1, "Demodulate raw bits for TI-type LF tag"},
2969 {"tiread", CmdTIRead
, 0, "Read and decode a TI 134 kHz tag"},
2970 {"tiwrite", CmdTIWrite
, 0, "Write new data to a r/w TI 134 kHz tag"},
2971 {"threshold", CmdThreshold
, 1, "Maximize/minimize every value in the graph window depending on threshold"},
2972 {"tune", CmdTune
, 0, "Measure antenna tuning"},
2973 {"vchdemod", CmdVchdemod
, 0, "['clone'] -- Demodulate samples for VeriChip"},
2974 {"version", CmdVersion
, 0, "Show version inforation about the connected Proxmark"},
2975 {"zerocrossings", CmdZerocrossings
, 1, "Count time between zero-crossings"},
2983 } CommandExtendedHelp
[]= {
2984 {"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."},
2985 {"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."},
2988 //-----------------------------------------------------------------------------
2989 // Entry point into our code: called whenever the user types a command and
2990 // then presses Enter, which the full command line that they typed.
2991 //-----------------------------------------------------------------------------
2992 void CommandReceived(char *cmd
)
2997 PrintToScrollback("> %s", cmd
);
2999 if(strcmp(cmd
, "help") == 0 || strncmp(cmd
,"help ",strlen("help ")) == 0) {
3000 // check if we're doing extended help
3001 if(strlen(cmd
) > strlen("help ")) {
3002 cmd
+= strlen("help ");
3003 for(i
= 0; i
< sizeof(CommandExtendedHelp
) / sizeof(CommandExtendedHelp
[0]); i
++) {
3004 if(strcmp(CommandExtendedHelp
[i
].name
,cmd
) == 0) {
3005 PrintToScrollback("\nExtended help for '%s':\n", cmd
);
3006 PrintToScrollback("Args: %s\t- %s\n",CommandExtendedHelp
[i
].args
,CommandExtendedHelp
[i
].argshelp
);
3007 PrintToScrollback(CommandExtendedHelp
[i
].description
);
3008 PrintToScrollback("");
3012 PrintToScrollback("No extended help available for '%s'", cmd
);
3015 if (offline
) PrintToScrollback("Operating in OFFLINE mode (no device connected)");
3016 PrintToScrollback("\r\nAvailable commands:");
3017 for(i
= 0; i
< sizeof(CommandTable
) / sizeof(CommandTable
[0]); i
++) {
3018 if (offline
&& (CommandTable
[i
].offline
==0)) continue;
3019 memset(line
, ' ', sizeof(line
));
3020 strcpy(line
+2, CommandTable
[i
].name
);
3021 line
[strlen(line
)] = ' ';
3022 sprintf(line
+15, " -- %s", CommandTable
[i
].docString
);
3023 PrintToScrollback("%s", line
);
3025 PrintToScrollback("");
3026 PrintToScrollback("'help <command>' for extended help on that command\n");
3030 for(i
= 0; i
< sizeof(CommandTable
) / sizeof(CommandTable
[0]); i
++) {
3031 char *name
= CommandTable
[i
].name
;
3032 if(memcmp(cmd
, name
, strlen(name
))==0 &&
3033 (cmd
[strlen(name
)] == ' ' || cmd
[strlen(name
)] == '\0'))
3035 cmd
+= strlen(name
);
3036 while(*cmd
== ' ') {
3039 if (offline
&& (CommandTable
[i
].offline
==0)) {
3040 PrintToScrollback("Offline mode, cannot use this command.");
3043 (CommandTable
[i
].handler
)(cmd
);
3047 PrintToScrollback(">> bad command '%s'", cmd
);
3050 //-----------------------------------------------------------------------------
3051 // Entry point into our code: called whenever we received a packet over USB
3052 // that we weren't necessarily expecting, for example a debug print.
3053 //-----------------------------------------------------------------------------
3054 void UsbCommandReceived(UsbCommand
*c
)
3057 case CMD_DEBUG_PRINT_STRING
: {
3059 if(c
->arg
[0] > 70 || c
->arg
[0] < 0) {
3062 memcpy(s
, c
->d
.asBytes
, c
->arg
[0]);
3063 s
[c
->arg
[0]] = '\0';
3064 PrintToScrollback("#db# %s", s
);
3068 case CMD_DEBUG_PRINT_INTEGERS
:
3069 PrintToScrollback("#db# %08x, %08x, %08x\r\n", c
->arg
[0], c
->arg
[1], c
->arg
[2]);
3072 case CMD_MEASURED_ANTENNA_TUNING
: {
3074 int vLf125
, vLf134
, vHf
;
3075 vLf125
= c
->arg
[0] & 0xffff;
3076 vLf134
= c
->arg
[0] >> 16;
3077 vHf
= c
->arg
[1] & 0xffff;;
3078 peakf
= c
->arg
[2] & 0xffff;
3079 peakv
= c
->arg
[2] >> 16;
3080 PrintToScrollback("");
3081 PrintToScrollback("");
3082 PrintToScrollback("# LF antenna: %5.2f V @ 125.00 kHz", vLf125
/1000.0);
3083 PrintToScrollback("# LF antenna: %5.2f V @ 134.00 kHz", vLf134
/1000.0);
3084 PrintToScrollback("# LF optimal: %5.2f V @%9.2f kHz", peakv
/1000.0, 12000.0/(peakf
+1));
3085 PrintToScrollback("# HF antenna: %5.2f V @ 13.56 MHz", vHf
/1000.0);
3087 PrintToScrollback("# Your LF antenna is unusable.");
3088 else if (peakv
<10000)
3089 PrintToScrollback("# Your LF antenna is marginal.");
3091 PrintToScrollback("# Your HF antenna is unusable.");
3093 PrintToScrollback("# Your HF antenna is marginal.");
3097 PrintToScrollback("unrecognized command %08x\n", c
->cmd
);