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
)
856 int requested
= strtol(str
, NULL
, 0);
859 if (requested
== 0) {
866 for(i
= 0; i
< n
; i
+= 12) {
867 UsbCommand c
= {CMD_DOWNLOAD_RAW_ADC_SAMPLES_125K
, {i
, 0, 0}};
869 wait_for_response(CMD_DOWNLOADED_RAW_ADC_SAMPLES_125K
);
870 for (j
= 0; j
< 48; j
+= 8) {
871 PrintToScrollback("%02x %02x %02x %02x %02x %02x %02x %02x",
883 if (delivered
>= requested
)
886 if (delivered
>= requested
)
891 static void CmdHisampless(char *str
)
895 int n
= strtol(str
, NULL
, 0);
903 for(i
= 0; i
< n
; i
+= 12) {
904 UsbCommand c
= {CMD_DOWNLOAD_RAW_ADC_SAMPLES_125K
, {i
, 0, 0}};
906 wait_for_response(CMD_DOWNLOADED_RAW_ADC_SAMPLES_125K
);
907 for(j
= 0; j
< 48; j
++) {
908 GraphBuffer
[cnt
++] = (int)(sample_buf
[j
]);
913 RepaintGraphWindow();
916 static uint16_t Iso15693Crc(uint8_t *v
, int n
)
922 for(i
= 0; i
< n
; i
++) {
923 reg
= reg
^ ((uint32_t)v
[i
]);
924 for (j
= 0; j
< 8; j
++) {
926 reg
= (reg
>> 1) ^ 0x8408;
933 return (uint16_t)~reg
;
936 static void CmdHi14bdemod(char *str
)
941 bool negateI
, negateQ
;
946 // As received, the samples are pairs, correlations against I and Q
947 // square waves. So estimate angle of initial carrier (or just
948 // quadrant, actually), and then do the demod.
950 // First, estimate where the tag starts modulating.
951 for(i
= 0; i
< GraphTraceLen
; i
+= 2) {
952 if(abs(GraphBuffer
[i
]) + abs(GraphBuffer
[i
+1]) > 40) {
956 if(i
>= GraphTraceLen
) {
957 PrintToScrollback("too weak to sync");
960 PrintToScrollback("out of weak at %d", i
);
963 // Now, estimate the phase in the initial modulation of the tag
966 for(; i
< (outOfWeakAt
+ 16); i
+= 2) {
967 isum
+= GraphBuffer
[i
+0];
968 qsum
+= GraphBuffer
[i
+1];
970 negateI
= (isum
< 0);
971 negateQ
= (qsum
< 0);
973 // Turn the correlation pairs into soft decisions on the bit.
975 for(i
= 0; i
< GraphTraceLen
/2; i
++) {
976 int si
= GraphBuffer
[j
];
977 int sq
= GraphBuffer
[j
+1];
978 if(negateI
) si
= -si
;
979 if(negateQ
) sq
= -sq
;
980 GraphBuffer
[i
] = si
+ sq
;
986 while(GraphBuffer
[i
] > 0 && i
< GraphTraceLen
)
988 if(i
>= GraphTraceLen
) goto demodError
;
991 while(GraphBuffer
[i
] < 0 && i
< GraphTraceLen
)
993 if(i
>= GraphTraceLen
) goto demodError
;
994 if((i
- iold
) > 23) goto demodError
;
996 PrintToScrollback("make it to demod loop");
1000 while(GraphBuffer
[i
] >= 0 && i
< GraphTraceLen
)
1002 if(i
>= GraphTraceLen
) goto demodError
;
1003 if((i
- iold
) > 6) goto demodError
;
1005 uint16_t shiftReg
= 0;
1006 if(i
+ 20 >= GraphTraceLen
) goto demodError
;
1008 for(j
= 0; j
< 10; j
++) {
1009 int soft
= GraphBuffer
[i
] + GraphBuffer
[i
+1];
1011 if(abs(soft
) < ((abs(isum
) + abs(qsum
))/20)) {
1012 PrintToScrollback("weak bit");
1016 if(GraphBuffer
[i
] + GraphBuffer
[i
+1] >= 0) {
1023 if( (shiftReg
& 0x200) &&
1024 !(shiftReg
& 0x001))
1026 // valid data byte, start and stop bits okay
1027 PrintToScrollback(" %02x", (shiftReg
>> 1) & 0xff);
1028 data
[dataLen
++] = (shiftReg
>> 1) & 0xff;
1029 if(dataLen
>= sizeof(data
)) {
1032 } else if(shiftReg
== 0x000) {
1040 uint8_t first
, second
;
1041 ComputeCrc14443(CRC_14443_B
, data
, dataLen
-2, &first
, &second
);
1042 PrintToScrollback("CRC: %02x %02x (%s)\n", first
, second
,
1043 (first
== data
[dataLen
-2] && second
== data
[dataLen
-1]) ?
1044 "ok" : "****FAIL****");
1046 RepaintGraphWindow();
1050 PrintToScrollback("demod error");
1051 RepaintGraphWindow();
1054 static void CmdHi14list(char *str
)
1057 GetFromBigBuf(got
, sizeof(got
));
1059 PrintToScrollback("recorded activity:");
1060 PrintToScrollback(" time :rssi: who bytes");
1061 PrintToScrollback("---------+----+----+-----------");
1072 int timestamp
= *((uint32_t *)(got
+i
));
1073 if(timestamp
& 0x80000000) {
1074 timestamp
&= 0x7fffffff;
1079 int metric
= *((uint32_t *)(got
+i
+4));
1086 if(i
+ len
>= 900) {
1090 uint8_t *frame
= (got
+i
+9);
1092 char line
[1000] = "";
1094 for(j
= 0; j
< len
; j
++) {
1095 sprintf(line
+(j
*3), "%02x ", frame
[j
]);
1101 ComputeCrc14443(CRC_14443_B
, frame
, len
-2, &b1
, &b2
);
1102 if(b1
!= frame
[len
-2] || b2
!= frame
[len
-1]) {
1103 crc
= "**FAIL CRC**";
1111 char metricString
[100];
1113 sprintf(metricString
, "%3d", metric
);
1115 strcpy(metricString
, " ");
1118 PrintToScrollback(" +%7d: %s: %s %s %s",
1119 (prev
< 0 ? 0 : timestamp
- prev
),
1121 (isResponse
? "TAG" : " "), line
, crc
);
1128 static void CmdHi14alist(char *str
)
1131 GetFromBigBuf(got
, sizeof(got
));
1133 PrintToScrollback("recorded activity:");
1134 PrintToScrollback(" ETU :rssi: who bytes");
1135 PrintToScrollback("---------+----+----+-----------");
1146 int timestamp
= *((uint32_t *)(got
+i
));
1147 if(timestamp
& 0x80000000) {
1148 timestamp
&= 0x7fffffff;
1155 int parityBits
= *((uint32_t *)(got
+i
+4));
1156 // 4 bytes of additional information...
1157 // maximum of 32 additional parity bit information
1160 // at each quarter bit period we can send power level (16 levels)
1161 // or each half bit period in 256 levels.
1169 if(i
+ len
>= 1900) {
1173 uint8_t *frame
= (got
+i
+9);
1175 // Break and stick with current result if buffer was not completely full
1176 if(frame
[0] == 0x44 && frame
[1] == 0x44 && frame
[3] == 0x44) { break; }
1178 char line
[1000] = "";
1180 for(j
= 0; j
< len
; j
++) {
1181 int oddparity
= 0x01;
1185 oddparity
^= (((frame
[j
] & 0xFF) >> k
) & 0x01);
1188 //if((parityBits >> (len - j - 1)) & 0x01) {
1189 if(isResponse
&& (oddparity
!= ((parityBits
>> (len
- j
- 1)) & 0x01))) {
1190 sprintf(line
+(j
*4), "%02x! ", frame
[j
]);
1193 sprintf(line
+(j
*4), "%02x ", frame
[j
]);
1201 for(j
= 0; j
< (len
- 1); j
++) {
1202 // gives problems... search for the reason..
1203 /*if(frame[j] == 0xAA) {
1204 switch(frame[j+1]) {
1206 crc = "[1] Two drops close after each other";
1209 crc = "[2] Potential SOC with a drop in second half of bitperiod";
1212 crc = "[3] Segment Z after segment X is not possible";
1215 crc = "[4] Parity bit of a fully received byte was wrong";
1218 crc = "[?] Unknown error";
1225 if(strlen(crc
)==0) {
1226 ComputeCrc14443(CRC_14443_A
, frame
, len
-2, &b1
, &b2
);
1227 if(b1
!= frame
[len
-2] || b2
!= frame
[len
-1]) {
1228 crc
= (isResponse
& (len
< 6)) ? "" : " !crc";
1237 char metricString
[100];
1239 sprintf(metricString
, "%3d", metric
);
1241 strcpy(metricString
, " ");
1244 PrintToScrollback(" +%7d: %s: %s %s %s",
1245 (prev
< 0 ? 0 : (timestamp
- prev
)),
1247 (isResponse
? "TAG" : " "), line
, crc
);
1252 CommandFinished
= 1;
1255 static void CmdHi15demod(char *str
)
1257 // The sampling rate is 106.353 ksps/s, for T = 18.8 us
1260 // 1) Unmodulated time of 56.64us
1261 // 2) 24 pulses of 423.75khz
1262 // 3) logic '1' (unmodulated for 18.88us followed by 8 pulses of 423.75khz)
1264 static const int FrameSOF
[] = {
1265 -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
1266 -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
1267 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
1268 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
1274 static const int Logic0
[] = {
1280 static const int Logic1
[] = {
1288 // 1) logic '0' (8 pulses of 423.75khz followed by unmodulated for 18.88us)
1289 // 2) 24 pulses of 423.75khz
1290 // 3) Unmodulated time of 56.64us
1292 static const int FrameEOF
[] = {
1297 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
1298 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
1299 -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
1300 -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1
1304 int max
= 0, maxPos
;
1308 if(GraphTraceLen
< 1000) return;
1310 // First, correlate for SOF
1311 for(i
= 0; i
< 100; i
++) {
1313 for(j
= 0; j
< arraylen(FrameSOF
); j
+= skip
) {
1314 corr
+= FrameSOF
[j
]*GraphBuffer
[i
+(j
/skip
)];
1321 PrintToScrollback("SOF at %d, correlation %d", maxPos
,
1322 max
/(arraylen(FrameSOF
)/skip
));
1324 i
= maxPos
+ arraylen(FrameSOF
)/skip
;
1327 memset(outBuf
, 0, sizeof(outBuf
));
1328 uint8_t mask
= 0x01;
1330 int corr0
= 0, corr1
= 0, corrEOF
= 0;
1331 for(j
= 0; j
< arraylen(Logic0
); j
+= skip
) {
1332 corr0
+= Logic0
[j
]*GraphBuffer
[i
+(j
/skip
)];
1334 for(j
= 0; j
< arraylen(Logic1
); j
+= skip
) {
1335 corr1
+= Logic1
[j
]*GraphBuffer
[i
+(j
/skip
)];
1337 for(j
= 0; j
< arraylen(FrameEOF
); j
+= skip
) {
1338 corrEOF
+= FrameEOF
[j
]*GraphBuffer
[i
+(j
/skip
)];
1340 // Even things out by the length of the target waveform.
1344 if(corrEOF
> corr1
&& corrEOF
> corr0
) {
1345 PrintToScrollback("EOF at %d", i
);
1347 } else if(corr1
> corr0
) {
1348 i
+= arraylen(Logic1
)/skip
;
1351 i
+= arraylen(Logic0
)/skip
;
1358 if((i
+(int)arraylen(FrameEOF
)) >= GraphTraceLen
) {
1359 PrintToScrollback("ran off end!");
1364 PrintToScrollback("error, uneven octet! (discard extra bits!)");
1365 PrintToScrollback(" mask=%02x", mask
);
1367 PrintToScrollback("%d octets", k
);
1369 for(i
= 0; i
< k
; i
++) {
1370 PrintToScrollback("# %2d: %02x ", i
, outBuf
[i
]);
1372 PrintToScrollback("CRC=%04x", Iso15693Crc(outBuf
, k
-2));
1375 static void CmdFSKdemod(char *cmdline
)
1377 static const int LowTone
[] = {
1378 1, 1, 1, 1, 1, -1, -1, -1, -1, -1,
1379 1, 1, 1, 1, 1, -1, -1, -1, -1, -1,
1380 1, 1, 1, 1, 1, -1, -1, -1, -1, -1,
1381 1, 1, 1, 1, 1, -1, -1, -1, -1, -1,
1382 1, 1, 1, 1, 1, -1, -1, -1, -1, -1
1384 static const int HighTone
[] = {
1385 1, 1, 1, 1, 1, -1, -1, -1, -1,
1386 1, 1, 1, 1, -1, -1, -1, -1,
1387 1, 1, 1, 1, -1, -1, -1, -1,
1388 1, 1, 1, 1, -1, -1, -1, -1,
1389 1, 1, 1, 1, -1, -1, -1, -1,
1390 1, 1, 1, 1, -1, -1, -1, -1, -1,
1393 int lowLen
= sizeof(LowTone
)/sizeof(int);
1394 int highLen
= sizeof(HighTone
)/sizeof(int);
1395 int convLen
= (highLen
>lowLen
)?highLen
:lowLen
;
1396 uint32_t hi
= 0, lo
= 0;
1399 int minMark
=0, maxMark
=0;
1401 for(i
= 0; i
< GraphTraceLen
- convLen
; i
++) {
1402 int lowSum
= 0, highSum
= 0;
1404 for(j
= 0; j
< lowLen
; j
++) {
1405 lowSum
+= LowTone
[j
]*GraphBuffer
[i
+j
];
1407 for(j
= 0; j
< highLen
; j
++) {
1408 highSum
+= HighTone
[j
]*GraphBuffer
[i
+j
];
1410 lowSum
= abs((100*lowSum
) / lowLen
);
1411 highSum
= abs((100*highSum
) / highLen
);
1412 GraphBuffer
[i
] = (highSum
<< 16) | lowSum
;
1415 for(i
= 0; i
< GraphTraceLen
- convLen
- 16; i
++) {
1417 int lowTot
= 0, highTot
= 0;
1418 // 10 and 8 are f_s divided by f_l and f_h, rounded
1419 for(j
= 0; j
< 10; j
++) {
1420 lowTot
+= (GraphBuffer
[i
+j
] & 0xffff);
1422 for(j
= 0; j
< 8; j
++) {
1423 highTot
+= (GraphBuffer
[i
+j
] >> 16);
1425 GraphBuffer
[i
] = lowTot
- highTot
;
1426 if (GraphBuffer
[i
]>maxMark
) maxMark
=GraphBuffer
[i
];
1427 if (GraphBuffer
[i
]<minMark
) minMark
=GraphBuffer
[i
];
1430 GraphTraceLen
-= (convLen
+ 16);
1432 RepaintGraphWindow();
1434 // Find bit-sync (3 lo followed by 3 high)
1435 int max
= 0, maxPos
= 0;
1436 for(i
= 0; i
< 6000; i
++) {
1438 for(j
= 0; j
< 3*lowLen
; j
++) {
1439 dec
-= GraphBuffer
[i
+j
];
1441 for(; j
< 3*(lowLen
+ highLen
); j
++) {
1442 dec
+= GraphBuffer
[i
+j
];
1450 // place start of bit sync marker in graph
1451 GraphBuffer
[maxPos
] = maxMark
;
1452 GraphBuffer
[maxPos
+1] = minMark
;
1456 // place end of bit sync marker in graph
1457 GraphBuffer
[maxPos
] = maxMark
;
1458 GraphBuffer
[maxPos
+1] = minMark
;
1460 PrintToScrollback("actual data bits start at sample %d", maxPos
);
1461 PrintToScrollback("length %d/%d", highLen
, lowLen
);
1464 bits
[sizeof(bits
)-1] = '\0';
1466 // find bit pairs and manchester decode them
1467 for(i
= 0; i
< arraylen(bits
)-1; i
++) {
1469 for(j
= 0; j
< lowLen
; j
++) {
1470 dec
-= GraphBuffer
[maxPos
+j
];
1472 for(; j
< lowLen
+ highLen
; j
++) {
1473 dec
+= GraphBuffer
[maxPos
+j
];
1476 // place inter bit marker in graph
1477 GraphBuffer
[maxPos
] = maxMark
;
1478 GraphBuffer
[maxPos
+1] = minMark
;
1480 // hi and lo form a 64 bit pair
1481 hi
= (hi
<<1)|(lo
>>31);
1483 // store decoded bit as binary (in hi/lo) and text (in bits[])
1491 PrintToScrollback("bits: '%s'", bits
);
1492 PrintToScrollback("hex: %08x %08x", hi
, lo
);
1495 // read a TI tag and return its ID
1496 static void CmdTIRead(char *str
)
1498 UsbCommand c
={CMD_READ_TI_TYPE
};
1502 // write new data to a r/w TI tag
1503 static void CmdTIWrite(char *str
)
1505 UsbCommand c
={CMD_WRITE_TI_TYPE
};
1508 res
= sscanf(str
, "0x%x 0x%x 0x%x ", &c
.arg
[0], &c
.arg
[1], &c
.arg
[2]);
1509 if (res
== 2) c
.arg
[2]=0;
1511 PrintToScrollback("Please specify the data as two hex strings, optionally the CRC as a third");
1516 static void CmdTIDemod(char *cmdline
)
1518 /* MATLAB as follows:
1519 f_s = 2000000; % sampling frequency
1520 f_l = 123200; % low FSK tone
1521 f_h = 134200; % high FSK tone
1523 T_l = 119e-6; % low bit duration
1524 T_h = 130e-6; % high bit duration
1526 l = 2*pi*ones(1, floor(f_s*T_l))*(f_l/f_s);
1527 h = 2*pi*ones(1, floor(f_s*T_h))*(f_h/f_s);
1529 l = sign(sin(cumsum(l)));
1530 h = sign(sin(cumsum(h)));
1533 // 2M*16/134.2k = 238
1534 static const int LowTone
[] = {
1535 1, 1, 1, 1, 1, 1, 1, 1, 1, -1, -1, -1, -1, -1, -1, -1, -1,
1536 1, 1, 1, 1, 1, 1, 1, 1, -1, -1, -1, -1, -1, -1, -1, -1,
1537 1, 1, 1, 1, 1, 1, 1, 1, -1, -1, -1, -1, -1, -1, -1, -1,
1538 1, 1, 1, 1, 1, 1, 1, 1, -1, -1, -1, -1, -1, -1, -1, -1,
1539 1, 1, 1, 1, 1, 1, 1, 1, 1, -1, -1, -1, -1, -1, -1, -1, -1,
1540 1, 1, 1, 1, 1, 1, 1, 1, -1, -1, -1, -1, -1, -1, -1, -1,
1541 1, 1, 1, 1, 1, 1, 1, 1, -1, -1, -1, -1, -1, -1, -1, -1,
1542 1, 1, 1, 1, 1, 1, 1, 1, -1, -1, -1, -1, -1, -1, -1, -1,
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
1551 // 2M*16/123.2k = 260
1552 static const int HighTone
[] = {
1553 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,
1555 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,
1557 1, 1, 1, 1, 1, 1, 1, -1, -1, -1, -1, -1, -1, -1, -1,
1558 1, 1, 1, 1, 1, 1, 1, -1, -1, -1, -1, -1, -1, -1,
1559 1, 1, 1, 1, 1, 1, 1, 1, -1, -1, -1, -1, -1, -1, -1,
1560 1, 1, 1, 1, 1, 1, 1, 1, -1, -1, -1, -1, -1, -1, -1,
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,
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, -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,
1570 1, 1, 1, 1, 1, 1, 1, 1
1572 int lowLen
= sizeof(LowTone
)/sizeof(int);
1573 int highLen
= sizeof(HighTone
)/sizeof(int);
1574 int convLen
= (highLen
>lowLen
)?highLen
:lowLen
;
1577 int lowSum
= 0, highSum
= 0;;
1578 int lowTot
= 0, highTot
= 0;
1580 for(i
= 0; i
< GraphTraceLen
- convLen
; i
++) {
1584 for(j
= 0; j
< lowLen
; j
++) {
1585 lowSum
+= LowTone
[j
]*GraphBuffer
[i
+j
];
1587 for(j
= 0; j
< highLen
; j
++) {
1588 highSum
+= HighTone
[j
]*GraphBuffer
[i
+j
];
1590 lowSum
= abs((100*lowSum
) / lowLen
);
1591 highSum
= abs((100*highSum
) / highLen
);
1592 lowSum
= (lowSum
<0)?-lowSum
:lowSum
;
1593 highSum
= (highSum
<0)?-highSum
:highSum
;
1595 GraphBuffer
[i
] = (highSum
<< 16) | lowSum
;
1598 for(i
= 0; i
< GraphTraceLen
- convLen
- 16; i
++) {
1601 // 16 and 15 are f_s divided by f_l and f_h, rounded
1602 for(j
= 0; j
< 16; j
++) {
1603 lowTot
+= (GraphBuffer
[i
+j
] & 0xffff);
1605 for(j
= 0; j
< 15; j
++) {
1606 highTot
+= (GraphBuffer
[i
+j
] >> 16);
1608 GraphBuffer
[i
] = lowTot
- highTot
;
1611 GraphTraceLen
-= (convLen
+ 16);
1613 RepaintGraphWindow();
1615 // TI tag data format is 16 prebits, 8 start bits, 64 data bits,
1616 // 16 crc CCITT bits, 8 stop bits, 15 end bits
1618 // the 16 prebits are always low
1619 // the 8 start and stop bits of a tag must match
1620 // the start/stop prebits of a ro tag are 01111110
1621 // the start/stop prebits of a rw tag are 11111110
1622 // the 15 end bits of a ro tag are all low
1623 // the 15 end bits of a rw tag match bits 15-1 of the data bits
1625 // Okay, so now we have unsliced soft decisions;
1626 // find bit-sync, and then get some bits.
1627 // look for 17 low bits followed by 6 highs (common pattern for ro and rw tags)
1628 int max
= 0, maxPos
= 0;
1629 for(i
= 0; i
< 6000; i
++) {
1632 // searching 17 consecutive lows
1633 for(j
= 0; j
< 17*lowLen
; j
++) {
1634 dec
-= GraphBuffer
[i
+j
];
1636 // searching 7 consecutive highs
1637 for(; j
< 17*lowLen
+ 6*highLen
; j
++) {
1638 dec
+= GraphBuffer
[i
+j
];
1646 // place a marker in the buffer to visually aid location
1647 // of the start of sync
1648 GraphBuffer
[maxPos
] = 800;
1649 GraphBuffer
[maxPos
+1] = -800;
1651 // advance pointer to start of actual data stream (after 16 pre and 8 start bits)
1652 maxPos
+= 17*lowLen
;
1653 maxPos
+= 6*highLen
;
1655 // place a marker in the buffer to visually aid location
1656 // of the end of sync
1657 GraphBuffer
[maxPos
] = 800;
1658 GraphBuffer
[maxPos
+1] = -800;
1660 PrintToScrollback("actual data bits start at sample %d", maxPos
);
1662 PrintToScrollback("length %d/%d", highLen
, lowLen
);
1664 uint8_t bits
[1+64+16+8+16];
1665 bits
[sizeof(bits
)-1] = '\0';
1667 uint32_t shift3
= 0x7e000000, shift2
= 0, shift1
= 0, shift0
= 0;
1669 for(i
= 0; i
< arraylen(bits
)-1; i
++) {
1673 for(j
= 0; j
< lowLen
; j
++) {
1674 low
-= GraphBuffer
[maxPos
+j
];
1676 for(j
= 0; j
< highLen
; j
++) {
1677 high
+= GraphBuffer
[maxPos
+j
];
1683 // bitstream arrives lsb first so shift right
1690 // 128 bit right shift register
1691 shift0
= (shift0
>>1) | (shift1
<< 31);
1692 shift1
= (shift1
>>1) | (shift2
<< 31);
1693 shift2
= (shift2
>>1) | (shift3
<< 31);
1696 // place a marker in the buffer between bits to visually aid location
1697 GraphBuffer
[maxPos
] = 800;
1698 GraphBuffer
[maxPos
+1] = -800;
1700 PrintToScrollback("Info: raw tag bits = %s", bits
);
1702 TagType
= (shift3
>>8)&0xff;
1703 if ( TagType
!= ((shift0
>>16)&0xff) ) {
1704 PrintToScrollback("Error: start and stop bits do not match!");
1707 else if (TagType
== 0x7e) {
1708 PrintToScrollback("Info: Readonly TI tag detected.");
1711 else if (TagType
== 0xfe) {
1712 PrintToScrollback("Info: Rewriteable TI tag detected.");
1714 // put 64 bit data into shift1 and shift0
1715 shift0
= (shift0
>>24) | (shift1
<< 8);
1716 shift1
= (shift1
>>24) | (shift2
<< 8);
1718 // align 16 bit crc into lower half of shift2
1719 shift2
= ((shift2
>>24) | (shift3
<< 8)) & 0x0ffff;
1721 // align 16 bit "end bits" or "ident" into lower half of shift3
1724 // only 15 bits compare, last bit of ident is not valid
1725 if ( (shift3
^shift0
)&0x7fff ) {
1726 PrintToScrollback("Error: Ident mismatch!");
1728 // WARNING the order of the bytes in which we calc crc below needs checking
1729 // i'm 99% sure the crc algorithm is correct, but it may need to eat the
1730 // bytes in reverse or something
1733 crc
= update_crc16(crc
, (shift0
)&0xff);
1734 crc
= update_crc16(crc
, (shift0
>>8)&0xff);
1735 crc
= update_crc16(crc
, (shift0
>>16)&0xff);
1736 crc
= update_crc16(crc
, (shift0
>>24)&0xff);
1737 crc
= update_crc16(crc
, (shift1
)&0xff);
1738 crc
= update_crc16(crc
, (shift1
>>8)&0xff);
1739 crc
= update_crc16(crc
, (shift1
>>16)&0xff);
1740 crc
= update_crc16(crc
, (shift1
>>24)&0xff);
1741 PrintToScrollback("Info: Tag data = %08X%08X", shift1
, shift0
);
1742 if (crc
!= (shift2
&0xffff)) {
1743 PrintToScrollback("Error: CRC mismatch, calculated %04X, got ^04X", crc
, shift2
&0xffff);
1745 PrintToScrollback("Info: CRC %04X is good", crc
);
1749 PrintToScrollback("Unknown tag type.");
1754 static void CmdNorm(char *str
)
1757 int max
= INT_MIN
, min
= INT_MAX
;
1758 for(i
= 10; i
< GraphTraceLen
; i
++) {
1759 if(GraphBuffer
[i
] > max
) {
1760 max
= GraphBuffer
[i
];
1762 if(GraphBuffer
[i
] < min
) {
1763 min
= GraphBuffer
[i
];
1767 for(i
= 0; i
< GraphTraceLen
; i
++) {
1768 GraphBuffer
[i
] = (GraphBuffer
[i
] - ((max
+ min
)/2))*1000/
1772 RepaintGraphWindow();
1775 static void CmdAmp(char *str
)
1777 int i
, rising
, falling
;
1778 int max
= INT_MIN
, min
= INT_MAX
;
1779 for(i
= 10; i
< GraphTraceLen
; i
++) {
1780 if(GraphBuffer
[i
] > max
) {
1781 max
= GraphBuffer
[i
];
1783 if(GraphBuffer
[i
] < min
) {
1784 min
= GraphBuffer
[i
];
1789 for(i
= 0; i
< GraphTraceLen
; i
++) {
1790 if(GraphBuffer
[i
+1] < GraphBuffer
[i
]) {
1792 GraphBuffer
[i
]= max
;
1797 if(GraphBuffer
[i
+1] > GraphBuffer
[i
]) {
1799 GraphBuffer
[i
]= min
;
1806 RepaintGraphWindow();
1809 static void CmdDec(char *str
)
1812 for(i
= 0; i
< (GraphTraceLen
/2); i
++) {
1813 GraphBuffer
[i
] = GraphBuffer
[i
*2];
1816 PrintToScrollback("decimated by 2");
1817 RepaintGraphWindow();
1820 static void CmdHpf(char *str
)
1824 for(i
= 10; i
< GraphTraceLen
; i
++) {
1825 accum
+= GraphBuffer
[i
];
1827 accum
/= (GraphTraceLen
- 10);
1828 for(i
= 0; i
< GraphTraceLen
; i
++) {
1829 GraphBuffer
[i
] -= accum
;
1832 RepaintGraphWindow();
1835 static void CmdZerocrossings(char *str
)
1838 // Zero-crossings aren't meaningful unless the signal is zero-mean.
1844 for(i
= 0; i
< GraphTraceLen
; i
++) {
1845 if(GraphBuffer
[i
]*sign
>= 0) {
1846 // No change in sign, reproduce the previous sample count.
1848 GraphBuffer
[i
] = lastZc
;
1850 // Change in sign, reset the sample count.
1852 GraphBuffer
[i
] = lastZc
;
1860 RepaintGraphWindow();
1863 static void CmdThreshold(char *str
)
1866 int threshold
= atoi(str
);
1868 for(i
= 0; i
< GraphTraceLen
; i
++) {
1869 if(GraphBuffer
[i
]>= threshold
)
1874 RepaintGraphWindow();
1877 static void CmdLtrim(char *str
)
1882 for(i
= ds
; i
< GraphTraceLen
; i
++) {
1883 GraphBuffer
[i
-ds
] = GraphBuffer
[i
];
1885 GraphTraceLen
-= ds
;
1887 RepaintGraphWindow();
1890 static void CmdAutoCorr(char *str
)
1892 static int CorrelBuffer
[MAX_GRAPH_TRACE_LEN
];
1894 int window
= atoi(str
);
1897 PrintToScrollback("needs a window");
1901 if(window
>= GraphTraceLen
) {
1902 PrintToScrollback("window must be smaller than trace (%d samples)",
1907 PrintToScrollback("performing %d correlations", GraphTraceLen
- window
);
1910 for(i
= 0; i
< GraphTraceLen
- window
; i
++) {
1913 for(j
= 0; j
< window
; j
++) {
1914 sum
+= (GraphBuffer
[j
]*GraphBuffer
[i
+j
]) / 256;
1916 CorrelBuffer
[i
] = sum
;
1918 GraphTraceLen
= GraphTraceLen
- window
;
1919 memcpy(GraphBuffer
, CorrelBuffer
, GraphTraceLen
*sizeof(int));
1921 RepaintGraphWindow();
1924 static void CmdVchdemod(char *str
)
1926 // Is this the entire sync pattern, or does this also include some
1927 // data bits that happen to be the same everywhere? That would be
1929 static const int SyncPattern
[] = {
1930 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
1931 1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
1932 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
1933 1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
1934 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
1935 1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
1936 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
1937 1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
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,
1942 // So first, we correlate for the sync pattern, and mark that.
1943 int bestCorrel
= 0, bestPos
= 0;
1945 // It does us no good to find the sync pattern, with fewer than
1946 // 2048 samples after it...
1947 for(i
= 0; i
< (GraphTraceLen
-2048); i
++) {
1950 for(j
= 0; j
< arraylen(SyncPattern
); j
++) {
1951 sum
+= GraphBuffer
[i
+j
]*SyncPattern
[j
];
1953 if(sum
> bestCorrel
) {
1958 PrintToScrollback("best sync at %d [metric %d]", bestPos
, bestCorrel
);
1963 int worst
= INT_MAX
;
1966 for(i
= 0; i
< 2048; i
+= 8) {
1969 for(j
= 0; j
< 8; j
++) {
1970 sum
+= GraphBuffer
[bestPos
+i
+j
];
1977 if(abs(sum
) < worst
) {
1982 PrintToScrollback("bits:");
1983 PrintToScrollback("%s", bits
);
1984 PrintToScrollback("worst metric: %d at pos %d", worst
, worstPos
);
1986 if(strcmp(str
, "clone")==0) {
1989 for(s
= bits
; *s
; s
++) {
1991 for(j
= 0; j
< 16; j
++) {
1992 GraphBuffer
[GraphTraceLen
++] = (*s
== '1') ? 1 : 0;
1995 RepaintGraphWindow();
1999 static void CmdIndalademod(char *str
)
2001 // Usage: recover 64bit UID by default, specify "224" as arg to recover a 224bit UID
2006 // worst case with GraphTraceLen=64000 is < 4096
2007 // under normal conditions it's < 2048
2008 uint8_t rawbits
[4096];
2010 int worst
= 0, worstPos
= 0;
2011 PrintToScrollback("Expecting a bit less than %d raw bits", GraphTraceLen
/32);
2012 for(i
= 0; i
< GraphTraceLen
-1; i
+= 2) {
2014 if((GraphBuffer
[i
] > GraphBuffer
[i
+ 1]) && (state
!= 1)) {
2016 for(j
= 0; j
< count
- 8; j
+= 16) {
2017 rawbits
[rawbit
++] = 0;
2019 if ((abs(count
- j
)) > worst
) {
2020 worst
= abs(count
- j
);
2026 } else if((GraphBuffer
[i
] < GraphBuffer
[i
+ 1]) && (state
!= 0)) {
2028 for(j
= 0; j
< count
- 8; j
+= 16) {
2029 rawbits
[rawbit
++] = 1;
2031 if ((abs(count
- j
)) > worst
) {
2032 worst
= abs(count
- j
);
2040 PrintToScrollback("Recovered %d raw bits", rawbit
);
2041 PrintToScrollback("worst metric (0=best..7=worst): %d at pos %d", worst
, worstPos
);
2043 // Finding the start of a UID
2044 int uidlen
, long_wait
;
2045 if(strcmp(str
, "224") == 0) {
2054 for(start
= 0; start
<= rawbit
- uidlen
; start
++) {
2055 first
= rawbits
[start
];
2056 for(i
= start
; i
< start
+ long_wait
; i
++) {
2057 if(rawbits
[i
] != first
) {
2061 if(i
== (start
+ long_wait
)) {
2065 if(start
== rawbit
- uidlen
+ 1) {
2066 PrintToScrollback("nothing to wait for");
2070 // Inverting signal if needed
2072 for(i
= start
; i
< rawbit
; i
++) {
2073 rawbits
[i
] = !rawbits
[i
];
2080 showbits
[uidlen
]='\0';
2084 if(uidlen
> rawbit
) {
2085 PrintToScrollback("Warning: not enough raw bits to get a full UID");
2086 for(bit
= 0; bit
< rawbit
; bit
++) {
2087 bits
[bit
] = rawbits
[i
++];
2088 // As we cannot know the parity, let's use "." and "/"
2089 showbits
[bit
] = '.' + bits
[bit
];
2091 showbits
[bit
+1]='\0';
2092 PrintToScrollback("Partial UID=%s", showbits
);
2095 for(bit
= 0; bit
< uidlen
; bit
++) {
2096 bits
[bit
] = rawbits
[i
++];
2097 showbits
[bit
] = '0' + bits
[bit
];
2101 PrintToScrollback("UID=%s", showbits
);
2103 // Checking UID against next occurences
2104 for(; i
+ uidlen
<= rawbit
;) {
2106 for(bit
= 0; bit
< uidlen
; bit
++) {
2107 if(bits
[bit
] != rawbits
[i
++]) {
2117 PrintToScrollback("Occurences: %d (expected %d)", times
, (rawbit
- start
) / uidlen
);
2119 // Remodulating for tag cloning
2120 GraphTraceLen
= 32*uidlen
;
2123 for(bit
= 0; bit
< uidlen
; bit
++) {
2124 if(bits
[bit
] == 0) {
2130 for(j
= 0; j
< 32; j
++) {
2131 GraphBuffer
[i
++] = phase
;
2136 RepaintGraphWindow();
2139 static void CmdFlexdemod(char *str
)
2142 for(i
= 0; i
< GraphTraceLen
; i
++) {
2143 if(GraphBuffer
[i
] < 0) {
2144 GraphBuffer
[i
] = -1;
2150 #define LONG_WAIT 100
2152 for(start
= 0; start
< GraphTraceLen
- LONG_WAIT
; start
++) {
2153 int first
= GraphBuffer
[start
];
2154 for(i
= start
; i
< start
+ LONG_WAIT
; i
++) {
2155 if(GraphBuffer
[i
] != first
) {
2159 if(i
== (start
+ LONG_WAIT
)) {
2163 if(start
== GraphTraceLen
- LONG_WAIT
) {
2164 PrintToScrollback("nothing to wait for");
2168 GraphBuffer
[start
] = 2;
2169 GraphBuffer
[start
+1] = -2;
2175 for(bit
= 0; bit
< 64; bit
++) {
2178 for(j
= 0; j
< 16; j
++) {
2179 sum
+= GraphBuffer
[i
++];
2186 PrintToScrollback("bit %d sum %d", bit
, sum
);
2189 for(bit
= 0; bit
< 64; bit
++) {
2192 for(j
= 0; j
< 16; j
++) {
2193 sum
+= GraphBuffer
[i
++];
2195 if(sum
> 0 && bits
[bit
] != 1) {
2196 PrintToScrollback("oops1 at %d", bit
);
2198 if(sum
< 0 && bits
[bit
] != 0) {
2199 PrintToScrollback("oops2 at %d", bit
);
2203 GraphTraceLen
= 32*64;
2206 for(bit
= 0; bit
< 64; bit
++) {
2207 if(bits
[bit
] == 0) {
2213 for(j
= 0; j
< 32; j
++) {
2214 GraphBuffer
[i
++] = phase
;
2219 RepaintGraphWindow();
2223 * Generic command to demodulate ASK.
2225 * Argument is convention: positive or negative (High mod means zero
2226 * or high mod means one)
2228 * Updates the Graph trace with 0/1 values
2234 static void Cmdaskdemod(char *str
) {
2236 int c
, high
= 0, low
= 0;
2238 // TODO: complain if we do not give 2 arguments here !
2239 // (AL - this doesn't make sense! we're only using one argument!!!)
2240 sscanf(str
, "%i", &c
);
2242 /* Detect high and lows and clock */
2244 for (i
= 0; i
< GraphTraceLen
; i
++)
2246 if (GraphBuffer
[i
] > high
)
2247 high
= GraphBuffer
[i
];
2248 else if (GraphBuffer
[i
] < low
)
2249 low
= GraphBuffer
[i
];
2251 if(c
!= 0 && c
!= 1) {
2252 PrintToScrollback("Invalid argument: %s",str
);
2256 if (GraphBuffer
[0] > 0) {
2257 GraphBuffer
[0] = 1-c
;
2261 for(i
=1;i
<GraphTraceLen
;i
++) {
2262 /* Transitions are detected at each peak
2263 * Transitions are either:
2264 * - we're low: transition if we hit a high
2265 * - we're high: transition if we hit a low
2266 * (we need to do it this way because some tags keep high or
2267 * low for long periods, others just reach the peak and go
2270 if ((GraphBuffer
[i
]==high
) && (GraphBuffer
[i
-1] == c
)) {
2272 } else if ((GraphBuffer
[i
]==low
) && (GraphBuffer
[i
-1] == (1-c
))){
2276 GraphBuffer
[i
] = GraphBuffer
[i
-1];
2279 RepaintGraphWindow();
2282 /* Print our clock rate */
2283 static void Cmddetectclockrate(char *str
)
2285 int clock
= detectclock(0);
2286 PrintToScrollback("Auto-detected clock rate: %d", clock
);
2292 int detectclock(int peak
)
2298 /* Detect peak if we don't have one */
2300 for (i
= 0; i
< GraphTraceLen
; i
++)
2301 if (GraphBuffer
[i
] > peak
)
2302 peak
= GraphBuffer
[i
];
2304 for (i
= 1; i
< GraphTraceLen
; i
++)
2306 /* If this is the beginning of a peak */
2307 if (GraphBuffer
[i
-1] != GraphBuffer
[i
] && GraphBuffer
[i
] == peak
)
2309 /* Find lowest difference between peaks */
2310 if (lastpeak
&& i
- lastpeak
< clock
)
2312 clock
= i
- lastpeak
;
2321 /* Get or auto-detect clock rate */
2322 int GetClock(char *str
, int peak
)
2326 sscanf(str
, "%i", &clock
);
2327 if (!strcmp(str
, ""))
2330 /* Auto-detect clock */
2333 clock
= detectclock(peak
);
2335 /* Only print this message if we're not looping something */
2337 PrintToScrollback("Auto-detected clock rate: %d", clock
);
2344 * Convert to a bitstream
2346 static void Cmdbitstream(char *str
) {
2353 int hithigh
, hitlow
, first
;
2355 /* Detect high and lows and clock */
2356 for (i
= 0; i
< GraphTraceLen
; i
++)
2358 if (GraphBuffer
[i
] > high
)
2359 high
= GraphBuffer
[i
];
2360 else if (GraphBuffer
[i
] < low
)
2361 low
= GraphBuffer
[i
];
2365 clock
= GetClock(str
, high
);
2367 gtl
= CmdClearGraph(0);
2370 for (i
= 0; i
< (int)(gtl
/ clock
); i
++)
2376 /* Find out if we hit both high and low peaks */
2377 for (j
= 0; j
< clock
; j
++)
2379 if (GraphBuffer
[(i
* clock
) + j
] == high
)
2381 else if (GraphBuffer
[(i
* clock
) + j
] == low
)
2384 /* it doesn't count if it's the first part of our read
2385 because it's really just trailing from the last sequence */
2386 if (first
&& (hithigh
|| hitlow
))
2387 hithigh
= hitlow
= 0;
2391 if (hithigh
&& hitlow
)
2395 /* If we didn't hit both high and low peaks, we had a bit transition */
2396 if (!hithigh
|| !hitlow
)
2399 CmdAppendGraph(0, clock
, bit
);
2400 // for (j = 0; j < (int)(clock/2); j++)
2401 // GraphBuffer[(i * clock) + j] = bit ^ 1;
2402 // for (j = (int)(clock/2); j < clock; j++)
2403 // GraphBuffer[(i * clock) + j] = bit;
2406 RepaintGraphWindow();
2409 /* Modulate our data into manchester */
2410 static void Cmdmanchestermod(char *str
)
2414 int bit
, lastbit
, wave
;
2417 clock
= GetClock(str
, 0);
2421 for (i
= 0; i
< (int)(GraphTraceLen
/ clock
); i
++)
2423 bit
= GraphBuffer
[i
* clock
] ^ 1;
2425 for (j
= 0; j
< (int)(clock
/2); j
++)
2426 GraphBuffer
[(i
* clock
) + j
] = bit
^ lastbit
^ wave
;
2427 for (j
= (int)(clock
/2); j
< clock
; j
++)
2428 GraphBuffer
[(i
* clock
) + j
] = bit
^ lastbit
^ wave
^ 1;
2430 /* Keep track of how we start our wave and if we changed or not this time */
2431 wave
^= bit
^ lastbit
;
2435 RepaintGraphWindow();
2439 * Manchester demodulate a bitstream. The bitstream needs to be already in
2440 * the GraphBuffer as 0 and 1 values
2442 * Give the clock rate as argument in order to help the sync - the algorithm
2443 * resyncs at each pulse anyway.
2445 * Not optimized by any means, this is the 1st time I'm writing this type of
2446 * routine, feel free to improve...
2448 * 1st argument: clock rate (as number of samples per clock rate)
2449 * Typical values can be 64, 32, 128...
2451 static void Cmdmanchesterdemod(char *str
) {
2452 int i
, j
, invert
= 0;
2458 int hithigh
, hitlow
, first
;
2464 /* check if we're inverting output */
2467 PrintToScrollback("Inverting output");
2471 while(*str
== ' '); // in case a 2nd argument was given
2474 /* Holds the decoded bitstream: each clock period contains 2 bits */
2475 /* later simplified to 1 bit after manchester decoding. */
2476 /* Add 10 bits to allow for noisy / uncertain traces without aborting */
2477 /* int BitStream[GraphTraceLen*2/clock+10]; */
2479 /* But it does not work if compiling on WIndows: therefore we just allocate a */
2481 int BitStream
[MAX_GRAPH_TRACE_LEN
];
2483 /* Detect high and lows */
2484 for (i
= 0; i
< GraphTraceLen
; i
++)
2486 if (GraphBuffer
[i
] > high
)
2487 high
= GraphBuffer
[i
];
2488 else if (GraphBuffer
[i
] < low
)
2489 low
= GraphBuffer
[i
];
2493 clock
= GetClock(str
, high
);
2495 int tolerance
= clock
/4;
2497 /* Detect first transition */
2498 /* Lo-Hi (arbitrary) */
2499 /* skip to the first high */
2500 for (i
= 0; i
< GraphTraceLen
; i
++)
2501 if(GraphBuffer
[i
] == high
)
2503 /* now look for the first low */
2504 for (; i
< GraphTraceLen
; i
++)
2506 if (GraphBuffer
[i
] == low
)
2513 /* If we're not working with 1/0s, demod based off clock */
2516 bit
= 0; /* We assume the 1st bit is zero, it may not be
2517 * the case: this routine (I think) has an init problem.
2520 for (; i
< (int)(GraphTraceLen
/ clock
); i
++)
2526 /* Find out if we hit both high and low peaks */
2527 for (j
= 0; j
< clock
; j
++)
2529 if (GraphBuffer
[(i
* clock
) + j
] == high
)
2531 else if (GraphBuffer
[(i
* clock
) + j
] == low
)
2534 /* it doesn't count if it's the first part of our read
2535 because it's really just trailing from the last sequence */
2536 if (first
&& (hithigh
|| hitlow
))
2537 hithigh
= hitlow
= 0;
2541 if (hithigh
&& hitlow
)
2545 /* If we didn't hit both high and low peaks, we had a bit transition */
2546 if (!hithigh
|| !hitlow
)
2549 BitStream
[bit2idx
++] = bit
^ invert
;
2553 /* standard 1/0 bitstream */
2557 /* Then detect duration between 2 successive transitions */
2558 for (bitidx
= 1; i
< GraphTraceLen
; i
++)
2560 if (GraphBuffer
[i
-1] != GraphBuffer
[i
])
2565 // Error check: if bitidx becomes too large, we do not
2566 // have a Manchester encoded bitstream or the clock is really
2568 if (bitidx
> (GraphTraceLen
*2/clock
+8) ) {
2569 PrintToScrollback("Error: the clock you gave is probably wrong, aborting.");
2572 // Then switch depending on lc length:
2573 // Tolerance is 1/4 of clock rate (arbitrary)
2574 if (abs(lc
-clock
/2) < tolerance
) {
2575 // Short pulse : either "1" or "0"
2576 BitStream
[bitidx
++]=GraphBuffer
[i
-1];
2577 } else if (abs(lc
-clock
) < tolerance
) {
2578 // Long pulse: either "11" or "00"
2579 BitStream
[bitidx
++]=GraphBuffer
[i
-1];
2580 BitStream
[bitidx
++]=GraphBuffer
[i
-1];
2584 PrintToScrollback("Warning: Manchester decode error for pulse width detection.");
2585 PrintToScrollback("(too many of those messages mean either the stream is not Manchester encoded, or clock is wrong)");
2589 PrintToScrollback("Error: too many detection errors, aborting.");
2596 // At this stage, we now have a bitstream of "01" ("1") or "10" ("0"), parse it into final decoded bitstream
2597 // Actually, we overwrite BitStream with the new decoded bitstream, we just need to be careful
2598 // to stop output at the final bitidx2 value, not bitidx
2599 for (i
= 0; i
< bitidx
; i
+= 2) {
2600 if ((BitStream
[i
] == 0) && (BitStream
[i
+1] == 1)) {
2601 BitStream
[bit2idx
++] = 1 ^ invert
;
2602 } else if ((BitStream
[i
] == 1) && (BitStream
[i
+1] == 0)) {
2603 BitStream
[bit2idx
++] = 0 ^ invert
;
2605 // We cannot end up in this state, this means we are unsynchronized,
2609 PrintToScrollback("Unsynchronized, resync...");
2610 PrintToScrollback("(too many of those messages mean the stream is not Manchester encoded)");
2614 PrintToScrollback("Error: too many decode errors, aborting.");
2621 PrintToScrollback("Manchester decoded bitstream");
2622 // Now output the bitstream to the scrollback by line of 16 bits
2623 for (i
= 0; i
< (bit2idx
-16); i
+=16) {
2624 PrintToScrollback("%i %i %i %i %i %i %i %i %i %i %i %i %i %i %i %i",
2647 static void CmdHiddemod(char *str
)
2649 if(GraphTraceLen
< 4800) {
2650 PrintToScrollback("too short; need at least 4800 samples");
2654 GraphTraceLen
= 4800;
2656 for(i
= 0; i
< GraphTraceLen
; i
++) {
2657 if(GraphBuffer
[i
] < 0) {
2663 RepaintGraphWindow();
2666 static void CmdPlot(char *str
)
2671 static void CmdGrid(char *str
)
2673 sscanf(str
, "%i %i", &PlotGridX
, &PlotGridY
);
2674 RepaintGraphWindow();
2677 static void CmdHide(char *str
)
2682 static void CmdScale(char *str
)
2684 CursorScaleFactor
= atoi(str
);
2685 if(CursorScaleFactor
== 0) {
2686 PrintToScrollback("bad, can't have zero scale");
2687 CursorScaleFactor
= 1;
2689 RepaintGraphWindow();
2692 static void CmdSave(char *str
)
2694 FILE *f
= fopen(str
, "w");
2696 PrintToScrollback("couldn't open '%s'", str
);
2700 for(i
= 0; i
< GraphTraceLen
; i
++) {
2701 fprintf(f
, "%d\n", GraphBuffer
[i
]);
2704 PrintToScrollback("saved to '%s'", str
);
2707 static void CmdLoad(char *str
)
2709 FILE *f
= fopen(str
, "r");
2711 PrintToScrollback("couldn't open '%s'", str
);
2717 while(fgets(line
, sizeof(line
), f
)) {
2718 GraphBuffer
[GraphTraceLen
] = atoi(line
);
2722 PrintToScrollback("loaded %d samples", GraphTraceLen
);
2723 RepaintGraphWindow();
2726 static void CmdHIDsimTAG(char *str
)
2728 unsigned int hi
=0, lo
=0;
2731 while (sscanf(&str
[i
++], "%1x", &n
) == 1) {
2732 hi
=(hi
<<4)|(lo
>>28);
2736 PrintToScrollback("Emulating tag with ID %x%16x", hi
, lo
);
2738 UsbCommand c
={CMD_HID_SIM_TAG
, {hi
, lo
, 0}};
2742 static void CmdReadmem(char *str
)
2744 UsbCommand c
={CMD_READ_MEM
, {strtol(str
, NULL
, 0), 0, 0}};
2748 static void CmdVersion(char *str
)
2750 UsbCommand c
={CMD_VERSION
};
2754 static void CmdLcdReset(char *str
)
2756 UsbCommand c
={CMD_LCD_RESET
, {strtol(str
, NULL
, 0), 0, 0}};
2760 static void CmdLcd(char *str
)
2763 UsbCommand c
={CMD_LCD
};
2764 sscanf(str
, "%x %d", &i
, &j
);
2772 * Sets the divisor for LF frequency clock: lets the user choose any LF frequency below
2775 static void CmdSetDivisor(char *str
)
2777 UsbCommand c
={CMD_SET_LF_DIVISOR
, {strtol(str
, NULL
, 0), 0, 0}};
2778 if (( c
.arg
[0]<0) || (c
.arg
[0]>255)) {
2779 PrintToScrollback("divisor must be between 19 and 255");
2782 PrintToScrollback("Divisor set, expected freq=%dHz", 12000000/(c
.arg
[0]+1));
2786 static void CmdSetMux(char *str
)
2788 UsbCommand c
={CMD_SET_ADC_MUX
};
2789 if(strcmp(str
, "lopkd") == 0) {
2791 } else if(strcmp(str
, "loraw") == 0) {
2793 } else if(strcmp(str
, "hipkd") == 0) {
2795 } else if(strcmp(str
, "hiraw") == 0) {
2801 typedef void HandlerFunction(char *cmdline
);
2803 /* in alphabetic order */
2806 HandlerFunction
*handler
;
2807 int offline
; // 1 if the command can be used when in offline mode
2809 } CommandTable
[] = {
2810 /* plot window / data buffer manipulation */
2811 {"buffclear", CmdBuffClear
, 1, "Clear sample buffer and graph window"},
2812 {"load", CmdLoad
, 1, "<filename> -- Load trace (to graph window"},
2813 {"save", CmdSave
, 1, "<filename> -- Save trace (from graph window)"},
2814 {"amp", CmdAmp
, 1, "Amplify peaks"},
2815 {"autocorr", CmdAutoCorr
, 1, "<window length> -- Autocorrelation over window"},
2816 {"dec", CmdDec
, 1, "Decimate samples"},
2817 {"hpf", CmdHpf
, 1, "Remove DC offset from trace"},
2818 {"ltrim", CmdLtrim
, 1, "<samples> -- Trim samples from left of trace"},
2819 {"norm", CmdNorm
, 1, "Normalize max/min to +/-500"},
2820 {"plot", CmdPlot
, 1, "Show graph window"},
2821 {"hide", CmdHide
, 1, "Hide graph window"},
2822 {"grid", CmdGrid
, 1, "<x> <y> -- overlay grid on graph window, use zero value to turn off either"},
2823 {"threshold", CmdThreshold
, 1, "Maximize/minimize every value in the graph window depending on threshold"},
2824 {"zerocrossings", CmdZerocrossings
, 1, "Count time between zero-crossings"},
2825 {"scale", CmdScale
, 1, "<int> -- Set cursor display scale"},
2826 {"bitstream", Cmdbitstream
, 1, "[clock rate] -- Convert waveform into a bitstream"},
2827 {"detectclock", Cmddetectclockrate
, 1, "Detect clock rate"},
2828 {"exit", CmdQuit
, 1, "Exit program"},
2829 {"quit", CmdQuit
, 1, "Exit program"},
2831 /* low-level hardware control */
2832 {"fpgaoff", CmdFPGAOff
, 0, "Set FPGA off"},
2833 {"tune", CmdTune
, 0, "Measure antenna tuning"},
2834 {"hitune", CmdHiTune
, 0, "Continuously measure HF antenna tuning"},
2835 {"readmem", CmdReadmem
, 0, "[address] -- Read memory at decimal address from flash"},
2836 {"reset", CmdReset
, 0, "Reset the Proxmark3"},
2837 {"setlfdivisor", CmdSetDivisor
, 0, "<19 - 255> -- Drive LF antenna at 12Mhz/(divisor+1)"},
2838 {"setmux", CmdSetMux
, 0, "<loraw|hiraw|lopkd|hipkd> -- Set the ADC mux to a specific value"},
2839 {"version", CmdVersion
, 0, "Show version inforation about the connected Proxmark"},
2840 {"lcd", CmdLcd
, 0, "<HEX command> <count> -- Send command/data to LCD"},
2841 {"lcdreset", CmdLcdReset
, 0, "Hardware reset LCD"},
2843 /* data transfer functions */
2845 {"bitsamples", CmdBitsamples
, 0, "Get raw samples as bitstring"},
2846 {"hexsamples", CmdHexsamples
, 0, "<blocks> -- Dump big buffer as hex bytes"},
2847 {"higet", CmdHi14read_sim
, 0, "<samples> -- Get samples HF, 'analog'"},
2848 {"hisamples", CmdHisamples
, 0, "Get raw samples for HF tag"},
2849 {"hisampless", CmdHisampless
, 0, "<samples> -- Get signed raw samples, HF tag"},
2850 {"hisamplest", CmdHi14readt
, 0, "Get samples HF, for testing"},
2851 {"losamples", CmdLosamples
, 0, "[128 - 16000] -- Get raw samples for LF tag"},
2852 {"detectreader", CmdDetectReader
, 0, "['l'|'h'] -- Detect external reader field (option 'l' or 'h' to limit to LF or HF)"},
2854 /* (de-)modulation */
2856 {"askdemod", Cmdaskdemod
, 1, "<0|1> -- Attempt to demodulate simple ASK tags"},
2857 {"flexdemod", CmdFlexdemod
, 1, "Demodulate samples for FlexPass"},
2858 {"fskdemod", CmdFSKdemod
, 1, "Demodulate graph window as a HID FSK"},
2859 {"hi14bdemod", CmdHi14bdemod
, 1, "Demodulate ISO14443 Type B from tag"},
2860 {"hi15demod", CmdHi15demod
, 1, "Demodulate ISO15693 from tag"},
2861 {"hiddemod", CmdHiddemod
, 1, "Demodulate HID Prox Card II (not optimal)"},
2862 {"hidfskdemod", CmdHIDdemodFSK
, 0, "Realtime HID FSK demodulator"},
2863 {"indalademod", CmdIndalademod
, 1, "['224'] -- Demodulate samples for Indala 64 bit UID (option '224' for 224 bit)"},
2864 {"mandemod", Cmdmanchesterdemod
, 1, "[i] [clock rate] -- Manchester demodulate binary stream (option 'i' to invert output)"},
2865 {"manmod", Cmdmanchestermod
, 1, "[clock rate] -- Manchester modulate a binary stream"},
2866 {"tidemod", CmdTIDemod
, 1, "Demodulate raw bits for TI-type LF tag"},
2867 {"vchdemod", CmdVchdemod
, 1, "['clone'] -- Demodulate samples for VeriChip"},
2870 {"em410xsim", CmdEM410xsim
, 1, "<UID> -- Simulate EM410x tag"},
2871 {"hi14sim", CmdHi14sim
, 0, "Fake ISO 14443 tag"},
2872 {"hi14asim", CmdHi14asim
, 0, "<UID> -- Fake ISO 14443a tag"},
2873 {"hi15sim", CmdHi15tag
, 0, "Fake an ISO15693 tag"},
2874 {"hidsimtag", CmdHIDsimTAG
, 0, "<ID> -- HID tag simulator"},
2875 {"hisimlisten", CmdHisimlisten
, 0, "Get HF samples as fake tag"},
2876 {"losim", CmdLosim
, 0, "Simulate LF tag"},
2877 {"losimbidir", CmdLosimBidir
, 0, "Simulate LF tag (with bidirectional data transmission between reader and tag)"},
2879 /* card reading functions */
2880 {"em410xread", CmdEM410xread
, 1, "[clock rate] -- Extract ID from EM410x tag"},
2881 {"em410xwatch", CmdEM410xwatch
, 0, "Watches for EM410x tags"},
2882 {"em4x50read", CmdEM4x50read
, 1, "Extract data from EM4x50 tag"},
2883 {"hi14alist", CmdHi14alist
, 0, "List ISO 14443a history"},
2884 {"hi14amifare", CmdHi14amifare
, 0, "Read out sector 0 parity error messages"},
2885 {"hi14areader", CmdHi14areader
, 0, "Act like an ISO14443 Type A reader"},
2886 {"hi14asnoop", CmdHi14asnoop
, 0, "Eavesdrop ISO 14443 Type A"},
2887 {"hi14list", CmdHi14list
, 0, "List ISO 14443 history"},
2888 {"hi14read", CmdHi14read
, 0, "Read HF tag (ISO 14443)"},
2889 {"hi14snoop", CmdHi14snoop
, 0, "Eavesdrop ISO 14443"},
2890 {"hi15read", CmdHi15read
, 0, "Read HF tag (ISO 15693)"},
2891 {"hi15reader", CmdHi15reader
, 0, "Act like an ISO15693 reader"},
2892 {"legicrfread", CmdLegicRfRead
, 0, "Start the LEGIC RF reader"},
2893 {"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)"},
2894 {"loread", CmdLoread
, 0, "['h'] -- Read 125/134 kHz LF ID-only tag (option 'h' for 134)"},
2895 {"sri512read", CmdSri512read
, 0, "<int> -- Read contents of a SRI512 tag"},
2896 {"srix4kread", CmdSrix4kread
, 0, "<int> -- Read contents of a SRIX4K tag"},
2897 {"tiread", CmdTIRead
, 0, "Read and decode a TI 134 kHz tag"},
2898 {"tiwrite", CmdTIWrite
, 0, "Write new data to a r/w TI 134 kHz tag"},
2906 } CommandExtendedHelp
[]= {
2907 {"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."},
2908 {"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."},
2911 //-----------------------------------------------------------------------------
2912 // Entry point into our code: called whenever the user types a command and
2913 // then presses Enter, which the full command line that they typed.
2914 //-----------------------------------------------------------------------------
2915 void CommandReceived(char *cmd
)
2920 PrintToScrollback("> %s", cmd
);
2922 if(strcmp(cmd
, "help") == 0 || strncmp(cmd
,"help ",strlen("help ")) == 0) {
2923 // check if we're doing extended help
2924 if(strlen(cmd
) > strlen("help ")) {
2925 cmd
+= strlen("help ");
2926 for(i
= 0; i
< sizeof(CommandExtendedHelp
) / sizeof(CommandExtendedHelp
[0]); i
++) {
2927 if(strcmp(CommandExtendedHelp
[i
].name
,cmd
) == 0) {
2928 PrintToScrollback("\nExtended help for '%s':\n", cmd
);
2929 PrintToScrollback("Args: %s\t- %s\n",CommandExtendedHelp
[i
].args
,CommandExtendedHelp
[i
].argshelp
);
2930 PrintToScrollback(CommandExtendedHelp
[i
].description
);
2931 PrintToScrollback("");
2935 PrintToScrollback("No extended help available for '%s'", cmd
);
2938 if (offline
) PrintToScrollback("Operating in OFFLINE mode (no device connected)");
2939 PrintToScrollback("\r\nAvailable commands:");
2940 for(i
= 0; i
< sizeof(CommandTable
) / sizeof(CommandTable
[0]); i
++) {
2941 if (offline
&& (CommandTable
[i
].offline
==0)) continue;
2942 memset(line
, ' ', sizeof(line
));
2943 strcpy(line
+2, CommandTable
[i
].name
);
2944 line
[strlen(line
)] = ' ';
2945 sprintf(line
+15, " -- %s", CommandTable
[i
].docString
);
2946 PrintToScrollback("%s", line
);
2948 PrintToScrollback("");
2949 PrintToScrollback("'help <command>' for extended help on that command\n");
2953 for(i
= 0; i
< sizeof(CommandTable
) / sizeof(CommandTable
[0]); i
++) {
2954 char *name
= CommandTable
[i
].name
;
2955 if(memcmp(cmd
, name
, strlen(name
))==0 &&
2956 (cmd
[strlen(name
)] == ' ' || cmd
[strlen(name
)] == '\0'))
2958 cmd
+= strlen(name
);
2959 while(*cmd
== ' ') {
2962 if (offline
&& (CommandTable
[i
].offline
==0)) {
2963 PrintToScrollback("Offline mode, cannot use this command.");
2966 (CommandTable
[i
].handler
)(cmd
);
2970 PrintToScrollback(">> bad command '%s'", cmd
);
2973 //-----------------------------------------------------------------------------
2974 // Entry point into our code: called whenever we received a packet over USB
2975 // that we weren't necessarily expecting, for example a debug print.
2976 //-----------------------------------------------------------------------------
2977 void UsbCommandReceived(UsbCommand
*c
)
2979 // printf("%s(%x) current cmd = %x\n", __FUNCTION__, c->cmd, current_command);
2980 /* If we recognize a response, return to avoid further processing */
2982 case CMD_DEBUG_PRINT_STRING
: {
2984 if(c
->arg
[0] > 70 || c
->arg
[0] < 0) {
2987 memcpy(s
, c
->d
.asBytes
, c
->arg
[0]);
2988 s
[c
->arg
[0]] = '\0';
2989 PrintToScrollback("#db# %s", s
);
2993 case CMD_DEBUG_PRINT_INTEGERS
:
2994 PrintToScrollback("#db# %08x, %08x, %08x\r\n", c
->arg
[0], c
->arg
[1], c
->arg
[2]);
2997 case CMD_MEASURED_ANTENNA_TUNING
: {
2999 int vLf125
, vLf134
, vHf
;
3000 vLf125
= c
->arg
[0] & 0xffff;
3001 vLf134
= c
->arg
[0] >> 16;
3002 vHf
= c
->arg
[1] & 0xffff;;
3003 peakf
= c
->arg
[2] & 0xffff;
3004 peakv
= c
->arg
[2] >> 16;
3005 PrintToScrollback("");
3006 PrintToScrollback("");
3007 PrintToScrollback("# LF antenna: %5.2f V @ 125.00 kHz", vLf125
/1000.0);
3008 PrintToScrollback("# LF antenna: %5.2f V @ 134.00 kHz", vLf134
/1000.0);
3009 PrintToScrollback("# LF optimal: %5.2f V @%9.2f kHz", peakv
/1000.0, 12000.0/(peakf
+1));
3010 PrintToScrollback("# HF antenna: %5.2f V @ 13.56 MHz", vHf
/1000.0);
3012 PrintToScrollback("# Your LF antenna is unusable.");
3013 else if (peakv
<10000)
3014 PrintToScrollback("# Your LF antenna is marginal.");
3016 PrintToScrollback("# Your HF antenna is unusable.");
3018 PrintToScrollback("# Your HF antenna is marginal.");
3024 /* Maybe it's a response: */
3025 switch(current_command
) {
3026 case CMD_DOWNLOAD_RAW_ADC_SAMPLES_125K
:
3027 if (c
->cmd
!= CMD_DOWNLOADED_RAW_ADC_SAMPLES_125K
) goto unexpected_response
;
3029 for(i
=0; i
<48; i
++) sample_buf
[i
] = c
->d
.asBytes
[i
];
3030 received_command
= c
->cmd
;
3033 unexpected_response
:
3034 PrintToScrollback("unrecognized command %08x\n", c
->cmd
);