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 CmdHi15read(char *str
)
98 UsbCommand c
={CMD_ACQUIRE_RAW_ADC_SAMPLES_ISO_15693
};
102 static void CmdHi14read(char *str
)
104 UsbCommand c
= {CMD_ACQUIRE_RAW_ADC_SAMPLES_ISO_14443
, {strtol(str
, NULL
, 0), 0, 0}};
109 /* New command to read the contents of a SRI512 tag
110 * SRI512 tags are ISO14443-B modulated memory tags,
111 * this command just dumps the contents of the memory
113 static void CmdSri512read(char *str
)
115 UsbCommand c
={CMD_READ_SRI512_TAG
, {strtol(str
, NULL
, 0), 0, 0}};
119 /* New command to read the contents of a SRIX4K tag
120 * SRIX4K tags are ISO14443-B modulated memory tags,
121 * this command just dumps the contents of the memory/
123 static void CmdSrix4kread(char *str
)
125 UsbCommand c
={CMD_READ_SRIX4K_TAG
, {strtol(str
, NULL
, 0), 0, 0}};
129 static void CmdHi14areader(char *str
)
131 UsbCommand c
={CMD_READER_ISO_14443a
, {strtol(str
, NULL
, 0), 0, 0}};
135 static void CmdHi14amifare(char *str
)
137 UsbCommand c
={CMD_READER_MIFARE
, {strtol(str
, NULL
, 0), 0, 0}};
141 static void CmdHi15reader(char *str
)
143 UsbCommand c
={CMD_READER_ISO_15693
, {strtol(str
, NULL
, 0), 0, 0}};
147 static void CmdHi15tag(char *str
)
149 UsbCommand c
={CMD_SIMTAG_ISO_15693
, {strtol(str
, NULL
, 0), 0, 0}};
153 static void CmdHi14read_sim(char *str
)
155 UsbCommand c
={CMD_ACQUIRE_RAW_ADC_SAMPLES_ISO_14443_SIM
, {strtol(str
, NULL
, 0), 0, 0}};
159 static void CmdHi14readt(char *str
)
161 UsbCommand c
={CMD_ACQUIRE_RAW_ADC_SAMPLES_ISO_14443
, {strtol(str
, NULL
, 0), 0, 0}};
164 //CmdHisamplest(str);
165 while(CmdHisamplest(str
,strtol(str
, NULL
, 0))==0) {
168 RepaintGraphWindow();
171 static void CmdHisimlisten(char *str
)
173 UsbCommand c
={CMD_SIMULATE_TAG_HF_LISTEN
};
177 static void CmdHi14sim(char *str
)
179 UsbCommand c
={CMD_SIMULATE_TAG_ISO_14443
};
183 static void CmdHi14asim(char *str
) // ## simulate iso14443a tag
184 { // ## greg - added ability to specify tag UID
186 unsigned int hi
=0, lo
=0;
188 while (sscanf(&str
[i
++], "%1x", &n
) == 1) {
193 // c.arg should be set to *str or convert *str to the correct format for a uid
194 UsbCommand c
= {CMD_SIMULATE_TAG_ISO_14443a
, {hi
, lo
, 0}};
195 PrintToScrollback("Emulating 14443A TAG with UID %x%16x", hi
, lo
);
199 static void CmdHi14snoop(char *str
)
201 UsbCommand c
={CMD_SNOOP_ISO_14443
};
205 static void CmdHi14asnoop(char *str
)
207 UsbCommand c
={CMD_SNOOP_ISO_14443a
};
211 static void CmdLegicRfRead(char *str
)
213 UsbCommand c
={CMD_READER_LEGIC_RF
};
217 static void CmdFPGAOff(char *str
) // ## FPGA Control
219 UsbCommand c
={CMD_FPGA_MAJOR_MODE_OFF
};
223 /* clear out our graph window */
224 int CmdClearGraph(int redraw
)
226 int gtl
= GraphTraceLen
;
230 RepaintGraphWindow();
235 /* write a bit to the graph */
236 static void CmdAppendGraph(int redraw
, int clock
, int bit
)
240 for (i
= 0; i
< (int)(clock
/2); i
++)
241 GraphBuffer
[GraphTraceLen
++] = bit
^ 1;
243 for (i
= (int)(clock
/2); i
< clock
; i
++)
244 GraphBuffer
[GraphTraceLen
++] = bit
;
247 RepaintGraphWindow();
250 /* Function is equivalent of loread + losamples + em410xread
251 * looped until an EM410x tag is detected */
252 static void CmdEM410xwatch(char *str
)
266 /* Read the transmitted data of an EM4x50 tag
269 * XXXXXXXX [row parity bit (even)] <- 8 bits plus parity
270 * XXXXXXXX [row parity bit (even)] <- 8 bits plus parity
271 * XXXXXXXX [row parity bit (even)] <- 8 bits plus parity
272 * XXXXXXXX [row parity bit (even)] <- 8 bits plus parity
273 * CCCCCCCC <- column parity bits
275 * LW <- Listen Window
277 * This pattern repeats for every block of data being transmitted.
278 * Transmission starts with two Listen Windows (LW - a modulated
279 * pattern of 320 cycles each (32/32/128/64/64)).
281 * Note that this data may or may not be the UID. It is whatever data
282 * is stored in the blocks defined in the control word First and Last
283 * Word Read values. UID is stored in block 32.
285 static void CmdEM4x50read(char *str
)
287 int i
, j
, startblock
, clock
, skip
, block
, start
, end
, low
, high
;
288 bool complete
= false;
289 int tmpbuff
[MAX_GRAPH_TRACE_LEN
/ 64];
295 /* first get high and low values */
296 for (i
= 0; i
< GraphTraceLen
; i
++)
298 if (GraphBuffer
[i
] > high
)
299 high
= GraphBuffer
[i
];
300 else if (GraphBuffer
[i
] < low
)
301 low
= GraphBuffer
[i
];
304 /* populate a buffer with pulse lengths */
307 while(i
< GraphTraceLen
)
309 // measure from low to low
310 while((GraphBuffer
[i
] > low
) && (i
<GraphTraceLen
))
313 while((GraphBuffer
[i
] < high
) && (i
<GraphTraceLen
))
315 while((GraphBuffer
[i
] > low
) && (i
<GraphTraceLen
))
317 if (j
>(MAX_GRAPH_TRACE_LEN
/64)) {
320 tmpbuff
[j
++]= i
- start
;
323 /* look for data start - should be 2 pairs of LW (pulses of 192,128) */
326 for (i
= 0; i
< j
- 4 ; ++i
)
329 if (tmpbuff
[i
] >= 190 && tmpbuff
[i
] <= 194)
330 if (tmpbuff
[i
+1] >= 126 && tmpbuff
[i
+1] <= 130)
331 if (tmpbuff
[i
+2] >= 190 && tmpbuff
[i
+2] <= 194)
332 if (tmpbuff
[i
+3] >= 126 && tmpbuff
[i
+3] <= 130)
340 /* skip over the remainder of the LW */
341 skip
+= tmpbuff
[i
+1]+tmpbuff
[i
+2];
342 while(skip
< MAX_GRAPH_TRACE_LEN
&& GraphBuffer
[skip
] > low
)
346 /* now do it again to find the end */
348 for (i
+= 3; i
< j
- 4 ; ++i
)
351 if (tmpbuff
[i
] >= 190 && tmpbuff
[i
] <= 194)
352 if (tmpbuff
[i
+1] >= 126 && tmpbuff
[i
+1] <= 130)
353 if (tmpbuff
[i
+2] >= 190 && tmpbuff
[i
+2] <= 194)
354 if (tmpbuff
[i
+3] >= 126 && tmpbuff
[i
+3] <= 130)
362 PrintToScrollback("Found data at sample: %i",skip
);
365 PrintToScrollback("No data found!");
366 PrintToScrollback("Try again with more samples.");
372 PrintToScrollback("*** Warning!");
373 PrintToScrollback("Partial data - no end found!");
374 PrintToScrollback("Try again with more samples.");
377 /* get rid of leading crap */
378 sprintf(tmp
,"%i",skip
);
381 /* now work through remaining buffer printing out data blocks */
386 PrintToScrollback("Block %i:", block
);
387 // mandemod routine needs to be split so we can call it for data
388 // just print for now for debugging
389 Cmdmanchesterdemod("i 64");
391 /* look for LW before start of next block */
392 for ( ; i
< j
- 4 ; ++i
)
395 if (tmpbuff
[i
] >= 190 && tmpbuff
[i
] <= 194)
396 if (tmpbuff
[i
+1] >= 126 && tmpbuff
[i
+1] <= 130)
399 while(GraphBuffer
[skip
] > low
)
402 sprintf(tmp
,"%i",skip
);
410 /* Read the ID of an EM410x tag.
412 * 1111 1111 1 <-- standard non-repeatable header
413 * XXXX [row parity bit] <-- 10 rows of 5 bits for our 40 bit tag ID
415 * CCCC <-- each bit here is parity for the 10 bits above in corresponding column
416 * 0 <-- stop bit, end of tag
418 static void CmdEM410xread(char *str
)
420 int i
, j
, clock
, header
, rows
, bit
, hithigh
, hitlow
, first
, bit2idx
, high
, low
;
424 int BitStream
[MAX_GRAPH_TRACE_LEN
];
427 /* Detect high and lows and clock */
428 for (i
= 0; i
< GraphTraceLen
; i
++)
430 if (GraphBuffer
[i
] > high
)
431 high
= GraphBuffer
[i
];
432 else if (GraphBuffer
[i
] < low
)
433 low
= GraphBuffer
[i
];
437 clock
= GetClock(str
, high
);
439 /* parity for our 4 columns */
440 parity
[0] = parity
[1] = parity
[2] = parity
[3] = 0;
443 /* manchester demodulate */
445 for (i
= 0; i
< (int)(GraphTraceLen
/ clock
); i
++)
451 /* Find out if we hit both high and low peaks */
452 for (j
= 0; j
< clock
; j
++)
454 if (GraphBuffer
[(i
* clock
) + j
] == high
)
456 else if (GraphBuffer
[(i
* clock
) + j
] == low
)
459 /* it doesn't count if it's the first part of our read
460 because it's really just trailing from the last sequence */
461 if (first
&& (hithigh
|| hitlow
))
462 hithigh
= hitlow
= 0;
466 if (hithigh
&& hitlow
)
470 /* If we didn't hit both high and low peaks, we had a bit transition */
471 if (!hithigh
|| !hitlow
)
474 BitStream
[bit2idx
++] = bit
;
478 /* We go till 5 before the graph ends because we'll get that far below */
479 for (i
= 1; i
< bit2idx
- 5; i
++)
481 /* Step 2: We have our header but need our tag ID */
482 if (header
== 9 && rows
< 10)
484 /* Confirm parity is correct */
485 if ((BitStream
[i
] ^ BitStream
[i
+1] ^ BitStream
[i
+2] ^ BitStream
[i
+3]) == BitStream
[i
+4])
487 /* Read another byte! */
488 sprintf(id
+rows
, "%x", (8 * BitStream
[i
]) + (4 * BitStream
[i
+1]) + (2 * BitStream
[i
+2]) + (1 * BitStream
[i
+3]));
491 /* Keep parity info */
492 parity
[0] ^= BitStream
[i
];
493 parity
[1] ^= BitStream
[i
+1];
494 parity
[2] ^= BitStream
[i
+2];
495 parity
[3] ^= BitStream
[i
+3];
497 /* Move 4 bits ahead */
501 /* Damn, something wrong! reset */
504 PrintToScrollback("Thought we had a valid tag but failed at word %d (i=%d)", rows
+ 1, i
);
506 /* Start back rows * 5 + 9 header bits, -1 to not start at same place */
507 i
-= 9 + (5 * rows
) - 5;
513 /* Step 3: Got our 40 bits! confirm column parity */
516 /* We need to make sure our 4 bits of parity are correct and we have a stop bit */
517 if (BitStream
[i
] == parity
[0] && BitStream
[i
+1] == parity
[1] &&
518 BitStream
[i
+2] == parity
[2] && BitStream
[i
+3] == parity
[3] &&
522 PrintToScrollback("EM410x Tag ID: %s", id
);
529 /* Crap! Incorrect parity or no stop bit, start all over */
534 /* Go back 59 bits (9 header bits + 10 rows at 4+1 parity) */
539 /* Step 1: get our header */
542 /* Need 9 consecutive 1's */
543 if (BitStream
[i
] == 1)
546 /* We don't have a header, not enough consecutive 1 bits */
552 /* if we've already retested after flipping bits, return */
556 /* if this didn't work, try flipping bits */
557 for (i
= 0; i
< bit2idx
; i
++)
563 /* emulate an EM410X tag
565 * 1111 1111 1 <-- standard non-repeatable header
566 * XXXX [row parity bit] <-- 10 rows of 5 bits for our 40 bit tag ID
568 * CCCC <-- each bit here is parity for the 10 bits above in corresponding column
569 * 0 <-- stop bit, end of tag
571 static void CmdEM410xsim(char *str
)
573 int i
, n
, j
, h
, binary
[4], parity
[4];
576 /* clock is 64 in EM410x tags */
579 /* clear our graph */
582 /* write it out a few times */
583 for (h
= 0; h
< 4; h
++)
585 /* write 9 start bits */
586 for (i
= 0; i
< 9; i
++)
587 CmdAppendGraph(0, clock
, 1);
589 /* for each hex char */
590 parity
[0] = parity
[1] = parity
[2] = parity
[3] = 0;
591 for (i
= 0; i
< 10; i
++)
593 /* read each hex char */
594 sscanf(&str
[i
], "%1x", &n
);
595 for (j
= 3; j
>= 0; j
--, n
/= 2)
598 /* append each bit */
599 CmdAppendGraph(0, clock
, binary
[0]);
600 CmdAppendGraph(0, clock
, binary
[1]);
601 CmdAppendGraph(0, clock
, binary
[2]);
602 CmdAppendGraph(0, clock
, binary
[3]);
604 /* append parity bit */
605 CmdAppendGraph(0, clock
, binary
[0] ^ binary
[1] ^ binary
[2] ^ binary
[3]);
607 /* keep track of column parity */
608 parity
[0] ^= binary
[0];
609 parity
[1] ^= binary
[1];
610 parity
[2] ^= binary
[2];
611 parity
[3] ^= binary
[3];
615 CmdAppendGraph(0, clock
, parity
[0]);
616 CmdAppendGraph(0, clock
, parity
[1]);
617 CmdAppendGraph(0, clock
, parity
[2]);
618 CmdAppendGraph(0, clock
, parity
[3]);
621 CmdAppendGraph(0, clock
, 0);
624 /* modulate that biatch */
628 RepaintGraphWindow();
633 static void ChkBitstream(char *str
)
637 /* convert to bitstream if necessary */
638 for (i
= 0; i
< (int)(GraphTraceLen
/ 2); i
++)
640 if (GraphBuffer
[i
] > 1 || GraphBuffer
[i
] < 0)
648 static void CmdLosim(char *str
)
652 /* convert to bitstream if necessary */
655 for (i
= 0; i
< GraphTraceLen
; i
+= 48) {
656 UsbCommand c
={CMD_DOWNLOADED_SIM_SAMPLES_125K
, {i
, 0, 0}};
658 for(j
= 0; j
< 48; j
++) {
659 c
.d
.asBytes
[j
] = GraphBuffer
[i
+j
];
664 UsbCommand c
={CMD_SIMULATE_TAG_125K
, {GraphTraceLen
, 0, 0}};
668 static void CmdLosimBidir(char *str
)
670 /* Set ADC to twice the carrier for a slight supersampling */
671 UsbCommand c
={CMD_LF_SIMULATE_BIDIR
, {47, 384, 0}};
675 static void CmdLoread(char *str
)
677 UsbCommand c
={CMD_ACQUIRE_RAW_ADC_SAMPLES_125K
};
678 // 'h' means higher-low-frequency, 134 kHz
681 } else if (*str
== '\0') {
684 PrintToScrollback("use 'loread' or 'loread h'");
690 static void CmdDetectReader(char *str
)
692 UsbCommand c
={CMD_LISTEN_READER_FIELD
};
693 // 'l' means LF - 125/134 kHz
696 } else if (*str
== 'h') {
698 } else if (*str
!= '\0') {
699 PrintToScrollback("use 'detectreader' or 'detectreader l' or 'detectreader h'");
705 /* send a command before reading */
706 static void CmdLoCommandRead(char *str
)
708 static char dummy
[3];
712 UsbCommand c
={CMD_MOD_THEN_ACQUIRE_RAW_ADC_SAMPLES_125K
};
713 sscanf(str
, "%i %i %i %s %s", &c
.arg
[0], &c
.arg
[1], &c
.arg
[2], (char *) &c
.d
.asBytes
,(char *) &dummy
+1);
714 // in case they specified 'h'
715 strcpy((char *)&c
.d
.asBytes
+ strlen((char *)c
.d
.asBytes
), dummy
);
719 static void CmdLosamples(char *str
)
724 n
=strtol(str
, NULL
, 0);
726 if (n
>16000) n
=16000;
728 PrintToScrollback("Reading %d samples\n", n
);
729 for(i
= 0; i
< n
; i
+= 12) {
730 UsbCommand c
= {CMD_DOWNLOAD_RAW_ADC_SAMPLES_125K
, {i
, 0, 0}};
732 wait_for_response(CMD_DOWNLOADED_RAW_ADC_SAMPLES_125K
);
733 for(j
= 0; j
< 48; j
++) {
734 GraphBuffer
[cnt
++] = ((int)sample_buf
[j
]) - 128;
737 PrintToScrollback("Done!\n");
739 RepaintGraphWindow();
742 static void CmdBitsamples(char *str
)
748 for(i
= 0; i
< n
; i
+= 12) {
749 UsbCommand c
= {CMD_DOWNLOAD_RAW_ADC_SAMPLES_125K
, {i
, 0, 0}};
751 wait_for_response(CMD_DOWNLOADED_RAW_ADC_SAMPLES_125K
);
753 for(j
= 0; j
< 48; j
++) {
754 for(k
= 0; k
< 8; k
++) {
755 if(sample_buf
[j
] & (1 << (7 - k
))) {
756 GraphBuffer
[cnt
++] = 1;
758 GraphBuffer
[cnt
++] = 0;
764 RepaintGraphWindow();
767 static void CmdHisamples(char *str
)
773 for(i
= 0; i
< n
; i
+= 12) {
774 UsbCommand c
= {CMD_DOWNLOAD_RAW_ADC_SAMPLES_125K
, {i
, 0, 0}};
776 wait_for_response(CMD_DOWNLOADED_RAW_ADC_SAMPLES_125K
);
777 for(j
= 0; j
< 48; j
++) {
778 GraphBuffer
[cnt
++] = (int)(sample_buf
[j
]);
783 RepaintGraphWindow();
786 static int CmdHisamplest(char *str
, int nrlow
)
796 for(i
= 0; i
< n
; i
+= 12) {
797 UsbCommand c
= {CMD_DOWNLOAD_RAW_ADC_SAMPLES_125K
, {i
, 0, 0}};
799 wait_for_response(CMD_DOWNLOADED_RAW_ADC_SAMPLES_125K
);
800 for(j
= 0; j
< 48; j
++) {
801 t2
= (int)(sample_buf
[j
]);
802 if((t2
^ 0xC0) & 0xC0) { hasbeennull
++; }
808 t1
= (t2
& 0x80) ^ (t2
& 0x20);
809 t2
= ((t2
<< 1) & 0x80) ^ ((t2
<< 1) & 0x20);
815 t2
= ((t2
<< 1) & 0x80);
821 t2
= ((t2
<< 1) & 0x20);
825 // both, but tag with other algorithm
826 t1
= (t2
& 0x80) ^ (t2
& 0x08);
827 t2
= ((t2
<< 1) & 0x80) ^ ((t2
<< 1) & 0x08);
831 GraphBuffer
[cnt
++] = t1
;
832 GraphBuffer
[cnt
++] = t2
;
837 if(hasbeennull
>nrlow
|| nrlow
==0) {
838 PrintToScrollback("hasbeennull=%d", hasbeennull
);
847 static void CmdHexsamples(char *str
)
850 int requested
= strtol(str
, NULL
, 0);
853 if (requested
== 0) {
860 for(i
= 0; i
< n
; i
+= 12) {
861 UsbCommand c
= {CMD_DOWNLOAD_RAW_ADC_SAMPLES_125K
, {i
, 0, 0}};
863 wait_for_response(CMD_DOWNLOADED_RAW_ADC_SAMPLES_125K
);
864 for (j
= 0; j
< 48; j
+= 8) {
865 PrintToScrollback("%02x %02x %02x %02x %02x %02x %02x %02x",
877 if (delivered
>= requested
)
880 if (delivered
>= requested
)
885 static void CmdHisampless(char *str
)
889 int n
= strtol(str
, NULL
, 0);
897 for(i
= 0; i
< n
; i
+= 12) {
898 UsbCommand c
= {CMD_DOWNLOAD_RAW_ADC_SAMPLES_125K
, {i
, 0, 0}};
900 wait_for_response(CMD_DOWNLOADED_RAW_ADC_SAMPLES_125K
);
901 for(j
= 0; j
< 48; j
++) {
902 GraphBuffer
[cnt
++] = (int)(sample_buf
[j
]);
907 RepaintGraphWindow();
910 static uint16_t Iso15693Crc(uint8_t *v
, int n
)
916 for(i
= 0; i
< n
; i
++) {
917 reg
= reg
^ ((uint32_t)v
[i
]);
918 for (j
= 0; j
< 8; j
++) {
920 reg
= (reg
>> 1) ^ 0x8408;
927 return (uint16_t)~reg
;
930 static void CmdHi14bdemod(char *str
)
935 bool negateI
, negateQ
;
940 // As received, the samples are pairs, correlations against I and Q
941 // square waves. So estimate angle of initial carrier (or just
942 // quadrant, actually), and then do the demod.
944 // First, estimate where the tag starts modulating.
945 for(i
= 0; i
< GraphTraceLen
; i
+= 2) {
946 if(abs(GraphBuffer
[i
]) + abs(GraphBuffer
[i
+1]) > 40) {
950 if(i
>= GraphTraceLen
) {
951 PrintToScrollback("too weak to sync");
954 PrintToScrollback("out of weak at %d", i
);
957 // Now, estimate the phase in the initial modulation of the tag
960 for(; i
< (outOfWeakAt
+ 16); i
+= 2) {
961 isum
+= GraphBuffer
[i
+0];
962 qsum
+= GraphBuffer
[i
+1];
964 negateI
= (isum
< 0);
965 negateQ
= (qsum
< 0);
967 // Turn the correlation pairs into soft decisions on the bit.
969 for(i
= 0; i
< GraphTraceLen
/2; i
++) {
970 int si
= GraphBuffer
[j
];
971 int sq
= GraphBuffer
[j
+1];
972 if(negateI
) si
= -si
;
973 if(negateQ
) sq
= -sq
;
974 GraphBuffer
[i
] = si
+ sq
;
980 while(GraphBuffer
[i
] > 0 && i
< GraphTraceLen
)
982 if(i
>= GraphTraceLen
) goto demodError
;
985 while(GraphBuffer
[i
] < 0 && i
< GraphTraceLen
)
987 if(i
>= GraphTraceLen
) goto demodError
;
988 if((i
- iold
) > 23) goto demodError
;
990 PrintToScrollback("make it to demod loop");
994 while(GraphBuffer
[i
] >= 0 && i
< GraphTraceLen
)
996 if(i
>= GraphTraceLen
) goto demodError
;
997 if((i
- iold
) > 6) goto demodError
;
999 uint16_t shiftReg
= 0;
1000 if(i
+ 20 >= GraphTraceLen
) goto demodError
;
1002 for(j
= 0; j
< 10; j
++) {
1003 int soft
= GraphBuffer
[i
] + GraphBuffer
[i
+1];
1005 if(abs(soft
) < ((abs(isum
) + abs(qsum
))/20)) {
1006 PrintToScrollback("weak bit");
1010 if(GraphBuffer
[i
] + GraphBuffer
[i
+1] >= 0) {
1017 if( (shiftReg
& 0x200) &&
1018 !(shiftReg
& 0x001))
1020 // valid data byte, start and stop bits okay
1021 PrintToScrollback(" %02x", (shiftReg
>> 1) & 0xff);
1022 data
[dataLen
++] = (shiftReg
>> 1) & 0xff;
1023 if(dataLen
>= sizeof(data
)) {
1026 } else if(shiftReg
== 0x000) {
1034 uint8_t first
, second
;
1035 ComputeCrc14443(CRC_14443_B
, data
, dataLen
-2, &first
, &second
);
1036 PrintToScrollback("CRC: %02x %02x (%s)\n", first
, second
,
1037 (first
== data
[dataLen
-2] && second
== data
[dataLen
-1]) ?
1038 "ok" : "****FAIL****");
1040 RepaintGraphWindow();
1044 PrintToScrollback("demod error");
1045 RepaintGraphWindow();
1048 static void CmdHi14list(char *str
)
1051 GetFromBigBuf(got
, sizeof(got
));
1053 PrintToScrollback("recorded activity:");
1054 PrintToScrollback(" time :rssi: who bytes");
1055 PrintToScrollback("---------+----+----+-----------");
1066 int timestamp
= *((uint32_t *)(got
+i
));
1067 if(timestamp
& 0x80000000) {
1068 timestamp
&= 0x7fffffff;
1073 int metric
= *((uint32_t *)(got
+i
+4));
1080 if(i
+ len
>= 900) {
1084 uint8_t *frame
= (got
+i
+9);
1086 char line
[1000] = "";
1088 for(j
= 0; j
< len
; j
++) {
1089 sprintf(line
+(j
*3), "%02x ", frame
[j
]);
1095 ComputeCrc14443(CRC_14443_B
, frame
, len
-2, &b1
, &b2
);
1096 if(b1
!= frame
[len
-2] || b2
!= frame
[len
-1]) {
1097 crc
= "**FAIL CRC**";
1105 char metricString
[100];
1107 sprintf(metricString
, "%3d", metric
);
1109 strcpy(metricString
, " ");
1112 PrintToScrollback(" +%7d: %s: %s %s %s",
1113 (prev
< 0 ? 0 : timestamp
- prev
),
1115 (isResponse
? "TAG" : " "), line
, crc
);
1122 static void CmdHi14alist(char *str
)
1125 GetFromBigBuf(got
, sizeof(got
));
1127 PrintToScrollback("recorded activity:");
1128 PrintToScrollback(" ETU :rssi: who bytes");
1129 PrintToScrollback("---------+----+----+-----------");
1140 int timestamp
= *((uint32_t *)(got
+i
));
1141 if(timestamp
& 0x80000000) {
1142 timestamp
&= 0x7fffffff;
1149 int parityBits
= *((uint32_t *)(got
+i
+4));
1150 // 4 bytes of additional information...
1151 // maximum of 32 additional parity bit information
1154 // at each quarter bit period we can send power level (16 levels)
1155 // or each half bit period in 256 levels.
1163 if(i
+ len
>= 1900) {
1167 uint8_t *frame
= (got
+i
+9);
1169 // Break and stick with current result if buffer was not completely full
1170 if(frame
[0] == 0x44 && frame
[1] == 0x44 && frame
[3] == 0x44) { break; }
1172 char line
[1000] = "";
1174 for(j
= 0; j
< len
; j
++) {
1175 int oddparity
= 0x01;
1179 oddparity
^= (((frame
[j
] & 0xFF) >> k
) & 0x01);
1182 //if((parityBits >> (len - j - 1)) & 0x01) {
1183 if(isResponse
&& (oddparity
!= ((parityBits
>> (len
- j
- 1)) & 0x01))) {
1184 sprintf(line
+(j
*4), "%02x! ", frame
[j
]);
1187 sprintf(line
+(j
*4), "%02x ", frame
[j
]);
1195 for(j
= 0; j
< (len
- 1); j
++) {
1196 // gives problems... search for the reason..
1197 /*if(frame[j] == 0xAA) {
1198 switch(frame[j+1]) {
1200 crc = "[1] Two drops close after each other";
1203 crc = "[2] Potential SOC with a drop in second half of bitperiod";
1206 crc = "[3] Segment Z after segment X is not possible";
1209 crc = "[4] Parity bit of a fully received byte was wrong";
1212 crc = "[?] Unknown error";
1219 if(strlen(crc
)==0) {
1220 ComputeCrc14443(CRC_14443_A
, frame
, len
-2, &b1
, &b2
);
1221 if(b1
!= frame
[len
-2] || b2
!= frame
[len
-1]) {
1222 crc
= (isResponse
& (len
< 6)) ? "" : " !crc";
1231 char metricString
[100];
1233 sprintf(metricString
, "%3d", metric
);
1235 strcpy(metricString
, " ");
1238 PrintToScrollback(" +%7d: %s: %s %s %s",
1239 (prev
< 0 ? 0 : (timestamp
- prev
)),
1241 (isResponse
? "TAG" : " "), line
, crc
);
1246 CommandFinished
= 1;
1249 static void CmdHi15demod(char *str
)
1251 // The sampling rate is 106.353 ksps/s, for T = 18.8 us
1254 // 1) Unmodulated time of 56.64us
1255 // 2) 24 pulses of 423.75khz
1256 // 3) logic '1' (unmodulated for 18.88us followed by 8 pulses of 423.75khz)
1258 static const int FrameSOF
[] = {
1259 -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
1260 -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
1261 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
1262 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
1268 static const int Logic0
[] = {
1274 static const int Logic1
[] = {
1282 // 1) logic '0' (8 pulses of 423.75khz followed by unmodulated for 18.88us)
1283 // 2) 24 pulses of 423.75khz
1284 // 3) Unmodulated time of 56.64us
1286 static const int FrameEOF
[] = {
1291 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
1292 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
1293 -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
1294 -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1
1298 int max
= 0, maxPos
;
1302 if(GraphTraceLen
< 1000) return;
1304 // First, correlate for SOF
1305 for(i
= 0; i
< 100; i
++) {
1307 for(j
= 0; j
< arraylen(FrameSOF
); j
+= skip
) {
1308 corr
+= FrameSOF
[j
]*GraphBuffer
[i
+(j
/skip
)];
1315 PrintToScrollback("SOF at %d, correlation %d", maxPos
,
1316 max
/(arraylen(FrameSOF
)/skip
));
1318 i
= maxPos
+ arraylen(FrameSOF
)/skip
;
1321 memset(outBuf
, 0, sizeof(outBuf
));
1322 uint8_t mask
= 0x01;
1324 int corr0
= 0, corr1
= 0, corrEOF
= 0;
1325 for(j
= 0; j
< arraylen(Logic0
); j
+= skip
) {
1326 corr0
+= Logic0
[j
]*GraphBuffer
[i
+(j
/skip
)];
1328 for(j
= 0; j
< arraylen(Logic1
); j
+= skip
) {
1329 corr1
+= Logic1
[j
]*GraphBuffer
[i
+(j
/skip
)];
1331 for(j
= 0; j
< arraylen(FrameEOF
); j
+= skip
) {
1332 corrEOF
+= FrameEOF
[j
]*GraphBuffer
[i
+(j
/skip
)];
1334 // Even things out by the length of the target waveform.
1338 if(corrEOF
> corr1
&& corrEOF
> corr0
) {
1339 PrintToScrollback("EOF at %d", i
);
1341 } else if(corr1
> corr0
) {
1342 i
+= arraylen(Logic1
)/skip
;
1345 i
+= arraylen(Logic0
)/skip
;
1352 if((i
+(int)arraylen(FrameEOF
)) >= GraphTraceLen
) {
1353 PrintToScrollback("ran off end!");
1358 PrintToScrollback("error, uneven octet! (discard extra bits!)");
1359 PrintToScrollback(" mask=%02x", mask
);
1361 PrintToScrollback("%d octets", k
);
1363 for(i
= 0; i
< k
; i
++) {
1364 PrintToScrollback("# %2d: %02x ", i
, outBuf
[i
]);
1366 PrintToScrollback("CRC=%04x", Iso15693Crc(outBuf
, k
-2));
1369 static void CmdFSKdemod(char *cmdline
)
1371 static const int LowTone
[] = {
1372 1, 1, 1, 1, 1, -1, -1, -1, -1, -1,
1373 1, 1, 1, 1, 1, -1, -1, -1, -1, -1,
1374 1, 1, 1, 1, 1, -1, -1, -1, -1, -1,
1375 1, 1, 1, 1, 1, -1, -1, -1, -1, -1,
1376 1, 1, 1, 1, 1, -1, -1, -1, -1, -1
1378 static const int HighTone
[] = {
1379 1, 1, 1, 1, 1, -1, -1, -1, -1,
1380 1, 1, 1, 1, -1, -1, -1, -1,
1381 1, 1, 1, 1, -1, -1, -1, -1,
1382 1, 1, 1, 1, -1, -1, -1, -1,
1383 1, 1, 1, 1, -1, -1, -1, -1,
1384 1, 1, 1, 1, -1, -1, -1, -1, -1,
1387 int lowLen
= sizeof(LowTone
)/sizeof(int);
1388 int highLen
= sizeof(HighTone
)/sizeof(int);
1389 int convLen
= (highLen
>lowLen
)?highLen
:lowLen
;
1390 uint32_t hi
= 0, lo
= 0;
1393 int minMark
=0, maxMark
=0;
1395 for(i
= 0; i
< GraphTraceLen
- convLen
; i
++) {
1396 int lowSum
= 0, highSum
= 0;
1398 for(j
= 0; j
< lowLen
; j
++) {
1399 lowSum
+= LowTone
[j
]*GraphBuffer
[i
+j
];
1401 for(j
= 0; j
< highLen
; j
++) {
1402 highSum
+= HighTone
[j
]*GraphBuffer
[i
+j
];
1404 lowSum
= abs((100*lowSum
) / lowLen
);
1405 highSum
= abs((100*highSum
) / highLen
);
1406 GraphBuffer
[i
] = (highSum
<< 16) | lowSum
;
1409 for(i
= 0; i
< GraphTraceLen
- convLen
- 16; i
++) {
1411 int lowTot
= 0, highTot
= 0;
1412 // 10 and 8 are f_s divided by f_l and f_h, rounded
1413 for(j
= 0; j
< 10; j
++) {
1414 lowTot
+= (GraphBuffer
[i
+j
] & 0xffff);
1416 for(j
= 0; j
< 8; j
++) {
1417 highTot
+= (GraphBuffer
[i
+j
] >> 16);
1419 GraphBuffer
[i
] = lowTot
- highTot
;
1420 if (GraphBuffer
[i
]>maxMark
) maxMark
=GraphBuffer
[i
];
1421 if (GraphBuffer
[i
]<minMark
) minMark
=GraphBuffer
[i
];
1424 GraphTraceLen
-= (convLen
+ 16);
1426 RepaintGraphWindow();
1428 // Find bit-sync (3 lo followed by 3 high)
1429 int max
= 0, maxPos
= 0;
1430 for(i
= 0; i
< 6000; i
++) {
1432 for(j
= 0; j
< 3*lowLen
; j
++) {
1433 dec
-= GraphBuffer
[i
+j
];
1435 for(; j
< 3*(lowLen
+ highLen
); j
++) {
1436 dec
+= GraphBuffer
[i
+j
];
1444 // place start of bit sync marker in graph
1445 GraphBuffer
[maxPos
] = maxMark
;
1446 GraphBuffer
[maxPos
+1] = minMark
;
1450 // place end of bit sync marker in graph
1451 GraphBuffer
[maxPos
] = maxMark
;
1452 GraphBuffer
[maxPos
+1] = minMark
;
1454 PrintToScrollback("actual data bits start at sample %d", maxPos
);
1455 PrintToScrollback("length %d/%d", highLen
, lowLen
);
1458 bits
[sizeof(bits
)-1] = '\0';
1460 // find bit pairs and manchester decode them
1461 for(i
= 0; i
< arraylen(bits
)-1; i
++) {
1463 for(j
= 0; j
< lowLen
; j
++) {
1464 dec
-= GraphBuffer
[maxPos
+j
];
1466 for(; j
< lowLen
+ highLen
; j
++) {
1467 dec
+= GraphBuffer
[maxPos
+j
];
1470 // place inter bit marker in graph
1471 GraphBuffer
[maxPos
] = maxMark
;
1472 GraphBuffer
[maxPos
+1] = minMark
;
1474 // hi and lo form a 64 bit pair
1475 hi
= (hi
<<1)|(lo
>>31);
1477 // store decoded bit as binary (in hi/lo) and text (in bits[])
1485 PrintToScrollback("bits: '%s'", bits
);
1486 PrintToScrollback("hex: %08x %08x", hi
, lo
);
1489 // read a TI tag and return its ID
1490 static void CmdTIRead(char *str
)
1492 UsbCommand c
={CMD_READ_TI_TYPE
};
1496 // write new data to a r/w TI tag
1497 static void CmdTIWrite(char *str
)
1499 UsbCommand c
={CMD_WRITE_TI_TYPE
};
1502 res
= sscanf(str
, "0x%x 0x%x 0x%x ", &c
.arg
[0], &c
.arg
[1], &c
.arg
[2]);
1503 if (res
== 2) c
.arg
[2]=0;
1505 PrintToScrollback("Please specify the data as two hex strings, optionally the CRC as a third");
1510 static void CmdTIDemod(char *cmdline
)
1512 /* MATLAB as follows:
1513 f_s = 2000000; % sampling frequency
1514 f_l = 123200; % low FSK tone
1515 f_h = 134200; % high FSK tone
1517 T_l = 119e-6; % low bit duration
1518 T_h = 130e-6; % high bit duration
1520 l = 2*pi*ones(1, floor(f_s*T_l))*(f_l/f_s);
1521 h = 2*pi*ones(1, floor(f_s*T_h))*(f_h/f_s);
1523 l = sign(sin(cumsum(l)));
1524 h = sign(sin(cumsum(h)));
1527 // 2M*16/134.2k = 238
1528 static const int LowTone
[] = {
1529 1, 1, 1, 1, 1, 1, 1, 1, 1, -1, -1, -1, -1, -1, -1, -1, -1,
1530 1, 1, 1, 1, 1, 1, 1, 1, -1, -1, -1, -1, -1, -1, -1, -1,
1531 1, 1, 1, 1, 1, 1, 1, 1, -1, -1, -1, -1, -1, -1, -1, -1,
1532 1, 1, 1, 1, 1, 1, 1, 1, -1, -1, -1, -1, -1, -1, -1, -1,
1533 1, 1, 1, 1, 1, 1, 1, 1, 1, -1, -1, -1, -1, -1, -1, -1, -1,
1534 1, 1, 1, 1, 1, 1, 1, 1, -1, -1, -1, -1, -1, -1, -1, -1,
1535 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, -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,
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, -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
1545 // 2M*16/123.2k = 260
1546 static const int HighTone
[] = {
1547 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,
1549 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,
1551 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,
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,
1558 1, 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
1566 int lowLen
= sizeof(LowTone
)/sizeof(int);
1567 int highLen
= sizeof(HighTone
)/sizeof(int);
1568 int convLen
= (highLen
>lowLen
)?highLen
:lowLen
;
1571 int lowSum
= 0, highSum
= 0;;
1572 int lowTot
= 0, highTot
= 0;
1574 for(i
= 0; i
< GraphTraceLen
- convLen
; i
++) {
1578 for(j
= 0; j
< lowLen
; j
++) {
1579 lowSum
+= LowTone
[j
]*GraphBuffer
[i
+j
];
1581 for(j
= 0; j
< highLen
; j
++) {
1582 highSum
+= HighTone
[j
]*GraphBuffer
[i
+j
];
1584 lowSum
= abs((100*lowSum
) / lowLen
);
1585 highSum
= abs((100*highSum
) / highLen
);
1586 lowSum
= (lowSum
<0)?-lowSum
:lowSum
;
1587 highSum
= (highSum
<0)?-highSum
:highSum
;
1589 GraphBuffer
[i
] = (highSum
<< 16) | lowSum
;
1592 for(i
= 0; i
< GraphTraceLen
- convLen
- 16; i
++) {
1595 // 16 and 15 are f_s divided by f_l and f_h, rounded
1596 for(j
= 0; j
< 16; j
++) {
1597 lowTot
+= (GraphBuffer
[i
+j
] & 0xffff);
1599 for(j
= 0; j
< 15; j
++) {
1600 highTot
+= (GraphBuffer
[i
+j
] >> 16);
1602 GraphBuffer
[i
] = lowTot
- highTot
;
1605 GraphTraceLen
-= (convLen
+ 16);
1607 RepaintGraphWindow();
1609 // TI tag data format is 16 prebits, 8 start bits, 64 data bits,
1610 // 16 crc CCITT bits, 8 stop bits, 15 end bits
1612 // the 16 prebits are always low
1613 // the 8 start and stop bits of a tag must match
1614 // the start/stop prebits of a ro tag are 01111110
1615 // the start/stop prebits of a rw tag are 11111110
1616 // the 15 end bits of a ro tag are all low
1617 // the 15 end bits of a rw tag match bits 15-1 of the data bits
1619 // Okay, so now we have unsliced soft decisions;
1620 // find bit-sync, and then get some bits.
1621 // look for 17 low bits followed by 6 highs (common pattern for ro and rw tags)
1622 int max
= 0, maxPos
= 0;
1623 for(i
= 0; i
< 6000; i
++) {
1626 // searching 17 consecutive lows
1627 for(j
= 0; j
< 17*lowLen
; j
++) {
1628 dec
-= GraphBuffer
[i
+j
];
1630 // searching 7 consecutive highs
1631 for(; j
< 17*lowLen
+ 6*highLen
; j
++) {
1632 dec
+= GraphBuffer
[i
+j
];
1640 // place a marker in the buffer to visually aid location
1641 // of the start of sync
1642 GraphBuffer
[maxPos
] = 800;
1643 GraphBuffer
[maxPos
+1] = -800;
1645 // advance pointer to start of actual data stream (after 16 pre and 8 start bits)
1646 maxPos
+= 17*lowLen
;
1647 maxPos
+= 6*highLen
;
1649 // place a marker in the buffer to visually aid location
1650 // of the end of sync
1651 GraphBuffer
[maxPos
] = 800;
1652 GraphBuffer
[maxPos
+1] = -800;
1654 PrintToScrollback("actual data bits start at sample %d", maxPos
);
1656 PrintToScrollback("length %d/%d", highLen
, lowLen
);
1658 uint8_t bits
[1+64+16+8+16];
1659 bits
[sizeof(bits
)-1] = '\0';
1661 uint32_t shift3
= 0x7e000000, shift2
= 0, shift1
= 0, shift0
= 0;
1663 for(i
= 0; i
< arraylen(bits
)-1; i
++) {
1667 for(j
= 0; j
< lowLen
; j
++) {
1668 low
-= GraphBuffer
[maxPos
+j
];
1670 for(j
= 0; j
< highLen
; j
++) {
1671 high
+= GraphBuffer
[maxPos
+j
];
1677 // bitstream arrives lsb first so shift right
1684 // 128 bit right shift register
1685 shift0
= (shift0
>>1) | (shift1
<< 31);
1686 shift1
= (shift1
>>1) | (shift2
<< 31);
1687 shift2
= (shift2
>>1) | (shift3
<< 31);
1690 // place a marker in the buffer between bits to visually aid location
1691 GraphBuffer
[maxPos
] = 800;
1692 GraphBuffer
[maxPos
+1] = -800;
1694 PrintToScrollback("Info: raw tag bits = %s", bits
);
1696 TagType
= (shift3
>>8)&0xff;
1697 if ( TagType
!= ((shift0
>>16)&0xff) ) {
1698 PrintToScrollback("Error: start and stop bits do not match!");
1701 else if (TagType
== 0x7e) {
1702 PrintToScrollback("Info: Readonly TI tag detected.");
1705 else if (TagType
== 0xfe) {
1706 PrintToScrollback("Info: Rewriteable TI tag detected.");
1708 // put 64 bit data into shift1 and shift0
1709 shift0
= (shift0
>>24) | (shift1
<< 8);
1710 shift1
= (shift1
>>24) | (shift2
<< 8);
1712 // align 16 bit crc into lower half of shift2
1713 shift2
= ((shift2
>>24) | (shift3
<< 8)) & 0x0ffff;
1715 // align 16 bit "end bits" or "ident" into lower half of shift3
1718 // only 15 bits compare, last bit of ident is not valid
1719 if ( (shift3
^shift0
)&0x7fff ) {
1720 PrintToScrollback("Error: Ident mismatch!");
1722 // WARNING the order of the bytes in which we calc crc below needs checking
1723 // i'm 99% sure the crc algorithm is correct, but it may need to eat the
1724 // bytes in reverse or something
1727 crc
= update_crc16(crc
, (shift0
)&0xff);
1728 crc
= update_crc16(crc
, (shift0
>>8)&0xff);
1729 crc
= update_crc16(crc
, (shift0
>>16)&0xff);
1730 crc
= update_crc16(crc
, (shift0
>>24)&0xff);
1731 crc
= update_crc16(crc
, (shift1
)&0xff);
1732 crc
= update_crc16(crc
, (shift1
>>8)&0xff);
1733 crc
= update_crc16(crc
, (shift1
>>16)&0xff);
1734 crc
= update_crc16(crc
, (shift1
>>24)&0xff);
1735 PrintToScrollback("Info: Tag data = %08X%08X", shift1
, shift0
);
1736 if (crc
!= (shift2
&0xffff)) {
1737 PrintToScrollback("Error: CRC mismatch, calculated %04X, got ^04X", crc
, shift2
&0xffff);
1739 PrintToScrollback("Info: CRC %04X is good", crc
);
1743 PrintToScrollback("Unknown tag type.");
1748 static void CmdNorm(char *str
)
1751 int max
= INT_MIN
, min
= INT_MAX
;
1752 for(i
= 10; i
< GraphTraceLen
; i
++) {
1753 if(GraphBuffer
[i
] > max
) {
1754 max
= GraphBuffer
[i
];
1756 if(GraphBuffer
[i
] < min
) {
1757 min
= GraphBuffer
[i
];
1761 for(i
= 0; i
< GraphTraceLen
; i
++) {
1762 GraphBuffer
[i
] = (GraphBuffer
[i
] - ((max
+ min
)/2))*1000/
1766 RepaintGraphWindow();
1769 static void CmdAmp(char *str
)
1771 int i
, rising
, falling
;
1772 int max
= INT_MIN
, min
= INT_MAX
;
1773 for(i
= 10; i
< GraphTraceLen
; i
++) {
1774 if(GraphBuffer
[i
] > max
) {
1775 max
= GraphBuffer
[i
];
1777 if(GraphBuffer
[i
] < min
) {
1778 min
= GraphBuffer
[i
];
1783 for(i
= 0; i
< GraphTraceLen
; i
++) {
1784 if(GraphBuffer
[i
+1] < GraphBuffer
[i
]) {
1786 GraphBuffer
[i
]= max
;
1791 if(GraphBuffer
[i
+1] > GraphBuffer
[i
]) {
1793 GraphBuffer
[i
]= min
;
1800 RepaintGraphWindow();
1803 static void CmdDec(char *str
)
1806 for(i
= 0; i
< (GraphTraceLen
/2); i
++) {
1807 GraphBuffer
[i
] = GraphBuffer
[i
*2];
1810 PrintToScrollback("decimated by 2");
1811 RepaintGraphWindow();
1814 static void CmdHpf(char *str
)
1818 for(i
= 10; i
< GraphTraceLen
; i
++) {
1819 accum
+= GraphBuffer
[i
];
1821 accum
/= (GraphTraceLen
- 10);
1822 for(i
= 0; i
< GraphTraceLen
; i
++) {
1823 GraphBuffer
[i
] -= accum
;
1826 RepaintGraphWindow();
1829 static void CmdZerocrossings(char *str
)
1832 // Zero-crossings aren't meaningful unless the signal is zero-mean.
1838 for(i
= 0; i
< GraphTraceLen
; i
++) {
1839 if(GraphBuffer
[i
]*sign
>= 0) {
1840 // No change in sign, reproduce the previous sample count.
1842 GraphBuffer
[i
] = lastZc
;
1844 // Change in sign, reset the sample count.
1846 GraphBuffer
[i
] = lastZc
;
1854 RepaintGraphWindow();
1857 static void CmdThreshold(char *str
)
1860 int threshold
= atoi(str
);
1862 for(i
= 0; i
< GraphTraceLen
; i
++) {
1863 if(GraphBuffer
[i
]>= threshold
)
1868 RepaintGraphWindow();
1871 static void CmdLtrim(char *str
)
1876 for(i
= ds
; i
< GraphTraceLen
; i
++) {
1877 GraphBuffer
[i
-ds
] = GraphBuffer
[i
];
1879 GraphTraceLen
-= ds
;
1881 RepaintGraphWindow();
1884 static void CmdAutoCorr(char *str
)
1886 static int CorrelBuffer
[MAX_GRAPH_TRACE_LEN
];
1888 int window
= atoi(str
);
1891 PrintToScrollback("needs a window");
1895 if(window
>= GraphTraceLen
) {
1896 PrintToScrollback("window must be smaller than trace (%d samples)",
1901 PrintToScrollback("performing %d correlations", GraphTraceLen
- window
);
1904 for(i
= 0; i
< GraphTraceLen
- window
; i
++) {
1907 for(j
= 0; j
< window
; j
++) {
1908 sum
+= (GraphBuffer
[j
]*GraphBuffer
[i
+j
]) / 256;
1910 CorrelBuffer
[i
] = sum
;
1912 GraphTraceLen
= GraphTraceLen
- window
;
1913 memcpy(GraphBuffer
, CorrelBuffer
, GraphTraceLen
*sizeof(int));
1915 RepaintGraphWindow();
1918 static void CmdVchdemod(char *str
)
1920 // Is this the entire sync pattern, or does this also include some
1921 // data bits that happen to be the same everywhere? That would be
1923 static const int SyncPattern
[] = {
1924 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
1925 1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
1926 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
1927 1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
1928 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
1929 1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
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,
1936 // So first, we correlate for the sync pattern, and mark that.
1937 int bestCorrel
= 0, bestPos
= 0;
1939 // It does us no good to find the sync pattern, with fewer than
1940 // 2048 samples after it...
1941 for(i
= 0; i
< (GraphTraceLen
-2048); i
++) {
1944 for(j
= 0; j
< arraylen(SyncPattern
); j
++) {
1945 sum
+= GraphBuffer
[i
+j
]*SyncPattern
[j
];
1947 if(sum
> bestCorrel
) {
1952 PrintToScrollback("best sync at %d [metric %d]", bestPos
, bestCorrel
);
1957 int worst
= INT_MAX
;
1960 for(i
= 0; i
< 2048; i
+= 8) {
1963 for(j
= 0; j
< 8; j
++) {
1964 sum
+= GraphBuffer
[bestPos
+i
+j
];
1971 if(abs(sum
) < worst
) {
1976 PrintToScrollback("bits:");
1977 PrintToScrollback("%s", bits
);
1978 PrintToScrollback("worst metric: %d at pos %d", worst
, worstPos
);
1980 if(strcmp(str
, "clone")==0) {
1983 for(s
= bits
; *s
; s
++) {
1985 for(j
= 0; j
< 16; j
++) {
1986 GraphBuffer
[GraphTraceLen
++] = (*s
== '1') ? 1 : 0;
1989 RepaintGraphWindow();
1993 static void CmdIndalademod(char *str
)
1995 // Usage: recover 64bit UID by default, specify "224" as arg to recover a 224bit UID
2000 // worst case with GraphTraceLen=64000 is < 4096
2001 // under normal conditions it's < 2048
2002 uint8_t rawbits
[4096];
2004 int worst
= 0, worstPos
= 0;
2005 PrintToScrollback("Expecting a bit less than %d raw bits", GraphTraceLen
/32);
2006 for(i
= 0; i
< GraphTraceLen
-1; i
+= 2) {
2008 if((GraphBuffer
[i
] > GraphBuffer
[i
+ 1]) && (state
!= 1)) {
2010 for(j
= 0; j
< count
- 8; j
+= 16) {
2011 rawbits
[rawbit
++] = 0;
2013 if ((abs(count
- j
)) > worst
) {
2014 worst
= abs(count
- j
);
2020 } else if((GraphBuffer
[i
] < GraphBuffer
[i
+ 1]) && (state
!= 0)) {
2022 for(j
= 0; j
< count
- 8; j
+= 16) {
2023 rawbits
[rawbit
++] = 1;
2025 if ((abs(count
- j
)) > worst
) {
2026 worst
= abs(count
- j
);
2034 PrintToScrollback("Recovered %d raw bits", rawbit
);
2035 PrintToScrollback("worst metric (0=best..7=worst): %d at pos %d", worst
, worstPos
);
2037 // Finding the start of a UID
2038 int uidlen
, long_wait
;
2039 if(strcmp(str
, "224") == 0) {
2048 for(start
= 0; start
<= rawbit
- uidlen
; start
++) {
2049 first
= rawbits
[start
];
2050 for(i
= start
; i
< start
+ long_wait
; i
++) {
2051 if(rawbits
[i
] != first
) {
2055 if(i
== (start
+ long_wait
)) {
2059 if(start
== rawbit
- uidlen
+ 1) {
2060 PrintToScrollback("nothing to wait for");
2064 // Inverting signal if needed
2066 for(i
= start
; i
< rawbit
; i
++) {
2067 rawbits
[i
] = !rawbits
[i
];
2074 showbits
[uidlen
]='\0';
2078 if(uidlen
> rawbit
) {
2079 PrintToScrollback("Warning: not enough raw bits to get a full UID");
2080 for(bit
= 0; bit
< rawbit
; bit
++) {
2081 bits
[bit
] = rawbits
[i
++];
2082 // As we cannot know the parity, let's use "." and "/"
2083 showbits
[bit
] = '.' + bits
[bit
];
2085 showbits
[bit
+1]='\0';
2086 PrintToScrollback("Partial UID=%s", showbits
);
2089 for(bit
= 0; bit
< uidlen
; bit
++) {
2090 bits
[bit
] = rawbits
[i
++];
2091 showbits
[bit
] = '0' + bits
[bit
];
2095 PrintToScrollback("UID=%s", showbits
);
2097 // Checking UID against next occurences
2098 for(; i
+ uidlen
<= rawbit
;) {
2100 for(bit
= 0; bit
< uidlen
; bit
++) {
2101 if(bits
[bit
] != rawbits
[i
++]) {
2111 PrintToScrollback("Occurences: %d (expected %d)", times
, (rawbit
- start
) / uidlen
);
2113 // Remodulating for tag cloning
2114 GraphTraceLen
= 32*uidlen
;
2117 for(bit
= 0; bit
< uidlen
; bit
++) {
2118 if(bits
[bit
] == 0) {
2124 for(j
= 0; j
< 32; j
++) {
2125 GraphBuffer
[i
++] = phase
;
2130 RepaintGraphWindow();
2133 static void CmdFlexdemod(char *str
)
2136 for(i
= 0; i
< GraphTraceLen
; i
++) {
2137 if(GraphBuffer
[i
] < 0) {
2138 GraphBuffer
[i
] = -1;
2144 #define LONG_WAIT 100
2146 for(start
= 0; start
< GraphTraceLen
- LONG_WAIT
; start
++) {
2147 int first
= GraphBuffer
[start
];
2148 for(i
= start
; i
< start
+ LONG_WAIT
; i
++) {
2149 if(GraphBuffer
[i
] != first
) {
2153 if(i
== (start
+ LONG_WAIT
)) {
2157 if(start
== GraphTraceLen
- LONG_WAIT
) {
2158 PrintToScrollback("nothing to wait for");
2162 GraphBuffer
[start
] = 2;
2163 GraphBuffer
[start
+1] = -2;
2169 for(bit
= 0; bit
< 64; bit
++) {
2172 for(j
= 0; j
< 16; j
++) {
2173 sum
+= GraphBuffer
[i
++];
2180 PrintToScrollback("bit %d sum %d", bit
, sum
);
2183 for(bit
= 0; bit
< 64; bit
++) {
2186 for(j
= 0; j
< 16; j
++) {
2187 sum
+= GraphBuffer
[i
++];
2189 if(sum
> 0 && bits
[bit
] != 1) {
2190 PrintToScrollback("oops1 at %d", bit
);
2192 if(sum
< 0 && bits
[bit
] != 0) {
2193 PrintToScrollback("oops2 at %d", bit
);
2197 GraphTraceLen
= 32*64;
2200 for(bit
= 0; bit
< 64; bit
++) {
2201 if(bits
[bit
] == 0) {
2207 for(j
= 0; j
< 32; j
++) {
2208 GraphBuffer
[i
++] = phase
;
2213 RepaintGraphWindow();
2217 * Generic command to demodulate ASK.
2219 * Argument is convention: positive or negative (High mod means zero
2220 * or high mod means one)
2222 * Updates the Graph trace with 0/1 values
2228 static void Cmdaskdemod(char *str
) {
2230 int c
, high
= 0, low
= 0;
2232 // TODO: complain if we do not give 2 arguments here !
2233 // (AL - this doesn't make sense! we're only using one argument!!!)
2234 sscanf(str
, "%i", &c
);
2236 /* Detect high and lows and clock */
2238 for (i
= 0; i
< GraphTraceLen
; i
++)
2240 if (GraphBuffer
[i
] > high
)
2241 high
= GraphBuffer
[i
];
2242 else if (GraphBuffer
[i
] < low
)
2243 low
= GraphBuffer
[i
];
2245 if(c
!= 0 && c
!= 1) {
2246 PrintToScrollback("Invalid argument: %s",str
);
2250 if (GraphBuffer
[0] > 0) {
2251 GraphBuffer
[0] = 1-c
;
2255 for(i
=1;i
<GraphTraceLen
;i
++) {
2256 /* Transitions are detected at each peak
2257 * Transitions are either:
2258 * - we're low: transition if we hit a high
2259 * - we're high: transition if we hit a low
2260 * (we need to do it this way because some tags keep high or
2261 * low for long periods, others just reach the peak and go
2264 if ((GraphBuffer
[i
]==high
) && (GraphBuffer
[i
-1] == c
)) {
2266 } else if ((GraphBuffer
[i
]==low
) && (GraphBuffer
[i
-1] == (1-c
))){
2270 GraphBuffer
[i
] = GraphBuffer
[i
-1];
2273 RepaintGraphWindow();
2276 /* Print our clock rate */
2277 static void Cmddetectclockrate(char *str
)
2279 int clock
= detectclock(0);
2280 PrintToScrollback("Auto-detected clock rate: %d", clock
);
2286 int detectclock(int peak
)
2292 /* Detect peak if we don't have one */
2294 for (i
= 0; i
< GraphTraceLen
; i
++)
2295 if (GraphBuffer
[i
] > peak
)
2296 peak
= GraphBuffer
[i
];
2298 for (i
= 1; i
< GraphTraceLen
; i
++)
2300 /* If this is the beginning of a peak */
2301 if (GraphBuffer
[i
-1] != GraphBuffer
[i
] && GraphBuffer
[i
] == peak
)
2303 /* Find lowest difference between peaks */
2304 if (lastpeak
&& i
- lastpeak
< clock
)
2306 clock
= i
- lastpeak
;
2315 /* Get or auto-detect clock rate */
2316 int GetClock(char *str
, int peak
)
2320 sscanf(str
, "%i", &clock
);
2321 if (!strcmp(str
, ""))
2324 /* Auto-detect clock */
2327 clock
= detectclock(peak
);
2329 /* Only print this message if we're not looping something */
2331 PrintToScrollback("Auto-detected clock rate: %d", clock
);
2338 * Convert to a bitstream
2340 static void Cmdbitstream(char *str
) {
2347 int hithigh
, hitlow
, first
;
2349 /* Detect high and lows and clock */
2350 for (i
= 0; i
< GraphTraceLen
; i
++)
2352 if (GraphBuffer
[i
] > high
)
2353 high
= GraphBuffer
[i
];
2354 else if (GraphBuffer
[i
] < low
)
2355 low
= GraphBuffer
[i
];
2359 clock
= GetClock(str
, high
);
2361 gtl
= CmdClearGraph(0);
2364 for (i
= 0; i
< (int)(gtl
/ clock
); i
++)
2370 /* Find out if we hit both high and low peaks */
2371 for (j
= 0; j
< clock
; j
++)
2373 if (GraphBuffer
[(i
* clock
) + j
] == high
)
2375 else if (GraphBuffer
[(i
* clock
) + j
] == low
)
2378 /* it doesn't count if it's the first part of our read
2379 because it's really just trailing from the last sequence */
2380 if (first
&& (hithigh
|| hitlow
))
2381 hithigh
= hitlow
= 0;
2385 if (hithigh
&& hitlow
)
2389 /* If we didn't hit both high and low peaks, we had a bit transition */
2390 if (!hithigh
|| !hitlow
)
2393 CmdAppendGraph(0, clock
, bit
);
2394 // for (j = 0; j < (int)(clock/2); j++)
2395 // GraphBuffer[(i * clock) + j] = bit ^ 1;
2396 // for (j = (int)(clock/2); j < clock; j++)
2397 // GraphBuffer[(i * clock) + j] = bit;
2400 RepaintGraphWindow();
2403 /* Modulate our data into manchester */
2404 static void Cmdmanchestermod(char *str
)
2408 int bit
, lastbit
, wave
;
2411 clock
= GetClock(str
, 0);
2415 for (i
= 0; i
< (int)(GraphTraceLen
/ clock
); i
++)
2417 bit
= GraphBuffer
[i
* clock
] ^ 1;
2419 for (j
= 0; j
< (int)(clock
/2); j
++)
2420 GraphBuffer
[(i
* clock
) + j
] = bit
^ lastbit
^ wave
;
2421 for (j
= (int)(clock
/2); j
< clock
; j
++)
2422 GraphBuffer
[(i
* clock
) + j
] = bit
^ lastbit
^ wave
^ 1;
2424 /* Keep track of how we start our wave and if we changed or not this time */
2425 wave
^= bit
^ lastbit
;
2429 RepaintGraphWindow();
2433 * Manchester demodulate a bitstream. The bitstream needs to be already in
2434 * the GraphBuffer as 0 and 1 values
2436 * Give the clock rate as argument in order to help the sync - the algorithm
2437 * resyncs at each pulse anyway.
2439 * Not optimized by any means, this is the 1st time I'm writing this type of
2440 * routine, feel free to improve...
2442 * 1st argument: clock rate (as number of samples per clock rate)
2443 * Typical values can be 64, 32, 128...
2445 static void Cmdmanchesterdemod(char *str
) {
2446 int i
, j
, invert
= 0;
2452 int hithigh
, hitlow
, first
;
2458 /* check if we're inverting output */
2461 PrintToScrollback("Inverting output");
2465 while(*str
== ' '); // in case a 2nd argument was given
2468 /* Holds the decoded bitstream: each clock period contains 2 bits */
2469 /* later simplified to 1 bit after manchester decoding. */
2470 /* Add 10 bits to allow for noisy / uncertain traces without aborting */
2471 /* int BitStream[GraphTraceLen*2/clock+10]; */
2473 /* But it does not work if compiling on WIndows: therefore we just allocate a */
2475 int BitStream
[MAX_GRAPH_TRACE_LEN
];
2477 /* Detect high and lows */
2478 for (i
= 0; i
< GraphTraceLen
; i
++)
2480 if (GraphBuffer
[i
] > high
)
2481 high
= GraphBuffer
[i
];
2482 else if (GraphBuffer
[i
] < low
)
2483 low
= GraphBuffer
[i
];
2487 clock
= GetClock(str
, high
);
2489 int tolerance
= clock
/4;
2491 /* Detect first transition */
2492 /* Lo-Hi (arbitrary) */
2493 /* skip to the first high */
2494 for (i
= 0; i
< GraphTraceLen
; i
++)
2495 if(GraphBuffer
[i
] == high
)
2497 /* now look for the first low */
2498 for (; i
< GraphTraceLen
; i
++)
2500 if (GraphBuffer
[i
] == low
)
2507 /* If we're not working with 1/0s, demod based off clock */
2510 bit
= 0; /* We assume the 1st bit is zero, it may not be
2511 * the case: this routine (I think) has an init problem.
2514 for (; i
< (int)(GraphTraceLen
/ clock
); i
++)
2520 /* Find out if we hit both high and low peaks */
2521 for (j
= 0; j
< clock
; j
++)
2523 if (GraphBuffer
[(i
* clock
) + j
] == high
)
2525 else if (GraphBuffer
[(i
* clock
) + j
] == low
)
2528 /* it doesn't count if it's the first part of our read
2529 because it's really just trailing from the last sequence */
2530 if (first
&& (hithigh
|| hitlow
))
2531 hithigh
= hitlow
= 0;
2535 if (hithigh
&& hitlow
)
2539 /* If we didn't hit both high and low peaks, we had a bit transition */
2540 if (!hithigh
|| !hitlow
)
2543 BitStream
[bit2idx
++] = bit
^ invert
;
2547 /* standard 1/0 bitstream */
2551 /* Then detect duration between 2 successive transitions */
2552 for (bitidx
= 1; i
< GraphTraceLen
; i
++)
2554 if (GraphBuffer
[i
-1] != GraphBuffer
[i
])
2559 // Error check: if bitidx becomes too large, we do not
2560 // have a Manchester encoded bitstream or the clock is really
2562 if (bitidx
> (GraphTraceLen
*2/clock
+8) ) {
2563 PrintToScrollback("Error: the clock you gave is probably wrong, aborting.");
2566 // Then switch depending on lc length:
2567 // Tolerance is 1/4 of clock rate (arbitrary)
2568 if (abs(lc
-clock
/2) < tolerance
) {
2569 // Short pulse : either "1" or "0"
2570 BitStream
[bitidx
++]=GraphBuffer
[i
-1];
2571 } else if (abs(lc
-clock
) < tolerance
) {
2572 // Long pulse: either "11" or "00"
2573 BitStream
[bitidx
++]=GraphBuffer
[i
-1];
2574 BitStream
[bitidx
++]=GraphBuffer
[i
-1];
2578 PrintToScrollback("Warning: Manchester decode error for pulse width detection.");
2579 PrintToScrollback("(too many of those messages mean either the stream is not Manchester encoded, or clock is wrong)");
2583 PrintToScrollback("Error: too many detection errors, aborting.");
2590 // At this stage, we now have a bitstream of "01" ("1") or "10" ("0"), parse it into final decoded bitstream
2591 // Actually, we overwrite BitStream with the new decoded bitstream, we just need to be careful
2592 // to stop output at the final bitidx2 value, not bitidx
2593 for (i
= 0; i
< bitidx
; i
+= 2) {
2594 if ((BitStream
[i
] == 0) && (BitStream
[i
+1] == 1)) {
2595 BitStream
[bit2idx
++] = 1 ^ invert
;
2596 } else if ((BitStream
[i
] == 1) && (BitStream
[i
+1] == 0)) {
2597 BitStream
[bit2idx
++] = 0 ^ invert
;
2599 // We cannot end up in this state, this means we are unsynchronized,
2603 PrintToScrollback("Unsynchronized, resync...");
2604 PrintToScrollback("(too many of those messages mean the stream is not Manchester encoded)");
2608 PrintToScrollback("Error: too many decode errors, aborting.");
2615 PrintToScrollback("Manchester decoded bitstream");
2616 // Now output the bitstream to the scrollback by line of 16 bits
2617 for (i
= 0; i
< (bit2idx
-16); i
+=16) {
2618 PrintToScrollback("%i %i %i %i %i %i %i %i %i %i %i %i %i %i %i %i",
2641 static void CmdHiddemod(char *str
)
2643 if(GraphTraceLen
< 4800) {
2644 PrintToScrollback("too short; need at least 4800 samples");
2648 GraphTraceLen
= 4800;
2650 for(i
= 0; i
< GraphTraceLen
; i
++) {
2651 if(GraphBuffer
[i
] < 0) {
2657 RepaintGraphWindow();
2660 static void CmdPlot(char *str
)
2665 static void CmdGrid(char *str
)
2667 sscanf(str
, "%i %i", &PlotGridX
, &PlotGridY
);
2668 RepaintGraphWindow();
2671 static void CmdHide(char *str
)
2676 static void CmdScale(char *str
)
2678 CursorScaleFactor
= atoi(str
);
2679 if(CursorScaleFactor
== 0) {
2680 PrintToScrollback("bad, can't have zero scale");
2681 CursorScaleFactor
= 1;
2683 RepaintGraphWindow();
2686 static void CmdSave(char *str
)
2688 FILE *f
= fopen(str
, "w");
2690 PrintToScrollback("couldn't open '%s'", str
);
2694 for(i
= 0; i
< GraphTraceLen
; i
++) {
2695 fprintf(f
, "%d\n", GraphBuffer
[i
]);
2698 PrintToScrollback("saved to '%s'", str
);
2701 static void CmdLoad(char *str
)
2703 FILE *f
= fopen(str
, "r");
2705 PrintToScrollback("couldn't open '%s'", str
);
2711 while(fgets(line
, sizeof(line
), f
)) {
2712 GraphBuffer
[GraphTraceLen
] = atoi(line
);
2716 PrintToScrollback("loaded %d samples", GraphTraceLen
);
2717 RepaintGraphWindow();
2720 static void CmdHIDsimTAG(char *str
)
2722 unsigned int hi
=0, lo
=0;
2725 while (sscanf(&str
[i
++], "%1x", &n
) == 1) {
2726 hi
=(hi
<<4)|(lo
>>28);
2730 PrintToScrollback("Emulating tag with ID %x%16x", hi
, lo
);
2732 UsbCommand c
={CMD_HID_SIM_TAG
, {hi
, lo
, 0}};
2736 static void CmdReadmem(char *str
)
2738 UsbCommand c
={CMD_READ_MEM
, {strtol(str
, NULL
, 0), 0, 0}};
2742 static void CmdVersion(char *str
)
2744 UsbCommand c
={CMD_VERSION
};
2748 static void CmdLcdReset(char *str
)
2750 UsbCommand c
={CMD_LCD_RESET
, {strtol(str
, NULL
, 0), 0, 0}};
2754 static void CmdLcd(char *str
)
2757 UsbCommand c
={CMD_LCD
};
2758 sscanf(str
, "%x %d", &i
, &j
);
2766 * Sets the divisor for LF frequency clock: lets the user choose any LF frequency below
2769 static void CmdSetDivisor(char *str
)
2771 UsbCommand c
={CMD_SET_LF_DIVISOR
, {strtol(str
, NULL
, 0), 0, 0}};
2772 if (( c
.arg
[0]<0) || (c
.arg
[0]>255)) {
2773 PrintToScrollback("divisor must be between 19 and 255");
2776 PrintToScrollback("Divisor set, expected freq=%dHz", 12000000/(c
.arg
[0]+1));
2780 static void CmdSetMux(char *str
)
2782 UsbCommand c
={CMD_SET_ADC_MUX
};
2783 if(strcmp(str
, "lopkd") == 0) {
2785 } else if(strcmp(str
, "loraw") == 0) {
2787 } else if(strcmp(str
, "hipkd") == 0) {
2789 } else if(strcmp(str
, "hiraw") == 0) {
2795 typedef void HandlerFunction(char *cmdline
);
2797 /* in alphabetic order */
2800 HandlerFunction
*handler
;
2801 int offline
; // 1 if the command can be used when in offline mode
2803 } CommandTable
[] = {
2804 {"amp", CmdAmp
, 1, "Amplify peaks"},
2805 {"askdemod", Cmdaskdemod
, 1, "<0|1> -- Attempt to demodulate simple ASK tags"},
2806 {"autocorr", CmdAutoCorr
, 1, "<window length> -- Autocorrelation over window"},
2807 {"bitsamples", CmdBitsamples
, 0, "Get raw samples as bitstring"},
2808 {"bitstream", Cmdbitstream
, 1, "[clock rate] -- Convert waveform into a bitstream"},
2809 {"buffclear", CmdBuffClear
, 1, "Clear sample buffer and graph window"},
2810 {"dec", CmdDec
, 1, "Decimate samples"},
2811 {"detectclock", Cmddetectclockrate
, 1, "Detect clock rate"},
2812 {"detectreader", CmdDetectReader
, 0, "['l'|'h'] -- Detect external reader field (option 'l' or 'h' to limit to LF or HF)"},
2813 {"em410xsim", CmdEM410xsim
, 1, "<UID> -- Simulate EM410x tag"},
2814 {"em410xread", CmdEM410xread
, 1, "[clock rate] -- Extract ID from EM410x tag"},
2815 {"em410xwatch", CmdEM410xwatch
, 0, "Watches for EM410x tags"},
2816 {"em4x50read", CmdEM4x50read
, 1, "Extract data from EM4x50 tag"},
2817 {"exit", CmdQuit
, 1, "Exit program"},
2818 {"flexdemod", CmdFlexdemod
, 1, "Demodulate samples for FlexPass"},
2819 {"fpgaoff", CmdFPGAOff
, 0, "Set FPGA off"},
2820 {"fskdemod", CmdFSKdemod
, 1, "Demodulate graph window as a HID FSK"},
2821 {"grid", CmdGrid
, 1, "<x> <y> -- overlay grid on graph window, use zero value to turn off either"},
2822 {"hexsamples", CmdHexsamples
, 0, "<blocks> -- Dump big buffer as hex bytes"},
2823 {"hi14alist", CmdHi14alist
, 0, "List ISO 14443a history"},
2824 {"hi14amifare", CmdHi14amifare
, 0, "Read out sector 0 parity error messages"},
2825 {"hi14areader", CmdHi14areader
, 0, "Act like an ISO14443 Type A reader"},
2826 {"hi14asim", CmdHi14asim
, 0, "<UID> -- Fake ISO 14443a tag"},
2827 {"hi14asnoop", CmdHi14asnoop
, 0, "Eavesdrop ISO 14443 Type A"},
2828 {"hi14bdemod", CmdHi14bdemod
, 1, "Demodulate ISO14443 Type B from tag"},
2829 {"hi14list", CmdHi14list
, 0, "List ISO 14443 history"},
2830 {"hi14read", CmdHi14read
, 0, "Read HF tag (ISO 14443)"},
2831 {"hi14sim", CmdHi14sim
, 0, "Fake ISO 14443 tag"},
2832 {"hi14snoop", CmdHi14snoop
, 0, "Eavesdrop ISO 14443"},
2833 {"hi15demod", CmdHi15demod
, 1, "Demodulate ISO15693 from tag"},
2834 {"hi15read", CmdHi15read
, 0, "Read HF tag (ISO 15693)"},
2835 {"hi15reader", CmdHi15reader
, 0, "Act like an ISO15693 reader"},
2836 {"hi15sim", CmdHi15tag
, 0, "Fake an ISO15693 tag"},
2837 {"hiddemod", CmdHiddemod
, 1, "Demodulate HID Prox Card II (not optimal)"},
2838 {"hide", CmdHide
, 1, "Hide graph window"},
2839 {"hidfskdemod", CmdHIDdemodFSK
, 0, "Realtime HID FSK demodulator"},
2840 {"hidsimtag", CmdHIDsimTAG
, 0, "<ID> -- HID tag simulator"},
2841 {"higet", CmdHi14read_sim
, 0, "<samples> -- Get samples HF, 'analog'"},
2842 {"hisamples", CmdHisamples
, 0, "Get raw samples for HF tag"},
2843 {"hisampless", CmdHisampless
, 0, "<samples> -- Get signed raw samples, HF tag"},
2844 {"hisamplest", CmdHi14readt
, 0, "Get samples HF, for testing"},
2845 {"hisimlisten", CmdHisimlisten
, 0, "Get HF samples as fake tag"},
2846 {"hpf", CmdHpf
, 1, "Remove DC offset from trace"},
2847 {"indalademod", CmdIndalademod
, 0, "['224'] -- Demodulate samples for Indala 64 bit UID (option '224' for 224 bit)"},
2848 {"lcd", CmdLcd
, 0, "<HEX command> <count> -- Send command/data to LCD"},
2849 {"lcdreset", CmdLcdReset
, 0, "Hardware reset LCD"},
2850 {"legicrfread", CmdLegicRfRead
, 0, "Start the LEGIC RF reader"},
2851 {"load", CmdLoad
, 1, "<filename> -- Load trace (to graph window"},
2852 {"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)"},
2853 {"loread", CmdLoread
, 0, "['h'] -- Read 125/134 kHz LF ID-only tag (option 'h' for 134)"},
2854 {"losamples", CmdLosamples
, 0, "[128 - 16000] -- Get raw samples for LF tag"},
2855 {"losim", CmdLosim
, 0, "Simulate LF tag"},
2856 {"losimbidir", CmdLosimBidir
, 0, "Simulate LF tag (with bidirectional data transmission between reader and tag)"},
2857 {"ltrim", CmdLtrim
, 1, "<samples> -- Trim samples from left of trace"},
2858 {"mandemod", Cmdmanchesterdemod
, 1, "[i] [clock rate] -- Manchester demodulate binary stream (option 'i' to invert output)"},
2859 {"manmod", Cmdmanchestermod
, 1, "[clock rate] -- Manchester modulate a binary stream"},
2860 {"norm", CmdNorm
, 1, "Normalize max/min to +/-500"},
2861 {"plot", CmdPlot
, 1, "Show graph window"},
2862 {"quit", CmdQuit
, 1, "Quit program"},
2863 {"readmem", CmdReadmem
, 0, "[address] -- Read memory at decimal address from flash"},
2864 {"reset", CmdReset
, 0, "Reset the Proxmark3"},
2865 {"save", CmdSave
, 1, "<filename> -- Save trace (from graph window)"},
2866 {"scale", CmdScale
, 1, "<int> -- Set cursor display scale"},
2867 {"setlfdivisor", CmdSetDivisor
, 0, "<19 - 255> -- Drive LF antenna at 12Mhz/(divisor+1)"},
2868 {"setmux", CmdSetMux
, 0, "<loraw|hiraw|lopkd|hipkd> -- Set the ADC mux to a specific value"},
2869 {"sri512read", CmdSri512read
, 0, "<int> -- Read contents of a SRI512 tag"},
2870 {"srix4kread", CmdSrix4kread
, 0, "<int> -- Read contents of a SRIX4K tag"},
2871 {"tidemod", CmdTIDemod
, 1, "Demodulate raw bits for TI-type LF tag"},
2872 {"tiread", CmdTIRead
, 0, "Read and decode a TI 134 kHz tag"},
2873 {"tiwrite", CmdTIWrite
, 0, "Write new data to a r/w TI 134 kHz tag"},
2874 {"threshold", CmdThreshold
, 1, "Maximize/minimize every value in the graph window depending on threshold"},
2875 {"tune", CmdTune
, 0, "Measure antenna tuning"},
2876 {"vchdemod", CmdVchdemod
, 0, "['clone'] -- Demodulate samples for VeriChip"},
2877 {"version", CmdVersion
, 0, "Show version inforation about the connected Proxmark"},
2878 {"zerocrossings", CmdZerocrossings
, 1, "Count time between zero-crossings"},
2886 } CommandExtendedHelp
[]= {
2887 {"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."},
2888 {"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."},
2891 //-----------------------------------------------------------------------------
2892 // Entry point into our code: called whenever the user types a command and
2893 // then presses Enter, which the full command line that they typed.
2894 //-----------------------------------------------------------------------------
2895 void CommandReceived(char *cmd
)
2900 PrintToScrollback("> %s", cmd
);
2902 if(strcmp(cmd
, "help") == 0 || strncmp(cmd
,"help ",strlen("help ")) == 0) {
2903 // check if we're doing extended help
2904 if(strlen(cmd
) > strlen("help ")) {
2905 cmd
+= strlen("help ");
2906 for(i
= 0; i
< sizeof(CommandExtendedHelp
) / sizeof(CommandExtendedHelp
[0]); i
++) {
2907 if(strcmp(CommandExtendedHelp
[i
].name
,cmd
) == 0) {
2908 PrintToScrollback("\nExtended help for '%s':\n", cmd
);
2909 PrintToScrollback("Args: %s\t- %s\n",CommandExtendedHelp
[i
].args
,CommandExtendedHelp
[i
].argshelp
);
2910 PrintToScrollback(CommandExtendedHelp
[i
].description
);
2911 PrintToScrollback("");
2915 PrintToScrollback("No extended help available for '%s'", cmd
);
2918 if (offline
) PrintToScrollback("Operating in OFFLINE mode (no device connected)");
2919 PrintToScrollback("\r\nAvailable commands:");
2920 for(i
= 0; i
< sizeof(CommandTable
) / sizeof(CommandTable
[0]); i
++) {
2921 if (offline
&& (CommandTable
[i
].offline
==0)) continue;
2922 memset(line
, ' ', sizeof(line
));
2923 strcpy(line
+2, CommandTable
[i
].name
);
2924 line
[strlen(line
)] = ' ';
2925 sprintf(line
+15, " -- %s", CommandTable
[i
].docString
);
2926 PrintToScrollback("%s", line
);
2928 PrintToScrollback("");
2929 PrintToScrollback("'help <command>' for extended help on that command\n");
2933 for(i
= 0; i
< sizeof(CommandTable
) / sizeof(CommandTable
[0]); i
++) {
2934 char *name
= CommandTable
[i
].name
;
2935 if(memcmp(cmd
, name
, strlen(name
))==0 &&
2936 (cmd
[strlen(name
)] == ' ' || cmd
[strlen(name
)] == '\0'))
2938 cmd
+= strlen(name
);
2939 while(*cmd
== ' ') {
2942 if (offline
&& (CommandTable
[i
].offline
==0)) {
2943 PrintToScrollback("Offline mode, cannot use this command.");
2946 (CommandTable
[i
].handler
)(cmd
);
2950 PrintToScrollback(">> bad command '%s'", cmd
);
2953 //-----------------------------------------------------------------------------
2954 // Entry point into our code: called whenever we received a packet over USB
2955 // that we weren't necessarily expecting, for example a debug print.
2956 //-----------------------------------------------------------------------------
2957 void UsbCommandReceived(UsbCommand
*c
)
2959 // printf("%s(%x) current cmd = %x\n", __FUNCTION__, c->cmd, current_command);
2960 /* If we recognize a response, return to avoid further processing */
2962 case CMD_DEBUG_PRINT_STRING
: {
2964 if(c
->arg
[0] > 70 || c
->arg
[0] < 0) {
2967 memcpy(s
, c
->d
.asBytes
, c
->arg
[0]);
2968 s
[c
->arg
[0]] = '\0';
2969 PrintToScrollback("#db# %s", s
);
2973 case CMD_DEBUG_PRINT_INTEGERS
:
2974 PrintToScrollback("#db# %08x, %08x, %08x\r\n", c
->arg
[0], c
->arg
[1], c
->arg
[2]);
2977 case CMD_MEASURED_ANTENNA_TUNING
: {
2979 int vLf125
, vLf134
, vHf
;
2980 vLf125
= c
->arg
[0] & 0xffff;
2981 vLf134
= c
->arg
[0] >> 16;
2982 vHf
= c
->arg
[1] & 0xffff;;
2983 peakf
= c
->arg
[2] & 0xffff;
2984 peakv
= c
->arg
[2] >> 16;
2985 PrintToScrollback("");
2986 PrintToScrollback("");
2987 PrintToScrollback("# LF antenna: %5.2f V @ 125.00 kHz", vLf125
/1000.0);
2988 PrintToScrollback("# LF antenna: %5.2f V @ 134.00 kHz", vLf134
/1000.0);
2989 PrintToScrollback("# LF optimal: %5.2f V @%9.2f kHz", peakv
/1000.0, 12000.0/(peakf
+1));
2990 PrintToScrollback("# HF antenna: %5.2f V @ 13.56 MHz", vHf
/1000.0);
2992 PrintToScrollback("# Your LF antenna is unusable.");
2993 else if (peakv
<10000)
2994 PrintToScrollback("# Your LF antenna is marginal.");
2996 PrintToScrollback("# Your HF antenna is unusable.");
2998 PrintToScrollback("# Your HF antenna is marginal.");
3004 /* Maybe it's a response: */
3005 switch(current_command
) {
3006 case CMD_DOWNLOAD_RAW_ADC_SAMPLES_125K
:
3007 if (c
->cmd
!= CMD_DOWNLOADED_RAW_ADC_SAMPLES_125K
) goto unexpected_response
;
3009 for(i
=0; i
<48; i
++) sample_buf
[i
] = c
->d
.asBytes
[i
];
3010 received_command
= c
->cmd
;
3013 unexpected_response
:
3014 PrintToScrollback("unrecognized command %08x\n", c
->cmd
);