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 PrintToScrollback("Sending data, please wait...");
692 for (i
= 0; i
< GraphTraceLen
; i
+= 48) {
693 UsbCommand c
={CMD_DOWNLOADED_SIM_SAMPLES_125K
, {i
, 0, 0}};
695 for(j
= 0; j
< 48; j
++) {
696 c
.d
.asBytes
[j
] = GraphBuffer
[i
+j
];
699 wait_for_response(CMD_ACK
);
702 PrintToScrollback("Starting simulator...");
703 UsbCommand c
={CMD_SIMULATE_TAG_125K
, {GraphTraceLen
, gap
, 0}};
707 static void CmdLosimBidir(char *str
)
709 /* Set ADC to twice the carrier for a slight supersampling */
710 UsbCommand c
={CMD_LF_SIMULATE_BIDIR
, {47, 384, 0}};
714 static void CmdLoread(char *str
)
716 UsbCommand c
={CMD_ACQUIRE_RAW_ADC_SAMPLES_125K
};
717 // 'h' means higher-low-frequency, 134 kHz
720 } else if (*str
== '\0') {
723 PrintToScrollback("use 'loread' or 'loread h'");
729 static void CmdDetectReader(char *str
)
731 UsbCommand c
={CMD_LISTEN_READER_FIELD
};
732 // 'l' means LF - 125/134 kHz
735 } else if (*str
== 'h') {
737 } else if (*str
!= '\0') {
738 PrintToScrollback("use 'detectreader' or 'detectreader l' or 'detectreader h'");
744 /* send a command before reading */
745 static void CmdLoCommandRead(char *str
)
747 static char dummy
[3];
751 UsbCommand c
={CMD_MOD_THEN_ACQUIRE_RAW_ADC_SAMPLES_125K
};
752 sscanf(str
, "%i %i %i %s %s", &c
.arg
[0], &c
.arg
[1], &c
.arg
[2], (char *) &c
.d
.asBytes
,(char *) &dummy
+1);
753 // in case they specified 'h'
754 strcpy((char *)&c
.d
.asBytes
+ strlen((char *)c
.d
.asBytes
), dummy
);
758 static void CmdLosamples(char *str
)
763 n
=strtol(str
, NULL
, 0);
765 if (n
>16000) n
=16000;
767 PrintToScrollback("Reading %d samples\n", n
);
768 for(i
= 0; i
< n
; i
+= 12) {
769 UsbCommand c
= {CMD_DOWNLOAD_RAW_ADC_SAMPLES_125K
, {i
, 0, 0}};
771 wait_for_response(CMD_DOWNLOADED_RAW_ADC_SAMPLES_125K
);
772 for(j
= 0; j
< 48; j
++) {
773 GraphBuffer
[cnt
++] = ((int)sample_buf
[j
]) - 128;
776 PrintToScrollback("Done!\n");
778 RepaintGraphWindow();
781 static void CmdBitsamples(char *str
)
787 for(i
= 0; i
< n
; i
+= 12) {
788 UsbCommand c
= {CMD_DOWNLOAD_RAW_ADC_SAMPLES_125K
, {i
, 0, 0}};
790 wait_for_response(CMD_DOWNLOADED_RAW_ADC_SAMPLES_125K
);
792 for(j
= 0; j
< 48; j
++) {
793 for(k
= 0; k
< 8; k
++) {
794 if(sample_buf
[j
] & (1 << (7 - k
))) {
795 GraphBuffer
[cnt
++] = 1;
797 GraphBuffer
[cnt
++] = 0;
803 RepaintGraphWindow();
806 static void CmdHisamples(char *str
)
812 for(i
= 0; i
< n
; i
+= 12) {
813 UsbCommand c
= {CMD_DOWNLOAD_RAW_ADC_SAMPLES_125K
, {i
, 0, 0}};
815 wait_for_response(CMD_DOWNLOADED_RAW_ADC_SAMPLES_125K
);
816 for(j
= 0; j
< 48; j
++) {
817 GraphBuffer
[cnt
++] = (int)(sample_buf
[j
]);
822 RepaintGraphWindow();
825 static int CmdHisamplest(char *str
, int nrlow
)
835 for(i
= 0; i
< n
; i
+= 12) {
836 UsbCommand c
= {CMD_DOWNLOAD_RAW_ADC_SAMPLES_125K
, {i
, 0, 0}};
838 wait_for_response(CMD_DOWNLOADED_RAW_ADC_SAMPLES_125K
);
839 for(j
= 0; j
< 48; j
++) {
840 t2
= (int)(sample_buf
[j
]);
841 if((t2
^ 0xC0) & 0xC0) { hasbeennull
++; }
847 t1
= (t2
& 0x80) ^ (t2
& 0x20);
848 t2
= ((t2
<< 1) & 0x80) ^ ((t2
<< 1) & 0x20);
854 t2
= ((t2
<< 1) & 0x80);
860 t2
= ((t2
<< 1) & 0x20);
864 // both, but tag with other algorithm
865 t1
= (t2
& 0x80) ^ (t2
& 0x08);
866 t2
= ((t2
<< 1) & 0x80) ^ ((t2
<< 1) & 0x08);
870 GraphBuffer
[cnt
++] = t1
;
871 GraphBuffer
[cnt
++] = t2
;
876 if(hasbeennull
>nrlow
|| nrlow
==0) {
877 PrintToScrollback("hasbeennull=%d", hasbeennull
);
886 static void CmdHexsamples(char *str
)
891 sscanf(str
, "%i %i", &requested
, &offset
);
893 PrintToScrollback("Offset must be a multiple of 4");
900 if (requested
== 0) {
907 for(i
= offset
; i
< n
+offset
; i
+= 12) {
908 UsbCommand c
= {CMD_DOWNLOAD_RAW_ADC_SAMPLES_125K
, {i
, 0, 0}};
910 wait_for_response(CMD_DOWNLOADED_RAW_ADC_SAMPLES_125K
);
911 for (j
= 0; j
< 48; j
+= 8) {
912 PrintToScrollback("%02x %02x %02x %02x %02x %02x %02x %02x",
924 if (delivered
>= requested
)
927 if (delivered
>= requested
)
932 static void CmdHisampless(char *str
)
936 int n
= strtol(str
, NULL
, 0);
944 for(i
= 0; i
< n
; i
+= 12) {
945 UsbCommand c
= {CMD_DOWNLOAD_RAW_ADC_SAMPLES_125K
, {i
, 0, 0}};
947 wait_for_response(CMD_DOWNLOADED_RAW_ADC_SAMPLES_125K
);
948 for(j
= 0; j
< 48; j
++) {
949 GraphBuffer
[cnt
++] = (int)(sample_buf
[j
]);
954 RepaintGraphWindow();
957 static uint16_t Iso15693Crc(uint8_t *v
, int n
)
963 for(i
= 0; i
< n
; i
++) {
964 reg
= reg
^ ((uint32_t)v
[i
]);
965 for (j
= 0; j
< 8; j
++) {
967 reg
= (reg
>> 1) ^ 0x8408;
974 return (uint16_t)~reg
;
977 static void CmdHi14bdemod(char *str
)
982 bool negateI
, negateQ
;
987 // As received, the samples are pairs, correlations against I and Q
988 // square waves. So estimate angle of initial carrier (or just
989 // quadrant, actually), and then do the demod.
991 // First, estimate where the tag starts modulating.
992 for(i
= 0; i
< GraphTraceLen
; i
+= 2) {
993 if(abs(GraphBuffer
[i
]) + abs(GraphBuffer
[i
+1]) > 40) {
997 if(i
>= GraphTraceLen
) {
998 PrintToScrollback("too weak to sync");
1001 PrintToScrollback("out of weak at %d", i
);
1004 // Now, estimate the phase in the initial modulation of the tag
1007 for(; i
< (outOfWeakAt
+ 16); i
+= 2) {
1008 isum
+= GraphBuffer
[i
+0];
1009 qsum
+= GraphBuffer
[i
+1];
1011 negateI
= (isum
< 0);
1012 negateQ
= (qsum
< 0);
1014 // Turn the correlation pairs into soft decisions on the bit.
1016 for(i
= 0; i
< GraphTraceLen
/2; i
++) {
1017 int si
= GraphBuffer
[j
];
1018 int sq
= GraphBuffer
[j
+1];
1019 if(negateI
) si
= -si
;
1020 if(negateQ
) sq
= -sq
;
1021 GraphBuffer
[i
] = si
+ sq
;
1027 while(GraphBuffer
[i
] > 0 && i
< GraphTraceLen
)
1029 if(i
>= GraphTraceLen
) goto demodError
;
1032 while(GraphBuffer
[i
] < 0 && i
< GraphTraceLen
)
1034 if(i
>= GraphTraceLen
) goto demodError
;
1035 if((i
- iold
) > 23) goto demodError
;
1037 PrintToScrollback("make it to demod loop");
1041 while(GraphBuffer
[i
] >= 0 && i
< GraphTraceLen
)
1043 if(i
>= GraphTraceLen
) goto demodError
;
1044 if((i
- iold
) > 6) goto demodError
;
1046 uint16_t shiftReg
= 0;
1047 if(i
+ 20 >= GraphTraceLen
) goto demodError
;
1049 for(j
= 0; j
< 10; j
++) {
1050 int soft
= GraphBuffer
[i
] + GraphBuffer
[i
+1];
1052 if(abs(soft
) < ((abs(isum
) + abs(qsum
))/20)) {
1053 PrintToScrollback("weak bit");
1057 if(GraphBuffer
[i
] + GraphBuffer
[i
+1] >= 0) {
1064 if( (shiftReg
& 0x200) &&
1065 !(shiftReg
& 0x001))
1067 // valid data byte, start and stop bits okay
1068 PrintToScrollback(" %02x", (shiftReg
>> 1) & 0xff);
1069 data
[dataLen
++] = (shiftReg
>> 1) & 0xff;
1070 if(dataLen
>= sizeof(data
)) {
1073 } else if(shiftReg
== 0x000) {
1081 uint8_t first
, second
;
1082 ComputeCrc14443(CRC_14443_B
, data
, dataLen
-2, &first
, &second
);
1083 PrintToScrollback("CRC: %02x %02x (%s)\n", first
, second
,
1084 (first
== data
[dataLen
-2] && second
== data
[dataLen
-1]) ?
1085 "ok" : "****FAIL****");
1087 RepaintGraphWindow();
1091 PrintToScrollback("demod error");
1092 RepaintGraphWindow();
1095 static void CmdHi14list(char *str
)
1098 GetFromBigBuf(got
, sizeof(got
));
1100 PrintToScrollback("recorded activity:");
1101 PrintToScrollback(" time :rssi: who bytes");
1102 PrintToScrollback("---------+----+----+-----------");
1113 int timestamp
= *((uint32_t *)(got
+i
));
1114 if(timestamp
& 0x80000000) {
1115 timestamp
&= 0x7fffffff;
1120 int metric
= *((uint32_t *)(got
+i
+4));
1127 if(i
+ len
>= 900) {
1131 uint8_t *frame
= (got
+i
+9);
1133 char line
[1000] = "";
1135 for(j
= 0; j
< len
; j
++) {
1136 sprintf(line
+(j
*3), "%02x ", frame
[j
]);
1142 ComputeCrc14443(CRC_14443_B
, frame
, len
-2, &b1
, &b2
);
1143 if(b1
!= frame
[len
-2] || b2
!= frame
[len
-1]) {
1144 crc
= "**FAIL CRC**";
1152 char metricString
[100];
1154 sprintf(metricString
, "%3d", metric
);
1156 strcpy(metricString
, " ");
1159 PrintToScrollback(" +%7d: %s: %s %s %s",
1160 (prev
< 0 ? 0 : timestamp
- prev
),
1162 (isResponse
? "TAG" : " "), line
, crc
);
1169 static void CmdHi14alist(char *str
)
1172 GetFromBigBuf(got
, sizeof(got
));
1174 PrintToScrollback("recorded activity:");
1175 PrintToScrollback(" ETU :rssi: who bytes");
1176 PrintToScrollback("---------+----+----+-----------");
1187 int timestamp
= *((uint32_t *)(got
+i
));
1188 if(timestamp
& 0x80000000) {
1189 timestamp
&= 0x7fffffff;
1196 int parityBits
= *((uint32_t *)(got
+i
+4));
1197 // 4 bytes of additional information...
1198 // maximum of 32 additional parity bit information
1201 // at each quarter bit period we can send power level (16 levels)
1202 // or each half bit period in 256 levels.
1210 if(i
+ len
>= 1900) {
1214 uint8_t *frame
= (got
+i
+9);
1216 // Break and stick with current result if buffer was not completely full
1217 if(frame
[0] == 0x44 && frame
[1] == 0x44 && frame
[3] == 0x44) { break; }
1219 char line
[1000] = "";
1221 for(j
= 0; j
< len
; j
++) {
1222 int oddparity
= 0x01;
1226 oddparity
^= (((frame
[j
] & 0xFF) >> k
) & 0x01);
1229 //if((parityBits >> (len - j - 1)) & 0x01) {
1230 if(isResponse
&& (oddparity
!= ((parityBits
>> (len
- j
- 1)) & 0x01))) {
1231 sprintf(line
+(j
*4), "%02x! ", frame
[j
]);
1234 sprintf(line
+(j
*4), "%02x ", frame
[j
]);
1242 for(j
= 0; j
< (len
- 1); j
++) {
1243 // gives problems... search for the reason..
1244 /*if(frame[j] == 0xAA) {
1245 switch(frame[j+1]) {
1247 crc = "[1] Two drops close after each other";
1250 crc = "[2] Potential SOC with a drop in second half of bitperiod";
1253 crc = "[3] Segment Z after segment X is not possible";
1256 crc = "[4] Parity bit of a fully received byte was wrong";
1259 crc = "[?] Unknown error";
1266 if(strlen(crc
)==0) {
1267 ComputeCrc14443(CRC_14443_A
, frame
, len
-2, &b1
, &b2
);
1268 if(b1
!= frame
[len
-2] || b2
!= frame
[len
-1]) {
1269 crc
= (isResponse
& (len
< 6)) ? "" : " !crc";
1278 char metricString
[100];
1280 sprintf(metricString
, "%3d", metric
);
1282 strcpy(metricString
, " ");
1285 PrintToScrollback(" +%7d: %s: %s %s %s",
1286 (prev
< 0 ? 0 : (timestamp
- prev
)),
1288 (isResponse
? "TAG" : " "), line
, crc
);
1293 CommandFinished
= 1;
1296 static void CmdHi15demod(char *str
)
1298 // The sampling rate is 106.353 ksps/s, for T = 18.8 us
1301 // 1) Unmodulated time of 56.64us
1302 // 2) 24 pulses of 423.75khz
1303 // 3) logic '1' (unmodulated for 18.88us followed by 8 pulses of 423.75khz)
1305 static const int FrameSOF
[] = {
1306 -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
1307 -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
1308 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
1309 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
1315 static const int Logic0
[] = {
1321 static const int Logic1
[] = {
1329 // 1) logic '0' (8 pulses of 423.75khz followed by unmodulated for 18.88us)
1330 // 2) 24 pulses of 423.75khz
1331 // 3) Unmodulated time of 56.64us
1333 static const int FrameEOF
[] = {
1338 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
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
1345 int max
= 0, maxPos
;
1349 if(GraphTraceLen
< 1000) return;
1351 // First, correlate for SOF
1352 for(i
= 0; i
< 100; i
++) {
1354 for(j
= 0; j
< arraylen(FrameSOF
); j
+= skip
) {
1355 corr
+= FrameSOF
[j
]*GraphBuffer
[i
+(j
/skip
)];
1362 PrintToScrollback("SOF at %d, correlation %d", maxPos
,
1363 max
/(arraylen(FrameSOF
)/skip
));
1365 i
= maxPos
+ arraylen(FrameSOF
)/skip
;
1368 memset(outBuf
, 0, sizeof(outBuf
));
1369 uint8_t mask
= 0x01;
1371 int corr0
= 0, corr1
= 0, corrEOF
= 0;
1372 for(j
= 0; j
< arraylen(Logic0
); j
+= skip
) {
1373 corr0
+= Logic0
[j
]*GraphBuffer
[i
+(j
/skip
)];
1375 for(j
= 0; j
< arraylen(Logic1
); j
+= skip
) {
1376 corr1
+= Logic1
[j
]*GraphBuffer
[i
+(j
/skip
)];
1378 for(j
= 0; j
< arraylen(FrameEOF
); j
+= skip
) {
1379 corrEOF
+= FrameEOF
[j
]*GraphBuffer
[i
+(j
/skip
)];
1381 // Even things out by the length of the target waveform.
1385 if(corrEOF
> corr1
&& corrEOF
> corr0
) {
1386 PrintToScrollback("EOF at %d", i
);
1388 } else if(corr1
> corr0
) {
1389 i
+= arraylen(Logic1
)/skip
;
1392 i
+= arraylen(Logic0
)/skip
;
1399 if((i
+(int)arraylen(FrameEOF
)) >= GraphTraceLen
) {
1400 PrintToScrollback("ran off end!");
1405 PrintToScrollback("error, uneven octet! (discard extra bits!)");
1406 PrintToScrollback(" mask=%02x", mask
);
1408 PrintToScrollback("%d octets", k
);
1410 for(i
= 0; i
< k
; i
++) {
1411 PrintToScrollback("# %2d: %02x ", i
, outBuf
[i
]);
1413 PrintToScrollback("CRC=%04x", Iso15693Crc(outBuf
, k
-2));
1416 static void CmdFSKdemod(char *cmdline
)
1418 static const int LowTone
[] = {
1419 1, 1, 1, 1, 1, -1, -1, -1, -1, -1,
1420 1, 1, 1, 1, 1, -1, -1, -1, -1, -1,
1421 1, 1, 1, 1, 1, -1, -1, -1, -1, -1,
1422 1, 1, 1, 1, 1, -1, -1, -1, -1, -1,
1423 1, 1, 1, 1, 1, -1, -1, -1, -1, -1
1425 static const int HighTone
[] = {
1426 1, 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,
1429 1, 1, 1, 1, -1, -1, -1, -1,
1430 1, 1, 1, 1, -1, -1, -1, -1,
1431 1, 1, 1, 1, -1, -1, -1, -1, -1,
1434 int lowLen
= sizeof(LowTone
)/sizeof(int);
1435 int highLen
= sizeof(HighTone
)/sizeof(int);
1436 int convLen
= (highLen
>lowLen
)?highLen
:lowLen
;
1437 uint32_t hi
= 0, lo
= 0;
1440 int minMark
=0, maxMark
=0;
1442 for(i
= 0; i
< GraphTraceLen
- convLen
; i
++) {
1443 int lowSum
= 0, highSum
= 0;
1445 for(j
= 0; j
< lowLen
; j
++) {
1446 lowSum
+= LowTone
[j
]*GraphBuffer
[i
+j
];
1448 for(j
= 0; j
< highLen
; j
++) {
1449 highSum
+= HighTone
[j
]*GraphBuffer
[i
+j
];
1451 lowSum
= abs((100*lowSum
) / lowLen
);
1452 highSum
= abs((100*highSum
) / highLen
);
1453 GraphBuffer
[i
] = (highSum
<< 16) | lowSum
;
1456 for(i
= 0; i
< GraphTraceLen
- convLen
- 16; i
++) {
1458 int lowTot
= 0, highTot
= 0;
1459 // 10 and 8 are f_s divided by f_l and f_h, rounded
1460 for(j
= 0; j
< 10; j
++) {
1461 lowTot
+= (GraphBuffer
[i
+j
] & 0xffff);
1463 for(j
= 0; j
< 8; j
++) {
1464 highTot
+= (GraphBuffer
[i
+j
] >> 16);
1466 GraphBuffer
[i
] = lowTot
- highTot
;
1467 if (GraphBuffer
[i
]>maxMark
) maxMark
=GraphBuffer
[i
];
1468 if (GraphBuffer
[i
]<minMark
) minMark
=GraphBuffer
[i
];
1471 GraphTraceLen
-= (convLen
+ 16);
1473 RepaintGraphWindow();
1475 // Find bit-sync (3 lo followed by 3 high)
1476 int max
= 0, maxPos
= 0;
1477 for(i
= 0; i
< 6000; i
++) {
1479 for(j
= 0; j
< 3*lowLen
; j
++) {
1480 dec
-= GraphBuffer
[i
+j
];
1482 for(; j
< 3*(lowLen
+ highLen
); j
++) {
1483 dec
+= GraphBuffer
[i
+j
];
1491 // place start of bit sync marker in graph
1492 GraphBuffer
[maxPos
] = maxMark
;
1493 GraphBuffer
[maxPos
+1] = minMark
;
1497 // place end of bit sync marker in graph
1498 GraphBuffer
[maxPos
] = maxMark
;
1499 GraphBuffer
[maxPos
+1] = minMark
;
1501 PrintToScrollback("actual data bits start at sample %d", maxPos
);
1502 PrintToScrollback("length %d/%d", highLen
, lowLen
);
1505 bits
[sizeof(bits
)-1] = '\0';
1507 // find bit pairs and manchester decode them
1508 for(i
= 0; i
< arraylen(bits
)-1; i
++) {
1510 for(j
= 0; j
< lowLen
; j
++) {
1511 dec
-= GraphBuffer
[maxPos
+j
];
1513 for(; j
< lowLen
+ highLen
; j
++) {
1514 dec
+= GraphBuffer
[maxPos
+j
];
1517 // place inter bit marker in graph
1518 GraphBuffer
[maxPos
] = maxMark
;
1519 GraphBuffer
[maxPos
+1] = minMark
;
1521 // hi and lo form a 64 bit pair
1522 hi
= (hi
<<1)|(lo
>>31);
1524 // store decoded bit as binary (in hi/lo) and text (in bits[])
1532 PrintToScrollback("bits: '%s'", bits
);
1533 PrintToScrollback("hex: %08x %08x", hi
, lo
);
1536 // read a TI tag and return its ID
1537 static void CmdTIRead(char *str
)
1539 UsbCommand c
={CMD_READ_TI_TYPE
};
1543 // write new data to a r/w TI tag
1544 static void CmdTIWrite(char *str
)
1546 UsbCommand c
={CMD_WRITE_TI_TYPE
};
1549 res
= sscanf(str
, "0x%x 0x%x 0x%x ", &c
.arg
[0], &c
.arg
[1], &c
.arg
[2]);
1550 if (res
== 2) c
.arg
[2]=0;
1552 PrintToScrollback("Please specify the data as two hex strings, optionally the CRC as a third");
1557 static void CmdTIDemod(char *cmdline
)
1559 /* MATLAB as follows:
1560 f_s = 2000000; % sampling frequency
1561 f_l = 123200; % low FSK tone
1562 f_h = 134200; % high FSK tone
1564 T_l = 119e-6; % low bit duration
1565 T_h = 130e-6; % high bit duration
1567 l = 2*pi*ones(1, floor(f_s*T_l))*(f_l/f_s);
1568 h = 2*pi*ones(1, floor(f_s*T_h))*(f_h/f_s);
1570 l = sign(sin(cumsum(l)));
1571 h = sign(sin(cumsum(h)));
1574 // 2M*16/134.2k = 238
1575 static const int LowTone
[] = {
1576 1, 1, 1, 1, 1, 1, 1, 1, 1, -1, -1, -1, -1, -1, -1, -1, -1,
1577 1, 1, 1, 1, 1, 1, 1, 1, -1, -1, -1, -1, -1, -1, -1, -1,
1578 1, 1, 1, 1, 1, 1, 1, 1, -1, -1, -1, -1, -1, -1, -1, -1,
1579 1, 1, 1, 1, 1, 1, 1, 1, -1, -1, -1, -1, -1, -1, -1, -1,
1580 1, 1, 1, 1, 1, 1, 1, 1, 1, -1, -1, -1, -1, -1, -1, -1, -1,
1581 1, 1, 1, 1, 1, 1, 1, 1, -1, -1, -1, -1, -1, -1, -1, -1,
1582 1, 1, 1, 1, 1, 1, 1, 1, -1, -1, -1, -1, -1, -1, -1, -1,
1583 1, 1, 1, 1, 1, 1, 1, 1, -1, -1, -1, -1, -1, -1, -1, -1,
1584 1, 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,
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, -1, -1, -1, -1, -1, -1,
1588 1, 1, 1, 1, 1, 1, 1, 1, 1, -1, -1, -1, -1, -1, -1, -1, -1,
1589 1, 1, 1, 1, 1, 1, 1, 1, -1, -1, -1, -1, -1, -1, -1, -1,
1590 1, 1, 1, 1, 1, 1, 1, 1, -1, -1
1592 // 2M*16/123.2k = 260
1593 static const int HighTone
[] = {
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, -1,
1597 1, 1, 1, 1, 1, 1, 1, -1, -1, -1, -1, -1, -1, -1, -1,
1598 1, 1, 1, 1, 1, 1, 1, -1, -1, -1, -1, -1, -1, -1, -1,
1599 1, 1, 1, 1, 1, 1, 1, -1, -1, -1, -1, -1, -1, -1,
1600 1, 1, 1, 1, 1, 1, 1, 1, -1, -1, -1, -1, -1, -1, -1,
1601 1, 1, 1, 1, 1, 1, 1, 1, -1, -1, -1, -1, -1, -1, -1,
1602 1, 1, 1, 1, 1, 1, 1, -1, -1, -1, -1, -1, -1, -1, -1,
1603 1, 1, 1, 1, 1, 1, 1, -1, -1, -1, -1, -1, -1, -1, -1,
1604 1, 1, 1, 1, 1, 1, 1, -1, -1, -1, -1, -1, -1, -1,
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, -1,
1608 1, 1, 1, 1, 1, 1, 1, -1, -1, -1, -1, -1, -1, -1, -1,
1609 1, 1, 1, 1, 1, 1, 1, -1, -1, -1, -1, -1, -1, -1, -1,
1610 1, 1, 1, 1, 1, 1, 1, -1, -1, -1, -1, -1, -1, -1,
1611 1, 1, 1, 1, 1, 1, 1, 1
1613 int lowLen
= sizeof(LowTone
)/sizeof(int);
1614 int highLen
= sizeof(HighTone
)/sizeof(int);
1615 int convLen
= (highLen
>lowLen
)?highLen
:lowLen
;
1618 int lowSum
= 0, highSum
= 0;;
1619 int lowTot
= 0, highTot
= 0;
1621 for(i
= 0; i
< GraphTraceLen
- convLen
; i
++) {
1625 for(j
= 0; j
< lowLen
; j
++) {
1626 lowSum
+= LowTone
[j
]*GraphBuffer
[i
+j
];
1628 for(j
= 0; j
< highLen
; j
++) {
1629 highSum
+= HighTone
[j
]*GraphBuffer
[i
+j
];
1631 lowSum
= abs((100*lowSum
) / lowLen
);
1632 highSum
= abs((100*highSum
) / highLen
);
1633 lowSum
= (lowSum
<0)?-lowSum
:lowSum
;
1634 highSum
= (highSum
<0)?-highSum
:highSum
;
1636 GraphBuffer
[i
] = (highSum
<< 16) | lowSum
;
1639 for(i
= 0; i
< GraphTraceLen
- convLen
- 16; i
++) {
1642 // 16 and 15 are f_s divided by f_l and f_h, rounded
1643 for(j
= 0; j
< 16; j
++) {
1644 lowTot
+= (GraphBuffer
[i
+j
] & 0xffff);
1646 for(j
= 0; j
< 15; j
++) {
1647 highTot
+= (GraphBuffer
[i
+j
] >> 16);
1649 GraphBuffer
[i
] = lowTot
- highTot
;
1652 GraphTraceLen
-= (convLen
+ 16);
1654 RepaintGraphWindow();
1656 // TI tag data format is 16 prebits, 8 start bits, 64 data bits,
1657 // 16 crc CCITT bits, 8 stop bits, 15 end bits
1659 // the 16 prebits are always low
1660 // the 8 start and stop bits of a tag must match
1661 // the start/stop prebits of a ro tag are 01111110
1662 // the start/stop prebits of a rw tag are 11111110
1663 // the 15 end bits of a ro tag are all low
1664 // the 15 end bits of a rw tag match bits 15-1 of the data bits
1666 // Okay, so now we have unsliced soft decisions;
1667 // find bit-sync, and then get some bits.
1668 // look for 17 low bits followed by 6 highs (common pattern for ro and rw tags)
1669 int max
= 0, maxPos
= 0;
1670 for(i
= 0; i
< 6000; i
++) {
1673 // searching 17 consecutive lows
1674 for(j
= 0; j
< 17*lowLen
; j
++) {
1675 dec
-= GraphBuffer
[i
+j
];
1677 // searching 7 consecutive highs
1678 for(; j
< 17*lowLen
+ 6*highLen
; j
++) {
1679 dec
+= GraphBuffer
[i
+j
];
1687 // place a marker in the buffer to visually aid location
1688 // of the start of sync
1689 GraphBuffer
[maxPos
] = 800;
1690 GraphBuffer
[maxPos
+1] = -800;
1692 // advance pointer to start of actual data stream (after 16 pre and 8 start bits)
1693 maxPos
+= 17*lowLen
;
1694 maxPos
+= 6*highLen
;
1696 // place a marker in the buffer to visually aid location
1697 // of the end of sync
1698 GraphBuffer
[maxPos
] = 800;
1699 GraphBuffer
[maxPos
+1] = -800;
1701 PrintToScrollback("actual data bits start at sample %d", maxPos
);
1703 PrintToScrollback("length %d/%d", highLen
, lowLen
);
1705 uint8_t bits
[1+64+16+8+16];
1706 bits
[sizeof(bits
)-1] = '\0';
1708 uint32_t shift3
= 0x7e000000, shift2
= 0, shift1
= 0, shift0
= 0;
1710 for(i
= 0; i
< arraylen(bits
)-1; i
++) {
1714 for(j
= 0; j
< lowLen
; j
++) {
1715 low
-= GraphBuffer
[maxPos
+j
];
1717 for(j
= 0; j
< highLen
; j
++) {
1718 high
+= GraphBuffer
[maxPos
+j
];
1724 // bitstream arrives lsb first so shift right
1731 // 128 bit right shift register
1732 shift0
= (shift0
>>1) | (shift1
<< 31);
1733 shift1
= (shift1
>>1) | (shift2
<< 31);
1734 shift2
= (shift2
>>1) | (shift3
<< 31);
1737 // place a marker in the buffer between bits to visually aid location
1738 GraphBuffer
[maxPos
] = 800;
1739 GraphBuffer
[maxPos
+1] = -800;
1741 PrintToScrollback("Info: raw tag bits = %s", bits
);
1743 TagType
= (shift3
>>8)&0xff;
1744 if ( TagType
!= ((shift0
>>16)&0xff) ) {
1745 PrintToScrollback("Error: start and stop bits do not match!");
1748 else if (TagType
== 0x7e) {
1749 PrintToScrollback("Info: Readonly TI tag detected.");
1752 else if (TagType
== 0xfe) {
1753 PrintToScrollback("Info: Rewriteable TI tag detected.");
1755 // put 64 bit data into shift1 and shift0
1756 shift0
= (shift0
>>24) | (shift1
<< 8);
1757 shift1
= (shift1
>>24) | (shift2
<< 8);
1759 // align 16 bit crc into lower half of shift2
1760 shift2
= ((shift2
>>24) | (shift3
<< 8)) & 0x0ffff;
1762 // align 16 bit "end bits" or "ident" into lower half of shift3
1765 // only 15 bits compare, last bit of ident is not valid
1766 if ( (shift3
^shift0
)&0x7fff ) {
1767 PrintToScrollback("Error: Ident mismatch!");
1769 // WARNING the order of the bytes in which we calc crc below needs checking
1770 // i'm 99% sure the crc algorithm is correct, but it may need to eat the
1771 // bytes in reverse or something
1774 crc
= update_crc16(crc
, (shift0
)&0xff);
1775 crc
= update_crc16(crc
, (shift0
>>8)&0xff);
1776 crc
= update_crc16(crc
, (shift0
>>16)&0xff);
1777 crc
= update_crc16(crc
, (shift0
>>24)&0xff);
1778 crc
= update_crc16(crc
, (shift1
)&0xff);
1779 crc
= update_crc16(crc
, (shift1
>>8)&0xff);
1780 crc
= update_crc16(crc
, (shift1
>>16)&0xff);
1781 crc
= update_crc16(crc
, (shift1
>>24)&0xff);
1782 PrintToScrollback("Info: Tag data = %08X%08X", shift1
, shift0
);
1783 if (crc
!= (shift2
&0xffff)) {
1784 PrintToScrollback("Error: CRC mismatch, calculated %04X, got ^04X", crc
, shift2
&0xffff);
1786 PrintToScrollback("Info: CRC %04X is good", crc
);
1790 PrintToScrollback("Unknown tag type.");
1795 static void CmdNorm(char *str
)
1798 int max
= INT_MIN
, min
= INT_MAX
;
1799 for(i
= 10; i
< GraphTraceLen
; i
++) {
1800 if(GraphBuffer
[i
] > max
) {
1801 max
= GraphBuffer
[i
];
1803 if(GraphBuffer
[i
] < min
) {
1804 min
= GraphBuffer
[i
];
1808 for(i
= 0; i
< GraphTraceLen
; i
++) {
1809 GraphBuffer
[i
] = (GraphBuffer
[i
] - ((max
+ min
)/2))*1000/
1813 RepaintGraphWindow();
1816 static void CmdAmp(char *str
)
1818 int i
, rising
, falling
;
1819 int max
= INT_MIN
, min
= INT_MAX
;
1820 for(i
= 10; i
< GraphTraceLen
; i
++) {
1821 if(GraphBuffer
[i
] > max
) {
1822 max
= GraphBuffer
[i
];
1824 if(GraphBuffer
[i
] < min
) {
1825 min
= GraphBuffer
[i
];
1830 for(i
= 0; i
< GraphTraceLen
; i
++) {
1831 if(GraphBuffer
[i
+1] < GraphBuffer
[i
]) {
1833 GraphBuffer
[i
]= max
;
1838 if(GraphBuffer
[i
+1] > GraphBuffer
[i
]) {
1840 GraphBuffer
[i
]= min
;
1847 RepaintGraphWindow();
1850 static void CmdDec(char *str
)
1853 for(i
= 0; i
< (GraphTraceLen
/2); i
++) {
1854 GraphBuffer
[i
] = GraphBuffer
[i
*2];
1857 PrintToScrollback("decimated by 2");
1858 RepaintGraphWindow();
1861 static void CmdHpf(char *str
)
1865 for(i
= 10; i
< GraphTraceLen
; i
++) {
1866 accum
+= GraphBuffer
[i
];
1868 accum
/= (GraphTraceLen
- 10);
1869 for(i
= 0; i
< GraphTraceLen
; i
++) {
1870 GraphBuffer
[i
] -= accum
;
1873 RepaintGraphWindow();
1876 static void CmdZerocrossings(char *str
)
1879 // Zero-crossings aren't meaningful unless the signal is zero-mean.
1885 for(i
= 0; i
< GraphTraceLen
; i
++) {
1886 if(GraphBuffer
[i
]*sign
>= 0) {
1887 // No change in sign, reproduce the previous sample count.
1889 GraphBuffer
[i
] = lastZc
;
1891 // Change in sign, reset the sample count.
1893 GraphBuffer
[i
] = lastZc
;
1901 RepaintGraphWindow();
1904 static void CmdThreshold(char *str
)
1907 int threshold
= atoi(str
);
1909 for(i
= 0; i
< GraphTraceLen
; i
++) {
1910 if(GraphBuffer
[i
]>= threshold
)
1915 RepaintGraphWindow();
1918 static void CmdLtrim(char *str
)
1923 for(i
= ds
; i
< GraphTraceLen
; i
++) {
1924 GraphBuffer
[i
-ds
] = GraphBuffer
[i
];
1926 GraphTraceLen
-= ds
;
1928 RepaintGraphWindow();
1931 static void CmdAutoCorr(char *str
)
1933 static int CorrelBuffer
[MAX_GRAPH_TRACE_LEN
];
1935 int window
= atoi(str
);
1938 PrintToScrollback("needs a window");
1942 if(window
>= GraphTraceLen
) {
1943 PrintToScrollback("window must be smaller than trace (%d samples)",
1948 PrintToScrollback("performing %d correlations", GraphTraceLen
- window
);
1951 for(i
= 0; i
< GraphTraceLen
- window
; i
++) {
1954 for(j
= 0; j
< window
; j
++) {
1955 sum
+= (GraphBuffer
[j
]*GraphBuffer
[i
+j
]) / 256;
1957 CorrelBuffer
[i
] = sum
;
1959 GraphTraceLen
= GraphTraceLen
- window
;
1960 memcpy(GraphBuffer
, CorrelBuffer
, GraphTraceLen
*sizeof(int));
1962 RepaintGraphWindow();
1965 static void CmdVchdemod(char *str
)
1967 // Is this the entire sync pattern, or does this also include some
1968 // data bits that happen to be the same everywhere? That would be
1970 static const int SyncPattern
[] = {
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,
1978 1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
1979 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
1980 1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
1983 // So first, we correlate for the sync pattern, and mark that.
1984 int bestCorrel
= 0, bestPos
= 0;
1986 // It does us no good to find the sync pattern, with fewer than
1987 // 2048 samples after it...
1988 for(i
= 0; i
< (GraphTraceLen
-2048); i
++) {
1991 for(j
= 0; j
< arraylen(SyncPattern
); j
++) {
1992 sum
+= GraphBuffer
[i
+j
]*SyncPattern
[j
];
1994 if(sum
> bestCorrel
) {
1999 PrintToScrollback("best sync at %d [metric %d]", bestPos
, bestCorrel
);
2004 int worst
= INT_MAX
;
2007 for(i
= 0; i
< 2048; i
+= 8) {
2010 for(j
= 0; j
< 8; j
++) {
2011 sum
+= GraphBuffer
[bestPos
+i
+j
];
2018 if(abs(sum
) < worst
) {
2023 PrintToScrollback("bits:");
2024 PrintToScrollback("%s", bits
);
2025 PrintToScrollback("worst metric: %d at pos %d", worst
, worstPos
);
2027 if(strcmp(str
, "clone")==0) {
2030 for(s
= bits
; *s
; s
++) {
2032 for(j
= 0; j
< 16; j
++) {
2033 GraphBuffer
[GraphTraceLen
++] = (*s
== '1') ? 1 : 0;
2036 RepaintGraphWindow();
2040 static void CmdIndalademod(char *str
)
2042 // Usage: recover 64bit UID by default, specify "224" as arg to recover a 224bit UID
2047 // worst case with GraphTraceLen=64000 is < 4096
2048 // under normal conditions it's < 2048
2049 uint8_t rawbits
[4096];
2051 int worst
= 0, worstPos
= 0;
2052 PrintToScrollback("Expecting a bit less than %d raw bits", GraphTraceLen
/32);
2053 for(i
= 0; i
< GraphTraceLen
-1; i
+= 2) {
2055 if((GraphBuffer
[i
] > GraphBuffer
[i
+ 1]) && (state
!= 1)) {
2057 for(j
= 0; j
< count
- 8; j
+= 16) {
2058 rawbits
[rawbit
++] = 0;
2060 if ((abs(count
- j
)) > worst
) {
2061 worst
= abs(count
- j
);
2067 } else if((GraphBuffer
[i
] < GraphBuffer
[i
+ 1]) && (state
!= 0)) {
2069 for(j
= 0; j
< count
- 8; j
+= 16) {
2070 rawbits
[rawbit
++] = 1;
2072 if ((abs(count
- j
)) > worst
) {
2073 worst
= abs(count
- j
);
2081 PrintToScrollback("Recovered %d raw bits", rawbit
);
2082 PrintToScrollback("worst metric (0=best..7=worst): %d at pos %d", worst
, worstPos
);
2084 // Finding the start of a UID
2085 int uidlen
, long_wait
;
2086 if(strcmp(str
, "224") == 0) {
2095 for(start
= 0; start
<= rawbit
- uidlen
; start
++) {
2096 first
= rawbits
[start
];
2097 for(i
= start
; i
< start
+ long_wait
; i
++) {
2098 if(rawbits
[i
] != first
) {
2102 if(i
== (start
+ long_wait
)) {
2106 if(start
== rawbit
- uidlen
+ 1) {
2107 PrintToScrollback("nothing to wait for");
2111 // Inverting signal if needed
2113 for(i
= start
; i
< rawbit
; i
++) {
2114 rawbits
[i
] = !rawbits
[i
];
2121 showbits
[uidlen
]='\0';
2125 if(uidlen
> rawbit
) {
2126 PrintToScrollback("Warning: not enough raw bits to get a full UID");
2127 for(bit
= 0; bit
< rawbit
; bit
++) {
2128 bits
[bit
] = rawbits
[i
++];
2129 // As we cannot know the parity, let's use "." and "/"
2130 showbits
[bit
] = '.' + bits
[bit
];
2132 showbits
[bit
+1]='\0';
2133 PrintToScrollback("Partial UID=%s", showbits
);
2136 for(bit
= 0; bit
< uidlen
; bit
++) {
2137 bits
[bit
] = rawbits
[i
++];
2138 showbits
[bit
] = '0' + bits
[bit
];
2142 PrintToScrollback("UID=%s", showbits
);
2144 // Checking UID against next occurences
2145 for(; i
+ uidlen
<= rawbit
;) {
2147 for(bit
= 0; bit
< uidlen
; bit
++) {
2148 if(bits
[bit
] != rawbits
[i
++]) {
2158 PrintToScrollback("Occurences: %d (expected %d)", times
, (rawbit
- start
) / uidlen
);
2160 // Remodulating for tag cloning
2161 GraphTraceLen
= 32*uidlen
;
2164 for(bit
= 0; bit
< uidlen
; bit
++) {
2165 if(bits
[bit
] == 0) {
2171 for(j
= 0; j
< 32; j
++) {
2172 GraphBuffer
[i
++] = phase
;
2177 RepaintGraphWindow();
2180 static void CmdFlexdemod(char *str
)
2183 for(i
= 0; i
< GraphTraceLen
; i
++) {
2184 if(GraphBuffer
[i
] < 0) {
2185 GraphBuffer
[i
] = -1;
2191 #define LONG_WAIT 100
2193 for(start
= 0; start
< GraphTraceLen
- LONG_WAIT
; start
++) {
2194 int first
= GraphBuffer
[start
];
2195 for(i
= start
; i
< start
+ LONG_WAIT
; i
++) {
2196 if(GraphBuffer
[i
] != first
) {
2200 if(i
== (start
+ LONG_WAIT
)) {
2204 if(start
== GraphTraceLen
- LONG_WAIT
) {
2205 PrintToScrollback("nothing to wait for");
2209 GraphBuffer
[start
] = 2;
2210 GraphBuffer
[start
+1] = -2;
2216 for(bit
= 0; bit
< 64; bit
++) {
2219 for(j
= 0; j
< 16; j
++) {
2220 sum
+= GraphBuffer
[i
++];
2227 PrintToScrollback("bit %d sum %d", bit
, sum
);
2230 for(bit
= 0; bit
< 64; bit
++) {
2233 for(j
= 0; j
< 16; j
++) {
2234 sum
+= GraphBuffer
[i
++];
2236 if(sum
> 0 && bits
[bit
] != 1) {
2237 PrintToScrollback("oops1 at %d", bit
);
2239 if(sum
< 0 && bits
[bit
] != 0) {
2240 PrintToScrollback("oops2 at %d", bit
);
2244 GraphTraceLen
= 32*64;
2247 for(bit
= 0; bit
< 64; bit
++) {
2248 if(bits
[bit
] == 0) {
2254 for(j
= 0; j
< 32; j
++) {
2255 GraphBuffer
[i
++] = phase
;
2260 RepaintGraphWindow();
2264 * Generic command to demodulate ASK.
2266 * Argument is convention: positive or negative (High mod means zero
2267 * or high mod means one)
2269 * Updates the Graph trace with 0/1 values
2275 static void Cmdaskdemod(char *str
) {
2277 int c
, high
= 0, low
= 0;
2279 // TODO: complain if we do not give 2 arguments here !
2280 // (AL - this doesn't make sense! we're only using one argument!!!)
2281 sscanf(str
, "%i", &c
);
2283 /* Detect high and lows and clock */
2285 for (i
= 0; i
< GraphTraceLen
; i
++)
2287 if (GraphBuffer
[i
] > high
)
2288 high
= GraphBuffer
[i
];
2289 else if (GraphBuffer
[i
] < low
)
2290 low
= GraphBuffer
[i
];
2292 if(c
!= 0 && c
!= 1) {
2293 PrintToScrollback("Invalid argument: %s",str
);
2297 if (GraphBuffer
[0] > 0) {
2298 GraphBuffer
[0] = 1-c
;
2302 for(i
=1;i
<GraphTraceLen
;i
++) {
2303 /* Transitions are detected at each peak
2304 * Transitions are either:
2305 * - we're low: transition if we hit a high
2306 * - we're high: transition if we hit a low
2307 * (we need to do it this way because some tags keep high or
2308 * low for long periods, others just reach the peak and go
2311 if ((GraphBuffer
[i
]==high
) && (GraphBuffer
[i
-1] == c
)) {
2313 } else if ((GraphBuffer
[i
]==low
) && (GraphBuffer
[i
-1] == (1-c
))){
2317 GraphBuffer
[i
] = GraphBuffer
[i
-1];
2320 RepaintGraphWindow();
2323 /* Print our clock rate */
2324 static void Cmddetectclockrate(char *str
)
2326 int clock
= detectclock(0);
2327 PrintToScrollback("Auto-detected clock rate: %d", clock
);
2333 int detectclock(int peak
)
2339 /* Detect peak if we don't have one */
2341 for (i
= 0; i
< GraphTraceLen
; i
++)
2342 if (GraphBuffer
[i
] > peak
)
2343 peak
= GraphBuffer
[i
];
2345 for (i
= 1; i
< GraphTraceLen
; i
++)
2347 /* If this is the beginning of a peak */
2348 if (GraphBuffer
[i
-1] != GraphBuffer
[i
] && GraphBuffer
[i
] == peak
)
2350 /* Find lowest difference between peaks */
2351 if (lastpeak
&& i
- lastpeak
< clock
)
2353 clock
= i
- lastpeak
;
2362 /* Get or auto-detect clock rate */
2363 int GetClock(char *str
, int peak
)
2367 sscanf(str
, "%i", &clock
);
2368 if (!strcmp(str
, ""))
2371 /* Auto-detect clock */
2374 clock
= detectclock(peak
);
2376 /* Only print this message if we're not looping something */
2378 PrintToScrollback("Auto-detected clock rate: %d", clock
);
2385 * Convert to a bitstream
2387 static void Cmdbitstream(char *str
) {
2394 int hithigh
, hitlow
, first
;
2396 /* Detect high and lows and clock */
2397 for (i
= 0; i
< GraphTraceLen
; i
++)
2399 if (GraphBuffer
[i
] > high
)
2400 high
= GraphBuffer
[i
];
2401 else if (GraphBuffer
[i
] < low
)
2402 low
= GraphBuffer
[i
];
2406 clock
= GetClock(str
, high
);
2408 gtl
= CmdClearGraph(0);
2411 for (i
= 0; i
< (int)(gtl
/ clock
); i
++)
2417 /* Find out if we hit both high and low peaks */
2418 for (j
= 0; j
< clock
; j
++)
2420 if (GraphBuffer
[(i
* clock
) + j
] == high
)
2422 else if (GraphBuffer
[(i
* clock
) + j
] == low
)
2425 /* it doesn't count if it's the first part of our read
2426 because it's really just trailing from the last sequence */
2427 if (first
&& (hithigh
|| hitlow
))
2428 hithigh
= hitlow
= 0;
2432 if (hithigh
&& hitlow
)
2436 /* If we didn't hit both high and low peaks, we had a bit transition */
2437 if (!hithigh
|| !hitlow
)
2440 CmdAppendGraph(0, clock
, bit
);
2441 // for (j = 0; j < (int)(clock/2); j++)
2442 // GraphBuffer[(i * clock) + j] = bit ^ 1;
2443 // for (j = (int)(clock/2); j < clock; j++)
2444 // GraphBuffer[(i * clock) + j] = bit;
2447 RepaintGraphWindow();
2450 /* Modulate our data into manchester */
2451 static void Cmdmanchestermod(char *str
)
2455 int bit
, lastbit
, wave
;
2458 clock
= GetClock(str
, 0);
2462 for (i
= 0; i
< (int)(GraphTraceLen
/ clock
); i
++)
2464 bit
= GraphBuffer
[i
* clock
] ^ 1;
2466 for (j
= 0; j
< (int)(clock
/2); j
++)
2467 GraphBuffer
[(i
* clock
) + j
] = bit
^ lastbit
^ wave
;
2468 for (j
= (int)(clock
/2); j
< clock
; j
++)
2469 GraphBuffer
[(i
* clock
) + j
] = bit
^ lastbit
^ wave
^ 1;
2471 /* Keep track of how we start our wave and if we changed or not this time */
2472 wave
^= bit
^ lastbit
;
2476 RepaintGraphWindow();
2480 * Manchester demodulate a bitstream. The bitstream needs to be already in
2481 * the GraphBuffer as 0 and 1 values
2483 * Give the clock rate as argument in order to help the sync - the algorithm
2484 * resyncs at each pulse anyway.
2486 * Not optimized by any means, this is the 1st time I'm writing this type of
2487 * routine, feel free to improve...
2489 * 1st argument: clock rate (as number of samples per clock rate)
2490 * Typical values can be 64, 32, 128...
2492 static void Cmdmanchesterdemod(char *str
) {
2493 int i
, j
, invert
= 0;
2499 int hithigh
, hitlow
, first
;
2505 /* check if we're inverting output */
2508 PrintToScrollback("Inverting output");
2512 while(*str
== ' '); // in case a 2nd argument was given
2515 /* Holds the decoded bitstream: each clock period contains 2 bits */
2516 /* later simplified to 1 bit after manchester decoding. */
2517 /* Add 10 bits to allow for noisy / uncertain traces without aborting */
2518 /* int BitStream[GraphTraceLen*2/clock+10]; */
2520 /* But it does not work if compiling on WIndows: therefore we just allocate a */
2522 int BitStream
[MAX_GRAPH_TRACE_LEN
];
2524 /* Detect high and lows */
2525 for (i
= 0; i
< GraphTraceLen
; i
++)
2527 if (GraphBuffer
[i
] > high
)
2528 high
= GraphBuffer
[i
];
2529 else if (GraphBuffer
[i
] < low
)
2530 low
= GraphBuffer
[i
];
2534 clock
= GetClock(str
, high
);
2536 int tolerance
= clock
/4;
2538 /* Detect first transition */
2539 /* Lo-Hi (arbitrary) */
2540 /* skip to the first high */
2541 for (i
= 0; i
< GraphTraceLen
; i
++)
2542 if(GraphBuffer
[i
] == high
)
2544 /* now look for the first low */
2545 for (; i
< GraphTraceLen
; i
++)
2547 if (GraphBuffer
[i
] == low
)
2554 /* If we're not working with 1/0s, demod based off clock */
2557 bit
= 0; /* We assume the 1st bit is zero, it may not be
2558 * the case: this routine (I think) has an init problem.
2561 for (; i
< (int)(GraphTraceLen
/ clock
); i
++)
2567 /* Find out if we hit both high and low peaks */
2568 for (j
= 0; j
< clock
; j
++)
2570 if (GraphBuffer
[(i
* clock
) + j
] == high
)
2572 else if (GraphBuffer
[(i
* clock
) + j
] == low
)
2575 /* it doesn't count if it's the first part of our read
2576 because it's really just trailing from the last sequence */
2577 if (first
&& (hithigh
|| hitlow
))
2578 hithigh
= hitlow
= 0;
2582 if (hithigh
&& hitlow
)
2586 /* If we didn't hit both high and low peaks, we had a bit transition */
2587 if (!hithigh
|| !hitlow
)
2590 BitStream
[bit2idx
++] = bit
^ invert
;
2594 /* standard 1/0 bitstream */
2598 /* Then detect duration between 2 successive transitions */
2599 for (bitidx
= 1; i
< GraphTraceLen
; i
++)
2601 if (GraphBuffer
[i
-1] != GraphBuffer
[i
])
2606 // Error check: if bitidx becomes too large, we do not
2607 // have a Manchester encoded bitstream or the clock is really
2609 if (bitidx
> (GraphTraceLen
*2/clock
+8) ) {
2610 PrintToScrollback("Error: the clock you gave is probably wrong, aborting.");
2613 // Then switch depending on lc length:
2614 // Tolerance is 1/4 of clock rate (arbitrary)
2615 if (abs(lc
-clock
/2) < tolerance
) {
2616 // Short pulse : either "1" or "0"
2617 BitStream
[bitidx
++]=GraphBuffer
[i
-1];
2618 } else if (abs(lc
-clock
) < tolerance
) {
2619 // Long pulse: either "11" or "00"
2620 BitStream
[bitidx
++]=GraphBuffer
[i
-1];
2621 BitStream
[bitidx
++]=GraphBuffer
[i
-1];
2625 PrintToScrollback("Warning: Manchester decode error for pulse width detection.");
2626 PrintToScrollback("(too many of those messages mean either the stream is not Manchester encoded, or clock is wrong)");
2630 PrintToScrollback("Error: too many detection errors, aborting.");
2637 // At this stage, we now have a bitstream of "01" ("1") or "10" ("0"), parse it into final decoded bitstream
2638 // Actually, we overwrite BitStream with the new decoded bitstream, we just need to be careful
2639 // to stop output at the final bitidx2 value, not bitidx
2640 for (i
= 0; i
< bitidx
; i
+= 2) {
2641 if ((BitStream
[i
] == 0) && (BitStream
[i
+1] == 1)) {
2642 BitStream
[bit2idx
++] = 1 ^ invert
;
2643 } else if ((BitStream
[i
] == 1) && (BitStream
[i
+1] == 0)) {
2644 BitStream
[bit2idx
++] = 0 ^ invert
;
2646 // We cannot end up in this state, this means we are unsynchronized,
2650 PrintToScrollback("Unsynchronized, resync...");
2651 PrintToScrollback("(too many of those messages mean the stream is not Manchester encoded)");
2655 PrintToScrollback("Error: too many decode errors, aborting.");
2662 PrintToScrollback("Manchester decoded bitstream");
2663 // Now output the bitstream to the scrollback by line of 16 bits
2664 for (i
= 0; i
< (bit2idx
-16); i
+=16) {
2665 PrintToScrollback("%i %i %i %i %i %i %i %i %i %i %i %i %i %i %i %i",
2688 static void CmdHiddemod(char *str
)
2690 if(GraphTraceLen
< 4800) {
2691 PrintToScrollback("too short; need at least 4800 samples");
2695 GraphTraceLen
= 4800;
2697 for(i
= 0; i
< GraphTraceLen
; i
++) {
2698 if(GraphBuffer
[i
] < 0) {
2704 RepaintGraphWindow();
2707 static void CmdPlot(char *str
)
2712 static void CmdGrid(char *str
)
2714 sscanf(str
, "%i %i", &PlotGridX
, &PlotGridY
);
2715 RepaintGraphWindow();
2718 static void CmdHide(char *str
)
2723 static void CmdScale(char *str
)
2725 CursorScaleFactor
= atoi(str
);
2726 if(CursorScaleFactor
== 0) {
2727 PrintToScrollback("bad, can't have zero scale");
2728 CursorScaleFactor
= 1;
2730 RepaintGraphWindow();
2733 static void CmdSave(char *str
)
2735 FILE *f
= fopen(str
, "w");
2737 PrintToScrollback("couldn't open '%s'", str
);
2741 for(i
= 0; i
< GraphTraceLen
; i
++) {
2742 fprintf(f
, "%d\n", GraphBuffer
[i
]);
2745 PrintToScrollback("saved to '%s'", str
);
2748 static void CmdLoad(char *str
)
2750 FILE *f
= fopen(str
, "r");
2752 PrintToScrollback("couldn't open '%s'", str
);
2758 while(fgets(line
, sizeof(line
), f
)) {
2759 GraphBuffer
[GraphTraceLen
] = atoi(line
);
2763 PrintToScrollback("loaded %d samples", GraphTraceLen
);
2764 RepaintGraphWindow();
2767 static void CmdHIDsimTAG(char *str
)
2769 unsigned int hi
=0, lo
=0;
2772 while (sscanf(&str
[i
++], "%1x", &n
) == 1) {
2773 hi
=(hi
<<4)|(lo
>>28);
2777 PrintToScrollback("Emulating tag with ID %x%16x", hi
, lo
);
2779 UsbCommand c
={CMD_HID_SIM_TAG
, {hi
, lo
, 0}};
2783 static void CmdReadmem(char *str
)
2785 UsbCommand c
={CMD_READ_MEM
, {strtol(str
, NULL
, 0), 0, 0}};
2789 static void CmdVersion(char *str
)
2791 UsbCommand c
={CMD_VERSION
};
2795 static void CmdLcdReset(char *str
)
2797 UsbCommand c
={CMD_LCD_RESET
, {strtol(str
, NULL
, 0), 0, 0}};
2801 static void CmdLcd(char *str
)
2804 UsbCommand c
={CMD_LCD
};
2805 sscanf(str
, "%x %d", &i
, &j
);
2813 * Sets the divisor for LF frequency clock: lets the user choose any LF frequency below
2816 static void CmdSetDivisor(char *str
)
2818 UsbCommand c
={CMD_SET_LF_DIVISOR
, {strtol(str
, NULL
, 0), 0, 0}};
2819 if (( c
.arg
[0]<0) || (c
.arg
[0]>255)) {
2820 PrintToScrollback("divisor must be between 19 and 255");
2823 PrintToScrollback("Divisor set, expected freq=%dHz", 12000000/(c
.arg
[0]+1));
2827 static void CmdSetMux(char *str
)
2829 UsbCommand c
={CMD_SET_ADC_MUX
};
2830 if(strcmp(str
, "lopkd") == 0) {
2832 } else if(strcmp(str
, "loraw") == 0) {
2834 } else if(strcmp(str
, "hipkd") == 0) {
2836 } else if(strcmp(str
, "hiraw") == 0) {
2842 typedef void HandlerFunction(char *cmdline
);
2844 /* in alphabetic order */
2847 HandlerFunction
*handler
;
2848 int offline
; // 1 if the command can be used when in offline mode
2850 } CommandTable
[] = {
2851 /* plot window / data buffer manipulation */
2852 {"buffclear", CmdBuffClear
, 1, "Clear sample buffer and graph window"},
2853 {"load", CmdLoad
, 1, "<filename> -- Load trace (to graph window"},
2854 {"save", CmdSave
, 1, "<filename> -- Save trace (from graph window)"},
2855 {"amp", CmdAmp
, 1, "Amplify peaks"},
2856 {"autocorr", CmdAutoCorr
, 1, "<window length> -- Autocorrelation over window"},
2857 {"dec", CmdDec
, 1, "Decimate samples"},
2858 {"hpf", CmdHpf
, 1, "Remove DC offset from trace"},
2859 {"ltrim", CmdLtrim
, 1, "<samples> -- Trim samples from left of trace"},
2860 {"norm", CmdNorm
, 1, "Normalize max/min to +/-500"},
2861 {"plot", CmdPlot
, 1, "Show graph window"},
2862 {"hide", CmdHide
, 1, "Hide graph window"},
2863 {"grid", CmdGrid
, 1, "<x> <y> -- overlay grid on graph window, use zero value to turn off either"},
2864 {"threshold", CmdThreshold
, 1, "Maximize/minimize every value in the graph window depending on threshold"},
2865 {"zerocrossings", CmdZerocrossings
, 1, "Count time between zero-crossings"},
2866 {"scale", CmdScale
, 1, "<int> -- Set cursor display scale"},
2867 {"bitstream", Cmdbitstream
, 1, "[clock rate] -- Convert waveform into a bitstream"},
2868 {"detectclock", Cmddetectclockrate
, 1, "Detect clock rate"},
2869 {"exit", CmdQuit
, 1, "Exit program"},
2870 {"quit", CmdQuit
, 1, "Exit program"},
2872 /* low-level hardware control */
2873 {"fpgaoff", CmdFPGAOff
, 0, "Set FPGA off"},
2874 {"tune", CmdTune
, 0, "Measure antenna tuning"},
2875 {"hitune", CmdHiTune
, 0, "Continuously measure HF antenna tuning"},
2876 {"readmem", CmdReadmem
, 0, "[address] -- Read memory at decimal address from flash"},
2877 {"reset", CmdReset
, 0, "Reset the Proxmark3"},
2878 {"setlfdivisor", CmdSetDivisor
, 0, "<19 - 255> -- Drive LF antenna at 12Mhz/(divisor+1)"},
2879 {"setmux", CmdSetMux
, 0, "<loraw|hiraw|lopkd|hipkd> -- Set the ADC mux to a specific value"},
2880 {"version", CmdVersion
, 0, "Show version inforation about the connected Proxmark"},
2881 {"lcd", CmdLcd
, 0, "<HEX command> <count> -- Send command/data to LCD"},
2882 {"lcdreset", CmdLcdReset
, 0, "Hardware reset LCD"},
2884 /* data transfer functions */
2886 {"bitsamples", CmdBitsamples
, 0, "Get raw samples as bitstring"},
2887 {"hexsamples", CmdHexsamples
, 0, "<blocks> [<offset>] -- Dump big buffer as hex bytes"},
2888 {"higet", CmdHi14read_sim
, 0, "<samples> -- Get samples HF, 'analog'"},
2889 {"hisamples", CmdHisamples
, 0, "Get raw samples for HF tag"},
2890 {"hisampless", CmdHisampless
, 0, "<samples> -- Get signed raw samples, HF tag"},
2891 {"hisamplest", CmdHi14readt
, 0, "Get samples HF, for testing"},
2892 {"losamples", CmdLosamples
, 0, "[128 - 16000] -- Get raw samples for LF tag"},
2893 {"detectreader", CmdDetectReader
, 0, "['l'|'h'] -- Detect external reader field (option 'l' or 'h' to limit to LF or HF)"},
2895 /* (de-)modulation */
2897 {"askdemod", Cmdaskdemod
, 1, "<0|1> -- Attempt to demodulate simple ASK tags"},
2898 {"flexdemod", CmdFlexdemod
, 1, "Demodulate samples for FlexPass"},
2899 {"fskdemod", CmdFSKdemod
, 1, "Demodulate graph window as a HID FSK"},
2900 {"hi14bdemod", CmdHi14bdemod
, 1, "Demodulate ISO14443 Type B from tag"},
2901 {"hi15demod", CmdHi15demod
, 1, "Demodulate ISO15693 from tag"},
2902 {"hiddemod", CmdHiddemod
, 1, "Demodulate HID Prox Card II (not optimal)"},
2903 {"hidfskdemod", CmdHIDdemodFSK
, 0, "Realtime HID FSK demodulator"},
2904 {"indalademod", CmdIndalademod
, 1, "['224'] -- Demodulate samples for Indala 64 bit UID (option '224' for 224 bit)"},
2905 {"mandemod", Cmdmanchesterdemod
, 1, "[i] [clock rate] -- Manchester demodulate binary stream (option 'i' to invert output)"},
2906 {"manmod", Cmdmanchestermod
, 1, "[clock rate] -- Manchester modulate a binary stream"},
2907 {"tidemod", CmdTIDemod
, 1, "Demodulate raw bits for TI-type LF tag"},
2908 {"vchdemod", CmdVchdemod
, 1, "['clone'] -- Demodulate samples for VeriChip"},
2911 {"em410xsim", CmdEM410xsim
, 1, "<UID> -- Simulate EM410x tag"},
2912 {"hi14sim", CmdHi14sim
, 0, "Fake ISO 14443 tag"},
2913 {"hi14asim", CmdHi14asim
, 0, "<UID> -- Fake ISO 14443a tag"},
2914 {"hi15sim", CmdHi15tag
, 0, "Fake an ISO15693 tag"},
2915 {"hidsimtag", CmdHIDsimTAG
, 0, "<ID> -- HID tag simulator"},
2916 {"hisimlisten", CmdHisimlisten
, 0, "Get HF samples as fake tag"},
2917 {"losim", CmdLosim
, 0, "[GAP] -- Simulate LF tag from buffer with optional GAP (in microseconds)"},
2918 {"losimman", CmdLosimManchester
, 0, "<Clock> <Bitstream> [GAP] Simulate arbitrary Manchester LF tag"},
2919 {"losimbidir", CmdLosimBidir
, 0, "Simulate LF tag (with bidirectional data transmission between reader and tag)"},
2921 /* card reading functions */
2922 {"em410xread", CmdEM410xread
, 1, "[clock rate] -- Extract ID from EM410x tag"},
2923 {"em410xwatch", CmdEM410xwatch
, 0, "Watches for EM410x tags"},
2924 {"em4x50read", CmdEM4x50read
, 1, "Extract data from EM4x50 tag"},
2925 {"hi14alist", CmdHi14alist
, 0, "List ISO 14443a history"},
2926 {"hi14amifare", CmdHi14amifare
, 0, "Read out sector 0 parity error messages"},
2927 {"hi14areader", CmdHi14areader
, 0, "Act like an ISO14443 Type A reader"},
2928 {"hi14asnoop", CmdHi14asnoop
, 0, "Eavesdrop ISO 14443 Type A"},
2929 {"hi14list", CmdHi14list
, 0, "List ISO 14443 history"},
2930 {"hi14read", CmdHi14read
, 0, "Read HF tag (ISO 14443)"},
2931 {"hi14snoop", CmdHi14snoop
, 0, "Eavesdrop ISO 14443"},
2932 {"hi15read", CmdHi15read
, 0, "Read HF tag (ISO 15693)"},
2933 {"hi15reader", CmdHi15reader
, 0, "Act like an ISO15693 reader"},
2934 {"legicrfread", CmdLegicRfRead
, 0, "Start the LEGIC RF reader"},
2935 {"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)"},
2936 {"loread", CmdLoread
, 0, "['h'] -- Read 125/134 kHz LF ID-only tag (option 'h' for 134)"},
2937 {"sri512read", CmdSri512read
, 0, "<int> -- Read contents of a SRI512 tag"},
2938 {"srix4kread", CmdSrix4kread
, 0, "<int> -- Read contents of a SRIX4K tag"},
2939 {"tiread", CmdTIRead
, 0, "Read and decode a TI 134 kHz tag"},
2940 {"tiwrite", CmdTIWrite
, 0, "Write new data to a r/w TI 134 kHz tag"},
2948 } CommandExtendedHelp
[]= {
2949 {"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."},
2950 {"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."},
2953 //-----------------------------------------------------------------------------
2954 // Entry point into our code: called whenever the user types a command and
2955 // then presses Enter, which the full command line that they typed.
2956 //-----------------------------------------------------------------------------
2957 void CommandReceived(char *cmd
)
2962 PrintToScrollback("> %s", cmd
);
2964 if(strcmp(cmd
, "help") == 0 || strncmp(cmd
,"help ",strlen("help ")) == 0) {
2965 // check if we're doing extended help
2966 if(strlen(cmd
) > strlen("help ")) {
2967 cmd
+= strlen("help ");
2968 for(i
= 0; i
< sizeof(CommandExtendedHelp
) / sizeof(CommandExtendedHelp
[0]); i
++) {
2969 if(strcmp(CommandExtendedHelp
[i
].name
,cmd
) == 0) {
2970 PrintToScrollback("\nExtended help for '%s':\n", cmd
);
2971 PrintToScrollback("Args: %s\t- %s\n",CommandExtendedHelp
[i
].args
,CommandExtendedHelp
[i
].argshelp
);
2972 PrintToScrollback(CommandExtendedHelp
[i
].description
);
2973 PrintToScrollback("");
2977 PrintToScrollback("No extended help available for '%s'", cmd
);
2980 if (offline
) PrintToScrollback("Operating in OFFLINE mode (no device connected)");
2981 PrintToScrollback("\r\nAvailable commands:");
2982 for(i
= 0; i
< sizeof(CommandTable
) / sizeof(CommandTable
[0]); i
++) {
2983 if (offline
&& (CommandTable
[i
].offline
==0)) continue;
2984 memset(line
, ' ', sizeof(line
));
2985 strcpy(line
+2, CommandTable
[i
].name
);
2986 line
[strlen(line
)] = ' ';
2987 sprintf(line
+15, " -- %s", CommandTable
[i
].docString
);
2988 PrintToScrollback("%s", line
);
2990 PrintToScrollback("");
2991 PrintToScrollback("'help <command>' for extended help on that command\n");
2995 for(i
= 0; i
< sizeof(CommandTable
) / sizeof(CommandTable
[0]); i
++) {
2996 char *name
= CommandTable
[i
].name
;
2997 if(memcmp(cmd
, name
, strlen(name
))==0 &&
2998 (cmd
[strlen(name
)] == ' ' || cmd
[strlen(name
)] == '\0'))
3000 cmd
+= strlen(name
);
3001 while(*cmd
== ' ') {
3004 if (offline
&& (CommandTable
[i
].offline
==0)) {
3005 PrintToScrollback("Offline mode, cannot use this command.");
3008 (CommandTable
[i
].handler
)(cmd
);
3012 PrintToScrollback(">> bad command '%s'", cmd
);
3015 //-----------------------------------------------------------------------------
3016 // Entry point into our code: called whenever we received a packet over USB
3017 // that we weren't necessarily expecting, for example a debug print.
3018 //-----------------------------------------------------------------------------
3019 void UsbCommandReceived(UsbCommand
*c
)
3021 // printf("%s(%x) current cmd = %x\n", __FUNCTION__, c->cmd, current_command);
3022 /* If we recognize a response, return to avoid further processing */
3024 case CMD_DEBUG_PRINT_STRING
: {
3026 if(c
->arg
[0] > 70 || c
->arg
[0] < 0) {
3029 memcpy(s
, c
->d
.asBytes
, c
->arg
[0]);
3030 s
[c
->arg
[0]] = '\0';
3031 PrintToScrollback("#db# %s", s
);
3035 case CMD_DEBUG_PRINT_INTEGERS
:
3036 PrintToScrollback("#db# %08x, %08x, %08x\r\n", c
->arg
[0], c
->arg
[1], c
->arg
[2]);
3039 case CMD_MEASURED_ANTENNA_TUNING
: {
3041 int vLf125
, vLf134
, vHf
;
3042 vLf125
= c
->arg
[0] & 0xffff;
3043 vLf134
= c
->arg
[0] >> 16;
3044 vHf
= c
->arg
[1] & 0xffff;;
3045 peakf
= c
->arg
[2] & 0xffff;
3046 peakv
= c
->arg
[2] >> 16;
3047 PrintToScrollback("");
3048 PrintToScrollback("");
3049 PrintToScrollback("# LF antenna: %5.2f V @ 125.00 kHz", vLf125
/1000.0);
3050 PrintToScrollback("# LF antenna: %5.2f V @ 134.00 kHz", vLf134
/1000.0);
3051 PrintToScrollback("# LF optimal: %5.2f V @%9.2f kHz", peakv
/1000.0, 12000.0/(peakf
+1));
3052 PrintToScrollback("# HF antenna: %5.2f V @ 13.56 MHz", vHf
/1000.0);
3054 PrintToScrollback("# Your LF antenna is unusable.");
3055 else if (peakv
<10000)
3056 PrintToScrollback("# Your LF antenna is marginal.");
3058 PrintToScrollback("# Your HF antenna is unusable.");
3060 PrintToScrollback("# Your HF antenna is marginal.");
3066 /* Maybe it's a response: */
3067 switch(current_command
) {
3068 case CMD_DOWNLOAD_RAW_ADC_SAMPLES_125K
:
3069 if (c
->cmd
!= CMD_DOWNLOADED_RAW_ADC_SAMPLES_125K
) goto unexpected_response
;
3071 for(i
=0; i
<48; i
++) sample_buf
[i
] = c
->d
.asBytes
[i
];
3072 received_command
= c
->cmd
;
3074 case CMD_DOWNLOADED_SIM_SAMPLES_125K
:
3075 if (c
->cmd
!= CMD_ACK
) goto unexpected_response
;
3077 received_command
= c
->cmd
;
3080 unexpected_response
:
3081 PrintToScrollback("unrecognized command %08x\n", c
->cmd
);