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];
582 /* clock is 64 in EM410x tags */
585 /* clear our graph */
588 /* write it out a few times */
589 for (h
= 0; h
< 4; h
++)
591 /* write 9 start bits */
592 for (i
= 0; i
< 9; i
++)
593 CmdAppendGraph(0, clock
, 1);
595 /* for each hex char */
596 parity
[0] = parity
[1] = parity
[2] = parity
[3] = 0;
597 for (i
= 0; i
< 10; i
++)
599 /* read each hex char */
600 sscanf(&str
[i
], "%1x", &n
);
601 for (j
= 3; j
>= 0; j
--, n
/= 2)
604 /* append each bit */
605 CmdAppendGraph(0, clock
, binary
[0]);
606 CmdAppendGraph(0, clock
, binary
[1]);
607 CmdAppendGraph(0, clock
, binary
[2]);
608 CmdAppendGraph(0, clock
, binary
[3]);
610 /* append parity bit */
611 CmdAppendGraph(0, clock
, binary
[0] ^ binary
[1] ^ binary
[2] ^ binary
[3]);
613 /* keep track of column parity */
614 parity
[0] ^= binary
[0];
615 parity
[1] ^= binary
[1];
616 parity
[2] ^= binary
[2];
617 parity
[3] ^= binary
[3];
621 CmdAppendGraph(0, clock
, parity
[0]);
622 CmdAppendGraph(0, clock
, parity
[1]);
623 CmdAppendGraph(0, clock
, parity
[2]);
624 CmdAppendGraph(0, clock
, parity
[3]);
627 CmdAppendGraph(0, clock
, 0);
630 /* modulate that biatch */
634 RepaintGraphWindow();
639 static void ChkBitstream(char *str
)
643 /* convert to bitstream if necessary */
644 for (i
= 0; i
< (int)(GraphTraceLen
/ 2); i
++)
646 if (GraphBuffer
[i
] > 1 || GraphBuffer
[i
] < 0)
654 static void CmdLosim(char *str
)
658 /* convert to bitstream if necessary */
661 for (i
= 0; i
< GraphTraceLen
; i
+= 48) {
662 UsbCommand c
={CMD_DOWNLOADED_SIM_SAMPLES_125K
, {i
, 0, 0}};
664 for(j
= 0; j
< 48; j
++) {
665 c
.d
.asBytes
[j
] = GraphBuffer
[i
+j
];
670 UsbCommand c
={CMD_SIMULATE_TAG_125K
, {GraphTraceLen
, 0, 0}};
674 static void CmdLosimBidir(char *str
)
676 /* Set ADC to twice the carrier for a slight supersampling */
677 UsbCommand c
={CMD_LF_SIMULATE_BIDIR
, {47, 384, 0}};
681 static void CmdLoread(char *str
)
683 UsbCommand c
={CMD_ACQUIRE_RAW_ADC_SAMPLES_125K
};
684 // 'h' means higher-low-frequency, 134 kHz
687 } else if (*str
== '\0') {
690 PrintToScrollback("use 'loread' or 'loread h'");
696 static void CmdDetectReader(char *str
)
698 UsbCommand c
={CMD_LISTEN_READER_FIELD
};
699 // 'l' means LF - 125/134 kHz
702 } else if (*str
== 'h') {
704 } else if (*str
!= '\0') {
705 PrintToScrollback("use 'detectreader' or 'detectreader l' or 'detectreader h'");
711 /* send a command before reading */
712 static void CmdLoCommandRead(char *str
)
714 static char dummy
[3];
718 UsbCommand c
={CMD_MOD_THEN_ACQUIRE_RAW_ADC_SAMPLES_125K
};
719 sscanf(str
, "%i %i %i %s %s", &c
.arg
[0], &c
.arg
[1], &c
.arg
[2], (char *) &c
.d
.asBytes
,(char *) &dummy
+1);
720 // in case they specified 'h'
721 strcpy((char *)&c
.d
.asBytes
+ strlen((char *)c
.d
.asBytes
), dummy
);
725 static void CmdLosamples(char *str
)
730 n
=strtol(str
, NULL
, 0);
732 if (n
>16000) n
=16000;
734 PrintToScrollback("Reading %d samples\n", n
);
735 for(i
= 0; i
< n
; i
+= 12) {
736 UsbCommand c
= {CMD_DOWNLOAD_RAW_ADC_SAMPLES_125K
, {i
, 0, 0}};
738 wait_for_response(CMD_DOWNLOADED_RAW_ADC_SAMPLES_125K
);
739 for(j
= 0; j
< 48; j
++) {
740 GraphBuffer
[cnt
++] = ((int)sample_buf
[j
]) - 128;
743 PrintToScrollback("Done!\n");
745 RepaintGraphWindow();
748 static void CmdBitsamples(char *str
)
754 for(i
= 0; i
< n
; i
+= 12) {
755 UsbCommand c
= {CMD_DOWNLOAD_RAW_ADC_SAMPLES_125K
, {i
, 0, 0}};
757 wait_for_response(CMD_DOWNLOADED_RAW_ADC_SAMPLES_125K
);
759 for(j
= 0; j
< 48; j
++) {
760 for(k
= 0; k
< 8; k
++) {
761 if(sample_buf
[j
] & (1 << (7 - k
))) {
762 GraphBuffer
[cnt
++] = 1;
764 GraphBuffer
[cnt
++] = 0;
770 RepaintGraphWindow();
773 static void CmdHisamples(char *str
)
779 for(i
= 0; i
< n
; i
+= 12) {
780 UsbCommand c
= {CMD_DOWNLOAD_RAW_ADC_SAMPLES_125K
, {i
, 0, 0}};
782 wait_for_response(CMD_DOWNLOADED_RAW_ADC_SAMPLES_125K
);
783 for(j
= 0; j
< 48; j
++) {
784 GraphBuffer
[cnt
++] = (int)(sample_buf
[j
]);
789 RepaintGraphWindow();
792 static int CmdHisamplest(char *str
, int nrlow
)
802 for(i
= 0; i
< n
; i
+= 12) {
803 UsbCommand c
= {CMD_DOWNLOAD_RAW_ADC_SAMPLES_125K
, {i
, 0, 0}};
805 wait_for_response(CMD_DOWNLOADED_RAW_ADC_SAMPLES_125K
);
806 for(j
= 0; j
< 48; j
++) {
807 t2
= (int)(sample_buf
[j
]);
808 if((t2
^ 0xC0) & 0xC0) { hasbeennull
++; }
814 t1
= (t2
& 0x80) ^ (t2
& 0x20);
815 t2
= ((t2
<< 1) & 0x80) ^ ((t2
<< 1) & 0x20);
821 t2
= ((t2
<< 1) & 0x80);
827 t2
= ((t2
<< 1) & 0x20);
831 // both, but tag with other algorithm
832 t1
= (t2
& 0x80) ^ (t2
& 0x08);
833 t2
= ((t2
<< 1) & 0x80) ^ ((t2
<< 1) & 0x08);
837 GraphBuffer
[cnt
++] = t1
;
838 GraphBuffer
[cnt
++] = t2
;
843 if(hasbeennull
>nrlow
|| nrlow
==0) {
844 PrintToScrollback("hasbeennull=%d", hasbeennull
);
853 static void CmdHexsamples(char *str
)
858 sscanf(str
, "%i %i", &requested
, &offset
);
860 PrintToScrollback("Offset must be a multiple of 4");
867 if (requested
== 0) {
874 for(i
= offset
; i
< n
+offset
; i
+= 12) {
875 UsbCommand c
= {CMD_DOWNLOAD_RAW_ADC_SAMPLES_125K
, {i
, 0, 0}};
877 wait_for_response(CMD_DOWNLOADED_RAW_ADC_SAMPLES_125K
);
878 for (j
= 0; j
< 48; j
+= 8) {
879 PrintToScrollback("%02x %02x %02x %02x %02x %02x %02x %02x",
891 if (delivered
>= requested
)
894 if (delivered
>= requested
)
899 static void CmdHisampless(char *str
)
903 int n
= strtol(str
, NULL
, 0);
911 for(i
= 0; i
< n
; i
+= 12) {
912 UsbCommand c
= {CMD_DOWNLOAD_RAW_ADC_SAMPLES_125K
, {i
, 0, 0}};
914 wait_for_response(CMD_DOWNLOADED_RAW_ADC_SAMPLES_125K
);
915 for(j
= 0; j
< 48; j
++) {
916 GraphBuffer
[cnt
++] = (int)(sample_buf
[j
]);
921 RepaintGraphWindow();
924 static uint16_t Iso15693Crc(uint8_t *v
, int n
)
930 for(i
= 0; i
< n
; i
++) {
931 reg
= reg
^ ((uint32_t)v
[i
]);
932 for (j
= 0; j
< 8; j
++) {
934 reg
= (reg
>> 1) ^ 0x8408;
941 return (uint16_t)~reg
;
944 static void CmdHi14bdemod(char *str
)
949 bool negateI
, negateQ
;
954 // As received, the samples are pairs, correlations against I and Q
955 // square waves. So estimate angle of initial carrier (or just
956 // quadrant, actually), and then do the demod.
958 // First, estimate where the tag starts modulating.
959 for(i
= 0; i
< GraphTraceLen
; i
+= 2) {
960 if(abs(GraphBuffer
[i
]) + abs(GraphBuffer
[i
+1]) > 40) {
964 if(i
>= GraphTraceLen
) {
965 PrintToScrollback("too weak to sync");
968 PrintToScrollback("out of weak at %d", i
);
971 // Now, estimate the phase in the initial modulation of the tag
974 for(; i
< (outOfWeakAt
+ 16); i
+= 2) {
975 isum
+= GraphBuffer
[i
+0];
976 qsum
+= GraphBuffer
[i
+1];
978 negateI
= (isum
< 0);
979 negateQ
= (qsum
< 0);
981 // Turn the correlation pairs into soft decisions on the bit.
983 for(i
= 0; i
< GraphTraceLen
/2; i
++) {
984 int si
= GraphBuffer
[j
];
985 int sq
= GraphBuffer
[j
+1];
986 if(negateI
) si
= -si
;
987 if(negateQ
) sq
= -sq
;
988 GraphBuffer
[i
] = si
+ sq
;
994 while(GraphBuffer
[i
] > 0 && i
< GraphTraceLen
)
996 if(i
>= GraphTraceLen
) goto demodError
;
999 while(GraphBuffer
[i
] < 0 && i
< GraphTraceLen
)
1001 if(i
>= GraphTraceLen
) goto demodError
;
1002 if((i
- iold
) > 23) goto demodError
;
1004 PrintToScrollback("make it to demod loop");
1008 while(GraphBuffer
[i
] >= 0 && i
< GraphTraceLen
)
1010 if(i
>= GraphTraceLen
) goto demodError
;
1011 if((i
- iold
) > 6) goto demodError
;
1013 uint16_t shiftReg
= 0;
1014 if(i
+ 20 >= GraphTraceLen
) goto demodError
;
1016 for(j
= 0; j
< 10; j
++) {
1017 int soft
= GraphBuffer
[i
] + GraphBuffer
[i
+1];
1019 if(abs(soft
) < ((abs(isum
) + abs(qsum
))/20)) {
1020 PrintToScrollback("weak bit");
1024 if(GraphBuffer
[i
] + GraphBuffer
[i
+1] >= 0) {
1031 if( (shiftReg
& 0x200) &&
1032 !(shiftReg
& 0x001))
1034 // valid data byte, start and stop bits okay
1035 PrintToScrollback(" %02x", (shiftReg
>> 1) & 0xff);
1036 data
[dataLen
++] = (shiftReg
>> 1) & 0xff;
1037 if(dataLen
>= sizeof(data
)) {
1040 } else if(shiftReg
== 0x000) {
1048 uint8_t first
, second
;
1049 ComputeCrc14443(CRC_14443_B
, data
, dataLen
-2, &first
, &second
);
1050 PrintToScrollback("CRC: %02x %02x (%s)\n", first
, second
,
1051 (first
== data
[dataLen
-2] && second
== data
[dataLen
-1]) ?
1052 "ok" : "****FAIL****");
1054 RepaintGraphWindow();
1058 PrintToScrollback("demod error");
1059 RepaintGraphWindow();
1062 static void CmdHi14list(char *str
)
1065 GetFromBigBuf(got
, sizeof(got
));
1067 PrintToScrollback("recorded activity:");
1068 PrintToScrollback(" time :rssi: who bytes");
1069 PrintToScrollback("---------+----+----+-----------");
1080 int timestamp
= *((uint32_t *)(got
+i
));
1081 if(timestamp
& 0x80000000) {
1082 timestamp
&= 0x7fffffff;
1087 int metric
= *((uint32_t *)(got
+i
+4));
1094 if(i
+ len
>= 900) {
1098 uint8_t *frame
= (got
+i
+9);
1100 char line
[1000] = "";
1102 for(j
= 0; j
< len
; j
++) {
1103 sprintf(line
+(j
*3), "%02x ", frame
[j
]);
1109 ComputeCrc14443(CRC_14443_B
, frame
, len
-2, &b1
, &b2
);
1110 if(b1
!= frame
[len
-2] || b2
!= frame
[len
-1]) {
1111 crc
= "**FAIL CRC**";
1119 char metricString
[100];
1121 sprintf(metricString
, "%3d", metric
);
1123 strcpy(metricString
, " ");
1126 PrintToScrollback(" +%7d: %s: %s %s %s",
1127 (prev
< 0 ? 0 : timestamp
- prev
),
1129 (isResponse
? "TAG" : " "), line
, crc
);
1136 static void CmdHi14alist(char *str
)
1139 GetFromBigBuf(got
, sizeof(got
));
1141 PrintToScrollback("recorded activity:");
1142 PrintToScrollback(" ETU :rssi: who bytes");
1143 PrintToScrollback("---------+----+----+-----------");
1154 int timestamp
= *((uint32_t *)(got
+i
));
1155 if(timestamp
& 0x80000000) {
1156 timestamp
&= 0x7fffffff;
1163 int parityBits
= *((uint32_t *)(got
+i
+4));
1164 // 4 bytes of additional information...
1165 // maximum of 32 additional parity bit information
1168 // at each quarter bit period we can send power level (16 levels)
1169 // or each half bit period in 256 levels.
1177 if(i
+ len
>= 1900) {
1181 uint8_t *frame
= (got
+i
+9);
1183 // Break and stick with current result if buffer was not completely full
1184 if(frame
[0] == 0x44 && frame
[1] == 0x44 && frame
[3] == 0x44) { break; }
1186 char line
[1000] = "";
1188 for(j
= 0; j
< len
; j
++) {
1189 int oddparity
= 0x01;
1193 oddparity
^= (((frame
[j
] & 0xFF) >> k
) & 0x01);
1196 //if((parityBits >> (len - j - 1)) & 0x01) {
1197 if(isResponse
&& (oddparity
!= ((parityBits
>> (len
- j
- 1)) & 0x01))) {
1198 sprintf(line
+(j
*4), "%02x! ", frame
[j
]);
1201 sprintf(line
+(j
*4), "%02x ", frame
[j
]);
1209 for(j
= 0; j
< (len
- 1); j
++) {
1210 // gives problems... search for the reason..
1211 /*if(frame[j] == 0xAA) {
1212 switch(frame[j+1]) {
1214 crc = "[1] Two drops close after each other";
1217 crc = "[2] Potential SOC with a drop in second half of bitperiod";
1220 crc = "[3] Segment Z after segment X is not possible";
1223 crc = "[4] Parity bit of a fully received byte was wrong";
1226 crc = "[?] Unknown error";
1233 if(strlen(crc
)==0) {
1234 ComputeCrc14443(CRC_14443_A
, frame
, len
-2, &b1
, &b2
);
1235 if(b1
!= frame
[len
-2] || b2
!= frame
[len
-1]) {
1236 crc
= (isResponse
& (len
< 6)) ? "" : " !crc";
1245 char metricString
[100];
1247 sprintf(metricString
, "%3d", metric
);
1249 strcpy(metricString
, " ");
1252 PrintToScrollback(" +%7d: %s: %s %s %s",
1253 (prev
< 0 ? 0 : (timestamp
- prev
)),
1255 (isResponse
? "TAG" : " "), line
, crc
);
1260 CommandFinished
= 1;
1263 static void CmdHi15demod(char *str
)
1265 // The sampling rate is 106.353 ksps/s, for T = 18.8 us
1268 // 1) Unmodulated time of 56.64us
1269 // 2) 24 pulses of 423.75khz
1270 // 3) logic '1' (unmodulated for 18.88us followed by 8 pulses of 423.75khz)
1272 static const int FrameSOF
[] = {
1273 -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
1274 -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
1275 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
1276 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
1282 static const int Logic0
[] = {
1288 static const int Logic1
[] = {
1296 // 1) logic '0' (8 pulses of 423.75khz followed by unmodulated for 18.88us)
1297 // 2) 24 pulses of 423.75khz
1298 // 3) Unmodulated time of 56.64us
1300 static const int FrameEOF
[] = {
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,
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
1312 int max
= 0, maxPos
;
1316 if(GraphTraceLen
< 1000) return;
1318 // First, correlate for SOF
1319 for(i
= 0; i
< 100; i
++) {
1321 for(j
= 0; j
< arraylen(FrameSOF
); j
+= skip
) {
1322 corr
+= FrameSOF
[j
]*GraphBuffer
[i
+(j
/skip
)];
1329 PrintToScrollback("SOF at %d, correlation %d", maxPos
,
1330 max
/(arraylen(FrameSOF
)/skip
));
1332 i
= maxPos
+ arraylen(FrameSOF
)/skip
;
1335 memset(outBuf
, 0, sizeof(outBuf
));
1336 uint8_t mask
= 0x01;
1338 int corr0
= 0, corr1
= 0, corrEOF
= 0;
1339 for(j
= 0; j
< arraylen(Logic0
); j
+= skip
) {
1340 corr0
+= Logic0
[j
]*GraphBuffer
[i
+(j
/skip
)];
1342 for(j
= 0; j
< arraylen(Logic1
); j
+= skip
) {
1343 corr1
+= Logic1
[j
]*GraphBuffer
[i
+(j
/skip
)];
1345 for(j
= 0; j
< arraylen(FrameEOF
); j
+= skip
) {
1346 corrEOF
+= FrameEOF
[j
]*GraphBuffer
[i
+(j
/skip
)];
1348 // Even things out by the length of the target waveform.
1352 if(corrEOF
> corr1
&& corrEOF
> corr0
) {
1353 PrintToScrollback("EOF at %d", i
);
1355 } else if(corr1
> corr0
) {
1356 i
+= arraylen(Logic1
)/skip
;
1359 i
+= arraylen(Logic0
)/skip
;
1366 if((i
+(int)arraylen(FrameEOF
)) >= GraphTraceLen
) {
1367 PrintToScrollback("ran off end!");
1372 PrintToScrollback("error, uneven octet! (discard extra bits!)");
1373 PrintToScrollback(" mask=%02x", mask
);
1375 PrintToScrollback("%d octets", k
);
1377 for(i
= 0; i
< k
; i
++) {
1378 PrintToScrollback("# %2d: %02x ", i
, outBuf
[i
]);
1380 PrintToScrollback("CRC=%04x", Iso15693Crc(outBuf
, k
-2));
1383 static void CmdFSKdemod(char *cmdline
)
1385 static const int LowTone
[] = {
1386 1, 1, 1, 1, 1, -1, -1, -1, -1, -1,
1387 1, 1, 1, 1, 1, -1, -1, -1, -1, -1,
1388 1, 1, 1, 1, 1, -1, -1, -1, -1, -1,
1389 1, 1, 1, 1, 1, -1, -1, -1, -1, -1,
1390 1, 1, 1, 1, 1, -1, -1, -1, -1, -1
1392 static const int HighTone
[] = {
1393 1, 1, 1, 1, 1, -1, -1, -1, -1,
1394 1, 1, 1, 1, -1, -1, -1, -1,
1395 1, 1, 1, 1, -1, -1, -1, -1,
1396 1, 1, 1, 1, -1, -1, -1, -1,
1397 1, 1, 1, 1, -1, -1, -1, -1,
1398 1, 1, 1, 1, -1, -1, -1, -1, -1,
1401 int lowLen
= sizeof(LowTone
)/sizeof(int);
1402 int highLen
= sizeof(HighTone
)/sizeof(int);
1403 int convLen
= (highLen
>lowLen
)?highLen
:lowLen
;
1404 uint32_t hi
= 0, lo
= 0;
1407 int minMark
=0, maxMark
=0;
1409 for(i
= 0; i
< GraphTraceLen
- convLen
; i
++) {
1410 int lowSum
= 0, highSum
= 0;
1412 for(j
= 0; j
< lowLen
; j
++) {
1413 lowSum
+= LowTone
[j
]*GraphBuffer
[i
+j
];
1415 for(j
= 0; j
< highLen
; j
++) {
1416 highSum
+= HighTone
[j
]*GraphBuffer
[i
+j
];
1418 lowSum
= abs((100*lowSum
) / lowLen
);
1419 highSum
= abs((100*highSum
) / highLen
);
1420 GraphBuffer
[i
] = (highSum
<< 16) | lowSum
;
1423 for(i
= 0; i
< GraphTraceLen
- convLen
- 16; i
++) {
1425 int lowTot
= 0, highTot
= 0;
1426 // 10 and 8 are f_s divided by f_l and f_h, rounded
1427 for(j
= 0; j
< 10; j
++) {
1428 lowTot
+= (GraphBuffer
[i
+j
] & 0xffff);
1430 for(j
= 0; j
< 8; j
++) {
1431 highTot
+= (GraphBuffer
[i
+j
] >> 16);
1433 GraphBuffer
[i
] = lowTot
- highTot
;
1434 if (GraphBuffer
[i
]>maxMark
) maxMark
=GraphBuffer
[i
];
1435 if (GraphBuffer
[i
]<minMark
) minMark
=GraphBuffer
[i
];
1438 GraphTraceLen
-= (convLen
+ 16);
1440 RepaintGraphWindow();
1442 // Find bit-sync (3 lo followed by 3 high)
1443 int max
= 0, maxPos
= 0;
1444 for(i
= 0; i
< 6000; i
++) {
1446 for(j
= 0; j
< 3*lowLen
; j
++) {
1447 dec
-= GraphBuffer
[i
+j
];
1449 for(; j
< 3*(lowLen
+ highLen
); j
++) {
1450 dec
+= GraphBuffer
[i
+j
];
1458 // place start of bit sync marker in graph
1459 GraphBuffer
[maxPos
] = maxMark
;
1460 GraphBuffer
[maxPos
+1] = minMark
;
1464 // place end of bit sync marker in graph
1465 GraphBuffer
[maxPos
] = maxMark
;
1466 GraphBuffer
[maxPos
+1] = minMark
;
1468 PrintToScrollback("actual data bits start at sample %d", maxPos
);
1469 PrintToScrollback("length %d/%d", highLen
, lowLen
);
1472 bits
[sizeof(bits
)-1] = '\0';
1474 // find bit pairs and manchester decode them
1475 for(i
= 0; i
< arraylen(bits
)-1; i
++) {
1477 for(j
= 0; j
< lowLen
; j
++) {
1478 dec
-= GraphBuffer
[maxPos
+j
];
1480 for(; j
< lowLen
+ highLen
; j
++) {
1481 dec
+= GraphBuffer
[maxPos
+j
];
1484 // place inter bit marker in graph
1485 GraphBuffer
[maxPos
] = maxMark
;
1486 GraphBuffer
[maxPos
+1] = minMark
;
1488 // hi and lo form a 64 bit pair
1489 hi
= (hi
<<1)|(lo
>>31);
1491 // store decoded bit as binary (in hi/lo) and text (in bits[])
1499 PrintToScrollback("bits: '%s'", bits
);
1500 PrintToScrollback("hex: %08x %08x", hi
, lo
);
1503 // read a TI tag and return its ID
1504 static void CmdTIRead(char *str
)
1506 UsbCommand c
={CMD_READ_TI_TYPE
};
1510 // write new data to a r/w TI tag
1511 static void CmdTIWrite(char *str
)
1513 UsbCommand c
={CMD_WRITE_TI_TYPE
};
1516 res
= sscanf(str
, "0x%x 0x%x 0x%x ", &c
.arg
[0], &c
.arg
[1], &c
.arg
[2]);
1517 if (res
== 2) c
.arg
[2]=0;
1519 PrintToScrollback("Please specify the data as two hex strings, optionally the CRC as a third");
1524 static void CmdTIDemod(char *cmdline
)
1526 /* MATLAB as follows:
1527 f_s = 2000000; % sampling frequency
1528 f_l = 123200; % low FSK tone
1529 f_h = 134200; % high FSK tone
1531 T_l = 119e-6; % low bit duration
1532 T_h = 130e-6; % high bit duration
1534 l = 2*pi*ones(1, floor(f_s*T_l))*(f_l/f_s);
1535 h = 2*pi*ones(1, floor(f_s*T_h))*(f_h/f_s);
1537 l = sign(sin(cumsum(l)));
1538 h = sign(sin(cumsum(h)));
1541 // 2M*16/134.2k = 238
1542 static const int LowTone
[] = {
1543 1, 1, 1, 1, 1, 1, 1, 1, 1, -1, -1, -1, -1, -1, -1, -1, -1,
1544 1, 1, 1, 1, 1, 1, 1, 1, -1, -1, -1, -1, -1, -1, -1, -1,
1545 1, 1, 1, 1, 1, 1, 1, 1, -1, -1, -1, -1, -1, -1, -1, -1,
1546 1, 1, 1, 1, 1, 1, 1, 1, -1, -1, -1, -1, -1, -1, -1, -1,
1547 1, 1, 1, 1, 1, 1, 1, 1, 1, -1, -1, -1, -1, -1, -1, -1, -1,
1548 1, 1, 1, 1, 1, 1, 1, 1, -1, -1, -1, -1, -1, -1, -1, -1,
1549 1, 1, 1, 1, 1, 1, 1, 1, -1, -1, -1, -1, -1, -1, -1, -1,
1550 1, 1, 1, 1, 1, 1, 1, 1, -1, -1, -1, -1, -1, -1, -1, -1,
1551 1, 1, 1, 1, 1, 1, 1, 1, 1, -1, -1, -1, -1, -1, -1, -1, -1,
1552 1, 1, 1, 1, 1, 1, 1, 1, -1, -1, -1, -1, -1, -1, -1, -1,
1553 1, 1, 1, 1, 1, 1, 1, 1, -1, -1, -1, -1, -1, -1, -1, -1,
1554 1, 1, 1, 1, 1, 1, 1, 1, -1, -1, -1, -1, -1, -1, -1, -1,
1555 1, 1, 1, 1, 1, 1, 1, 1, 1, -1, -1, -1, -1, -1, -1, -1, -1,
1556 1, 1, 1, 1, 1, 1, 1, 1, -1, -1, -1, -1, -1, -1, -1, -1,
1557 1, 1, 1, 1, 1, 1, 1, 1, -1, -1
1559 // 2M*16/123.2k = 260
1560 static const int HighTone
[] = {
1561 1, 1, 1, 1, 1, 1, 1, 1, -1, -1, -1, -1, -1, -1, -1,
1562 1, 1, 1, 1, 1, 1, 1, 1, -1, -1, -1, -1, -1, -1, -1,
1563 1, 1, 1, 1, 1, 1, 1, -1, -1, -1, -1, -1, -1, -1, -1,
1564 1, 1, 1, 1, 1, 1, 1, -1, -1, -1, -1, -1, -1, -1, -1,
1565 1, 1, 1, 1, 1, 1, 1, -1, -1, -1, -1, -1, -1, -1, -1,
1566 1, 1, 1, 1, 1, 1, 1, -1, -1, -1, -1, -1, -1, -1,
1567 1, 1, 1, 1, 1, 1, 1, 1, -1, -1, -1, -1, -1, -1, -1,
1568 1, 1, 1, 1, 1, 1, 1, 1, -1, -1, -1, -1, -1, -1, -1,
1569 1, 1, 1, 1, 1, 1, 1, -1, -1, -1, -1, -1, -1, -1, -1,
1570 1, 1, 1, 1, 1, 1, 1, -1, -1, -1, -1, -1, -1, -1, -1,
1571 1, 1, 1, 1, 1, 1, 1, -1, -1, -1, -1, -1, -1, -1,
1572 1, 1, 1, 1, 1, 1, 1, 1, -1, -1, -1, -1, -1, -1, -1,
1573 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,
1575 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,
1577 1, 1, 1, 1, 1, 1, 1, -1, -1, -1, -1, -1, -1, -1,
1578 1, 1, 1, 1, 1, 1, 1, 1
1580 int lowLen
= sizeof(LowTone
)/sizeof(int);
1581 int highLen
= sizeof(HighTone
)/sizeof(int);
1582 int convLen
= (highLen
>lowLen
)?highLen
:lowLen
;
1585 int lowSum
= 0, highSum
= 0;;
1586 int lowTot
= 0, highTot
= 0;
1588 for(i
= 0; i
< GraphTraceLen
- convLen
; i
++) {
1592 for(j
= 0; j
< lowLen
; j
++) {
1593 lowSum
+= LowTone
[j
]*GraphBuffer
[i
+j
];
1595 for(j
= 0; j
< highLen
; j
++) {
1596 highSum
+= HighTone
[j
]*GraphBuffer
[i
+j
];
1598 lowSum
= abs((100*lowSum
) / lowLen
);
1599 highSum
= abs((100*highSum
) / highLen
);
1600 lowSum
= (lowSum
<0)?-lowSum
:lowSum
;
1601 highSum
= (highSum
<0)?-highSum
:highSum
;
1603 GraphBuffer
[i
] = (highSum
<< 16) | lowSum
;
1606 for(i
= 0; i
< GraphTraceLen
- convLen
- 16; i
++) {
1609 // 16 and 15 are f_s divided by f_l and f_h, rounded
1610 for(j
= 0; j
< 16; j
++) {
1611 lowTot
+= (GraphBuffer
[i
+j
] & 0xffff);
1613 for(j
= 0; j
< 15; j
++) {
1614 highTot
+= (GraphBuffer
[i
+j
] >> 16);
1616 GraphBuffer
[i
] = lowTot
- highTot
;
1619 GraphTraceLen
-= (convLen
+ 16);
1621 RepaintGraphWindow();
1623 // TI tag data format is 16 prebits, 8 start bits, 64 data bits,
1624 // 16 crc CCITT bits, 8 stop bits, 15 end bits
1626 // the 16 prebits are always low
1627 // the 8 start and stop bits of a tag must match
1628 // the start/stop prebits of a ro tag are 01111110
1629 // the start/stop prebits of a rw tag are 11111110
1630 // the 15 end bits of a ro tag are all low
1631 // the 15 end bits of a rw tag match bits 15-1 of the data bits
1633 // Okay, so now we have unsliced soft decisions;
1634 // find bit-sync, and then get some bits.
1635 // look for 17 low bits followed by 6 highs (common pattern for ro and rw tags)
1636 int max
= 0, maxPos
= 0;
1637 for(i
= 0; i
< 6000; i
++) {
1640 // searching 17 consecutive lows
1641 for(j
= 0; j
< 17*lowLen
; j
++) {
1642 dec
-= GraphBuffer
[i
+j
];
1644 // searching 7 consecutive highs
1645 for(; j
< 17*lowLen
+ 6*highLen
; j
++) {
1646 dec
+= GraphBuffer
[i
+j
];
1654 // place a marker in the buffer to visually aid location
1655 // of the start of sync
1656 GraphBuffer
[maxPos
] = 800;
1657 GraphBuffer
[maxPos
+1] = -800;
1659 // advance pointer to start of actual data stream (after 16 pre and 8 start bits)
1660 maxPos
+= 17*lowLen
;
1661 maxPos
+= 6*highLen
;
1663 // place a marker in the buffer to visually aid location
1664 // of the end of sync
1665 GraphBuffer
[maxPos
] = 800;
1666 GraphBuffer
[maxPos
+1] = -800;
1668 PrintToScrollback("actual data bits start at sample %d", maxPos
);
1670 PrintToScrollback("length %d/%d", highLen
, lowLen
);
1672 uint8_t bits
[1+64+16+8+16];
1673 bits
[sizeof(bits
)-1] = '\0';
1675 uint32_t shift3
= 0x7e000000, shift2
= 0, shift1
= 0, shift0
= 0;
1677 for(i
= 0; i
< arraylen(bits
)-1; i
++) {
1681 for(j
= 0; j
< lowLen
; j
++) {
1682 low
-= GraphBuffer
[maxPos
+j
];
1684 for(j
= 0; j
< highLen
; j
++) {
1685 high
+= GraphBuffer
[maxPos
+j
];
1691 // bitstream arrives lsb first so shift right
1698 // 128 bit right shift register
1699 shift0
= (shift0
>>1) | (shift1
<< 31);
1700 shift1
= (shift1
>>1) | (shift2
<< 31);
1701 shift2
= (shift2
>>1) | (shift3
<< 31);
1704 // place a marker in the buffer between bits to visually aid location
1705 GraphBuffer
[maxPos
] = 800;
1706 GraphBuffer
[maxPos
+1] = -800;
1708 PrintToScrollback("Info: raw tag bits = %s", bits
);
1710 TagType
= (shift3
>>8)&0xff;
1711 if ( TagType
!= ((shift0
>>16)&0xff) ) {
1712 PrintToScrollback("Error: start and stop bits do not match!");
1715 else if (TagType
== 0x7e) {
1716 PrintToScrollback("Info: Readonly TI tag detected.");
1719 else if (TagType
== 0xfe) {
1720 PrintToScrollback("Info: Rewriteable TI tag detected.");
1722 // put 64 bit data into shift1 and shift0
1723 shift0
= (shift0
>>24) | (shift1
<< 8);
1724 shift1
= (shift1
>>24) | (shift2
<< 8);
1726 // align 16 bit crc into lower half of shift2
1727 shift2
= ((shift2
>>24) | (shift3
<< 8)) & 0x0ffff;
1729 // align 16 bit "end bits" or "ident" into lower half of shift3
1732 // only 15 bits compare, last bit of ident is not valid
1733 if ( (shift3
^shift0
)&0x7fff ) {
1734 PrintToScrollback("Error: Ident mismatch!");
1736 // WARNING the order of the bytes in which we calc crc below needs checking
1737 // i'm 99% sure the crc algorithm is correct, but it may need to eat the
1738 // bytes in reverse or something
1741 crc
= update_crc16(crc
, (shift0
)&0xff);
1742 crc
= update_crc16(crc
, (shift0
>>8)&0xff);
1743 crc
= update_crc16(crc
, (shift0
>>16)&0xff);
1744 crc
= update_crc16(crc
, (shift0
>>24)&0xff);
1745 crc
= update_crc16(crc
, (shift1
)&0xff);
1746 crc
= update_crc16(crc
, (shift1
>>8)&0xff);
1747 crc
= update_crc16(crc
, (shift1
>>16)&0xff);
1748 crc
= update_crc16(crc
, (shift1
>>24)&0xff);
1749 PrintToScrollback("Info: Tag data = %08X%08X", shift1
, shift0
);
1750 if (crc
!= (shift2
&0xffff)) {
1751 PrintToScrollback("Error: CRC mismatch, calculated %04X, got ^04X", crc
, shift2
&0xffff);
1753 PrintToScrollback("Info: CRC %04X is good", crc
);
1757 PrintToScrollback("Unknown tag type.");
1762 static void CmdNorm(char *str
)
1765 int max
= INT_MIN
, min
= INT_MAX
;
1766 for(i
= 10; i
< GraphTraceLen
; i
++) {
1767 if(GraphBuffer
[i
] > max
) {
1768 max
= GraphBuffer
[i
];
1770 if(GraphBuffer
[i
] < min
) {
1771 min
= GraphBuffer
[i
];
1775 for(i
= 0; i
< GraphTraceLen
; i
++) {
1776 GraphBuffer
[i
] = (GraphBuffer
[i
] - ((max
+ min
)/2))*1000/
1780 RepaintGraphWindow();
1783 static void CmdAmp(char *str
)
1785 int i
, rising
, falling
;
1786 int max
= INT_MIN
, min
= INT_MAX
;
1787 for(i
= 10; i
< GraphTraceLen
; i
++) {
1788 if(GraphBuffer
[i
] > max
) {
1789 max
= GraphBuffer
[i
];
1791 if(GraphBuffer
[i
] < min
) {
1792 min
= GraphBuffer
[i
];
1797 for(i
= 0; i
< GraphTraceLen
; i
++) {
1798 if(GraphBuffer
[i
+1] < GraphBuffer
[i
]) {
1800 GraphBuffer
[i
]= max
;
1805 if(GraphBuffer
[i
+1] > GraphBuffer
[i
]) {
1807 GraphBuffer
[i
]= min
;
1814 RepaintGraphWindow();
1817 static void CmdDec(char *str
)
1820 for(i
= 0; i
< (GraphTraceLen
/2); i
++) {
1821 GraphBuffer
[i
] = GraphBuffer
[i
*2];
1824 PrintToScrollback("decimated by 2");
1825 RepaintGraphWindow();
1828 static void CmdHpf(char *str
)
1832 for(i
= 10; i
< GraphTraceLen
; i
++) {
1833 accum
+= GraphBuffer
[i
];
1835 accum
/= (GraphTraceLen
- 10);
1836 for(i
= 0; i
< GraphTraceLen
; i
++) {
1837 GraphBuffer
[i
] -= accum
;
1840 RepaintGraphWindow();
1843 static void CmdZerocrossings(char *str
)
1846 // Zero-crossings aren't meaningful unless the signal is zero-mean.
1852 for(i
= 0; i
< GraphTraceLen
; i
++) {
1853 if(GraphBuffer
[i
]*sign
>= 0) {
1854 // No change in sign, reproduce the previous sample count.
1856 GraphBuffer
[i
] = lastZc
;
1858 // Change in sign, reset the sample count.
1860 GraphBuffer
[i
] = lastZc
;
1868 RepaintGraphWindow();
1871 static void CmdThreshold(char *str
)
1874 int threshold
= atoi(str
);
1876 for(i
= 0; i
< GraphTraceLen
; i
++) {
1877 if(GraphBuffer
[i
]>= threshold
)
1882 RepaintGraphWindow();
1885 static void CmdLtrim(char *str
)
1890 for(i
= ds
; i
< GraphTraceLen
; i
++) {
1891 GraphBuffer
[i
-ds
] = GraphBuffer
[i
];
1893 GraphTraceLen
-= ds
;
1895 RepaintGraphWindow();
1898 static void CmdAutoCorr(char *str
)
1900 static int CorrelBuffer
[MAX_GRAPH_TRACE_LEN
];
1902 int window
= atoi(str
);
1905 PrintToScrollback("needs a window");
1909 if(window
>= GraphTraceLen
) {
1910 PrintToScrollback("window must be smaller than trace (%d samples)",
1915 PrintToScrollback("performing %d correlations", GraphTraceLen
- window
);
1918 for(i
= 0; i
< GraphTraceLen
- window
; i
++) {
1921 for(j
= 0; j
< window
; j
++) {
1922 sum
+= (GraphBuffer
[j
]*GraphBuffer
[i
+j
]) / 256;
1924 CorrelBuffer
[i
] = sum
;
1926 GraphTraceLen
= GraphTraceLen
- window
;
1927 memcpy(GraphBuffer
, CorrelBuffer
, GraphTraceLen
*sizeof(int));
1929 RepaintGraphWindow();
1932 static void CmdVchdemod(char *str
)
1934 // Is this the entire sync pattern, or does this also include some
1935 // data bits that happen to be the same everywhere? That would be
1937 static const int SyncPattern
[] = {
1938 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
1939 1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
1940 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
1941 1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
1942 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
1943 1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
1944 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
1945 1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
1946 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
1947 1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
1950 // So first, we correlate for the sync pattern, and mark that.
1951 int bestCorrel
= 0, bestPos
= 0;
1953 // It does us no good to find the sync pattern, with fewer than
1954 // 2048 samples after it...
1955 for(i
= 0; i
< (GraphTraceLen
-2048); i
++) {
1958 for(j
= 0; j
< arraylen(SyncPattern
); j
++) {
1959 sum
+= GraphBuffer
[i
+j
]*SyncPattern
[j
];
1961 if(sum
> bestCorrel
) {
1966 PrintToScrollback("best sync at %d [metric %d]", bestPos
, bestCorrel
);
1971 int worst
= INT_MAX
;
1974 for(i
= 0; i
< 2048; i
+= 8) {
1977 for(j
= 0; j
< 8; j
++) {
1978 sum
+= GraphBuffer
[bestPos
+i
+j
];
1985 if(abs(sum
) < worst
) {
1990 PrintToScrollback("bits:");
1991 PrintToScrollback("%s", bits
);
1992 PrintToScrollback("worst metric: %d at pos %d", worst
, worstPos
);
1994 if(strcmp(str
, "clone")==0) {
1997 for(s
= bits
; *s
; s
++) {
1999 for(j
= 0; j
< 16; j
++) {
2000 GraphBuffer
[GraphTraceLen
++] = (*s
== '1') ? 1 : 0;
2003 RepaintGraphWindow();
2007 static void CmdIndalademod(char *str
)
2009 // Usage: recover 64bit UID by default, specify "224" as arg to recover a 224bit UID
2014 // worst case with GraphTraceLen=64000 is < 4096
2015 // under normal conditions it's < 2048
2016 uint8_t rawbits
[4096];
2018 int worst
= 0, worstPos
= 0;
2019 PrintToScrollback("Expecting a bit less than %d raw bits", GraphTraceLen
/32);
2020 for(i
= 0; i
< GraphTraceLen
-1; i
+= 2) {
2022 if((GraphBuffer
[i
] > GraphBuffer
[i
+ 1]) && (state
!= 1)) {
2024 for(j
= 0; j
< count
- 8; j
+= 16) {
2025 rawbits
[rawbit
++] = 0;
2027 if ((abs(count
- j
)) > worst
) {
2028 worst
= abs(count
- j
);
2034 } else if((GraphBuffer
[i
] < GraphBuffer
[i
+ 1]) && (state
!= 0)) {
2036 for(j
= 0; j
< count
- 8; j
+= 16) {
2037 rawbits
[rawbit
++] = 1;
2039 if ((abs(count
- j
)) > worst
) {
2040 worst
= abs(count
- j
);
2048 PrintToScrollback("Recovered %d raw bits", rawbit
);
2049 PrintToScrollback("worst metric (0=best..7=worst): %d at pos %d", worst
, worstPos
);
2051 // Finding the start of a UID
2052 int uidlen
, long_wait
;
2053 if(strcmp(str
, "224") == 0) {
2062 for(start
= 0; start
<= rawbit
- uidlen
; start
++) {
2063 first
= rawbits
[start
];
2064 for(i
= start
; i
< start
+ long_wait
; i
++) {
2065 if(rawbits
[i
] != first
) {
2069 if(i
== (start
+ long_wait
)) {
2073 if(start
== rawbit
- uidlen
+ 1) {
2074 PrintToScrollback("nothing to wait for");
2078 // Inverting signal if needed
2080 for(i
= start
; i
< rawbit
; i
++) {
2081 rawbits
[i
] = !rawbits
[i
];
2088 showbits
[uidlen
]='\0';
2092 if(uidlen
> rawbit
) {
2093 PrintToScrollback("Warning: not enough raw bits to get a full UID");
2094 for(bit
= 0; bit
< rawbit
; bit
++) {
2095 bits
[bit
] = rawbits
[i
++];
2096 // As we cannot know the parity, let's use "." and "/"
2097 showbits
[bit
] = '.' + bits
[bit
];
2099 showbits
[bit
+1]='\0';
2100 PrintToScrollback("Partial UID=%s", showbits
);
2103 for(bit
= 0; bit
< uidlen
; bit
++) {
2104 bits
[bit
] = rawbits
[i
++];
2105 showbits
[bit
] = '0' + bits
[bit
];
2109 PrintToScrollback("UID=%s", showbits
);
2111 // Checking UID against next occurences
2112 for(; i
+ uidlen
<= rawbit
;) {
2114 for(bit
= 0; bit
< uidlen
; bit
++) {
2115 if(bits
[bit
] != rawbits
[i
++]) {
2125 PrintToScrollback("Occurences: %d (expected %d)", times
, (rawbit
- start
) / uidlen
);
2127 // Remodulating for tag cloning
2128 GraphTraceLen
= 32*uidlen
;
2131 for(bit
= 0; bit
< uidlen
; bit
++) {
2132 if(bits
[bit
] == 0) {
2138 for(j
= 0; j
< 32; j
++) {
2139 GraphBuffer
[i
++] = phase
;
2144 RepaintGraphWindow();
2147 static void CmdFlexdemod(char *str
)
2150 for(i
= 0; i
< GraphTraceLen
; i
++) {
2151 if(GraphBuffer
[i
] < 0) {
2152 GraphBuffer
[i
] = -1;
2158 #define LONG_WAIT 100
2160 for(start
= 0; start
< GraphTraceLen
- LONG_WAIT
; start
++) {
2161 int first
= GraphBuffer
[start
];
2162 for(i
= start
; i
< start
+ LONG_WAIT
; i
++) {
2163 if(GraphBuffer
[i
] != first
) {
2167 if(i
== (start
+ LONG_WAIT
)) {
2171 if(start
== GraphTraceLen
- LONG_WAIT
) {
2172 PrintToScrollback("nothing to wait for");
2176 GraphBuffer
[start
] = 2;
2177 GraphBuffer
[start
+1] = -2;
2183 for(bit
= 0; bit
< 64; bit
++) {
2186 for(j
= 0; j
< 16; j
++) {
2187 sum
+= GraphBuffer
[i
++];
2194 PrintToScrollback("bit %d sum %d", bit
, sum
);
2197 for(bit
= 0; bit
< 64; bit
++) {
2200 for(j
= 0; j
< 16; j
++) {
2201 sum
+= GraphBuffer
[i
++];
2203 if(sum
> 0 && bits
[bit
] != 1) {
2204 PrintToScrollback("oops1 at %d", bit
);
2206 if(sum
< 0 && bits
[bit
] != 0) {
2207 PrintToScrollback("oops2 at %d", bit
);
2211 GraphTraceLen
= 32*64;
2214 for(bit
= 0; bit
< 64; bit
++) {
2215 if(bits
[bit
] == 0) {
2221 for(j
= 0; j
< 32; j
++) {
2222 GraphBuffer
[i
++] = phase
;
2227 RepaintGraphWindow();
2231 * Generic command to demodulate ASK.
2233 * Argument is convention: positive or negative (High mod means zero
2234 * or high mod means one)
2236 * Updates the Graph trace with 0/1 values
2242 static void Cmdaskdemod(char *str
) {
2244 int c
, high
= 0, low
= 0;
2246 // TODO: complain if we do not give 2 arguments here !
2247 // (AL - this doesn't make sense! we're only using one argument!!!)
2248 sscanf(str
, "%i", &c
);
2250 /* Detect high and lows and clock */
2252 for (i
= 0; i
< GraphTraceLen
; i
++)
2254 if (GraphBuffer
[i
] > high
)
2255 high
= GraphBuffer
[i
];
2256 else if (GraphBuffer
[i
] < low
)
2257 low
= GraphBuffer
[i
];
2259 if(c
!= 0 && c
!= 1) {
2260 PrintToScrollback("Invalid argument: %s",str
);
2264 if (GraphBuffer
[0] > 0) {
2265 GraphBuffer
[0] = 1-c
;
2269 for(i
=1;i
<GraphTraceLen
;i
++) {
2270 /* Transitions are detected at each peak
2271 * Transitions are either:
2272 * - we're low: transition if we hit a high
2273 * - we're high: transition if we hit a low
2274 * (we need to do it this way because some tags keep high or
2275 * low for long periods, others just reach the peak and go
2278 if ((GraphBuffer
[i
]==high
) && (GraphBuffer
[i
-1] == c
)) {
2280 } else if ((GraphBuffer
[i
]==low
) && (GraphBuffer
[i
-1] == (1-c
))){
2284 GraphBuffer
[i
] = GraphBuffer
[i
-1];
2287 RepaintGraphWindow();
2290 /* Print our clock rate */
2291 static void Cmddetectclockrate(char *str
)
2293 int clock
= detectclock(0);
2294 PrintToScrollback("Auto-detected clock rate: %d", clock
);
2300 int detectclock(int peak
)
2306 /* Detect peak if we don't have one */
2308 for (i
= 0; i
< GraphTraceLen
; i
++)
2309 if (GraphBuffer
[i
] > peak
)
2310 peak
= GraphBuffer
[i
];
2312 for (i
= 1; i
< GraphTraceLen
; i
++)
2314 /* If this is the beginning of a peak */
2315 if (GraphBuffer
[i
-1] != GraphBuffer
[i
] && GraphBuffer
[i
] == peak
)
2317 /* Find lowest difference between peaks */
2318 if (lastpeak
&& i
- lastpeak
< clock
)
2320 clock
= i
- lastpeak
;
2329 /* Get or auto-detect clock rate */
2330 int GetClock(char *str
, int peak
)
2334 sscanf(str
, "%i", &clock
);
2335 if (!strcmp(str
, ""))
2338 /* Auto-detect clock */
2341 clock
= detectclock(peak
);
2343 /* Only print this message if we're not looping something */
2345 PrintToScrollback("Auto-detected clock rate: %d", clock
);
2352 * Convert to a bitstream
2354 static void Cmdbitstream(char *str
) {
2361 int hithigh
, hitlow
, first
;
2363 /* Detect high and lows and clock */
2364 for (i
= 0; i
< GraphTraceLen
; i
++)
2366 if (GraphBuffer
[i
] > high
)
2367 high
= GraphBuffer
[i
];
2368 else if (GraphBuffer
[i
] < low
)
2369 low
= GraphBuffer
[i
];
2373 clock
= GetClock(str
, high
);
2375 gtl
= CmdClearGraph(0);
2378 for (i
= 0; i
< (int)(gtl
/ clock
); i
++)
2384 /* Find out if we hit both high and low peaks */
2385 for (j
= 0; j
< clock
; j
++)
2387 if (GraphBuffer
[(i
* clock
) + j
] == high
)
2389 else if (GraphBuffer
[(i
* clock
) + j
] == low
)
2392 /* it doesn't count if it's the first part of our read
2393 because it's really just trailing from the last sequence */
2394 if (first
&& (hithigh
|| hitlow
))
2395 hithigh
= hitlow
= 0;
2399 if (hithigh
&& hitlow
)
2403 /* If we didn't hit both high and low peaks, we had a bit transition */
2404 if (!hithigh
|| !hitlow
)
2407 CmdAppendGraph(0, clock
, bit
);
2408 // for (j = 0; j < (int)(clock/2); j++)
2409 // GraphBuffer[(i * clock) + j] = bit ^ 1;
2410 // for (j = (int)(clock/2); j < clock; j++)
2411 // GraphBuffer[(i * clock) + j] = bit;
2414 RepaintGraphWindow();
2417 /* Modulate our data into manchester */
2418 static void Cmdmanchestermod(char *str
)
2422 int bit
, lastbit
, wave
;
2425 clock
= GetClock(str
, 0);
2429 for (i
= 0; i
< (int)(GraphTraceLen
/ clock
); i
++)
2431 bit
= GraphBuffer
[i
* clock
] ^ 1;
2433 for (j
= 0; j
< (int)(clock
/2); j
++)
2434 GraphBuffer
[(i
* clock
) + j
] = bit
^ lastbit
^ wave
;
2435 for (j
= (int)(clock
/2); j
< clock
; j
++)
2436 GraphBuffer
[(i
* clock
) + j
] = bit
^ lastbit
^ wave
^ 1;
2438 /* Keep track of how we start our wave and if we changed or not this time */
2439 wave
^= bit
^ lastbit
;
2443 RepaintGraphWindow();
2447 * Manchester demodulate a bitstream. The bitstream needs to be already in
2448 * the GraphBuffer as 0 and 1 values
2450 * Give the clock rate as argument in order to help the sync - the algorithm
2451 * resyncs at each pulse anyway.
2453 * Not optimized by any means, this is the 1st time I'm writing this type of
2454 * routine, feel free to improve...
2456 * 1st argument: clock rate (as number of samples per clock rate)
2457 * Typical values can be 64, 32, 128...
2459 static void Cmdmanchesterdemod(char *str
) {
2460 int i
, j
, invert
= 0;
2466 int hithigh
, hitlow
, first
;
2472 /* check if we're inverting output */
2475 PrintToScrollback("Inverting output");
2479 while(*str
== ' '); // in case a 2nd argument was given
2482 /* Holds the decoded bitstream: each clock period contains 2 bits */
2483 /* later simplified to 1 bit after manchester decoding. */
2484 /* Add 10 bits to allow for noisy / uncertain traces without aborting */
2485 /* int BitStream[GraphTraceLen*2/clock+10]; */
2487 /* But it does not work if compiling on WIndows: therefore we just allocate a */
2489 int BitStream
[MAX_GRAPH_TRACE_LEN
];
2491 /* Detect high and lows */
2492 for (i
= 0; i
< GraphTraceLen
; i
++)
2494 if (GraphBuffer
[i
] > high
)
2495 high
= GraphBuffer
[i
];
2496 else if (GraphBuffer
[i
] < low
)
2497 low
= GraphBuffer
[i
];
2501 clock
= GetClock(str
, high
);
2503 int tolerance
= clock
/4;
2505 /* Detect first transition */
2506 /* Lo-Hi (arbitrary) */
2507 /* skip to the first high */
2508 for (i
= 0; i
< GraphTraceLen
; i
++)
2509 if(GraphBuffer
[i
] == high
)
2511 /* now look for the first low */
2512 for (; i
< GraphTraceLen
; i
++)
2514 if (GraphBuffer
[i
] == low
)
2521 /* If we're not working with 1/0s, demod based off clock */
2524 bit
= 0; /* We assume the 1st bit is zero, it may not be
2525 * the case: this routine (I think) has an init problem.
2528 for (; i
< (int)(GraphTraceLen
/ clock
); i
++)
2534 /* Find out if we hit both high and low peaks */
2535 for (j
= 0; j
< clock
; j
++)
2537 if (GraphBuffer
[(i
* clock
) + j
] == high
)
2539 else if (GraphBuffer
[(i
* clock
) + j
] == low
)
2542 /* it doesn't count if it's the first part of our read
2543 because it's really just trailing from the last sequence */
2544 if (first
&& (hithigh
|| hitlow
))
2545 hithigh
= hitlow
= 0;
2549 if (hithigh
&& hitlow
)
2553 /* If we didn't hit both high and low peaks, we had a bit transition */
2554 if (!hithigh
|| !hitlow
)
2557 BitStream
[bit2idx
++] = bit
^ invert
;
2561 /* standard 1/0 bitstream */
2565 /* Then detect duration between 2 successive transitions */
2566 for (bitidx
= 1; i
< GraphTraceLen
; i
++)
2568 if (GraphBuffer
[i
-1] != GraphBuffer
[i
])
2573 // Error check: if bitidx becomes too large, we do not
2574 // have a Manchester encoded bitstream or the clock is really
2576 if (bitidx
> (GraphTraceLen
*2/clock
+8) ) {
2577 PrintToScrollback("Error: the clock you gave is probably wrong, aborting.");
2580 // Then switch depending on lc length:
2581 // Tolerance is 1/4 of clock rate (arbitrary)
2582 if (abs(lc
-clock
/2) < tolerance
) {
2583 // Short pulse : either "1" or "0"
2584 BitStream
[bitidx
++]=GraphBuffer
[i
-1];
2585 } else if (abs(lc
-clock
) < tolerance
) {
2586 // Long pulse: either "11" or "00"
2587 BitStream
[bitidx
++]=GraphBuffer
[i
-1];
2588 BitStream
[bitidx
++]=GraphBuffer
[i
-1];
2592 PrintToScrollback("Warning: Manchester decode error for pulse width detection.");
2593 PrintToScrollback("(too many of those messages mean either the stream is not Manchester encoded, or clock is wrong)");
2597 PrintToScrollback("Error: too many detection errors, aborting.");
2604 // At this stage, we now have a bitstream of "01" ("1") or "10" ("0"), parse it into final decoded bitstream
2605 // Actually, we overwrite BitStream with the new decoded bitstream, we just need to be careful
2606 // to stop output at the final bitidx2 value, not bitidx
2607 for (i
= 0; i
< bitidx
; i
+= 2) {
2608 if ((BitStream
[i
] == 0) && (BitStream
[i
+1] == 1)) {
2609 BitStream
[bit2idx
++] = 1 ^ invert
;
2610 } else if ((BitStream
[i
] == 1) && (BitStream
[i
+1] == 0)) {
2611 BitStream
[bit2idx
++] = 0 ^ invert
;
2613 // We cannot end up in this state, this means we are unsynchronized,
2617 PrintToScrollback("Unsynchronized, resync...");
2618 PrintToScrollback("(too many of those messages mean the stream is not Manchester encoded)");
2622 PrintToScrollback("Error: too many decode errors, aborting.");
2629 PrintToScrollback("Manchester decoded bitstream");
2630 // Now output the bitstream to the scrollback by line of 16 bits
2631 for (i
= 0; i
< (bit2idx
-16); i
+=16) {
2632 PrintToScrollback("%i %i %i %i %i %i %i %i %i %i %i %i %i %i %i %i",
2655 static void CmdHiddemod(char *str
)
2657 if(GraphTraceLen
< 4800) {
2658 PrintToScrollback("too short; need at least 4800 samples");
2662 GraphTraceLen
= 4800;
2664 for(i
= 0; i
< GraphTraceLen
; i
++) {
2665 if(GraphBuffer
[i
] < 0) {
2671 RepaintGraphWindow();
2674 static void CmdPlot(char *str
)
2679 static void CmdGrid(char *str
)
2681 sscanf(str
, "%i %i", &PlotGridX
, &PlotGridY
);
2682 RepaintGraphWindow();
2685 static void CmdHide(char *str
)
2690 static void CmdScale(char *str
)
2692 CursorScaleFactor
= atoi(str
);
2693 if(CursorScaleFactor
== 0) {
2694 PrintToScrollback("bad, can't have zero scale");
2695 CursorScaleFactor
= 1;
2697 RepaintGraphWindow();
2700 static void CmdSave(char *str
)
2702 FILE *f
= fopen(str
, "w");
2704 PrintToScrollback("couldn't open '%s'", str
);
2708 for(i
= 0; i
< GraphTraceLen
; i
++) {
2709 fprintf(f
, "%d\n", GraphBuffer
[i
]);
2712 PrintToScrollback("saved to '%s'", str
);
2715 static void CmdLoad(char *str
)
2717 FILE *f
= fopen(str
, "r");
2719 PrintToScrollback("couldn't open '%s'", str
);
2725 while(fgets(line
, sizeof(line
), f
)) {
2726 GraphBuffer
[GraphTraceLen
] = atoi(line
);
2730 PrintToScrollback("loaded %d samples", GraphTraceLen
);
2731 RepaintGraphWindow();
2734 static void CmdHIDsimTAG(char *str
)
2736 unsigned int hi
=0, lo
=0;
2739 while (sscanf(&str
[i
++], "%1x", &n
) == 1) {
2740 hi
=(hi
<<4)|(lo
>>28);
2744 PrintToScrollback("Emulating tag with ID %x%16x", hi
, lo
);
2746 UsbCommand c
={CMD_HID_SIM_TAG
, {hi
, lo
, 0}};
2750 static void CmdReadmem(char *str
)
2752 UsbCommand c
={CMD_READ_MEM
, {strtol(str
, NULL
, 0), 0, 0}};
2756 static void CmdVersion(char *str
)
2758 UsbCommand c
={CMD_VERSION
};
2762 static void CmdLcdReset(char *str
)
2764 UsbCommand c
={CMD_LCD_RESET
, {strtol(str
, NULL
, 0), 0, 0}};
2768 static void CmdLcd(char *str
)
2771 UsbCommand c
={CMD_LCD
};
2772 sscanf(str
, "%x %d", &i
, &j
);
2780 * Sets the divisor for LF frequency clock: lets the user choose any LF frequency below
2783 static void CmdSetDivisor(char *str
)
2785 UsbCommand c
={CMD_SET_LF_DIVISOR
, {strtol(str
, NULL
, 0), 0, 0}};
2786 if (( c
.arg
[0]<0) || (c
.arg
[0]>255)) {
2787 PrintToScrollback("divisor must be between 19 and 255");
2790 PrintToScrollback("Divisor set, expected freq=%dHz", 12000000/(c
.arg
[0]+1));
2794 static void CmdSetMux(char *str
)
2796 UsbCommand c
={CMD_SET_ADC_MUX
};
2797 if(strcmp(str
, "lopkd") == 0) {
2799 } else if(strcmp(str
, "loraw") == 0) {
2801 } else if(strcmp(str
, "hipkd") == 0) {
2803 } else if(strcmp(str
, "hiraw") == 0) {
2809 typedef void HandlerFunction(char *cmdline
);
2811 /* in alphabetic order */
2814 HandlerFunction
*handler
;
2815 int offline
; // 1 if the command can be used when in offline mode
2817 } CommandTable
[] = {
2818 /* plot window / data buffer manipulation */
2819 {"buffclear", CmdBuffClear
, 1, "Clear sample buffer and graph window"},
2820 {"load", CmdLoad
, 1, "<filename> -- Load trace (to graph window"},
2821 {"save", CmdSave
, 1, "<filename> -- Save trace (from graph window)"},
2822 {"amp", CmdAmp
, 1, "Amplify peaks"},
2823 {"autocorr", CmdAutoCorr
, 1, "<window length> -- Autocorrelation over window"},
2824 {"dec", CmdDec
, 1, "Decimate samples"},
2825 {"hpf", CmdHpf
, 1, "Remove DC offset from trace"},
2826 {"ltrim", CmdLtrim
, 1, "<samples> -- Trim samples from left of trace"},
2827 {"norm", CmdNorm
, 1, "Normalize max/min to +/-500"},
2828 {"plot", CmdPlot
, 1, "Show graph window"},
2829 {"hide", CmdHide
, 1, "Hide graph window"},
2830 {"grid", CmdGrid
, 1, "<x> <y> -- overlay grid on graph window, use zero value to turn off either"},
2831 {"threshold", CmdThreshold
, 1, "Maximize/minimize every value in the graph window depending on threshold"},
2832 {"zerocrossings", CmdZerocrossings
, 1, "Count time between zero-crossings"},
2833 {"scale", CmdScale
, 1, "<int> -- Set cursor display scale"},
2834 {"bitstream", Cmdbitstream
, 1, "[clock rate] -- Convert waveform into a bitstream"},
2835 {"detectclock", Cmddetectclockrate
, 1, "Detect clock rate"},
2836 {"exit", CmdQuit
, 1, "Exit program"},
2837 {"quit", CmdQuit
, 1, "Exit program"},
2839 /* low-level hardware control */
2840 {"fpgaoff", CmdFPGAOff
, 0, "Set FPGA off"},
2841 {"tune", CmdTune
, 0, "Measure antenna tuning"},
2842 {"hitune", CmdHiTune
, 0, "Continuously measure HF antenna tuning"},
2843 {"readmem", CmdReadmem
, 0, "[address] -- Read memory at decimal address from flash"},
2844 {"reset", CmdReset
, 0, "Reset the Proxmark3"},
2845 {"setlfdivisor", CmdSetDivisor
, 0, "<19 - 255> -- Drive LF antenna at 12Mhz/(divisor+1)"},
2846 {"setmux", CmdSetMux
, 0, "<loraw|hiraw|lopkd|hipkd> -- Set the ADC mux to a specific value"},
2847 {"version", CmdVersion
, 0, "Show version inforation about the connected Proxmark"},
2848 {"lcd", CmdLcd
, 0, "<HEX command> <count> -- Send command/data to LCD"},
2849 {"lcdreset", CmdLcdReset
, 0, "Hardware reset LCD"},
2851 /* data transfer functions */
2853 {"bitsamples", CmdBitsamples
, 0, "Get raw samples as bitstring"},
2854 {"hexsamples", CmdHexsamples
, 0, "<blocks> [<offset>] -- Dump big buffer as hex bytes"},
2855 {"higet", CmdHi14read_sim
, 0, "<samples> -- Get samples HF, 'analog'"},
2856 {"hisamples", CmdHisamples
, 0, "Get raw samples for HF tag"},
2857 {"hisampless", CmdHisampless
, 0, "<samples> -- Get signed raw samples, HF tag"},
2858 {"hisamplest", CmdHi14readt
, 0, "Get samples HF, for testing"},
2859 {"losamples", CmdLosamples
, 0, "[128 - 16000] -- Get raw samples for LF tag"},
2860 {"detectreader", CmdDetectReader
, 0, "['l'|'h'] -- Detect external reader field (option 'l' or 'h' to limit to LF or HF)"},
2862 /* (de-)modulation */
2864 {"askdemod", Cmdaskdemod
, 1, "<0|1> -- Attempt to demodulate simple ASK tags"},
2865 {"flexdemod", CmdFlexdemod
, 1, "Demodulate samples for FlexPass"},
2866 {"fskdemod", CmdFSKdemod
, 1, "Demodulate graph window as a HID FSK"},
2867 {"hi14bdemod", CmdHi14bdemod
, 1, "Demodulate ISO14443 Type B from tag"},
2868 {"hi15demod", CmdHi15demod
, 1, "Demodulate ISO15693 from tag"},
2869 {"hiddemod", CmdHiddemod
, 1, "Demodulate HID Prox Card II (not optimal)"},
2870 {"hidfskdemod", CmdHIDdemodFSK
, 0, "Realtime HID FSK demodulator"},
2871 {"indalademod", CmdIndalademod
, 1, "['224'] -- Demodulate samples for Indala 64 bit UID (option '224' for 224 bit)"},
2872 {"mandemod", Cmdmanchesterdemod
, 1, "[i] [clock rate] -- Manchester demodulate binary stream (option 'i' to invert output)"},
2873 {"manmod", Cmdmanchestermod
, 1, "[clock rate] -- Manchester modulate a binary stream"},
2874 {"tidemod", CmdTIDemod
, 1, "Demodulate raw bits for TI-type LF tag"},
2875 {"vchdemod", CmdVchdemod
, 1, "['clone'] -- Demodulate samples for VeriChip"},
2878 {"em410xsim", CmdEM410xsim
, 1, "<UID> -- Simulate EM410x tag"},
2879 {"hi14sim", CmdHi14sim
, 0, "Fake ISO 14443 tag"},
2880 {"hi14asim", CmdHi14asim
, 0, "<UID> -- Fake ISO 14443a tag"},
2881 {"hi15sim", CmdHi15tag
, 0, "Fake an ISO15693 tag"},
2882 {"hidsimtag", CmdHIDsimTAG
, 0, "<ID> -- HID tag simulator"},
2883 {"hisimlisten", CmdHisimlisten
, 0, "Get HF samples as fake tag"},
2884 {"losim", CmdLosim
, 0, "Simulate LF tag"},
2885 {"losimbidir", CmdLosimBidir
, 0, "Simulate LF tag (with bidirectional data transmission between reader and tag)"},
2887 /* card reading functions */
2888 {"em410xread", CmdEM410xread
, 1, "[clock rate] -- Extract ID from EM410x tag"},
2889 {"em410xwatch", CmdEM410xwatch
, 0, "Watches for EM410x tags"},
2890 {"em4x50read", CmdEM4x50read
, 1, "Extract data from EM4x50 tag"},
2891 {"hi14alist", CmdHi14alist
, 0, "List ISO 14443a history"},
2892 {"hi14amifare", CmdHi14amifare
, 0, "Read out sector 0 parity error messages"},
2893 {"hi14areader", CmdHi14areader
, 0, "Act like an ISO14443 Type A reader"},
2894 {"hi14asnoop", CmdHi14asnoop
, 0, "Eavesdrop ISO 14443 Type A"},
2895 {"hi14list", CmdHi14list
, 0, "List ISO 14443 history"},
2896 {"hi14read", CmdHi14read
, 0, "Read HF tag (ISO 14443)"},
2897 {"hi14snoop", CmdHi14snoop
, 0, "Eavesdrop ISO 14443"},
2898 {"hi15read", CmdHi15read
, 0, "Read HF tag (ISO 15693)"},
2899 {"hi15reader", CmdHi15reader
, 0, "Act like an ISO15693 reader"},
2900 {"legicrfread", CmdLegicRfRead
, 0, "Start the LEGIC RF reader"},
2901 {"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)"},
2902 {"loread", CmdLoread
, 0, "['h'] -- Read 125/134 kHz LF ID-only tag (option 'h' for 134)"},
2903 {"sri512read", CmdSri512read
, 0, "<int> -- Read contents of a SRI512 tag"},
2904 {"srix4kread", CmdSrix4kread
, 0, "<int> -- Read contents of a SRIX4K tag"},
2905 {"tiread", CmdTIRead
, 0, "Read and decode a TI 134 kHz tag"},
2906 {"tiwrite", CmdTIWrite
, 0, "Write new data to a r/w TI 134 kHz tag"},
2914 } CommandExtendedHelp
[]= {
2915 {"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."},
2916 {"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."},
2919 //-----------------------------------------------------------------------------
2920 // Entry point into our code: called whenever the user types a command and
2921 // then presses Enter, which the full command line that they typed.
2922 //-----------------------------------------------------------------------------
2923 void CommandReceived(char *cmd
)
2928 PrintToScrollback("> %s", cmd
);
2930 if(strcmp(cmd
, "help") == 0 || strncmp(cmd
,"help ",strlen("help ")) == 0) {
2931 // check if we're doing extended help
2932 if(strlen(cmd
) > strlen("help ")) {
2933 cmd
+= strlen("help ");
2934 for(i
= 0; i
< sizeof(CommandExtendedHelp
) / sizeof(CommandExtendedHelp
[0]); i
++) {
2935 if(strcmp(CommandExtendedHelp
[i
].name
,cmd
) == 0) {
2936 PrintToScrollback("\nExtended help for '%s':\n", cmd
);
2937 PrintToScrollback("Args: %s\t- %s\n",CommandExtendedHelp
[i
].args
,CommandExtendedHelp
[i
].argshelp
);
2938 PrintToScrollback(CommandExtendedHelp
[i
].description
);
2939 PrintToScrollback("");
2943 PrintToScrollback("No extended help available for '%s'", cmd
);
2946 if (offline
) PrintToScrollback("Operating in OFFLINE mode (no device connected)");
2947 PrintToScrollback("\r\nAvailable commands:");
2948 for(i
= 0; i
< sizeof(CommandTable
) / sizeof(CommandTable
[0]); i
++) {
2949 if (offline
&& (CommandTable
[i
].offline
==0)) continue;
2950 memset(line
, ' ', sizeof(line
));
2951 strcpy(line
+2, CommandTable
[i
].name
);
2952 line
[strlen(line
)] = ' ';
2953 sprintf(line
+15, " -- %s", CommandTable
[i
].docString
);
2954 PrintToScrollback("%s", line
);
2956 PrintToScrollback("");
2957 PrintToScrollback("'help <command>' for extended help on that command\n");
2961 for(i
= 0; i
< sizeof(CommandTable
) / sizeof(CommandTable
[0]); i
++) {
2962 char *name
= CommandTable
[i
].name
;
2963 if(memcmp(cmd
, name
, strlen(name
))==0 &&
2964 (cmd
[strlen(name
)] == ' ' || cmd
[strlen(name
)] == '\0'))
2966 cmd
+= strlen(name
);
2967 while(*cmd
== ' ') {
2970 if (offline
&& (CommandTable
[i
].offline
==0)) {
2971 PrintToScrollback("Offline mode, cannot use this command.");
2974 (CommandTable
[i
].handler
)(cmd
);
2978 PrintToScrollback(">> bad command '%s'", cmd
);
2981 //-----------------------------------------------------------------------------
2982 // Entry point into our code: called whenever we received a packet over USB
2983 // that we weren't necessarily expecting, for example a debug print.
2984 //-----------------------------------------------------------------------------
2985 void UsbCommandReceived(UsbCommand
*c
)
2987 // printf("%s(%x) current cmd = %x\n", __FUNCTION__, c->cmd, current_command);
2988 /* If we recognize a response, return to avoid further processing */
2990 case CMD_DEBUG_PRINT_STRING
: {
2992 if(c
->arg
[0] > 70 || c
->arg
[0] < 0) {
2995 memcpy(s
, c
->d
.asBytes
, c
->arg
[0]);
2996 s
[c
->arg
[0]] = '\0';
2997 PrintToScrollback("#db# %s", s
);
3001 case CMD_DEBUG_PRINT_INTEGERS
:
3002 PrintToScrollback("#db# %08x, %08x, %08x\r\n", c
->arg
[0], c
->arg
[1], c
->arg
[2]);
3005 case CMD_MEASURED_ANTENNA_TUNING
: {
3007 int vLf125
, vLf134
, vHf
;
3008 vLf125
= c
->arg
[0] & 0xffff;
3009 vLf134
= c
->arg
[0] >> 16;
3010 vHf
= c
->arg
[1] & 0xffff;;
3011 peakf
= c
->arg
[2] & 0xffff;
3012 peakv
= c
->arg
[2] >> 16;
3013 PrintToScrollback("");
3014 PrintToScrollback("");
3015 PrintToScrollback("# LF antenna: %5.2f V @ 125.00 kHz", vLf125
/1000.0);
3016 PrintToScrollback("# LF antenna: %5.2f V @ 134.00 kHz", vLf134
/1000.0);
3017 PrintToScrollback("# LF optimal: %5.2f V @%9.2f kHz", peakv
/1000.0, 12000.0/(peakf
+1));
3018 PrintToScrollback("# HF antenna: %5.2f V @ 13.56 MHz", vHf
/1000.0);
3020 PrintToScrollback("# Your LF antenna is unusable.");
3021 else if (peakv
<10000)
3022 PrintToScrollback("# Your LF antenna is marginal.");
3024 PrintToScrollback("# Your HF antenna is unusable.");
3026 PrintToScrollback("# Your HF antenna is marginal.");
3032 /* Maybe it's a response: */
3033 switch(current_command
) {
3034 case CMD_DOWNLOAD_RAW_ADC_SAMPLES_125K
:
3035 if (c
->cmd
!= CMD_DOWNLOADED_RAW_ADC_SAMPLES_125K
) goto unexpected_response
;
3037 for(i
=0; i
<48; i
++) sample_buf
[i
] = c
->d
.asBytes
[i
];
3038 received_command
= c
->cmd
;
3041 unexpected_response
:
3042 PrintToScrollback("unrecognized command %08x\n", c
->cmd
);