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 //-----------------------------------------------------------------------------
17 #include "../common/iso14443_crc.c"
18 #include "../common/crc16.c"
19 #include "../include/usb_cmd.h"
21 #define arraylen(x) (sizeof(x)/sizeof((x)[0]))
22 #define BIT(x) GraphBuffer[x * clock]
23 #define BITS (GraphTraceLen / clock)
24 #define SAMPLE_BUFFER_SIZE 64 // XXX check this
27 static int CmdHisamplest(char *str
, int nrlow
);
28 unsigned int current_command
= CMD_UNKNOWN
;
29 unsigned int received_command
= CMD_UNKNOWN
;
30 static uint8_t sample_buf
[SAMPLE_BUFFER_SIZE
];
32 void wait_for_response(uint32_t response_type
)
34 while (received_command
!= response_type
) {
37 if (ReceiveCommandPoll(&c
))
38 UsbCommandReceived(&c
);
41 usleep(10000); // XXX ugh
44 received_command
= CMD_UNKNOWN
;
47 static void GetFromBigBuf(uint8_t *dest
, int bytes
)
52 PrintToScrollback("bad len in GetFromBigBuf");
57 for(i
= 0; i
< n
; i
+= 12) {
58 UsbCommand c
= {CMD_DOWNLOAD_RAW_ADC_SAMPLES_125K
, {i
, 0, 0}};
60 wait_for_response(CMD_DOWNLOADED_RAW_ADC_SAMPLES_125K
);
62 memcpy(dest
+(i
*4), sample_buf
, 48);
66 static void CmdReset(char *str
)
68 UsbCommand c
= {CMD_HARDWARE_RESET
};
72 static void CmdBuffClear(char *str
)
74 UsbCommand c
= {CMD_BUFF_CLEAR
};
79 static void CmdQuit(char *str
)
84 static void CmdHIDdemodFSK(char *str
)
86 UsbCommand c
={CMD_HID_DEMOD_FSK
};
90 static void CmdTune(char *str
)
92 UsbCommand c
={CMD_MEASURE_ANTENNA_TUNING
};
96 static void CmdHiTune(char *str
)
98 UsbCommand c
={CMD_MEASURE_ANTENNA_TUNING_HF
};
102 static void CmdHi15read(char *str
)
104 UsbCommand c
={CMD_ACQUIRE_RAW_ADC_SAMPLES_ISO_15693
};
108 static void CmdHi14read(char *str
)
110 UsbCommand c
= {CMD_ACQUIRE_RAW_ADC_SAMPLES_ISO_14443
, {strtol(str
, NULL
, 0), 0, 0}};
115 /* New command to read the contents of a SRI512 tag
116 * SRI512 tags are ISO14443-B modulated memory tags,
117 * this command just dumps the contents of the memory
119 static void CmdSri512read(char *str
)
121 UsbCommand c
={CMD_READ_SRI512_TAG
, {strtol(str
, NULL
, 0), 0, 0}};
125 /* New command to read the contents of a SRIX4K tag
126 * SRIX4K tags are ISO14443-B modulated memory tags,
127 * this command just dumps the contents of the memory/
129 static void CmdSrix4kread(char *str
)
131 UsbCommand c
={CMD_READ_SRIX4K_TAG
, {strtol(str
, NULL
, 0), 0, 0}};
135 static void CmdHi14areader(char *str
)
137 UsbCommand c
={CMD_READER_ISO_14443a
, {strtol(str
, NULL
, 0), 0, 0}};
141 static void CmdHi14amifare(char *str
)
143 UsbCommand c
={CMD_READER_MIFARE
, {strtol(str
, NULL
, 0), 0, 0}};
147 static void CmdHi15reader(char *str
)
149 UsbCommand c
={CMD_READER_ISO_15693
, {strtol(str
, NULL
, 0), 0, 0}};
153 static void CmdHi15tag(char *str
)
155 UsbCommand c
={CMD_SIMTAG_ISO_15693
, {strtol(str
, NULL
, 0), 0, 0}};
159 static void CmdHi14read_sim(char *str
)
161 UsbCommand c
={CMD_ACQUIRE_RAW_ADC_SAMPLES_ISO_14443_SIM
, {strtol(str
, NULL
, 0), 0, 0}};
165 static void CmdHi14readt(char *str
)
167 UsbCommand c
={CMD_ACQUIRE_RAW_ADC_SAMPLES_ISO_14443
, {strtol(str
, NULL
, 0), 0, 0}};
170 //CmdHisamplest(str);
171 while(CmdHisamplest(str
,strtol(str
, NULL
, 0))==0) {
174 RepaintGraphWindow();
177 static void CmdHisimlisten(char *str
)
179 UsbCommand c
={CMD_SIMULATE_TAG_HF_LISTEN
};
183 static void CmdHi14sim(char *str
)
185 UsbCommand c
={CMD_SIMULATE_TAG_ISO_14443
};
189 static void CmdHi14asim(char *str
) // ## simulate iso14443a tag
190 { // ## greg - added ability to specify tag UID
192 unsigned int hi
=0, lo
=0;
194 while (sscanf(&str
[i
++], "%1x", &n
) == 1) {
199 // c.arg should be set to *str or convert *str to the correct format for a uid
200 UsbCommand c
= {CMD_SIMULATE_TAG_ISO_14443a
, {hi
, lo
, 0}};
201 PrintToScrollback("Emulating 14443A TAG with UID %x%16x", hi
, lo
);
205 static void CmdHi14snoop(char *str
)
207 UsbCommand c
={CMD_SNOOP_ISO_14443
};
211 static void CmdHi14asnoop(char *str
)
213 UsbCommand c
={CMD_SNOOP_ISO_14443a
};
217 static void CmdLegicRfRead(char *str
)
219 UsbCommand c
={CMD_READER_LEGIC_RF
};
223 static void CmdFPGAOff(char *str
) // ## FPGA Control
225 UsbCommand c
={CMD_FPGA_MAJOR_MODE_OFF
};
229 /* clear out our graph window */
230 int CmdClearGraph(int redraw
)
232 int gtl
= GraphTraceLen
;
236 RepaintGraphWindow();
241 /* write a bit to the graph */
242 static void CmdAppendGraph(int redraw
, int clock
, int bit
)
246 for (i
= 0; i
< (int)(clock
/2); i
++)
247 GraphBuffer
[GraphTraceLen
++] = bit
^ 1;
249 for (i
= (int)(clock
/2); i
< clock
; i
++)
250 GraphBuffer
[GraphTraceLen
++] = bit
;
253 RepaintGraphWindow();
256 /* Function is equivalent of loread + losamples + em410xread
257 * looped until an EM410x tag is detected */
258 static void CmdEM410xwatch(char *str
)
272 /* Read the transmitted data of an EM4x50 tag
275 * XXXXXXXX [row parity bit (even)] <- 8 bits plus parity
276 * XXXXXXXX [row parity bit (even)] <- 8 bits plus parity
277 * XXXXXXXX [row parity bit (even)] <- 8 bits plus parity
278 * XXXXXXXX [row parity bit (even)] <- 8 bits plus parity
279 * CCCCCCCC <- column parity bits
281 * LW <- Listen Window
283 * This pattern repeats for every block of data being transmitted.
284 * Transmission starts with two Listen Windows (LW - a modulated
285 * pattern of 320 cycles each (32/32/128/64/64)).
287 * Note that this data may or may not be the UID. It is whatever data
288 * is stored in the blocks defined in the control word First and Last
289 * Word Read values. UID is stored in block 32.
291 static void CmdEM4x50read(char *str
)
293 int i
, j
, startblock
, clock
, skip
, block
, start
, end
, low
, high
;
294 bool complete
= false;
295 int tmpbuff
[MAX_GRAPH_TRACE_LEN
/ 64];
301 /* first get high and low values */
302 for (i
= 0; i
< GraphTraceLen
; i
++)
304 if (GraphBuffer
[i
] > high
)
305 high
= GraphBuffer
[i
];
306 else if (GraphBuffer
[i
] < low
)
307 low
= GraphBuffer
[i
];
310 /* populate a buffer with pulse lengths */
313 while(i
< GraphTraceLen
)
315 // measure from low to low
316 while((GraphBuffer
[i
] > low
) && (i
<GraphTraceLen
))
319 while((GraphBuffer
[i
] < high
) && (i
<GraphTraceLen
))
321 while((GraphBuffer
[i
] > low
) && (i
<GraphTraceLen
))
323 if (j
>(MAX_GRAPH_TRACE_LEN
/64)) {
326 tmpbuff
[j
++]= i
- start
;
329 /* look for data start - should be 2 pairs of LW (pulses of 192,128) */
332 for (i
= 0; i
< j
- 4 ; ++i
)
335 if (tmpbuff
[i
] >= 190 && tmpbuff
[i
] <= 194)
336 if (tmpbuff
[i
+1] >= 126 && tmpbuff
[i
+1] <= 130)
337 if (tmpbuff
[i
+2] >= 190 && tmpbuff
[i
+2] <= 194)
338 if (tmpbuff
[i
+3] >= 126 && tmpbuff
[i
+3] <= 130)
346 /* skip over the remainder of the LW */
347 skip
+= tmpbuff
[i
+1]+tmpbuff
[i
+2];
348 while(skip
< MAX_GRAPH_TRACE_LEN
&& GraphBuffer
[skip
] > low
)
352 /* now do it again to find the end */
354 for (i
+= 3; i
< j
- 4 ; ++i
)
357 if (tmpbuff
[i
] >= 190 && tmpbuff
[i
] <= 194)
358 if (tmpbuff
[i
+1] >= 126 && tmpbuff
[i
+1] <= 130)
359 if (tmpbuff
[i
+2] >= 190 && tmpbuff
[i
+2] <= 194)
360 if (tmpbuff
[i
+3] >= 126 && tmpbuff
[i
+3] <= 130)
368 PrintToScrollback("Found data at sample: %i",skip
);
371 PrintToScrollback("No data found!");
372 PrintToScrollback("Try again with more samples.");
378 PrintToScrollback("*** Warning!");
379 PrintToScrollback("Partial data - no end found!");
380 PrintToScrollback("Try again with more samples.");
383 /* get rid of leading crap */
384 sprintf(tmp
,"%i",skip
);
387 /* now work through remaining buffer printing out data blocks */
392 PrintToScrollback("Block %i:", block
);
393 // mandemod routine needs to be split so we can call it for data
394 // just print for now for debugging
395 Cmdmanchesterdemod("i 64");
397 /* look for LW before start of next block */
398 for ( ; i
< j
- 4 ; ++i
)
401 if (tmpbuff
[i
] >= 190 && tmpbuff
[i
] <= 194)
402 if (tmpbuff
[i
+1] >= 126 && tmpbuff
[i
+1] <= 130)
405 while(GraphBuffer
[skip
] > low
)
408 sprintf(tmp
,"%i",skip
);
416 /* Read the ID of an EM410x tag.
418 * 1111 1111 1 <-- standard non-repeatable header
419 * XXXX [row parity bit] <-- 10 rows of 5 bits for our 40 bit tag ID
421 * CCCC <-- each bit here is parity for the 10 bits above in corresponding column
422 * 0 <-- stop bit, end of tag
424 static void CmdEM410xread(char *str
)
426 int i
, j
, clock
, header
, rows
, bit
, hithigh
, hitlow
, first
, bit2idx
, high
, low
;
430 int BitStream
[MAX_GRAPH_TRACE_LEN
];
433 /* Detect high and lows and clock */
434 for (i
= 0; i
< GraphTraceLen
; i
++)
436 if (GraphBuffer
[i
] > high
)
437 high
= GraphBuffer
[i
];
438 else if (GraphBuffer
[i
] < low
)
439 low
= GraphBuffer
[i
];
443 clock
= GetClock(str
, high
);
445 /* parity for our 4 columns */
446 parity
[0] = parity
[1] = parity
[2] = parity
[3] = 0;
449 /* manchester demodulate */
451 for (i
= 0; i
< (int)(GraphTraceLen
/ clock
); i
++)
457 /* Find out if we hit both high and low peaks */
458 for (j
= 0; j
< clock
; j
++)
460 if (GraphBuffer
[(i
* clock
) + j
] == high
)
462 else if (GraphBuffer
[(i
* clock
) + j
] == low
)
465 /* it doesn't count if it's the first part of our read
466 because it's really just trailing from the last sequence */
467 if (first
&& (hithigh
|| hitlow
))
468 hithigh
= hitlow
= 0;
472 if (hithigh
&& hitlow
)
476 /* If we didn't hit both high and low peaks, we had a bit transition */
477 if (!hithigh
|| !hitlow
)
480 BitStream
[bit2idx
++] = bit
;
484 /* We go till 5 before the graph ends because we'll get that far below */
485 for (i
= 1; i
< bit2idx
- 5; i
++)
487 /* Step 2: We have our header but need our tag ID */
488 if (header
== 9 && rows
< 10)
490 /* Confirm parity is correct */
491 if ((BitStream
[i
] ^ BitStream
[i
+1] ^ BitStream
[i
+2] ^ BitStream
[i
+3]) == BitStream
[i
+4])
493 /* Read another byte! */
494 sprintf(id
+rows
, "%x", (8 * BitStream
[i
]) + (4 * BitStream
[i
+1]) + (2 * BitStream
[i
+2]) + (1 * BitStream
[i
+3]));
497 /* Keep parity info */
498 parity
[0] ^= BitStream
[i
];
499 parity
[1] ^= BitStream
[i
+1];
500 parity
[2] ^= BitStream
[i
+2];
501 parity
[3] ^= BitStream
[i
+3];
503 /* Move 4 bits ahead */
507 /* Damn, something wrong! reset */
510 PrintToScrollback("Thought we had a valid tag but failed at word %d (i=%d)", rows
+ 1, i
);
512 /* Start back rows * 5 + 9 header bits, -1 to not start at same place */
513 i
-= 9 + (5 * rows
) - 5;
519 /* Step 3: Got our 40 bits! confirm column parity */
522 /* We need to make sure our 4 bits of parity are correct and we have a stop bit */
523 if (BitStream
[i
] == parity
[0] && BitStream
[i
+1] == parity
[1] &&
524 BitStream
[i
+2] == parity
[2] && BitStream
[i
+3] == parity
[3] &&
528 PrintToScrollback("EM410x Tag ID: %s", id
);
535 /* Crap! Incorrect parity or no stop bit, start all over */
540 /* Go back 59 bits (9 header bits + 10 rows at 4+1 parity) */
545 /* Step 1: get our header */
548 /* Need 9 consecutive 1's */
549 if (BitStream
[i
] == 1)
552 /* We don't have a header, not enough consecutive 1 bits */
558 /* if we've already retested after flipping bits, return */
562 /* if this didn't work, try flipping bits */
563 for (i
= 0; i
< bit2idx
; i
++)
569 /* emulate an EM410X tag
571 * 1111 1111 1 <-- standard non-repeatable header
572 * XXXX [row parity bit] <-- 10 rows of 5 bits for our 40 bit tag ID
574 * CCCC <-- each bit here is parity for the 10 bits above in corresponding column
575 * 0 <-- stop bit, end of tag
577 static void CmdEM410xsim(char *str
)
579 int i
, n
, j
, h
, binary
[4], parity
[4];
581 /* clock is 64 in EM410x tags */
584 /* clear our graph */
587 /* write it out a few times */
588 for (h
= 0; h
< 4; h
++)
590 /* write 9 start bits */
591 for (i
= 0; i
< 9; i
++)
592 CmdAppendGraph(0, clock
, 1);
594 /* for each hex char */
595 parity
[0] = parity
[1] = parity
[2] = parity
[3] = 0;
596 for (i
= 0; i
< 10; i
++)
598 /* read each hex char */
599 sscanf(&str
[i
], "%1x", &n
);
600 for (j
= 3; j
>= 0; j
--, n
/= 2)
603 /* append each bit */
604 CmdAppendGraph(0, clock
, binary
[0]);
605 CmdAppendGraph(0, clock
, binary
[1]);
606 CmdAppendGraph(0, clock
, binary
[2]);
607 CmdAppendGraph(0, clock
, binary
[3]);
609 /* append parity bit */
610 CmdAppendGraph(0, clock
, binary
[0] ^ binary
[1] ^ binary
[2] ^ binary
[3]);
612 /* keep track of column parity */
613 parity
[0] ^= binary
[0];
614 parity
[1] ^= binary
[1];
615 parity
[2] ^= binary
[2];
616 parity
[3] ^= binary
[3];
620 CmdAppendGraph(0, clock
, parity
[0]);
621 CmdAppendGraph(0, clock
, parity
[1]);
622 CmdAppendGraph(0, clock
, parity
[2]);
623 CmdAppendGraph(0, clock
, parity
[3]);
626 CmdAppendGraph(0, clock
, 0);
629 /* modulate that biatch */
630 Cmdmanchestermod("");
633 RepaintGraphWindow();
638 /* simulate an LF Manchester encoded tag with specified bitstream, clock rate and inter-id gap */
639 static void CmdLosimManchester(char *str
)
641 static int clock
, gap
;
642 static char data
[1024], gapstring
[8];
645 /* get settings/bits */
646 sscanf(str
, "%i %s %i", &clock
, &data
[0], &gap
);
648 /* clear our graph */
651 /* fill it with our bitstream */
652 for (i
= 0; i
< strlen(data
) ; ++i
)
653 CmdAppendGraph(0, clock
, data
[i
]- '0');
656 Cmdmanchestermod("");
658 /* show what we've done */
659 RepaintGraphWindow();
662 sprintf(&gapstring
[0], "%i", gap
);
666 static void ChkBitstream(char *str
)
670 /* convert to bitstream if necessary */
671 for (i
= 0; i
< (int)(GraphTraceLen
/ 2); i
++)
673 if (GraphBuffer
[i
] > 1 || GraphBuffer
[i
] < 0)
681 static void CmdLosim(char *str
)
686 sscanf(str
,"%i",&gap
);
688 /* convert to bitstream if necessary */
691 for (i
= 0; i
< GraphTraceLen
; i
+= 48) {
692 UsbCommand c
={CMD_DOWNLOADED_SIM_SAMPLES_125K
, {i
, 0, 0}};
694 for(j
= 0; j
< 48; j
++) {
695 c
.d
.asBytes
[j
] = GraphBuffer
[i
+j
];
700 UsbCommand c
={CMD_SIMULATE_TAG_125K
, {GraphTraceLen
, gap
, 0}};
704 static void CmdLosimBidir(char *str
)
706 /* Set ADC to twice the carrier for a slight supersampling */
707 UsbCommand c
={CMD_LF_SIMULATE_BIDIR
, {47, 384, 0}};
711 static void CmdLoread(char *str
)
713 UsbCommand c
={CMD_ACQUIRE_RAW_ADC_SAMPLES_125K
};
714 // 'h' means higher-low-frequency, 134 kHz
717 } else if (*str
== '\0') {
720 PrintToScrollback("use 'loread' or 'loread h'");
726 static void CmdDetectReader(char *str
)
728 UsbCommand c
={CMD_LISTEN_READER_FIELD
};
729 // 'l' means LF - 125/134 kHz
732 } else if (*str
== 'h') {
734 } else if (*str
!= '\0') {
735 PrintToScrollback("use 'detectreader' or 'detectreader l' or 'detectreader h'");
741 /* send a command before reading */
742 static void CmdLoCommandRead(char *str
)
744 static char dummy
[3];
748 UsbCommand c
={CMD_MOD_THEN_ACQUIRE_RAW_ADC_SAMPLES_125K
};
749 sscanf(str
, "%i %i %i %s %s", &c
.arg
[0], &c
.arg
[1], &c
.arg
[2], (char *) &c
.d
.asBytes
,(char *) &dummy
+1);
750 // in case they specified 'h'
751 strcpy((char *)&c
.d
.asBytes
+ strlen((char *)c
.d
.asBytes
), dummy
);
755 static void CmdLosamples(char *str
)
760 n
=strtol(str
, NULL
, 0);
762 if (n
>16000) n
=16000;
764 PrintToScrollback("Reading %d samples\n", n
);
765 for(i
= 0; i
< n
; i
+= 12) {
766 UsbCommand c
= {CMD_DOWNLOAD_RAW_ADC_SAMPLES_125K
, {i
, 0, 0}};
768 wait_for_response(CMD_DOWNLOADED_RAW_ADC_SAMPLES_125K
);
769 for(j
= 0; j
< 48; j
++) {
770 GraphBuffer
[cnt
++] = ((int)sample_buf
[j
]) - 128;
773 PrintToScrollback("Done!\n");
775 RepaintGraphWindow();
778 static void CmdBitsamples(char *str
)
784 for(i
= 0; i
< n
; i
+= 12) {
785 UsbCommand c
= {CMD_DOWNLOAD_RAW_ADC_SAMPLES_125K
, {i
, 0, 0}};
787 wait_for_response(CMD_DOWNLOADED_RAW_ADC_SAMPLES_125K
);
789 for(j
= 0; j
< 48; j
++) {
790 for(k
= 0; k
< 8; k
++) {
791 if(sample_buf
[j
] & (1 << (7 - k
))) {
792 GraphBuffer
[cnt
++] = 1;
794 GraphBuffer
[cnt
++] = 0;
800 RepaintGraphWindow();
803 static void CmdHisamples(char *str
)
809 for(i
= 0; i
< n
; i
+= 12) {
810 UsbCommand c
= {CMD_DOWNLOAD_RAW_ADC_SAMPLES_125K
, {i
, 0, 0}};
812 wait_for_response(CMD_DOWNLOADED_RAW_ADC_SAMPLES_125K
);
813 for(j
= 0; j
< 48; j
++) {
814 GraphBuffer
[cnt
++] = (int)(sample_buf
[j
]);
819 RepaintGraphWindow();
822 static int CmdHisamplest(char *str
, int nrlow
)
832 for(i
= 0; i
< n
; i
+= 12) {
833 UsbCommand c
= {CMD_DOWNLOAD_RAW_ADC_SAMPLES_125K
, {i
, 0, 0}};
835 wait_for_response(CMD_DOWNLOADED_RAW_ADC_SAMPLES_125K
);
836 for(j
= 0; j
< 48; j
++) {
837 t2
= (int)(sample_buf
[j
]);
838 if((t2
^ 0xC0) & 0xC0) { hasbeennull
++; }
844 t1
= (t2
& 0x80) ^ (t2
& 0x20);
845 t2
= ((t2
<< 1) & 0x80) ^ ((t2
<< 1) & 0x20);
851 t2
= ((t2
<< 1) & 0x80);
857 t2
= ((t2
<< 1) & 0x20);
861 // both, but tag with other algorithm
862 t1
= (t2
& 0x80) ^ (t2
& 0x08);
863 t2
= ((t2
<< 1) & 0x80) ^ ((t2
<< 1) & 0x08);
867 GraphBuffer
[cnt
++] = t1
;
868 GraphBuffer
[cnt
++] = t2
;
873 if(hasbeennull
>nrlow
|| nrlow
==0) {
874 PrintToScrollback("hasbeennull=%d", hasbeennull
);
883 static void CmdHexsamples(char *str
)
888 sscanf(str
, "%i %i", &requested
, &offset
);
890 PrintToScrollback("Offset must be a multiple of 4");
897 if (requested
== 0) {
904 for(i
= offset
; i
< n
+offset
; i
+= 12) {
905 UsbCommand c
= {CMD_DOWNLOAD_RAW_ADC_SAMPLES_125K
, {i
, 0, 0}};
907 wait_for_response(CMD_DOWNLOADED_RAW_ADC_SAMPLES_125K
);
908 for (j
= 0; j
< 48; j
+= 8) {
909 PrintToScrollback("%02x %02x %02x %02x %02x %02x %02x %02x",
921 if (delivered
>= requested
)
924 if (delivered
>= requested
)
929 static void CmdHisampless(char *str
)
933 int n
= strtol(str
, NULL
, 0);
941 for(i
= 0; i
< n
; i
+= 12) {
942 UsbCommand c
= {CMD_DOWNLOAD_RAW_ADC_SAMPLES_125K
, {i
, 0, 0}};
944 wait_for_response(CMD_DOWNLOADED_RAW_ADC_SAMPLES_125K
);
945 for(j
= 0; j
< 48; j
++) {
946 GraphBuffer
[cnt
++] = (int)(sample_buf
[j
]);
951 RepaintGraphWindow();
954 static uint16_t Iso15693Crc(uint8_t *v
, int n
)
960 for(i
= 0; i
< n
; i
++) {
961 reg
= reg
^ ((uint32_t)v
[i
]);
962 for (j
= 0; j
< 8; j
++) {
964 reg
= (reg
>> 1) ^ 0x8408;
971 return (uint16_t)~reg
;
974 static void CmdHi14bdemod(char *str
)
979 bool negateI
, negateQ
;
984 // As received, the samples are pairs, correlations against I and Q
985 // square waves. So estimate angle of initial carrier (or just
986 // quadrant, actually), and then do the demod.
988 // First, estimate where the tag starts modulating.
989 for(i
= 0; i
< GraphTraceLen
; i
+= 2) {
990 if(abs(GraphBuffer
[i
]) + abs(GraphBuffer
[i
+1]) > 40) {
994 if(i
>= GraphTraceLen
) {
995 PrintToScrollback("too weak to sync");
998 PrintToScrollback("out of weak at %d", i
);
1001 // Now, estimate the phase in the initial modulation of the tag
1004 for(; i
< (outOfWeakAt
+ 16); i
+= 2) {
1005 isum
+= GraphBuffer
[i
+0];
1006 qsum
+= GraphBuffer
[i
+1];
1008 negateI
= (isum
< 0);
1009 negateQ
= (qsum
< 0);
1011 // Turn the correlation pairs into soft decisions on the bit.
1013 for(i
= 0; i
< GraphTraceLen
/2; i
++) {
1014 int si
= GraphBuffer
[j
];
1015 int sq
= GraphBuffer
[j
+1];
1016 if(negateI
) si
= -si
;
1017 if(negateQ
) sq
= -sq
;
1018 GraphBuffer
[i
] = si
+ sq
;
1024 while(GraphBuffer
[i
] > 0 && i
< GraphTraceLen
)
1026 if(i
>= GraphTraceLen
) goto demodError
;
1029 while(GraphBuffer
[i
] < 0 && i
< GraphTraceLen
)
1031 if(i
>= GraphTraceLen
) goto demodError
;
1032 if((i
- iold
) > 23) goto demodError
;
1034 PrintToScrollback("make it to demod loop");
1038 while(GraphBuffer
[i
] >= 0 && i
< GraphTraceLen
)
1040 if(i
>= GraphTraceLen
) goto demodError
;
1041 if((i
- iold
) > 6) goto demodError
;
1043 uint16_t shiftReg
= 0;
1044 if(i
+ 20 >= GraphTraceLen
) goto demodError
;
1046 for(j
= 0; j
< 10; j
++) {
1047 int soft
= GraphBuffer
[i
] + GraphBuffer
[i
+1];
1049 if(abs(soft
) < ((abs(isum
) + abs(qsum
))/20)) {
1050 PrintToScrollback("weak bit");
1054 if(GraphBuffer
[i
] + GraphBuffer
[i
+1] >= 0) {
1061 if( (shiftReg
& 0x200) &&
1062 !(shiftReg
& 0x001))
1064 // valid data byte, start and stop bits okay
1065 PrintToScrollback(" %02x", (shiftReg
>> 1) & 0xff);
1066 data
[dataLen
++] = (shiftReg
>> 1) & 0xff;
1067 if(dataLen
>= sizeof(data
)) {
1070 } else if(shiftReg
== 0x000) {
1078 uint8_t first
, second
;
1079 ComputeCrc14443(CRC_14443_B
, data
, dataLen
-2, &first
, &second
);
1080 PrintToScrollback("CRC: %02x %02x (%s)\n", first
, second
,
1081 (first
== data
[dataLen
-2] && second
== data
[dataLen
-1]) ?
1082 "ok" : "****FAIL****");
1084 RepaintGraphWindow();
1088 PrintToScrollback("demod error");
1089 RepaintGraphWindow();
1092 static void CmdHi14list(char *str
)
1095 GetFromBigBuf(got
, sizeof(got
));
1097 PrintToScrollback("recorded activity:");
1098 PrintToScrollback(" time :rssi: who bytes");
1099 PrintToScrollback("---------+----+----+-----------");
1110 int timestamp
= *((uint32_t *)(got
+i
));
1111 if(timestamp
& 0x80000000) {
1112 timestamp
&= 0x7fffffff;
1117 int metric
= *((uint32_t *)(got
+i
+4));
1124 if(i
+ len
>= 900) {
1128 uint8_t *frame
= (got
+i
+9);
1130 char line
[1000] = "";
1132 for(j
= 0; j
< len
; j
++) {
1133 sprintf(line
+(j
*3), "%02x ", frame
[j
]);
1139 ComputeCrc14443(CRC_14443_B
, frame
, len
-2, &b1
, &b2
);
1140 if(b1
!= frame
[len
-2] || b2
!= frame
[len
-1]) {
1141 crc
= "**FAIL CRC**";
1149 char metricString
[100];
1151 sprintf(metricString
, "%3d", metric
);
1153 strcpy(metricString
, " ");
1156 PrintToScrollback(" +%7d: %s: %s %s %s",
1157 (prev
< 0 ? 0 : timestamp
- prev
),
1159 (isResponse
? "TAG" : " "), line
, crc
);
1166 static void CmdHi14alist(char *str
)
1169 GetFromBigBuf(got
, sizeof(got
));
1171 PrintToScrollback("recorded activity:");
1172 PrintToScrollback(" ETU :rssi: who bytes");
1173 PrintToScrollback("---------+----+----+-----------");
1184 int timestamp
= *((uint32_t *)(got
+i
));
1185 if(timestamp
& 0x80000000) {
1186 timestamp
&= 0x7fffffff;
1193 int parityBits
= *((uint32_t *)(got
+i
+4));
1194 // 4 bytes of additional information...
1195 // maximum of 32 additional parity bit information
1198 // at each quarter bit period we can send power level (16 levels)
1199 // or each half bit period in 256 levels.
1207 if(i
+ len
>= 1900) {
1211 uint8_t *frame
= (got
+i
+9);
1213 // Break and stick with current result if buffer was not completely full
1214 if(frame
[0] == 0x44 && frame
[1] == 0x44 && frame
[3] == 0x44) { break; }
1216 char line
[1000] = "";
1218 for(j
= 0; j
< len
; j
++) {
1219 int oddparity
= 0x01;
1223 oddparity
^= (((frame
[j
] & 0xFF) >> k
) & 0x01);
1226 //if((parityBits >> (len - j - 1)) & 0x01) {
1227 if(isResponse
&& (oddparity
!= ((parityBits
>> (len
- j
- 1)) & 0x01))) {
1228 sprintf(line
+(j
*4), "%02x! ", frame
[j
]);
1231 sprintf(line
+(j
*4), "%02x ", frame
[j
]);
1239 for(j
= 0; j
< (len
- 1); j
++) {
1240 // gives problems... search for the reason..
1241 /*if(frame[j] == 0xAA) {
1242 switch(frame[j+1]) {
1244 crc = "[1] Two drops close after each other";
1247 crc = "[2] Potential SOC with a drop in second half of bitperiod";
1250 crc = "[3] Segment Z after segment X is not possible";
1253 crc = "[4] Parity bit of a fully received byte was wrong";
1256 crc = "[?] Unknown error";
1263 if(strlen(crc
)==0) {
1264 ComputeCrc14443(CRC_14443_A
, frame
, len
-2, &b1
, &b2
);
1265 if(b1
!= frame
[len
-2] || b2
!= frame
[len
-1]) {
1266 crc
= (isResponse
& (len
< 6)) ? "" : " !crc";
1275 char metricString
[100];
1277 sprintf(metricString
, "%3d", metric
);
1279 strcpy(metricString
, " ");
1282 PrintToScrollback(" +%7d: %s: %s %s %s",
1283 (prev
< 0 ? 0 : (timestamp
- prev
)),
1285 (isResponse
? "TAG" : " "), line
, crc
);
1290 CommandFinished
= 1;
1293 static void CmdHi15demod(char *str
)
1295 // The sampling rate is 106.353 ksps/s, for T = 18.8 us
1298 // 1) Unmodulated time of 56.64us
1299 // 2) 24 pulses of 423.75khz
1300 // 3) logic '1' (unmodulated for 18.88us followed by 8 pulses of 423.75khz)
1302 static const int FrameSOF
[] = {
1303 -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
1304 -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
1305 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
1306 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
1312 static const int Logic0
[] = {
1318 static const int Logic1
[] = {
1326 // 1) logic '0' (8 pulses of 423.75khz followed by unmodulated for 18.88us)
1327 // 2) 24 pulses of 423.75khz
1328 // 3) Unmodulated time of 56.64us
1330 static const int FrameEOF
[] = {
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
1342 int max
= 0, maxPos
;
1346 if(GraphTraceLen
< 1000) return;
1348 // First, correlate for SOF
1349 for(i
= 0; i
< 100; i
++) {
1351 for(j
= 0; j
< arraylen(FrameSOF
); j
+= skip
) {
1352 corr
+= FrameSOF
[j
]*GraphBuffer
[i
+(j
/skip
)];
1359 PrintToScrollback("SOF at %d, correlation %d", maxPos
,
1360 max
/(arraylen(FrameSOF
)/skip
));
1362 i
= maxPos
+ arraylen(FrameSOF
)/skip
;
1365 memset(outBuf
, 0, sizeof(outBuf
));
1366 uint8_t mask
= 0x01;
1368 int corr0
= 0, corr1
= 0, corrEOF
= 0;
1369 for(j
= 0; j
< arraylen(Logic0
); j
+= skip
) {
1370 corr0
+= Logic0
[j
]*GraphBuffer
[i
+(j
/skip
)];
1372 for(j
= 0; j
< arraylen(Logic1
); j
+= skip
) {
1373 corr1
+= Logic1
[j
]*GraphBuffer
[i
+(j
/skip
)];
1375 for(j
= 0; j
< arraylen(FrameEOF
); j
+= skip
) {
1376 corrEOF
+= FrameEOF
[j
]*GraphBuffer
[i
+(j
/skip
)];
1378 // Even things out by the length of the target waveform.
1382 if(corrEOF
> corr1
&& corrEOF
> corr0
) {
1383 PrintToScrollback("EOF at %d", i
);
1385 } else if(corr1
> corr0
) {
1386 i
+= arraylen(Logic1
)/skip
;
1389 i
+= arraylen(Logic0
)/skip
;
1396 if((i
+(int)arraylen(FrameEOF
)) >= GraphTraceLen
) {
1397 PrintToScrollback("ran off end!");
1402 PrintToScrollback("error, uneven octet! (discard extra bits!)");
1403 PrintToScrollback(" mask=%02x", mask
);
1405 PrintToScrollback("%d octets", k
);
1407 for(i
= 0; i
< k
; i
++) {
1408 PrintToScrollback("# %2d: %02x ", i
, outBuf
[i
]);
1410 PrintToScrollback("CRC=%04x", Iso15693Crc(outBuf
, k
-2));
1413 static void CmdFSKdemod(char *cmdline
)
1415 static const int LowTone
[] = {
1416 1, 1, 1, 1, 1, -1, -1, -1, -1, -1,
1417 1, 1, 1, 1, 1, -1, -1, -1, -1, -1,
1418 1, 1, 1, 1, 1, -1, -1, -1, -1, -1,
1419 1, 1, 1, 1, 1, -1, -1, -1, -1, -1,
1420 1, 1, 1, 1, 1, -1, -1, -1, -1, -1
1422 static const int HighTone
[] = {
1423 1, 1, 1, 1, 1, -1, -1, -1, -1,
1424 1, 1, 1, 1, -1, -1, -1, -1,
1425 1, 1, 1, 1, -1, -1, -1, -1,
1426 1, 1, 1, 1, -1, -1, -1, -1,
1427 1, 1, 1, 1, -1, -1, -1, -1,
1428 1, 1, 1, 1, -1, -1, -1, -1, -1,
1431 int lowLen
= sizeof(LowTone
)/sizeof(int);
1432 int highLen
= sizeof(HighTone
)/sizeof(int);
1433 int convLen
= (highLen
>lowLen
)?highLen
:lowLen
;
1434 uint32_t hi
= 0, lo
= 0;
1437 int minMark
=0, maxMark
=0;
1439 for(i
= 0; i
< GraphTraceLen
- convLen
; i
++) {
1440 int lowSum
= 0, highSum
= 0;
1442 for(j
= 0; j
< lowLen
; j
++) {
1443 lowSum
+= LowTone
[j
]*GraphBuffer
[i
+j
];
1445 for(j
= 0; j
< highLen
; j
++) {
1446 highSum
+= HighTone
[j
]*GraphBuffer
[i
+j
];
1448 lowSum
= abs((100*lowSum
) / lowLen
);
1449 highSum
= abs((100*highSum
) / highLen
);
1450 GraphBuffer
[i
] = (highSum
<< 16) | lowSum
;
1453 for(i
= 0; i
< GraphTraceLen
- convLen
- 16; i
++) {
1455 int lowTot
= 0, highTot
= 0;
1456 // 10 and 8 are f_s divided by f_l and f_h, rounded
1457 for(j
= 0; j
< 10; j
++) {
1458 lowTot
+= (GraphBuffer
[i
+j
] & 0xffff);
1460 for(j
= 0; j
< 8; j
++) {
1461 highTot
+= (GraphBuffer
[i
+j
] >> 16);
1463 GraphBuffer
[i
] = lowTot
- highTot
;
1464 if (GraphBuffer
[i
]>maxMark
) maxMark
=GraphBuffer
[i
];
1465 if (GraphBuffer
[i
]<minMark
) minMark
=GraphBuffer
[i
];
1468 GraphTraceLen
-= (convLen
+ 16);
1470 RepaintGraphWindow();
1472 // Find bit-sync (3 lo followed by 3 high)
1473 int max
= 0, maxPos
= 0;
1474 for(i
= 0; i
< 6000; i
++) {
1476 for(j
= 0; j
< 3*lowLen
; j
++) {
1477 dec
-= GraphBuffer
[i
+j
];
1479 for(; j
< 3*(lowLen
+ highLen
); j
++) {
1480 dec
+= GraphBuffer
[i
+j
];
1488 // place start of bit sync marker in graph
1489 GraphBuffer
[maxPos
] = maxMark
;
1490 GraphBuffer
[maxPos
+1] = minMark
;
1494 // place end of bit sync marker in graph
1495 GraphBuffer
[maxPos
] = maxMark
;
1496 GraphBuffer
[maxPos
+1] = minMark
;
1498 PrintToScrollback("actual data bits start at sample %d", maxPos
);
1499 PrintToScrollback("length %d/%d", highLen
, lowLen
);
1502 bits
[sizeof(bits
)-1] = '\0';
1504 // find bit pairs and manchester decode them
1505 for(i
= 0; i
< arraylen(bits
)-1; i
++) {
1507 for(j
= 0; j
< lowLen
; j
++) {
1508 dec
-= GraphBuffer
[maxPos
+j
];
1510 for(; j
< lowLen
+ highLen
; j
++) {
1511 dec
+= GraphBuffer
[maxPos
+j
];
1514 // place inter bit marker in graph
1515 GraphBuffer
[maxPos
] = maxMark
;
1516 GraphBuffer
[maxPos
+1] = minMark
;
1518 // hi and lo form a 64 bit pair
1519 hi
= (hi
<<1)|(lo
>>31);
1521 // store decoded bit as binary (in hi/lo) and text (in bits[])
1529 PrintToScrollback("bits: '%s'", bits
);
1530 PrintToScrollback("hex: %08x %08x", hi
, lo
);
1533 // read a TI tag and return its ID
1534 static void CmdTIRead(char *str
)
1536 UsbCommand c
={CMD_READ_TI_TYPE
};
1540 // write new data to a r/w TI tag
1541 static void CmdTIWrite(char *str
)
1543 UsbCommand c
={CMD_WRITE_TI_TYPE
};
1546 res
= sscanf(str
, "0x%x 0x%x 0x%x ", &c
.arg
[0], &c
.arg
[1], &c
.arg
[2]);
1547 if (res
== 2) c
.arg
[2]=0;
1549 PrintToScrollback("Please specify the data as two hex strings, optionally the CRC as a third");
1554 static void CmdTIDemod(char *cmdline
)
1556 /* MATLAB as follows:
1557 f_s = 2000000; % sampling frequency
1558 f_l = 123200; % low FSK tone
1559 f_h = 134200; % high FSK tone
1561 T_l = 119e-6; % low bit duration
1562 T_h = 130e-6; % high bit duration
1564 l = 2*pi*ones(1, floor(f_s*T_l))*(f_l/f_s);
1565 h = 2*pi*ones(1, floor(f_s*T_h))*(f_h/f_s);
1567 l = sign(sin(cumsum(l)));
1568 h = sign(sin(cumsum(h)));
1571 // 2M*16/134.2k = 238
1572 static const int LowTone
[] = {
1573 1, 1, 1, 1, 1, 1, 1, 1, 1, -1, -1, -1, -1, -1, -1, -1, -1,
1574 1, 1, 1, 1, 1, 1, 1, 1, -1, -1, -1, -1, -1, -1, -1, -1,
1575 1, 1, 1, 1, 1, 1, 1, 1, -1, -1, -1, -1, -1, -1, -1, -1,
1576 1, 1, 1, 1, 1, 1, 1, 1, -1, -1, -1, -1, -1, -1, -1, -1,
1577 1, 1, 1, 1, 1, 1, 1, 1, 1, -1, -1, -1, -1, -1, -1, -1, -1,
1578 1, 1, 1, 1, 1, 1, 1, 1, -1, -1, -1, -1, -1, -1, -1, -1,
1579 1, 1, 1, 1, 1, 1, 1, 1, -1, -1, -1, -1, -1, -1, -1, -1,
1580 1, 1, 1, 1, 1, 1, 1, 1, -1, -1, -1, -1, -1, -1, -1, -1,
1581 1, 1, 1, 1, 1, 1, 1, 1, 1, -1, -1, -1, -1, -1, -1, -1, -1,
1582 1, 1, 1, 1, 1, 1, 1, 1, -1, -1, -1, -1, -1, -1, -1, -1,
1583 1, 1, 1, 1, 1, 1, 1, 1, -1, -1, -1, -1, -1, -1, -1, -1,
1584 1, 1, 1, 1, 1, 1, 1, 1, -1, -1, -1, -1, -1, -1, -1, -1,
1585 1, 1, 1, 1, 1, 1, 1, 1, 1, -1, -1, -1, -1, -1, -1, -1, -1,
1586 1, 1, 1, 1, 1, 1, 1, 1, -1, -1, -1, -1, -1, -1, -1, -1,
1587 1, 1, 1, 1, 1, 1, 1, 1, -1, -1
1589 // 2M*16/123.2k = 260
1590 static const int HighTone
[] = {
1591 1, 1, 1, 1, 1, 1, 1, 1, -1, -1, -1, -1, -1, -1, -1,
1592 1, 1, 1, 1, 1, 1, 1, 1, -1, -1, -1, -1, -1, -1, -1,
1593 1, 1, 1, 1, 1, 1, 1, -1, -1, -1, -1, -1, -1, -1, -1,
1594 1, 1, 1, 1, 1, 1, 1, -1, -1, -1, -1, -1, -1, -1, -1,
1595 1, 1, 1, 1, 1, 1, 1, -1, -1, -1, -1, -1, -1, -1, -1,
1596 1, 1, 1, 1, 1, 1, 1, -1, -1, -1, -1, -1, -1, -1,
1597 1, 1, 1, 1, 1, 1, 1, 1, -1, -1, -1, -1, -1, -1, -1,
1598 1, 1, 1, 1, 1, 1, 1, 1, -1, -1, -1, -1, -1, -1, -1,
1599 1, 1, 1, 1, 1, 1, 1, -1, -1, -1, -1, -1, -1, -1, -1,
1600 1, 1, 1, 1, 1, 1, 1, -1, -1, -1, -1, -1, -1, -1, -1,
1601 1, 1, 1, 1, 1, 1, 1, -1, -1, -1, -1, -1, -1, -1,
1602 1, 1, 1, 1, 1, 1, 1, 1, -1, -1, -1, -1, -1, -1, -1,
1603 1, 1, 1, 1, 1, 1, 1, 1, -1, -1, -1, -1, -1, -1, -1,
1604 1, 1, 1, 1, 1, 1, 1, 1, -1, -1, -1, -1, -1, -1, -1,
1605 1, 1, 1, 1, 1, 1, 1, -1, -1, -1, -1, -1, -1, -1, -1,
1606 1, 1, 1, 1, 1, 1, 1, -1, -1, -1, -1, -1, -1, -1, -1,
1607 1, 1, 1, 1, 1, 1, 1, -1, -1, -1, -1, -1, -1, -1,
1608 1, 1, 1, 1, 1, 1, 1, 1
1610 int lowLen
= sizeof(LowTone
)/sizeof(int);
1611 int highLen
= sizeof(HighTone
)/sizeof(int);
1612 int convLen
= (highLen
>lowLen
)?highLen
:lowLen
;
1615 int lowSum
= 0, highSum
= 0;;
1616 int lowTot
= 0, highTot
= 0;
1618 for(i
= 0; i
< GraphTraceLen
- convLen
; i
++) {
1622 for(j
= 0; j
< lowLen
; j
++) {
1623 lowSum
+= LowTone
[j
]*GraphBuffer
[i
+j
];
1625 for(j
= 0; j
< highLen
; j
++) {
1626 highSum
+= HighTone
[j
]*GraphBuffer
[i
+j
];
1628 lowSum
= abs((100*lowSum
) / lowLen
);
1629 highSum
= abs((100*highSum
) / highLen
);
1630 lowSum
= (lowSum
<0)?-lowSum
:lowSum
;
1631 highSum
= (highSum
<0)?-highSum
:highSum
;
1633 GraphBuffer
[i
] = (highSum
<< 16) | lowSum
;
1636 for(i
= 0; i
< GraphTraceLen
- convLen
- 16; i
++) {
1639 // 16 and 15 are f_s divided by f_l and f_h, rounded
1640 for(j
= 0; j
< 16; j
++) {
1641 lowTot
+= (GraphBuffer
[i
+j
] & 0xffff);
1643 for(j
= 0; j
< 15; j
++) {
1644 highTot
+= (GraphBuffer
[i
+j
] >> 16);
1646 GraphBuffer
[i
] = lowTot
- highTot
;
1649 GraphTraceLen
-= (convLen
+ 16);
1651 RepaintGraphWindow();
1653 // TI tag data format is 16 prebits, 8 start bits, 64 data bits,
1654 // 16 crc CCITT bits, 8 stop bits, 15 end bits
1656 // the 16 prebits are always low
1657 // the 8 start and stop bits of a tag must match
1658 // the start/stop prebits of a ro tag are 01111110
1659 // the start/stop prebits of a rw tag are 11111110
1660 // the 15 end bits of a ro tag are all low
1661 // the 15 end bits of a rw tag match bits 15-1 of the data bits
1663 // Okay, so now we have unsliced soft decisions;
1664 // find bit-sync, and then get some bits.
1665 // look for 17 low bits followed by 6 highs (common pattern for ro and rw tags)
1666 int max
= 0, maxPos
= 0;
1667 for(i
= 0; i
< 6000; i
++) {
1670 // searching 17 consecutive lows
1671 for(j
= 0; j
< 17*lowLen
; j
++) {
1672 dec
-= GraphBuffer
[i
+j
];
1674 // searching 7 consecutive highs
1675 for(; j
< 17*lowLen
+ 6*highLen
; j
++) {
1676 dec
+= GraphBuffer
[i
+j
];
1684 // place a marker in the buffer to visually aid location
1685 // of the start of sync
1686 GraphBuffer
[maxPos
] = 800;
1687 GraphBuffer
[maxPos
+1] = -800;
1689 // advance pointer to start of actual data stream (after 16 pre and 8 start bits)
1690 maxPos
+= 17*lowLen
;
1691 maxPos
+= 6*highLen
;
1693 // place a marker in the buffer to visually aid location
1694 // of the end of sync
1695 GraphBuffer
[maxPos
] = 800;
1696 GraphBuffer
[maxPos
+1] = -800;
1698 PrintToScrollback("actual data bits start at sample %d", maxPos
);
1700 PrintToScrollback("length %d/%d", highLen
, lowLen
);
1702 uint8_t bits
[1+64+16+8+16];
1703 bits
[sizeof(bits
)-1] = '\0';
1705 uint32_t shift3
= 0x7e000000, shift2
= 0, shift1
= 0, shift0
= 0;
1707 for(i
= 0; i
< arraylen(bits
)-1; i
++) {
1711 for(j
= 0; j
< lowLen
; j
++) {
1712 low
-= GraphBuffer
[maxPos
+j
];
1714 for(j
= 0; j
< highLen
; j
++) {
1715 high
+= GraphBuffer
[maxPos
+j
];
1721 // bitstream arrives lsb first so shift right
1728 // 128 bit right shift register
1729 shift0
= (shift0
>>1) | (shift1
<< 31);
1730 shift1
= (shift1
>>1) | (shift2
<< 31);
1731 shift2
= (shift2
>>1) | (shift3
<< 31);
1734 // place a marker in the buffer between bits to visually aid location
1735 GraphBuffer
[maxPos
] = 800;
1736 GraphBuffer
[maxPos
+1] = -800;
1738 PrintToScrollback("Info: raw tag bits = %s", bits
);
1740 TagType
= (shift3
>>8)&0xff;
1741 if ( TagType
!= ((shift0
>>16)&0xff) ) {
1742 PrintToScrollback("Error: start and stop bits do not match!");
1745 else if (TagType
== 0x7e) {
1746 PrintToScrollback("Info: Readonly TI tag detected.");
1749 else if (TagType
== 0xfe) {
1750 PrintToScrollback("Info: Rewriteable TI tag detected.");
1752 // put 64 bit data into shift1 and shift0
1753 shift0
= (shift0
>>24) | (shift1
<< 8);
1754 shift1
= (shift1
>>24) | (shift2
<< 8);
1756 // align 16 bit crc into lower half of shift2
1757 shift2
= ((shift2
>>24) | (shift3
<< 8)) & 0x0ffff;
1759 // align 16 bit "end bits" or "ident" into lower half of shift3
1762 // only 15 bits compare, last bit of ident is not valid
1763 if ( (shift3
^shift0
)&0x7fff ) {
1764 PrintToScrollback("Error: Ident mismatch!");
1766 // WARNING the order of the bytes in which we calc crc below needs checking
1767 // i'm 99% sure the crc algorithm is correct, but it may need to eat the
1768 // bytes in reverse or something
1771 crc
= update_crc16(crc
, (shift0
)&0xff);
1772 crc
= update_crc16(crc
, (shift0
>>8)&0xff);
1773 crc
= update_crc16(crc
, (shift0
>>16)&0xff);
1774 crc
= update_crc16(crc
, (shift0
>>24)&0xff);
1775 crc
= update_crc16(crc
, (shift1
)&0xff);
1776 crc
= update_crc16(crc
, (shift1
>>8)&0xff);
1777 crc
= update_crc16(crc
, (shift1
>>16)&0xff);
1778 crc
= update_crc16(crc
, (shift1
>>24)&0xff);
1779 PrintToScrollback("Info: Tag data = %08X%08X", shift1
, shift0
);
1780 if (crc
!= (shift2
&0xffff)) {
1781 PrintToScrollback("Error: CRC mismatch, calculated %04X, got ^04X", crc
, shift2
&0xffff);
1783 PrintToScrollback("Info: CRC %04X is good", crc
);
1787 PrintToScrollback("Unknown tag type.");
1792 static void CmdNorm(char *str
)
1795 int max
= INT_MIN
, min
= INT_MAX
;
1796 for(i
= 10; i
< GraphTraceLen
; i
++) {
1797 if(GraphBuffer
[i
] > max
) {
1798 max
= GraphBuffer
[i
];
1800 if(GraphBuffer
[i
] < min
) {
1801 min
= GraphBuffer
[i
];
1805 for(i
= 0; i
< GraphTraceLen
; i
++) {
1806 GraphBuffer
[i
] = (GraphBuffer
[i
] - ((max
+ min
)/2))*1000/
1810 RepaintGraphWindow();
1813 static void CmdAmp(char *str
)
1815 int i
, rising
, falling
;
1816 int max
= INT_MIN
, min
= INT_MAX
;
1817 for(i
= 10; i
< GraphTraceLen
; i
++) {
1818 if(GraphBuffer
[i
] > max
) {
1819 max
= GraphBuffer
[i
];
1821 if(GraphBuffer
[i
] < min
) {
1822 min
= GraphBuffer
[i
];
1827 for(i
= 0; i
< GraphTraceLen
; i
++) {
1828 if(GraphBuffer
[i
+1] < GraphBuffer
[i
]) {
1830 GraphBuffer
[i
]= max
;
1835 if(GraphBuffer
[i
+1] > GraphBuffer
[i
]) {
1837 GraphBuffer
[i
]= min
;
1844 RepaintGraphWindow();
1847 static void CmdDec(char *str
)
1850 for(i
= 0; i
< (GraphTraceLen
/2); i
++) {
1851 GraphBuffer
[i
] = GraphBuffer
[i
*2];
1854 PrintToScrollback("decimated by 2");
1855 RepaintGraphWindow();
1858 static void CmdHpf(char *str
)
1862 for(i
= 10; i
< GraphTraceLen
; i
++) {
1863 accum
+= GraphBuffer
[i
];
1865 accum
/= (GraphTraceLen
- 10);
1866 for(i
= 0; i
< GraphTraceLen
; i
++) {
1867 GraphBuffer
[i
] -= accum
;
1870 RepaintGraphWindow();
1873 static void CmdZerocrossings(char *str
)
1876 // Zero-crossings aren't meaningful unless the signal is zero-mean.
1882 for(i
= 0; i
< GraphTraceLen
; i
++) {
1883 if(GraphBuffer
[i
]*sign
>= 0) {
1884 // No change in sign, reproduce the previous sample count.
1886 GraphBuffer
[i
] = lastZc
;
1888 // Change in sign, reset the sample count.
1890 GraphBuffer
[i
] = lastZc
;
1898 RepaintGraphWindow();
1901 static void CmdThreshold(char *str
)
1904 int threshold
= atoi(str
);
1906 for(i
= 0; i
< GraphTraceLen
; i
++) {
1907 if(GraphBuffer
[i
]>= threshold
)
1912 RepaintGraphWindow();
1915 static void CmdLtrim(char *str
)
1920 for(i
= ds
; i
< GraphTraceLen
; i
++) {
1921 GraphBuffer
[i
-ds
] = GraphBuffer
[i
];
1923 GraphTraceLen
-= ds
;
1925 RepaintGraphWindow();
1928 static void CmdAutoCorr(char *str
)
1930 static int CorrelBuffer
[MAX_GRAPH_TRACE_LEN
];
1932 int window
= atoi(str
);
1935 PrintToScrollback("needs a window");
1939 if(window
>= GraphTraceLen
) {
1940 PrintToScrollback("window must be smaller than trace (%d samples)",
1945 PrintToScrollback("performing %d correlations", GraphTraceLen
- window
);
1948 for(i
= 0; i
< GraphTraceLen
- window
; i
++) {
1951 for(j
= 0; j
< window
; j
++) {
1952 sum
+= (GraphBuffer
[j
]*GraphBuffer
[i
+j
]) / 256;
1954 CorrelBuffer
[i
] = sum
;
1956 GraphTraceLen
= GraphTraceLen
- window
;
1957 memcpy(GraphBuffer
, CorrelBuffer
, GraphTraceLen
*sizeof(int));
1959 RepaintGraphWindow();
1962 static void CmdVchdemod(char *str
)
1964 // Is this the entire sync pattern, or does this also include some
1965 // data bits that happen to be the same everywhere? That would be
1967 static const int SyncPattern
[] = {
1968 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
1969 1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
1970 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
1971 1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
1972 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
1973 1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
1974 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
1975 1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
1976 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
1977 1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
1980 // So first, we correlate for the sync pattern, and mark that.
1981 int bestCorrel
= 0, bestPos
= 0;
1983 // It does us no good to find the sync pattern, with fewer than
1984 // 2048 samples after it...
1985 for(i
= 0; i
< (GraphTraceLen
-2048); i
++) {
1988 for(j
= 0; j
< arraylen(SyncPattern
); j
++) {
1989 sum
+= GraphBuffer
[i
+j
]*SyncPattern
[j
];
1991 if(sum
> bestCorrel
) {
1996 PrintToScrollback("best sync at %d [metric %d]", bestPos
, bestCorrel
);
2001 int worst
= INT_MAX
;
2004 for(i
= 0; i
< 2048; i
+= 8) {
2007 for(j
= 0; j
< 8; j
++) {
2008 sum
+= GraphBuffer
[bestPos
+i
+j
];
2015 if(abs(sum
) < worst
) {
2020 PrintToScrollback("bits:");
2021 PrintToScrollback("%s", bits
);
2022 PrintToScrollback("worst metric: %d at pos %d", worst
, worstPos
);
2024 if(strcmp(str
, "clone")==0) {
2027 for(s
= bits
; *s
; s
++) {
2029 for(j
= 0; j
< 16; j
++) {
2030 GraphBuffer
[GraphTraceLen
++] = (*s
== '1') ? 1 : 0;
2033 RepaintGraphWindow();
2037 static void CmdIndalademod(char *str
)
2039 // Usage: recover 64bit UID by default, specify "224" as arg to recover a 224bit UID
2044 // worst case with GraphTraceLen=64000 is < 4096
2045 // under normal conditions it's < 2048
2046 uint8_t rawbits
[4096];
2048 int worst
= 0, worstPos
= 0;
2049 PrintToScrollback("Expecting a bit less than %d raw bits", GraphTraceLen
/32);
2050 for(i
= 0; i
< GraphTraceLen
-1; i
+= 2) {
2052 if((GraphBuffer
[i
] > GraphBuffer
[i
+ 1]) && (state
!= 1)) {
2054 for(j
= 0; j
< count
- 8; j
+= 16) {
2055 rawbits
[rawbit
++] = 0;
2057 if ((abs(count
- j
)) > worst
) {
2058 worst
= abs(count
- j
);
2064 } else if((GraphBuffer
[i
] < GraphBuffer
[i
+ 1]) && (state
!= 0)) {
2066 for(j
= 0; j
< count
- 8; j
+= 16) {
2067 rawbits
[rawbit
++] = 1;
2069 if ((abs(count
- j
)) > worst
) {
2070 worst
= abs(count
- j
);
2078 PrintToScrollback("Recovered %d raw bits", rawbit
);
2079 PrintToScrollback("worst metric (0=best..7=worst): %d at pos %d", worst
, worstPos
);
2081 // Finding the start of a UID
2082 int uidlen
, long_wait
;
2083 if(strcmp(str
, "224") == 0) {
2092 for(start
= 0; start
<= rawbit
- uidlen
; start
++) {
2093 first
= rawbits
[start
];
2094 for(i
= start
; i
< start
+ long_wait
; i
++) {
2095 if(rawbits
[i
] != first
) {
2099 if(i
== (start
+ long_wait
)) {
2103 if(start
== rawbit
- uidlen
+ 1) {
2104 PrintToScrollback("nothing to wait for");
2108 // Inverting signal if needed
2110 for(i
= start
; i
< rawbit
; i
++) {
2111 rawbits
[i
] = !rawbits
[i
];
2118 showbits
[uidlen
]='\0';
2122 if(uidlen
> rawbit
) {
2123 PrintToScrollback("Warning: not enough raw bits to get a full UID");
2124 for(bit
= 0; bit
< rawbit
; bit
++) {
2125 bits
[bit
] = rawbits
[i
++];
2126 // As we cannot know the parity, let's use "." and "/"
2127 showbits
[bit
] = '.' + bits
[bit
];
2129 showbits
[bit
+1]='\0';
2130 PrintToScrollback("Partial UID=%s", showbits
);
2133 for(bit
= 0; bit
< uidlen
; bit
++) {
2134 bits
[bit
] = rawbits
[i
++];
2135 showbits
[bit
] = '0' + bits
[bit
];
2139 PrintToScrollback("UID=%s", showbits
);
2141 // Checking UID against next occurences
2142 for(; i
+ uidlen
<= rawbit
;) {
2144 for(bit
= 0; bit
< uidlen
; bit
++) {
2145 if(bits
[bit
] != rawbits
[i
++]) {
2155 PrintToScrollback("Occurences: %d (expected %d)", times
, (rawbit
- start
) / uidlen
);
2157 // Remodulating for tag cloning
2158 GraphTraceLen
= 32*uidlen
;
2161 for(bit
= 0; bit
< uidlen
; bit
++) {
2162 if(bits
[bit
] == 0) {
2168 for(j
= 0; j
< 32; j
++) {
2169 GraphBuffer
[i
++] = phase
;
2174 RepaintGraphWindow();
2177 static void CmdFlexdemod(char *str
)
2180 for(i
= 0; i
< GraphTraceLen
; i
++) {
2181 if(GraphBuffer
[i
] < 0) {
2182 GraphBuffer
[i
] = -1;
2188 #define LONG_WAIT 100
2190 for(start
= 0; start
< GraphTraceLen
- LONG_WAIT
; start
++) {
2191 int first
= GraphBuffer
[start
];
2192 for(i
= start
; i
< start
+ LONG_WAIT
; i
++) {
2193 if(GraphBuffer
[i
] != first
) {
2197 if(i
== (start
+ LONG_WAIT
)) {
2201 if(start
== GraphTraceLen
- LONG_WAIT
) {
2202 PrintToScrollback("nothing to wait for");
2206 GraphBuffer
[start
] = 2;
2207 GraphBuffer
[start
+1] = -2;
2213 for(bit
= 0; bit
< 64; bit
++) {
2216 for(j
= 0; j
< 16; j
++) {
2217 sum
+= GraphBuffer
[i
++];
2224 PrintToScrollback("bit %d sum %d", bit
, sum
);
2227 for(bit
= 0; bit
< 64; bit
++) {
2230 for(j
= 0; j
< 16; j
++) {
2231 sum
+= GraphBuffer
[i
++];
2233 if(sum
> 0 && bits
[bit
] != 1) {
2234 PrintToScrollback("oops1 at %d", bit
);
2236 if(sum
< 0 && bits
[bit
] != 0) {
2237 PrintToScrollback("oops2 at %d", bit
);
2241 GraphTraceLen
= 32*64;
2244 for(bit
= 0; bit
< 64; bit
++) {
2245 if(bits
[bit
] == 0) {
2251 for(j
= 0; j
< 32; j
++) {
2252 GraphBuffer
[i
++] = phase
;
2257 RepaintGraphWindow();
2261 * Generic command to demodulate ASK.
2263 * Argument is convention: positive or negative (High mod means zero
2264 * or high mod means one)
2266 * Updates the Graph trace with 0/1 values
2272 static void Cmdaskdemod(char *str
) {
2274 int c
, high
= 0, low
= 0;
2276 // TODO: complain if we do not give 2 arguments here !
2277 // (AL - this doesn't make sense! we're only using one argument!!!)
2278 sscanf(str
, "%i", &c
);
2280 /* Detect high and lows and clock */
2282 for (i
= 0; i
< GraphTraceLen
; i
++)
2284 if (GraphBuffer
[i
] > high
)
2285 high
= GraphBuffer
[i
];
2286 else if (GraphBuffer
[i
] < low
)
2287 low
= GraphBuffer
[i
];
2289 if(c
!= 0 && c
!= 1) {
2290 PrintToScrollback("Invalid argument: %s",str
);
2294 if (GraphBuffer
[0] > 0) {
2295 GraphBuffer
[0] = 1-c
;
2299 for(i
=1;i
<GraphTraceLen
;i
++) {
2300 /* Transitions are detected at each peak
2301 * Transitions are either:
2302 * - we're low: transition if we hit a high
2303 * - we're high: transition if we hit a low
2304 * (we need to do it this way because some tags keep high or
2305 * low for long periods, others just reach the peak and go
2308 if ((GraphBuffer
[i
]==high
) && (GraphBuffer
[i
-1] == c
)) {
2310 } else if ((GraphBuffer
[i
]==low
) && (GraphBuffer
[i
-1] == (1-c
))){
2314 GraphBuffer
[i
] = GraphBuffer
[i
-1];
2317 RepaintGraphWindow();
2320 /* Print our clock rate */
2321 static void Cmddetectclockrate(char *str
)
2323 int clock
= detectclock(0);
2324 PrintToScrollback("Auto-detected clock rate: %d", clock
);
2330 int detectclock(int peak
)
2336 /* Detect peak if we don't have one */
2338 for (i
= 0; i
< GraphTraceLen
; i
++)
2339 if (GraphBuffer
[i
] > peak
)
2340 peak
= GraphBuffer
[i
];
2342 for (i
= 1; i
< GraphTraceLen
; i
++)
2344 /* If this is the beginning of a peak */
2345 if (GraphBuffer
[i
-1] != GraphBuffer
[i
] && GraphBuffer
[i
] == peak
)
2347 /* Find lowest difference between peaks */
2348 if (lastpeak
&& i
- lastpeak
< clock
)
2350 clock
= i
- lastpeak
;
2359 /* Get or auto-detect clock rate */
2360 int GetClock(char *str
, int peak
)
2364 sscanf(str
, "%i", &clock
);
2365 if (!strcmp(str
, ""))
2368 /* Auto-detect clock */
2371 clock
= detectclock(peak
);
2373 /* Only print this message if we're not looping something */
2375 PrintToScrollback("Auto-detected clock rate: %d", clock
);
2382 * Convert to a bitstream
2384 static void Cmdbitstream(char *str
) {
2391 int hithigh
, hitlow
, first
;
2393 /* Detect high and lows and clock */
2394 for (i
= 0; i
< GraphTraceLen
; i
++)
2396 if (GraphBuffer
[i
] > high
)
2397 high
= GraphBuffer
[i
];
2398 else if (GraphBuffer
[i
] < low
)
2399 low
= GraphBuffer
[i
];
2403 clock
= GetClock(str
, high
);
2405 gtl
= CmdClearGraph(0);
2408 for (i
= 0; i
< (int)(gtl
/ clock
); i
++)
2414 /* Find out if we hit both high and low peaks */
2415 for (j
= 0; j
< clock
; j
++)
2417 if (GraphBuffer
[(i
* clock
) + j
] == high
)
2419 else if (GraphBuffer
[(i
* clock
) + j
] == low
)
2422 /* it doesn't count if it's the first part of our read
2423 because it's really just trailing from the last sequence */
2424 if (first
&& (hithigh
|| hitlow
))
2425 hithigh
= hitlow
= 0;
2429 if (hithigh
&& hitlow
)
2433 /* If we didn't hit both high and low peaks, we had a bit transition */
2434 if (!hithigh
|| !hitlow
)
2437 CmdAppendGraph(0, clock
, bit
);
2438 // for (j = 0; j < (int)(clock/2); j++)
2439 // GraphBuffer[(i * clock) + j] = bit ^ 1;
2440 // for (j = (int)(clock/2); j < clock; j++)
2441 // GraphBuffer[(i * clock) + j] = bit;
2444 RepaintGraphWindow();
2447 /* Modulate our data into manchester */
2448 static void Cmdmanchestermod(char *str
)
2452 int bit
, lastbit
, wave
;
2455 clock
= GetClock(str
, 0);
2459 for (i
= 0; i
< (int)(GraphTraceLen
/ clock
); i
++)
2461 bit
= GraphBuffer
[i
* clock
] ^ 1;
2463 for (j
= 0; j
< (int)(clock
/2); j
++)
2464 GraphBuffer
[(i
* clock
) + j
] = bit
^ lastbit
^ wave
;
2465 for (j
= (int)(clock
/2); j
< clock
; j
++)
2466 GraphBuffer
[(i
* clock
) + j
] = bit
^ lastbit
^ wave
^ 1;
2468 /* Keep track of how we start our wave and if we changed or not this time */
2469 wave
^= bit
^ lastbit
;
2473 RepaintGraphWindow();
2477 * Manchester demodulate a bitstream. The bitstream needs to be already in
2478 * the GraphBuffer as 0 and 1 values
2480 * Give the clock rate as argument in order to help the sync - the algorithm
2481 * resyncs at each pulse anyway.
2483 * Not optimized by any means, this is the 1st time I'm writing this type of
2484 * routine, feel free to improve...
2486 * 1st argument: clock rate (as number of samples per clock rate)
2487 * Typical values can be 64, 32, 128...
2489 static void Cmdmanchesterdemod(char *str
) {
2490 int i
, j
, invert
= 0;
2496 int hithigh
, hitlow
, first
;
2502 /* check if we're inverting output */
2505 PrintToScrollback("Inverting output");
2509 while(*str
== ' '); // in case a 2nd argument was given
2512 /* Holds the decoded bitstream: each clock period contains 2 bits */
2513 /* later simplified to 1 bit after manchester decoding. */
2514 /* Add 10 bits to allow for noisy / uncertain traces without aborting */
2515 /* int BitStream[GraphTraceLen*2/clock+10]; */
2517 /* But it does not work if compiling on WIndows: therefore we just allocate a */
2519 int BitStream
[MAX_GRAPH_TRACE_LEN
];
2521 /* Detect high and lows */
2522 for (i
= 0; i
< GraphTraceLen
; i
++)
2524 if (GraphBuffer
[i
] > high
)
2525 high
= GraphBuffer
[i
];
2526 else if (GraphBuffer
[i
] < low
)
2527 low
= GraphBuffer
[i
];
2531 clock
= GetClock(str
, high
);
2533 int tolerance
= clock
/4;
2535 /* Detect first transition */
2536 /* Lo-Hi (arbitrary) */
2537 /* skip to the first high */
2538 for (i
= 0; i
< GraphTraceLen
; i
++)
2539 if(GraphBuffer
[i
] == high
)
2541 /* now look for the first low */
2542 for (; i
< GraphTraceLen
; i
++)
2544 if (GraphBuffer
[i
] == low
)
2551 /* If we're not working with 1/0s, demod based off clock */
2554 bit
= 0; /* We assume the 1st bit is zero, it may not be
2555 * the case: this routine (I think) has an init problem.
2558 for (; i
< (int)(GraphTraceLen
/ clock
); i
++)
2564 /* Find out if we hit both high and low peaks */
2565 for (j
= 0; j
< clock
; j
++)
2567 if (GraphBuffer
[(i
* clock
) + j
] == high
)
2569 else if (GraphBuffer
[(i
* clock
) + j
] == low
)
2572 /* it doesn't count if it's the first part of our read
2573 because it's really just trailing from the last sequence */
2574 if (first
&& (hithigh
|| hitlow
))
2575 hithigh
= hitlow
= 0;
2579 if (hithigh
&& hitlow
)
2583 /* If we didn't hit both high and low peaks, we had a bit transition */
2584 if (!hithigh
|| !hitlow
)
2587 BitStream
[bit2idx
++] = bit
^ invert
;
2591 /* standard 1/0 bitstream */
2595 /* Then detect duration between 2 successive transitions */
2596 for (bitidx
= 1; i
< GraphTraceLen
; i
++)
2598 if (GraphBuffer
[i
-1] != GraphBuffer
[i
])
2603 // Error check: if bitidx becomes too large, we do not
2604 // have a Manchester encoded bitstream or the clock is really
2606 if (bitidx
> (GraphTraceLen
*2/clock
+8) ) {
2607 PrintToScrollback("Error: the clock you gave is probably wrong, aborting.");
2610 // Then switch depending on lc length:
2611 // Tolerance is 1/4 of clock rate (arbitrary)
2612 if (abs(lc
-clock
/2) < tolerance
) {
2613 // Short pulse : either "1" or "0"
2614 BitStream
[bitidx
++]=GraphBuffer
[i
-1];
2615 } else if (abs(lc
-clock
) < tolerance
) {
2616 // Long pulse: either "11" or "00"
2617 BitStream
[bitidx
++]=GraphBuffer
[i
-1];
2618 BitStream
[bitidx
++]=GraphBuffer
[i
-1];
2622 PrintToScrollback("Warning: Manchester decode error for pulse width detection.");
2623 PrintToScrollback("(too many of those messages mean either the stream is not Manchester encoded, or clock is wrong)");
2627 PrintToScrollback("Error: too many detection errors, aborting.");
2634 // At this stage, we now have a bitstream of "01" ("1") or "10" ("0"), parse it into final decoded bitstream
2635 // Actually, we overwrite BitStream with the new decoded bitstream, we just need to be careful
2636 // to stop output at the final bitidx2 value, not bitidx
2637 for (i
= 0; i
< bitidx
; i
+= 2) {
2638 if ((BitStream
[i
] == 0) && (BitStream
[i
+1] == 1)) {
2639 BitStream
[bit2idx
++] = 1 ^ invert
;
2640 } else if ((BitStream
[i
] == 1) && (BitStream
[i
+1] == 0)) {
2641 BitStream
[bit2idx
++] = 0 ^ invert
;
2643 // We cannot end up in this state, this means we are unsynchronized,
2647 PrintToScrollback("Unsynchronized, resync...");
2648 PrintToScrollback("(too many of those messages mean the stream is not Manchester encoded)");
2652 PrintToScrollback("Error: too many decode errors, aborting.");
2659 PrintToScrollback("Manchester decoded bitstream");
2660 // Now output the bitstream to the scrollback by line of 16 bits
2661 for (i
= 0; i
< (bit2idx
-16); i
+=16) {
2662 PrintToScrollback("%i %i %i %i %i %i %i %i %i %i %i %i %i %i %i %i",
2685 static void CmdHiddemod(char *str
)
2687 if(GraphTraceLen
< 4800) {
2688 PrintToScrollback("too short; need at least 4800 samples");
2692 GraphTraceLen
= 4800;
2694 for(i
= 0; i
< GraphTraceLen
; i
++) {
2695 if(GraphBuffer
[i
] < 0) {
2701 RepaintGraphWindow();
2704 static void CmdPlot(char *str
)
2709 static void CmdGrid(char *str
)
2711 sscanf(str
, "%i %i", &PlotGridX
, &PlotGridY
);
2712 RepaintGraphWindow();
2715 static void CmdHide(char *str
)
2720 static void CmdScale(char *str
)
2722 CursorScaleFactor
= atoi(str
);
2723 if(CursorScaleFactor
== 0) {
2724 PrintToScrollback("bad, can't have zero scale");
2725 CursorScaleFactor
= 1;
2727 RepaintGraphWindow();
2730 static void CmdSave(char *str
)
2732 FILE *f
= fopen(str
, "w");
2734 PrintToScrollback("couldn't open '%s'", str
);
2738 for(i
= 0; i
< GraphTraceLen
; i
++) {
2739 fprintf(f
, "%d\n", GraphBuffer
[i
]);
2742 PrintToScrollback("saved to '%s'", str
);
2745 static void CmdLoad(char *str
)
2747 FILE *f
= fopen(str
, "r");
2749 PrintToScrollback("couldn't open '%s'", str
);
2755 while(fgets(line
, sizeof(line
), f
)) {
2756 GraphBuffer
[GraphTraceLen
] = atoi(line
);
2760 PrintToScrollback("loaded %d samples", GraphTraceLen
);
2761 RepaintGraphWindow();
2764 static void CmdHIDsimTAG(char *str
)
2766 unsigned int hi
=0, lo
=0;
2769 while (sscanf(&str
[i
++], "%1x", &n
) == 1) {
2770 hi
=(hi
<<4)|(lo
>>28);
2774 PrintToScrollback("Emulating tag with ID %x%16x", hi
, lo
);
2776 UsbCommand c
={CMD_HID_SIM_TAG
, {hi
, lo
, 0}};
2780 static void CmdReadmem(char *str
)
2782 UsbCommand c
={CMD_READ_MEM
, {strtol(str
, NULL
, 0), 0, 0}};
2786 static void CmdVersion(char *str
)
2788 UsbCommand c
={CMD_VERSION
};
2792 static void CmdLcdReset(char *str
)
2794 UsbCommand c
={CMD_LCD_RESET
, {strtol(str
, NULL
, 0), 0, 0}};
2798 static void CmdLcd(char *str
)
2801 UsbCommand c
={CMD_LCD
};
2802 sscanf(str
, "%x %d", &i
, &j
);
2810 * Sets the divisor for LF frequency clock: lets the user choose any LF frequency below
2813 static void CmdSetDivisor(char *str
)
2815 UsbCommand c
={CMD_SET_LF_DIVISOR
, {strtol(str
, NULL
, 0), 0, 0}};
2816 if (( c
.arg
[0]<0) || (c
.arg
[0]>255)) {
2817 PrintToScrollback("divisor must be between 19 and 255");
2820 PrintToScrollback("Divisor set, expected freq=%dHz", 12000000/(c
.arg
[0]+1));
2824 static void CmdSetMux(char *str
)
2826 UsbCommand c
={CMD_SET_ADC_MUX
};
2827 if(strcmp(str
, "lopkd") == 0) {
2829 } else if(strcmp(str
, "loraw") == 0) {
2831 } else if(strcmp(str
, "hipkd") == 0) {
2833 } else if(strcmp(str
, "hiraw") == 0) {
2839 typedef void HandlerFunction(char *cmdline
);
2841 /* in alphabetic order */
2844 HandlerFunction
*handler
;
2845 int offline
; // 1 if the command can be used when in offline mode
2847 } CommandTable
[] = {
2848 /* plot window / data buffer manipulation */
2849 {"buffclear", CmdBuffClear
, 1, "Clear sample buffer and graph window"},
2850 {"load", CmdLoad
, 1, "<filename> -- Load trace (to graph window"},
2851 {"save", CmdSave
, 1, "<filename> -- Save trace (from graph window)"},
2852 {"amp", CmdAmp
, 1, "Amplify peaks"},
2853 {"autocorr", CmdAutoCorr
, 1, "<window length> -- Autocorrelation over window"},
2854 {"dec", CmdDec
, 1, "Decimate samples"},
2855 {"hpf", CmdHpf
, 1, "Remove DC offset from trace"},
2856 {"ltrim", CmdLtrim
, 1, "<samples> -- Trim samples from left of trace"},
2857 {"norm", CmdNorm
, 1, "Normalize max/min to +/-500"},
2858 {"plot", CmdPlot
, 1, "Show graph window"},
2859 {"hide", CmdHide
, 1, "Hide graph window"},
2860 {"grid", CmdGrid
, 1, "<x> <y> -- overlay grid on graph window, use zero value to turn off either"},
2861 {"threshold", CmdThreshold
, 1, "Maximize/minimize every value in the graph window depending on threshold"},
2862 {"zerocrossings", CmdZerocrossings
, 1, "Count time between zero-crossings"},
2863 {"scale", CmdScale
, 1, "<int> -- Set cursor display scale"},
2864 {"bitstream", Cmdbitstream
, 1, "[clock rate] -- Convert waveform into a bitstream"},
2865 {"detectclock", Cmddetectclockrate
, 1, "Detect clock rate"},
2866 {"exit", CmdQuit
, 1, "Exit program"},
2867 {"quit", CmdQuit
, 1, "Exit program"},
2869 /* low-level hardware control */
2870 {"fpgaoff", CmdFPGAOff
, 0, "Set FPGA off"},
2871 {"tune", CmdTune
, 0, "Measure antenna tuning"},
2872 {"hitune", CmdHiTune
, 0, "Continuously measure HF antenna tuning"},
2873 {"readmem", CmdReadmem
, 0, "[address] -- Read memory at decimal address from flash"},
2874 {"reset", CmdReset
, 0, "Reset the Proxmark3"},
2875 {"setlfdivisor", CmdSetDivisor
, 0, "<19 - 255> -- Drive LF antenna at 12Mhz/(divisor+1)"},
2876 {"setmux", CmdSetMux
, 0, "<loraw|hiraw|lopkd|hipkd> -- Set the ADC mux to a specific value"},
2877 {"version", CmdVersion
, 0, "Show version inforation about the connected Proxmark"},
2878 {"lcd", CmdLcd
, 0, "<HEX command> <count> -- Send command/data to LCD"},
2879 {"lcdreset", CmdLcdReset
, 0, "Hardware reset LCD"},
2881 /* data transfer functions */
2883 {"bitsamples", CmdBitsamples
, 0, "Get raw samples as bitstring"},
2884 {"hexsamples", CmdHexsamples
, 0, "<blocks> [<offset>] -- Dump big buffer as hex bytes"},
2885 {"higet", CmdHi14read_sim
, 0, "<samples> -- Get samples HF, 'analog'"},
2886 {"hisamples", CmdHisamples
, 0, "Get raw samples for HF tag"},
2887 {"hisampless", CmdHisampless
, 0, "<samples> -- Get signed raw samples, HF tag"},
2888 {"hisamplest", CmdHi14readt
, 0, "Get samples HF, for testing"},
2889 {"losamples", CmdLosamples
, 0, "[128 - 16000] -- Get raw samples for LF tag"},
2890 {"detectreader", CmdDetectReader
, 0, "['l'|'h'] -- Detect external reader field (option 'l' or 'h' to limit to LF or HF)"},
2892 /* (de-)modulation */
2894 {"askdemod", Cmdaskdemod
, 1, "<0|1> -- Attempt to demodulate simple ASK tags"},
2895 {"flexdemod", CmdFlexdemod
, 1, "Demodulate samples for FlexPass"},
2896 {"fskdemod", CmdFSKdemod
, 1, "Demodulate graph window as a HID FSK"},
2897 {"hi14bdemod", CmdHi14bdemod
, 1, "Demodulate ISO14443 Type B from tag"},
2898 {"hi15demod", CmdHi15demod
, 1, "Demodulate ISO15693 from tag"},
2899 {"hiddemod", CmdHiddemod
, 1, "Demodulate HID Prox Card II (not optimal)"},
2900 {"hidfskdemod", CmdHIDdemodFSK
, 0, "Realtime HID FSK demodulator"},
2901 {"indalademod", CmdIndalademod
, 1, "['224'] -- Demodulate samples for Indala 64 bit UID (option '224' for 224 bit)"},
2902 {"mandemod", Cmdmanchesterdemod
, 1, "[i] [clock rate] -- Manchester demodulate binary stream (option 'i' to invert output)"},
2903 {"manmod", Cmdmanchestermod
, 1, "[clock rate] -- Manchester modulate a binary stream"},
2904 {"tidemod", CmdTIDemod
, 1, "Demodulate raw bits for TI-type LF tag"},
2905 {"vchdemod", CmdVchdemod
, 1, "['clone'] -- Demodulate samples for VeriChip"},
2908 {"em410xsim", CmdEM410xsim
, 1, "<UID> -- Simulate EM410x tag"},
2909 {"hi14sim", CmdHi14sim
, 0, "Fake ISO 14443 tag"},
2910 {"hi14asim", CmdHi14asim
, 0, "<UID> -- Fake ISO 14443a tag"},
2911 {"hi15sim", CmdHi15tag
, 0, "Fake an ISO15693 tag"},
2912 {"hidsimtag", CmdHIDsimTAG
, 0, "<ID> -- HID tag simulator"},
2913 {"hisimlisten", CmdHisimlisten
, 0, "Get HF samples as fake tag"},
2914 {"losim", CmdLosim
, 0, "[GAP] -- Simulate LF tag from buffer with optional GAP (in microseconds)"},
2915 {"losimman", CmdLosimManchester
, 0, "<Clock> <Bitstream> [GAP] Simulate arbitrary Manchester LF tag"},
2916 {"losimbidir", CmdLosimBidir
, 0, "Simulate LF tag (with bidirectional data transmission between reader and tag)"},
2918 /* card reading functions */
2919 {"em410xread", CmdEM410xread
, 1, "[clock rate] -- Extract ID from EM410x tag"},
2920 {"em410xwatch", CmdEM410xwatch
, 0, "Watches for EM410x tags"},
2921 {"em4x50read", CmdEM4x50read
, 1, "Extract data from EM4x50 tag"},
2922 {"hi14alist", CmdHi14alist
, 0, "List ISO 14443a history"},
2923 {"hi14amifare", CmdHi14amifare
, 0, "Read out sector 0 parity error messages"},
2924 {"hi14areader", CmdHi14areader
, 0, "Act like an ISO14443 Type A reader"},
2925 {"hi14asnoop", CmdHi14asnoop
, 0, "Eavesdrop ISO 14443 Type A"},
2926 {"hi14list", CmdHi14list
, 0, "List ISO 14443 history"},
2927 {"hi14read", CmdHi14read
, 0, "Read HF tag (ISO 14443)"},
2928 {"hi14snoop", CmdHi14snoop
, 0, "Eavesdrop ISO 14443"},
2929 {"hi15read", CmdHi15read
, 0, "Read HF tag (ISO 15693)"},
2930 {"hi15reader", CmdHi15reader
, 0, "Act like an ISO15693 reader"},
2931 {"legicrfread", CmdLegicRfRead
, 0, "Start the LEGIC RF reader"},
2932 {"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)"},
2933 {"loread", CmdLoread
, 0, "['h'] -- Read 125/134 kHz LF ID-only tag (option 'h' for 134)"},
2934 {"sri512read", CmdSri512read
, 0, "<int> -- Read contents of a SRI512 tag"},
2935 {"srix4kread", CmdSrix4kread
, 0, "<int> -- Read contents of a SRIX4K tag"},
2936 {"tiread", CmdTIRead
, 0, "Read and decode a TI 134 kHz tag"},
2937 {"tiwrite", CmdTIWrite
, 0, "Write new data to a r/w TI 134 kHz tag"},
2945 } CommandExtendedHelp
[]= {
2946 {"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."},
2947 {"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."},
2950 //-----------------------------------------------------------------------------
2951 // Entry point into our code: called whenever the user types a command and
2952 // then presses Enter, which the full command line that they typed.
2953 //-----------------------------------------------------------------------------
2954 void CommandReceived(char *cmd
)
2959 PrintToScrollback("> %s", cmd
);
2961 if(strcmp(cmd
, "help") == 0 || strncmp(cmd
,"help ",strlen("help ")) == 0) {
2962 // check if we're doing extended help
2963 if(strlen(cmd
) > strlen("help ")) {
2964 cmd
+= strlen("help ");
2965 for(i
= 0; i
< sizeof(CommandExtendedHelp
) / sizeof(CommandExtendedHelp
[0]); i
++) {
2966 if(strcmp(CommandExtendedHelp
[i
].name
,cmd
) == 0) {
2967 PrintToScrollback("\nExtended help for '%s':\n", cmd
);
2968 PrintToScrollback("Args: %s\t- %s\n",CommandExtendedHelp
[i
].args
,CommandExtendedHelp
[i
].argshelp
);
2969 PrintToScrollback(CommandExtendedHelp
[i
].description
);
2970 PrintToScrollback("");
2974 PrintToScrollback("No extended help available for '%s'", cmd
);
2977 if (offline
) PrintToScrollback("Operating in OFFLINE mode (no device connected)");
2978 PrintToScrollback("\r\nAvailable commands:");
2979 for(i
= 0; i
< sizeof(CommandTable
) / sizeof(CommandTable
[0]); i
++) {
2980 if (offline
&& (CommandTable
[i
].offline
==0)) continue;
2981 memset(line
, ' ', sizeof(line
));
2982 strcpy(line
+2, CommandTable
[i
].name
);
2983 line
[strlen(line
)] = ' ';
2984 sprintf(line
+15, " -- %s", CommandTable
[i
].docString
);
2985 PrintToScrollback("%s", line
);
2987 PrintToScrollback("");
2988 PrintToScrollback("'help <command>' for extended help on that command\n");
2992 for(i
= 0; i
< sizeof(CommandTable
) / sizeof(CommandTable
[0]); i
++) {
2993 char *name
= CommandTable
[i
].name
;
2994 if(memcmp(cmd
, name
, strlen(name
))==0 &&
2995 (cmd
[strlen(name
)] == ' ' || cmd
[strlen(name
)] == '\0'))
2997 cmd
+= strlen(name
);
2998 while(*cmd
== ' ') {
3001 if (offline
&& (CommandTable
[i
].offline
==0)) {
3002 PrintToScrollback("Offline mode, cannot use this command.");
3005 (CommandTable
[i
].handler
)(cmd
);
3009 PrintToScrollback(">> bad command '%s'", cmd
);
3012 //-----------------------------------------------------------------------------
3013 // Entry point into our code: called whenever we received a packet over USB
3014 // that we weren't necessarily expecting, for example a debug print.
3015 //-----------------------------------------------------------------------------
3016 void UsbCommandReceived(UsbCommand
*c
)
3018 // printf("%s(%x) current cmd = %x\n", __FUNCTION__, c->cmd, current_command);
3019 /* If we recognize a response, return to avoid further processing */
3021 case CMD_DEBUG_PRINT_STRING
: {
3023 if(c
->arg
[0] > 70 || c
->arg
[0] < 0) {
3026 memcpy(s
, c
->d
.asBytes
, c
->arg
[0]);
3027 s
[c
->arg
[0]] = '\0';
3028 PrintToScrollback("#db# %s", s
);
3032 case CMD_DEBUG_PRINT_INTEGERS
:
3033 PrintToScrollback("#db# %08x, %08x, %08x\r\n", c
->arg
[0], c
->arg
[1], c
->arg
[2]);
3036 case CMD_MEASURED_ANTENNA_TUNING
: {
3038 int vLf125
, vLf134
, vHf
;
3039 vLf125
= c
->arg
[0] & 0xffff;
3040 vLf134
= c
->arg
[0] >> 16;
3041 vHf
= c
->arg
[1] & 0xffff;;
3042 peakf
= c
->arg
[2] & 0xffff;
3043 peakv
= c
->arg
[2] >> 16;
3044 PrintToScrollback("");
3045 PrintToScrollback("");
3046 PrintToScrollback("# LF antenna: %5.2f V @ 125.00 kHz", vLf125
/1000.0);
3047 PrintToScrollback("# LF antenna: %5.2f V @ 134.00 kHz", vLf134
/1000.0);
3048 PrintToScrollback("# LF optimal: %5.2f V @%9.2f kHz", peakv
/1000.0, 12000.0/(peakf
+1));
3049 PrintToScrollback("# HF antenna: %5.2f V @ 13.56 MHz", vHf
/1000.0);
3051 PrintToScrollback("# Your LF antenna is unusable.");
3052 else if (peakv
<10000)
3053 PrintToScrollback("# Your LF antenna is marginal.");
3055 PrintToScrollback("# Your HF antenna is unusable.");
3057 PrintToScrollback("# Your HF antenna is marginal.");
3063 /* Maybe it's a response: */
3064 switch(current_command
) {
3065 case CMD_DOWNLOAD_RAW_ADC_SAMPLES_125K
:
3066 if (c
->cmd
!= CMD_DOWNLOADED_RAW_ADC_SAMPLES_125K
) goto unexpected_response
;
3068 for(i
=0; i
<48; i
++) sample_buf
[i
] = c
->d
.asBytes
[i
];
3069 received_command
= c
->cmd
;
3072 unexpected_response
:
3073 PrintToScrollback("unrecognized command %08x\n", c
->cmd
);