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 //-----------------------------------------------------------------------------
14 #include "../common/iso14443_crc.c"
16 #define arraylen(x) (sizeof(x)/sizeof((x)[0]))
17 #define BIT(x) GraphBuffer[x * clock]
18 #define BITS (GraphTraceLen / clock)
21 static int CmdHisamplest(char *str
, int nrlow
);
23 static void GetFromBigBuf(BYTE
*dest
, int bytes
)
28 PrintToScrollback("bad len in GetFromBigBuf");
33 for(i
= 0; i
< n
; i
+= 12) {
35 c
.cmd
= CMD_DOWNLOAD_RAW_ADC_SAMPLES_125K
;
37 SendCommand(&c
, FALSE
);
39 if(c
.cmd
!= CMD_DOWNLOADED_RAW_ADC_SAMPLES_125K
) {
40 PrintToScrollback("bad resp");
44 memcpy(dest
+(i
*4), c
.d
.asBytes
, 48);
48 static void CmdReset(char *str
)
51 c
.cmd
= CMD_HARDWARE_RESET
;
52 SendCommand(&c
, FALSE
);
55 static void CmdBuffClear(char *str
)
58 c
.cmd
= CMD_BUFF_CLEAR
;
59 SendCommand(&c
, FALSE
);
63 static void CmdQuit(char *str
)
68 static void CmdHIDdemodFSK(char *str
)
71 c
.cmd
= CMD_HID_DEMOD_FSK
;
72 SendCommand(&c
, FALSE
);
75 static void CmdTune(char *str
)
78 c
.cmd
= CMD_MEASURE_ANTENNA_TUNING
;
79 SendCommand(&c
, FALSE
);
82 static void CmdHi15read(char *str
)
85 c
.cmd
= CMD_ACQUIRE_RAW_ADC_SAMPLES_ISO_15693
;
86 SendCommand(&c
, FALSE
);
89 static void CmdHi14read(char *str
)
92 c
.cmd
= CMD_ACQUIRE_RAW_ADC_SAMPLES_ISO_14443
;
94 SendCommand(&c
, FALSE
);
98 /* New command to read the contents of a SRI512 tag
99 * SRI512 tags are ISO14443-B modulated memory tags,
100 * this command just dumps the contents of the memory/
102 static void CmdSri512read(char *str
)
105 c
.cmd
= CMD_READ_SRI512_TAG
;
107 SendCommand(&c
, FALSE
);
111 static void CmdHi14areader(char *str
)
114 c
.cmd
= CMD_READER_ISO_14443a
;
116 SendCommand(&c
, FALSE
);
120 static void CmdHi15reader(char *str
)
123 c
.cmd
= CMD_READER_ISO_15693
;
125 SendCommand(&c
, FALSE
);
129 static void CmdHi15tag(char *str
)
132 c
.cmd
= CMD_SIMTAG_ISO_15693
;
134 SendCommand(&c
, FALSE
);
137 static void CmdHi14read_sim(char *str
)
140 c
.cmd
= CMD_ACQUIRE_RAW_ADC_SAMPLES_ISO_14443_SIM
;
142 SendCommand(&c
, FALSE
);
145 static void CmdHi14readt(char *str
)
148 c
.cmd
= CMD_ACQUIRE_RAW_ADC_SAMPLES_ISO_14443
;
150 SendCommand(&c
, FALSE
);
152 //CmdHisamplest(str);
153 while(CmdHisamplest(str
,atoi(str
))==0) {
154 c
.cmd
= CMD_ACQUIRE_RAW_ADC_SAMPLES_ISO_14443
;
156 SendCommand(&c
, FALSE
);
158 RepaintGraphWindow();
161 static void CmdHisimlisten(char *str
)
164 c
.cmd
= CMD_SIMULATE_TAG_HF_LISTEN
;
165 SendCommand(&c
, FALSE
);
168 static void CmdHi14sim(char *str
)
171 c
.cmd
= CMD_SIMULATE_TAG_ISO_14443
;
172 SendCommand(&c
, FALSE
);
175 static void CmdHi14asim(char *str
) // ## simulate iso14443a tag
176 { // ## greg - added ability to specify tag UID
178 unsigned int hi
=0, lo
=0;
182 while (sscanf(&str
[i
++], "%1x", &n
) == 1) {
187 c
.cmd
= CMD_SIMULATE_TAG_ISO_14443a
;
188 // c.ext should be set to *str or convert *str to the correct format for a uid
191 PrintToScrollback("Emulating 14443A TAG with UID %x%16x", hi
, lo
);
192 SendCommand(&c
, FALSE
);
195 static void CmdHi14snoop(char *str
)
198 c
.cmd
= CMD_SNOOP_ISO_14443
;
199 SendCommand(&c
, FALSE
);
202 static void CmdHi14asnoop(char *str
)
205 c
.cmd
= CMD_SNOOP_ISO_14443a
;
206 SendCommand(&c
, FALSE
);
209 static void CmdFPGAOff(char *str
) // ## FPGA Control
212 c
.cmd
= CMD_FPGA_MAJOR_MODE_OFF
;
213 SendCommand(&c
, FALSE
);
216 /* clear out our graph window */
217 int CmdClearGraph(int redraw
)
219 int gtl
= GraphTraceLen
;
223 RepaintGraphWindow();
228 /* write a bit to the graph */
229 static void CmdAppendGraph(int redraw
, int clock
, int bit
)
233 for (i
= 0; i
< (int)(clock
/2); i
++)
234 GraphBuffer
[GraphTraceLen
++] = bit
^ 1;
236 for (i
= (int)(clock
/2); i
< clock
; i
++)
237 GraphBuffer
[GraphTraceLen
++] = bit
;
240 RepaintGraphWindow();
243 /* Function is equivalent of loread + losamples + em410xread
244 * looped until an EM410x tag is detected */
245 static void CmdEM410xwatch(char *str
)
259 /* Read the transmitted data of an EM4x50 tag
262 * XXXXXXXX [row parity bit (even)] <- 8 bits plus parity
263 * XXXXXXXX [row parity bit (even)] <- 8 bits plus parity
264 * XXXXXXXX [row parity bit (even)] <- 8 bits plus parity
265 * XXXXXXXX [row parity bit (even)] <- 8 bits plus parity
266 * CCCCCCCC <- column parity bits
268 * LW <- Listen Window
270 * This pattern repeats for every block of data being transmitted.
271 * Transmission starts with two Listen Windows (LW - a modulated
272 * pattern of 320 cycles each (32/32/128/64/64)).
274 * Note that this data may or may not be the UID. It is whatever data
275 * is stored in the blocks defined in the control word First and Last
276 * Word Read values. UID is stored in block 32.
278 static void CmdEM4x50read(char *str
)
280 int i
, j
, startblock
, clock
, skip
, block
, start
, end
, low
, high
;
281 BOOL complete
= FALSE
;
282 int tmpbuff
[MAX_GRAPH_TRACE_LEN
/ 64];
288 /* first get high and low values */
289 for (i
= 0; i
< GraphTraceLen
; i
++)
291 if (GraphBuffer
[i
] > high
)
292 high
= GraphBuffer
[i
];
293 else if (GraphBuffer
[i
] < low
)
294 low
= GraphBuffer
[i
];
297 /* populate a buffer with pulse lengths */
300 while(i
< GraphTraceLen
)
302 // measure from low to low
303 while(GraphBuffer
[i
] > low
)
306 while(GraphBuffer
[i
] < high
)
308 while(GraphBuffer
[i
] > low
)
310 tmpbuff
[j
++]= i
- start
;
314 /* look for data start - should be 2 pairs of LW (pulses of 192,128) */
317 for (i
= 0; i
< j
- 4 ; ++i
)
320 if (tmpbuff
[i
] >= 190 && tmpbuff
[i
] <= 194)
321 if (tmpbuff
[i
+1] >= 126 && tmpbuff
[i
+1] <= 130)
322 if (tmpbuff
[i
+2] >= 190 && tmpbuff
[i
+2] <= 194)
323 if (tmpbuff
[i
+3] >= 126 && tmpbuff
[i
+3] <= 130)
331 /* skip over the remainder of the LW */
332 skip
+= tmpbuff
[i
+1]+tmpbuff
[i
+2];
333 while(GraphBuffer
[skip
] > low
)
337 /* now do it again to find the end */
339 for (i
+= 3; i
< j
- 4 ; ++i
)
342 if (tmpbuff
[i
] >= 190 && tmpbuff
[i
] <= 194)
343 if (tmpbuff
[i
+1] >= 126 && tmpbuff
[i
+1] <= 130)
344 if (tmpbuff
[i
+2] >= 190 && tmpbuff
[i
+2] <= 194)
345 if (tmpbuff
[i
+3] >= 126 && tmpbuff
[i
+3] <= 130)
353 PrintToScrollback("Found data at sample: %i",skip
);
356 PrintToScrollback("No data found!");
357 PrintToScrollback("Try again with more samples.");
363 PrintToScrollback("*** Warning!");
364 PrintToScrollback("Partial data - no end found!");
365 PrintToScrollback("Try again with more samples.");
368 /* get rid of leading crap */
369 sprintf(tmp
,"%i",skip
);
372 /* now work through remaining buffer printing out data blocks */
377 PrintToScrollback("Block %i:", block
);
378 // mandemod routine needs to be split so we can call it for data
379 // just print for now for debugging
380 Cmdmanchesterdemod("i 64");
382 /* look for LW before start of next block */
383 for ( ; i
< j
- 4 ; ++i
)
386 if (tmpbuff
[i
] >= 190 && tmpbuff
[i
] <= 194)
387 if (tmpbuff
[i
+1] >= 126 && tmpbuff
[i
+1] <= 130)
390 while(GraphBuffer
[skip
] > low
)
393 sprintf(tmp
,"%i",skip
);
401 /* Read the ID of an EM410x tag.
403 * 1111 1111 1 <-- standard non-repeatable header
404 * XXXX [row parity bit] <-- 10 rows of 5 bits for our 40 bit tag ID
406 * CCCC <-- each bit here is parity for the 10 bits above in corresponding column
407 * 0 <-- stop bit, end of tag
409 static void CmdEM410xread(char *str
)
411 int i
, j
, clock
, header
, rows
, bit
, hithigh
, hitlow
, first
, bit2idx
, high
, low
;
415 int BitStream
[MAX_GRAPH_TRACE_LEN
];
418 /* Detect high and lows and clock */
419 for (i
= 0; i
< GraphTraceLen
; i
++)
421 if (GraphBuffer
[i
] > high
)
422 high
= GraphBuffer
[i
];
423 else if (GraphBuffer
[i
] < low
)
424 low
= GraphBuffer
[i
];
428 clock
= GetClock(str
, high
);
430 /* parity for our 4 columns */
431 parity
[0] = parity
[1] = parity
[2] = parity
[3] = 0;
434 /* manchester demodulate */
436 for (i
= 0; i
< (int)(GraphTraceLen
/ clock
); i
++)
442 /* Find out if we hit both high and low peaks */
443 for (j
= 0; j
< clock
; j
++)
445 if (GraphBuffer
[(i
* clock
) + j
] == high
)
447 else if (GraphBuffer
[(i
* clock
) + j
] == low
)
450 /* it doesn't count if it's the first part of our read
451 because it's really just trailing from the last sequence */
452 if (first
&& (hithigh
|| hitlow
))
453 hithigh
= hitlow
= 0;
457 if (hithigh
&& hitlow
)
461 /* If we didn't hit both high and low peaks, we had a bit transition */
462 if (!hithigh
|| !hitlow
)
465 BitStream
[bit2idx
++] = bit
;
469 /* We go till 5 before the graph ends because we'll get that far below */
470 for (i
= 1; i
< bit2idx
- 5; i
++)
472 /* Step 2: We have our header but need our tag ID */
473 if (header
== 9 && rows
< 10)
475 /* Confirm parity is correct */
476 if ((BitStream
[i
] ^ BitStream
[i
+1] ^ BitStream
[i
+2] ^ BitStream
[i
+3]) == BitStream
[i
+4])
478 /* Read another byte! */
479 sprintf(id
+rows
, "%x", (8 * BitStream
[i
]) + (4 * BitStream
[i
+1]) + (2 * BitStream
[i
+2]) + (1 * BitStream
[i
+3]));
482 /* Keep parity info */
483 parity
[0] ^= BitStream
[i
];
484 parity
[1] ^= BitStream
[i
+1];
485 parity
[2] ^= BitStream
[i
+2];
486 parity
[3] ^= BitStream
[i
+3];
488 /* Move 4 bits ahead */
492 /* Damn, something wrong! reset */
495 PrintToScrollback("Thought we had a valid tag but failed at word %d (i=%d)", rows
+ 1, i
);
497 /* Start back rows * 5 + 9 header bits, -1 to not start at same place */
498 i
-= 9 + (5 * rows
) - 5;
504 /* Step 3: Got our 40 bits! confirm column parity */
507 /* We need to make sure our 4 bits of parity are correct and we have a stop bit */
508 if (BitStream
[i
] == parity
[0] && BitStream
[i
+1] == parity
[1] &&
509 BitStream
[i
+2] == parity
[2] && BitStream
[i
+3] == parity
[3] &&
513 PrintToScrollback("EM410x Tag ID: %s", id
);
520 /* Crap! Incorrect parity or no stop bit, start all over */
525 /* Go back 59 bits (9 header bits + 10 rows at 4+1 parity) */
530 /* Step 1: get our header */
533 /* Need 9 consecutive 1's */
534 if (BitStream
[i
] == 1)
537 /* We don't have a header, not enough consecutive 1 bits */
543 /* if we've already retested after flipping bits, return */
547 /* if this didn't work, try flipping bits */
548 for (i
= 0; i
< bit2idx
; i
++)
554 /* emulate an EM410X tag
556 * 1111 1111 1 <-- standard non-repeatable header
557 * XXXX [row parity bit] <-- 10 rows of 5 bits for our 40 bit tag ID
559 * CCCC <-- each bit here is parity for the 10 bits above in corresponding column
560 * 0 <-- stop bit, end of tag
562 static void CmdEM410xsim(char *str
)
564 int i
, n
, j
, h
, binary
[4], parity
[4];
567 /* clock is 64 in EM410x tags */
570 /* clear our graph */
573 /* write it out a few times */
574 for (h
= 0; h
< 4; h
++)
576 /* write 9 start bits */
577 for (i
= 0; i
< 9; i
++)
578 CmdAppendGraph(0, clock
, 1);
580 /* for each hex char */
581 parity
[0] = parity
[1] = parity
[2] = parity
[3] = 0;
582 for (i
= 0; i
< 10; i
++)
584 /* read each hex char */
585 sscanf(&str
[i
], "%1x", &n
);
586 for (j
= 3; j
>= 0; j
--, n
/= 2)
589 /* append each bit */
590 CmdAppendGraph(0, clock
, binary
[0]);
591 CmdAppendGraph(0, clock
, binary
[1]);
592 CmdAppendGraph(0, clock
, binary
[2]);
593 CmdAppendGraph(0, clock
, binary
[3]);
595 /* append parity bit */
596 CmdAppendGraph(0, clock
, binary
[0] ^ binary
[1] ^ binary
[2] ^ binary
[3]);
598 /* keep track of column parity */
599 parity
[0] ^= binary
[0];
600 parity
[1] ^= binary
[1];
601 parity
[2] ^= binary
[2];
602 parity
[3] ^= binary
[3];
606 CmdAppendGraph(0, clock
, parity
[0]);
607 CmdAppendGraph(0, clock
, parity
[1]);
608 CmdAppendGraph(0, clock
, parity
[2]);
609 CmdAppendGraph(0, clock
, parity
[3]);
612 CmdAppendGraph(0, clock
, 0);
615 /* modulate that biatch */
619 RepaintGraphWindow();
624 static void ChkBitstream(char *str
)
628 /* convert to bitstream if necessary */
629 for (i
= 0; i
< (int)(GraphTraceLen
/ 2); i
++)
631 if (GraphBuffer
[i
] > 1 || GraphBuffer
[i
] < 0)
639 static void CmdLosim(char *str
)
644 /* convert to bitstream if necessary */
647 for (i
= 0; i
< GraphTraceLen
; i
+= 48) {
650 for(j
= 0; j
< 48; j
++) {
651 c
.d
.asBytes
[j
] = GraphBuffer
[i
+j
];
653 c
.cmd
= CMD_DOWNLOADED_SIM_SAMPLES_125K
;
655 SendCommand(&c
, FALSE
);
659 c
.cmd
= CMD_SIMULATE_TAG_125K
;
660 c
.ext1
= GraphTraceLen
;
661 SendCommand(&c
, FALSE
);
664 static void CmdLoread(char *str
)
667 // 'h' means higher-low-frequency, 134 kHz
670 } else if (*str
== '\0') {
673 PrintToScrollback("use 'loread' or 'loread h'");
676 c
.cmd
= CMD_ACQUIRE_RAW_ADC_SAMPLES_125K
;
677 SendCommand(&c
, FALSE
);
680 static void CmdDetectReader(char *str
)
683 // 'l' means LF - 125/134 kHz
686 } else if (*str
== 'h') {
688 } else if (*str
!= '\0') {
689 PrintToScrollback("use 'detectreader' or 'detectreader l' or 'detectreader h'");
692 c
.cmd
= CMD_LISTEN_READER_FIELD
;
693 SendCommand(&c
, FALSE
);
696 /* send a command before reading */
697 static void CmdLoCommandRead(char *str
)
699 static char dummy
[3];
704 c
.cmd
= CMD_MOD_THEN_ACQUIRE_RAW_ADC_SAMPLES_125K
;
705 sscanf(str
, "%i %i %i %s %s", &c
.ext1
, &c
.ext2
, &c
.ext3
, &c
.d
.asBytes
,&dummy
+1);
706 // in case they specified 'h'
707 strcpy(&c
.d
.asBytes
+ strlen(c
.d
.asBytes
),dummy
);
708 SendCommand(&c
, FALSE
);
711 static void CmdLosamples(char *str
)
719 if (n
>16000) n
=16000;
721 for(i
= 0; i
< n
; i
+= 12) {
723 c
.cmd
= CMD_DOWNLOAD_RAW_ADC_SAMPLES_125K
;
725 SendCommand(&c
, FALSE
);
727 if(c
.cmd
!= CMD_DOWNLOADED_RAW_ADC_SAMPLES_125K
) {
729 PrintToScrollback("bad resp");
733 for(j
= 0; j
< 48; j
++) {
734 GraphBuffer
[cnt
++] = ((int)c
.d
.asBytes
[j
]) - 128;
738 RepaintGraphWindow();
741 static void CmdBitsamples(char *str
)
748 for(i
= 0; i
< n
; i
+= 12) {
750 c
.cmd
= CMD_DOWNLOAD_RAW_ADC_SAMPLES_125K
;
752 SendCommand(&c
, FALSE
);
754 if(c
.cmd
!= CMD_DOWNLOADED_RAW_ADC_SAMPLES_125K
) {
755 PrintToScrollback("bad resp");
759 for(j
= 0; j
< 48; j
++) {
760 for(k
= 0; k
< 8; k
++) {
761 if(c
.d
.asBytes
[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) {
781 c
.cmd
= CMD_DOWNLOAD_RAW_ADC_SAMPLES_125K
;
783 SendCommand(&c
, FALSE
);
785 if(c
.cmd
!= CMD_DOWNLOADED_RAW_ADC_SAMPLES_125K
) {
786 PrintToScrollback("bad resp");
790 for(j
= 0; j
< 48; j
++) {
791 GraphBuffer
[cnt
++] = (int)((BYTE
)c
.d
.asBytes
[j
]);
796 RepaintGraphWindow();
800 static int CmdHisamplest(char *str
, int nrlow
)
812 for(i
= 0; i
< n
; i
+= 12) {
814 c
.cmd
= CMD_DOWNLOAD_RAW_ADC_SAMPLES_125K
;
816 SendCommand(&c
, FALSE
);
818 if(c
.cmd
!= CMD_DOWNLOADED_RAW_ADC_SAMPLES_125K
) {
819 PrintToScrollback("bad resp");
823 for(j
= 0; j
< 48; j
++) {
824 t2
= (int)((BYTE
)c
.d
.asBytes
[j
]);
825 if((t2
^ 0xC0) & 0xC0) { hasbeennull
++; }
831 t1
= (t2
& 0x80) ^ (t2
& 0x20);
832 t2
= ((t2
<< 1) & 0x80) ^ ((t2
<< 1) & 0x20);
838 t2
= ((t2
<< 1) & 0x80);
844 t2
= ((t2
<< 1) & 0x20);
848 // both, but tag with other algorithm
849 t1
= (t2
& 0x80) ^ (t2
& 0x08);
850 t2
= ((t2
<< 1) & 0x80) ^ ((t2
<< 1) & 0x08);
854 GraphBuffer
[cnt
++] = t1
;
855 GraphBuffer
[cnt
++] = t2
;
860 if(hasbeennull
>nrlow
|| nrlow
==0) {
861 PrintToScrollback("hasbeennull=%d", hasbeennull
);
870 static void CmdHexsamples(char *str
)
881 for(i
= 0; i
< n
; i
+= 12) {
883 c
.cmd
= CMD_DOWNLOAD_RAW_ADC_SAMPLES_125K
;
885 SendCommand(&c
, FALSE
);
887 if(c
.cmd
!= CMD_DOWNLOADED_RAW_ADC_SAMPLES_125K
) {
888 PrintToScrollback("bad resp");
892 for(j
= 0; j
< 48; j
+= 8) {
893 PrintToScrollback("%02x %02x %02x %02x %02x %02x %02x %02x",
908 static void CmdHisampless(char *str
)
920 for(i
= 0; i
< n
; i
+= 12) {
922 c
.cmd
= CMD_DOWNLOAD_RAW_ADC_SAMPLES_125K
;
924 SendCommand(&c
, FALSE
);
926 if(c
.cmd
!= CMD_DOWNLOADED_RAW_ADC_SAMPLES_125K
) {
927 PrintToScrollback("bad resp");
931 for(j
= 0; j
< 48; j
++) {
932 GraphBuffer
[cnt
++] = (int)((signed char)c
.d
.asBytes
[j
]);
937 RepaintGraphWindow();
940 static WORD
Iso15693Crc(BYTE
*v
, int n
)
946 for(i
= 0; i
< n
; i
++) {
947 reg
= reg
^ ((DWORD
)v
[i
]);
948 for (j
= 0; j
< 8; j
++) {
950 reg
= (reg
>> 1) ^ 0x8408;
960 static void CmdHi14bdemod(char *str
)
965 BOOL negateI
, negateQ
;
970 // As received, the samples are pairs, correlations against I and Q
971 // square waves. So estimate angle of initial carrier (or just
972 // quadrant, actually), and then do the demod.
974 // First, estimate where the tag starts modulating.
975 for(i
= 0; i
< GraphTraceLen
; i
+= 2) {
976 if(abs(GraphBuffer
[i
]) + abs(GraphBuffer
[i
+1]) > 40) {
980 if(i
>= GraphTraceLen
) {
981 PrintToScrollback("too weak to sync");
984 PrintToScrollback("out of weak at %d", i
);
987 // Now, estimate the phase in the initial modulation of the tag
990 for(; i
< (outOfWeakAt
+ 16); i
+= 2) {
991 isum
+= GraphBuffer
[i
+0];
992 qsum
+= GraphBuffer
[i
+1];
994 negateI
= (isum
< 0);
995 negateQ
= (qsum
< 0);
997 // Turn the correlation pairs into soft decisions on the bit.
999 for(i
= 0; i
< GraphTraceLen
/2; i
++) {
1000 int si
= GraphBuffer
[j
];
1001 int sq
= GraphBuffer
[j
+1];
1002 if(negateI
) si
= -si
;
1003 if(negateQ
) sq
= -sq
;
1004 GraphBuffer
[i
] = si
+ sq
;
1010 while(GraphBuffer
[i
] > 0 && i
< GraphTraceLen
)
1012 if(i
>= GraphTraceLen
) goto demodError
;
1015 while(GraphBuffer
[i
] < 0 && i
< GraphTraceLen
)
1017 if(i
>= GraphTraceLen
) goto demodError
;
1018 if((i
- iold
) > 23) goto demodError
;
1020 PrintToScrollback("make it to demod loop");
1024 while(GraphBuffer
[i
] >= 0 && i
< GraphTraceLen
)
1026 if(i
>= GraphTraceLen
) goto demodError
;
1027 if((i
- iold
) > 6) goto demodError
;
1030 if(i
+ 20 >= GraphTraceLen
) goto demodError
;
1032 for(j
= 0; j
< 10; j
++) {
1033 int soft
= GraphBuffer
[i
] + GraphBuffer
[i
+1];
1035 if(abs(soft
) < ((abs(isum
) + abs(qsum
))/20)) {
1036 PrintToScrollback("weak bit");
1040 if(GraphBuffer
[i
] + GraphBuffer
[i
+1] >= 0) {
1047 if( (shiftReg
& 0x200) &&
1048 !(shiftReg
& 0x001))
1050 // valid data byte, start and stop bits okay
1051 PrintToScrollback(" %02x", (shiftReg
>> 1) & 0xff);
1052 data
[dataLen
++] = (shiftReg
>> 1) & 0xff;
1053 if(dataLen
>= sizeof(data
)) {
1056 } else if(shiftReg
== 0x000) {
1065 ComputeCrc14443(CRC_14443_B
, data
, dataLen
-2, &first
, &second
);
1066 PrintToScrollback("CRC: %02x %02x (%s)\n", first
, second
,
1067 (first
== data
[dataLen
-2] && second
== data
[dataLen
-1]) ?
1068 "ok" : "****FAIL****");
1070 RepaintGraphWindow();
1074 PrintToScrollback("demod error");
1075 RepaintGraphWindow();
1078 static void CmdHi14list(char *str
)
1081 GetFromBigBuf(got
, sizeof(got
));
1083 PrintToScrollback("recorded activity:");
1084 PrintToScrollback(" time :rssi: who bytes");
1085 PrintToScrollback("---------+----+----+-----------");
1096 int timestamp
= *((DWORD
*)(got
+i
));
1097 if(timestamp
& 0x80000000) {
1098 timestamp
&= 0x7fffffff;
1103 int metric
= *((DWORD
*)(got
+i
+4));
1110 if(i
+ len
>= 900) {
1114 BYTE
*frame
= (got
+i
+9);
1116 char line
[1000] = "";
1118 for(j
= 0; j
< len
; j
++) {
1119 sprintf(line
+(j
*3), "%02x ", frame
[j
]);
1125 ComputeCrc14443(CRC_14443_B
, frame
, len
-2, &b1
, &b2
);
1126 if(b1
!= frame
[len
-2] || b2
!= frame
[len
-1]) {
1127 crc
= "**FAIL CRC**";
1135 char metricString
[100];
1137 sprintf(metricString
, "%3d", metric
);
1139 strcpy(metricString
, " ");
1142 PrintToScrollback(" +%7d: %s: %s %s %s",
1143 (prev
< 0 ? 0 : timestamp
- prev
),
1145 (isResponse
? "TAG" : " "), line
, crc
);
1152 static void CmdHi14alist(char *str
)
1155 GetFromBigBuf(got
, sizeof(got
));
1157 PrintToScrollback("recorded activity:");
1158 PrintToScrollback(" ETU :rssi: who bytes");
1159 PrintToScrollback("---------+----+----+-----------");
1170 int timestamp
= *((DWORD
*)(got
+i
));
1171 if(timestamp
& 0x80000000) {
1172 timestamp
&= 0x7fffffff;
1179 int parityBits
= *((DWORD
*)(got
+i
+4));
1180 // 4 bytes of additional information...
1181 // maximum of 32 additional parity bit information
1184 // at each quarter bit period we can send power level (16 levels)
1185 // or each half bit period in 256 levels.
1193 if(i
+ len
>= 1900) {
1197 BYTE
*frame
= (got
+i
+9);
1199 // Break and stick with current result if buffer was not completely full
1200 if(frame
[0] == 0x44 && frame
[1] == 0x44 && frame
[3] == 0x44) { break; }
1202 char line
[1000] = "";
1204 for(j
= 0; j
< len
; j
++) {
1205 int oddparity
= 0x01;
1209 oddparity
^= (((frame
[j
] & 0xFF) >> k
) & 0x01);
1212 //if((parityBits >> (len - j - 1)) & 0x01) {
1213 if(isResponse
&& (oddparity
!= ((parityBits
>> (len
- j
- 1)) & 0x01))) {
1214 sprintf(line
+(j
*4), "%02x! ", frame
[j
]);
1217 sprintf(line
+(j
*4), "%02x ", frame
[j
]);
1225 for(j
= 0; j
< (len
- 1); j
++) {
1226 // gives problems... search for the reason..
1227 /*if(frame[j] == 0xAA) {
1228 switch(frame[j+1]) {
1230 crc = "[1] Two drops close after each other";
1233 crc = "[2] Potential SOC with a drop in second half of bitperiod";
1236 crc = "[3] Segment Z after segment X is not possible";
1239 crc = "[4] Parity bit of a fully received byte was wrong";
1242 crc = "[?] Unknown error";
1249 if(strlen(crc
)==0) {
1250 ComputeCrc14443(CRC_14443_A
, frame
, len
-2, &b1
, &b2
);
1251 if(b1
!= frame
[len
-2] || b2
!= frame
[len
-1]) {
1252 crc
= (isResponse
& (len
< 6)) ? "" : " !crc";
1261 char metricString
[100];
1263 sprintf(metricString
, "%3d", metric
);
1265 strcpy(metricString
, " ");
1268 PrintToScrollback(" +%7d: %s: %s %s %s",
1269 (prev
< 0 ? 0 : (timestamp
- prev
)),
1271 (isResponse
? "TAG" : " "), line
, crc
);
1276 CommandFinished
= 1;
1279 static void CmdHi15demod(char *str
)
1281 // The sampling rate is 106.353 ksps/s, for T = 18.8 us
1284 // 1) Unmodulated time of 56.64us
1285 // 2) 24 pulses of 423.75khz
1286 // 3) logic '1' (unmodulated for 18.88us followed by 8 pulses of 423.75khz)
1288 static const int FrameSOF
[] = {
1289 -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
1290 -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
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,
1298 static const int Logic0
[] = {
1304 static const int Logic1
[] = {
1312 // 1) logic '0' (8 pulses of 423.75khz followed by unmodulated for 18.88us)
1313 // 2) 24 pulses of 423.75khz
1314 // 3) Unmodulated time of 56.64us
1316 static const int FrameEOF
[] = {
1321 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
1322 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
1323 -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
1324 -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1
1328 int max
= 0, maxPos
;
1332 if(GraphTraceLen
< 1000) return;
1334 // First, correlate for SOF
1335 for(i
= 0; i
< 100; i
++) {
1337 for(j
= 0; j
< arraylen(FrameSOF
); j
+= skip
) {
1338 corr
+= FrameSOF
[j
]*GraphBuffer
[i
+(j
/skip
)];
1345 PrintToScrollback("SOF at %d, correlation %d", maxPos
,
1346 max
/(arraylen(FrameSOF
)/skip
));
1348 i
= maxPos
+ arraylen(FrameSOF
)/skip
;
1351 memset(outBuf
, 0, sizeof(outBuf
));
1354 int corr0
= 0, corr1
= 0, corrEOF
= 0;
1355 for(j
= 0; j
< arraylen(Logic0
); j
+= skip
) {
1356 corr0
+= Logic0
[j
]*GraphBuffer
[i
+(j
/skip
)];
1358 for(j
= 0; j
< arraylen(Logic1
); j
+= skip
) {
1359 corr1
+= Logic1
[j
]*GraphBuffer
[i
+(j
/skip
)];
1361 for(j
= 0; j
< arraylen(FrameEOF
); j
+= skip
) {
1362 corrEOF
+= FrameEOF
[j
]*GraphBuffer
[i
+(j
/skip
)];
1364 // Even things out by the length of the target waveform.
1368 if(corrEOF
> corr1
&& corrEOF
> corr0
) {
1369 PrintToScrollback("EOF at %d", i
);
1371 } else if(corr1
> corr0
) {
1372 i
+= arraylen(Logic1
)/skip
;
1375 i
+= arraylen(Logic0
)/skip
;
1382 if((i
+(int)arraylen(FrameEOF
)) >= GraphTraceLen
) {
1383 PrintToScrollback("ran off end!");
1388 PrintToScrollback("error, uneven octet! (discard extra bits!)");
1389 PrintToScrollback(" mask=%02x", mask
);
1391 PrintToScrollback("%d octets", k
);
1393 for(i
= 0; i
< k
; i
++) {
1394 PrintToScrollback("# %2d: %02x ", i
, outBuf
[i
]);
1396 PrintToScrollback("CRC=%04x", Iso15693Crc(outBuf
, k
-2));
1399 static void CmdTiread(char *str
)
1402 c
.cmd
= CMD_ACQUIRE_RAW_BITS_TI_TYPE
;
1403 SendCommand(&c
, FALSE
);
1406 static void CmdTibits(char *str
)
1410 for(i
= 0; i
< 1536; i
+= 12) {
1412 c
.cmd
= CMD_DOWNLOAD_RAW_BITS_TI_TYPE
;
1414 SendCommand(&c
, FALSE
);
1416 if(c
.cmd
!= CMD_DOWNLOADED_RAW_BITS_TI_TYPE
) {
1417 PrintToScrollback("bad resp");
1421 for(j
= 0; j
< 12; j
++) {
1423 for(k
= 31; k
>= 0; k
--) {
1424 if(c
.d
.asDwords
[j
] & (1 << k
)) {
1425 GraphBuffer
[cnt
++] = 1;
1427 GraphBuffer
[cnt
++] = -1;
1432 GraphTraceLen
= 1536*32;
1433 RepaintGraphWindow();
1436 static void CmdTidemod(char *cmdline
)
1438 /* MATLAB as follows:
1439 f_s = 2000000; % sampling frequency
1440 f_l = 123200; % low FSK tone
1441 f_h = 134200; % high FSK tone
1443 T_l = 119e-6; % low bit duration
1444 T_h = 130e-6; % high bit duration
1446 l = 2*pi*ones(1, floor(f_s*T_l))*(f_l/f_s);
1447 h = 2*pi*ones(1, floor(f_s*T_h))*(f_h/f_s);
1449 l = sign(sin(cumsum(l)));
1450 h = sign(sin(cumsum(h)));
1452 static const int LowTone
[] = {
1453 1, 1, 1, 1, 1, 1, 1, 1, -1, -1, -1, -1, -1, -1, -1, -1, 1, 1, 1,
1454 1, 1, 1, 1, 1, -1, -1, -1, -1, -1, -1, -1, -1, 1, 1, 1, 1, 1, 1,
1455 1, 1, -1, -1, -1, -1, -1, -1, -1, -1, 1, 1, 1, 1, 1, 1, 1, 1, -1,
1456 -1, -1, -1, -1, -1, -1, -1, 1, 1, 1, 1, 1, 1, 1, 1, 1, -1, -1, -1,
1457 -1, -1, -1, -1, -1, 1, 1, 1, 1, 1, 1, 1, 1, -1, -1, -1, -1, -1, -1,
1458 -1, -1, 1, 1, 1, 1, 1, 1, 1, 1, -1, -1, -1, -1, -1, -1, -1, -1, 1,
1459 1, 1, 1, 1, 1, 1, 1, -1, -1, -1, -1, -1, -1, -1, -1, 1, 1, 1, 1,
1460 1, 1, 1, 1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 1, 1, 1, 1, 1, 1,
1461 1, 1, -1, -1, -1, -1, -1, -1, -1, -1, 1, 1, 1, 1, 1, 1, 1, 1, -1,
1462 -1, -1, -1, -1, -1, -1, -1, 1, 1, 1, 1, 1, 1, 1, 1, -1, -1, -1, -1,
1463 -1, -1, -1, -1, 1, 1, 1, 1, 1, 1, 1, 1, -1, -1, -1, -1, -1, -1, -1,
1464 -1, -1, 1, 1, 1, 1, 1, 1, 1, 1, -1, -1, -1, -1, -1, -1, -1, -1, 1,
1465 1, 1, 1, 1, 1, 1, 1, -1, -1, -1,
1467 static const int HighTone
[] = {
1468 1, 1, 1, 1, 1, 1, 1, -1, -1, -1, -1, -1, -1, -1, 1, 1, 1, 1, 1, 1,
1469 1, 1, -1, -1, -1, -1, -1, -1, -1, 1, 1, 1, 1, 1, 1, 1, 1, -1, -1,
1470 -1, -1, -1, -1, -1, 1, 1, 1, 1, 1, 1, 1, 1, -1, -1, -1, -1, -1,
1471 -1, -1, 1, 1, 1, 1, 1, 1, 1, 1, -1, -1, -1, -1, -1, -1, -1, 1, 1,
1472 1, 1, 1, 1, 1, -1, -1, -1, -1, -1, -1, -1, -1, 1, 1, 1, 1, 1, 1,
1473 1, -1, -1, -1, -1, -1, -1, -1, -1, 1, 1, 1, 1, 1, 1, 1, -1, -1,
1474 -1, -1, -1, -1, -1, -1, 1, 1, 1, 1, 1, 1, 1, -1, -1, -1, -1, -1,
1475 -1, -1, -1, 1, 1, 1, 1, 1, 1, 1, -1, -1, -1, -1, -1, -1, -1, -1,
1476 1, 1, 1, 1, 1, 1, 1, -1, -1, -1, -1, -1, -1, -1, 1, 1, 1, 1, 1, 1,
1477 1, 1, -1, -1, -1, -1, -1, -1, -1, 1, 1, 1, 1, 1, 1, 1, 1, -1, -1,
1478 -1, -1, -1, -1, -1, 1, 1, 1, 1, 1, 1, 1, 1, -1, -1, -1, -1, -1,
1479 -1, -1, 1, 1, 1, 1, 1, 1, 1, 1, -1, -1, -1, -1, -1, -1, -1, 1, 1,
1480 1, 1, 1, 1, 1, -1, -1, -1, -1, -1, -1, -1, -1, 1, 1, 1, 1, 1, 1,
1481 1, -1, -1, -1, -1, -1, -1, -1, -1, 1, 1, 1, 1, 1, 1, 1,
1484 int convLen
= max(arraylen(HighTone
), arraylen(LowTone
));
1487 for(i
= 0; i
< GraphTraceLen
- convLen
; i
++) {
1489 int lowSum
= 0, highSum
= 0;;
1490 int lowLen
= arraylen(LowTone
);
1491 int highLen
= arraylen(HighTone
);
1493 for(j
= 0; j
< lowLen
; j
++) {
1494 lowSum
+= LowTone
[j
]*GraphBuffer
[i
+j
];
1496 for(j
= 0; j
< highLen
; j
++) {
1497 highSum
+= HighTone
[j
]*GraphBuffer
[i
+j
];
1499 lowSum
= abs((100*lowSum
) / lowLen
);
1500 highSum
= abs((100*highSum
) / highLen
);
1501 GraphBuffer
[i
] = (highSum
<< 16) | lowSum
;
1504 for(i
= 0; i
< GraphTraceLen
- convLen
- 16; i
++) {
1506 int lowTot
= 0, highTot
= 0;
1507 // 16 and 15 are f_s divided by f_l and f_h, rounded
1508 for(j
= 0; j
< 16; j
++) {
1509 lowTot
+= (GraphBuffer
[i
+j
] & 0xffff);
1511 for(j
= 0; j
< 15; j
++) {
1512 highTot
+= (GraphBuffer
[i
+j
] >> 16);
1514 GraphBuffer
[i
] = lowTot
- highTot
;
1517 GraphTraceLen
-= (convLen
+ 16);
1519 RepaintGraphWindow();
1521 // Okay, so now we have unsliced soft decisions; find bit-sync, and then
1524 int max
= 0, maxPos
= 0;
1525 for(i
= 0; i
< 6000; i
++) {
1528 for(j
= 0; j
< 8*arraylen(LowTone
); j
++) {
1529 dec
-= GraphBuffer
[i
+j
];
1531 for(; j
< 8*arraylen(LowTone
) + 8*arraylen(HighTone
); j
++) {
1532 dec
+= GraphBuffer
[i
+j
];
1539 GraphBuffer
[maxPos
] = 800;
1540 GraphBuffer
[maxPos
+1] = -800;
1542 maxPos
+= 8*arraylen(LowTone
);
1543 GraphBuffer
[maxPos
] = 800;
1544 GraphBuffer
[maxPos
+1] = -800;
1545 maxPos
+= 8*arraylen(HighTone
);
1547 GraphBuffer
[maxPos
] = 800;
1548 GraphBuffer
[maxPos
+1] = -800;
1550 PrintToScrollback("actual data bits start at sample %d", maxPos
);
1552 PrintToScrollback("length %d/%d", arraylen(HighTone
), arraylen(LowTone
));
1554 GraphBuffer
[maxPos
] = 800;
1555 GraphBuffer
[maxPos
+1] = -800;
1557 BYTE bits
[64+16+8+1];
1558 bits
[sizeof(bits
)-1] = '\0';
1560 for(i
= 0; i
< arraylen(bits
); i
++) {
1564 for(j
= 0; j
< arraylen(LowTone
); j
++) {
1565 low
-= GraphBuffer
[maxPos
+j
];
1567 for(j
= 0; j
< arraylen(HighTone
); j
++) {
1568 high
+= GraphBuffer
[maxPos
+j
];
1572 maxPos
+= arraylen(HighTone
);
1575 maxPos
+= arraylen(LowTone
);
1577 GraphBuffer
[maxPos
] = 800;
1578 GraphBuffer
[maxPos
+1] = -800;
1580 PrintToScrollback("bits: '%s'", bits
);
1583 for(i
= 0; i
< 32; i
++) {
1584 if(bits
[i
] == '1') {
1588 for(i
= 32; i
< 64; i
++) {
1589 if(bits
[i
] == '1') {
1593 PrintToScrollback("hex: %08x %08x", h
, l
);
1596 static void CmdNorm(char *str
)
1599 int max
= INT_MIN
, min
= INT_MAX
;
1600 for(i
= 10; i
< GraphTraceLen
; i
++) {
1601 if(GraphBuffer
[i
] > max
) {
1602 max
= GraphBuffer
[i
];
1604 if(GraphBuffer
[i
] < min
) {
1605 min
= GraphBuffer
[i
];
1609 for(i
= 0; i
< GraphTraceLen
; i
++) {
1610 GraphBuffer
[i
] = (GraphBuffer
[i
] - ((max
+ min
)/2))*1000/
1614 RepaintGraphWindow();
1617 static void CmdDec(char *str
)
1620 for(i
= 0; i
< (GraphTraceLen
/2); i
++) {
1621 GraphBuffer
[i
] = GraphBuffer
[i
*2];
1624 PrintToScrollback("decimated by 2");
1625 RepaintGraphWindow();
1628 static void CmdHpf(char *str
)
1632 for(i
= 10; i
< GraphTraceLen
; i
++) {
1633 accum
+= GraphBuffer
[i
];
1635 accum
/= (GraphTraceLen
- 10);
1636 for(i
= 0; i
< GraphTraceLen
; i
++) {
1637 GraphBuffer
[i
] -= accum
;
1640 RepaintGraphWindow();
1643 static void CmdZerocrossings(char *str
)
1646 // Zero-crossings aren't meaningful unless the signal is zero-mean.
1652 for(i
= 0; i
< GraphTraceLen
; i
++) {
1653 if(GraphBuffer
[i
]*sign
>= 0) {
1654 // No change in sign, reproduce the previous sample count.
1656 GraphBuffer
[i
] = lastZc
;
1658 // Change in sign, reset the sample count.
1660 GraphBuffer
[i
] = lastZc
;
1668 RepaintGraphWindow();
1671 static void CmdLtrim(char *str
)
1676 for(i
= ds
; i
< GraphTraceLen
; i
++) {
1677 GraphBuffer
[i
-ds
] = GraphBuffer
[i
];
1679 GraphTraceLen
-= ds
;
1681 RepaintGraphWindow();
1684 static void CmdAutoCorr(char *str
)
1686 static int CorrelBuffer
[MAX_GRAPH_TRACE_LEN
];
1688 int window
= atoi(str
);
1691 PrintToScrollback("needs a window");
1695 if(window
>= GraphTraceLen
) {
1696 PrintToScrollback("window must be smaller than trace (%d samples)",
1701 PrintToScrollback("performing %d correlations", GraphTraceLen
- window
);
1704 for(i
= 0; i
< GraphTraceLen
- window
; i
++) {
1707 for(j
= 0; j
< window
; j
++) {
1708 sum
+= (GraphBuffer
[j
]*GraphBuffer
[i
+j
]) / 256;
1710 CorrelBuffer
[i
] = sum
;
1712 GraphTraceLen
= GraphTraceLen
- window
;
1713 memcpy(GraphBuffer
, CorrelBuffer
, GraphTraceLen
*sizeof(int));
1715 RepaintGraphWindow();
1718 static void CmdVchdemod(char *str
)
1720 // Is this the entire sync pattern, or does this also include some
1721 // data bits that happen to be the same everywhere? That would be
1723 static const int SyncPattern
[] = {
1724 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
1725 1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
1726 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
1727 1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
1728 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
1729 1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
1730 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
1731 1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
1732 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
1733 1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
1736 // So first, we correlate for the sync pattern, and mark that.
1737 int bestCorrel
= 0, bestPos
= 0;
1739 // It does us no good to find the sync pattern, with fewer than
1740 // 2048 samples after it...
1741 for(i
= 0; i
< (GraphTraceLen
-2048); i
++) {
1744 for(j
= 0; j
< arraylen(SyncPattern
); j
++) {
1745 sum
+= GraphBuffer
[i
+j
]*SyncPattern
[j
];
1747 if(sum
> bestCorrel
) {
1752 PrintToScrollback("best sync at %d [metric %d]", bestPos
, bestCorrel
);
1757 int worst
= INT_MAX
;
1760 for(i
= 0; i
< 2048; i
+= 8) {
1763 for(j
= 0; j
< 8; j
++) {
1764 sum
+= GraphBuffer
[bestPos
+i
+j
];
1771 if(abs(sum
) < worst
) {
1776 PrintToScrollback("bits:");
1777 PrintToScrollback("%s", bits
);
1778 PrintToScrollback("worst metric: %d at pos %d", worst
, worstPos
);
1780 if(strcmp(str
, "clone")==0) {
1783 for(s
= bits
; *s
; s
++) {
1785 for(j
= 0; j
< 16; j
++) {
1786 GraphBuffer
[GraphTraceLen
++] = (*s
== '1') ? 1 : 0;
1789 RepaintGraphWindow();
1793 static void CmdIndalademod(char *str
)
1795 // Usage: recover 64bit UID by default, specify "224" as arg to recover a 224bit UID
1800 // worst case with GraphTraceLen=64000 is < 4096
1801 // under normal conditions it's < 2048
1804 int worst
= 0, worstPos
= 0;
1805 PrintToScrollback("Expecting a bit less than %d raw bits", GraphTraceLen
/32);
1806 for(i
= 0; i
< GraphTraceLen
-1; i
+= 2) {
1808 if((GraphBuffer
[i
] > GraphBuffer
[i
+ 1]) && (state
!= 1)) {
1810 for(j
= 0; j
< count
- 8; j
+= 16) {
1811 rawbits
[rawbit
++] = 0;
1813 if ((abs(count
- j
)) > worst
) {
1814 worst
= abs(count
- j
);
1820 } else if((GraphBuffer
[i
] < GraphBuffer
[i
+ 1]) && (state
!= 0)) {
1822 for(j
= 0; j
< count
- 8; j
+= 16) {
1823 rawbits
[rawbit
++] = 1;
1825 if ((abs(count
- j
)) > worst
) {
1826 worst
= abs(count
- j
);
1834 PrintToScrollback("Recovered %d raw bits", rawbit
);
1835 PrintToScrollback("worst metric (0=best..7=worst): %d at pos %d", worst
, worstPos
);
1837 // Finding the start of a UID
1838 int uidlen
, long_wait
;
1839 if(strcmp(str
, "224") == 0) {
1848 for(start
= 0; start
<= rawbit
- uidlen
; start
++) {
1849 first
= rawbits
[start
];
1850 for(i
= start
; i
< start
+ long_wait
; i
++) {
1851 if(rawbits
[i
] != first
) {
1855 if(i
== (start
+ long_wait
)) {
1859 if(start
== rawbit
- uidlen
+ 1) {
1860 PrintToScrollback("nothing to wait for");
1864 // Inverting signal if needed
1866 for(i
= start
; i
< rawbit
; i
++) {
1867 rawbits
[i
] = !rawbits
[i
];
1874 showbits
[uidlen
]='\0';
1878 if(uidlen
> rawbit
) {
1879 PrintToScrollback("Warning: not enough raw bits to get a full UID");
1880 for(bit
= 0; bit
< rawbit
; bit
++) {
1881 bits
[bit
] = rawbits
[i
++];
1882 // As we cannot know the parity, let's use "." and "/"
1883 showbits
[bit
] = '.' + bits
[bit
];
1885 showbits
[bit
+1]='\0';
1886 PrintToScrollback("Partial UID=%s", showbits
);
1889 for(bit
= 0; bit
< uidlen
; bit
++) {
1890 bits
[bit
] = rawbits
[i
++];
1891 showbits
[bit
] = '0' + bits
[bit
];
1895 PrintToScrollback("UID=%s", showbits
);
1897 // Checking UID against next occurences
1898 for(; i
+ uidlen
<= rawbit
;) {
1900 for(bit
= 0; bit
< uidlen
; bit
++) {
1901 if(bits
[bit
] != rawbits
[i
++]) {
1911 PrintToScrollback("Occurences: %d (expected %d)", times
, (rawbit
- start
) / uidlen
);
1913 // Remodulating for tag cloning
1914 GraphTraceLen
= 32*uidlen
;
1917 for(bit
= 0; bit
< uidlen
; bit
++) {
1918 if(bits
[bit
] == 0) {
1924 for(j
= 0; j
< 32; j
++) {
1925 GraphBuffer
[i
++] = phase
;
1930 RepaintGraphWindow();
1933 static void CmdFlexdemod(char *str
)
1936 for(i
= 0; i
< GraphTraceLen
; i
++) {
1937 if(GraphBuffer
[i
] < 0) {
1938 GraphBuffer
[i
] = -1;
1944 #define LONG_WAIT 100
1946 for(start
= 0; start
< GraphTraceLen
- LONG_WAIT
; start
++) {
1947 int first
= GraphBuffer
[start
];
1948 for(i
= start
; i
< start
+ LONG_WAIT
; i
++) {
1949 if(GraphBuffer
[i
] != first
) {
1953 if(i
== (start
+ LONG_WAIT
)) {
1957 if(start
== GraphTraceLen
- LONG_WAIT
) {
1958 PrintToScrollback("nothing to wait for");
1962 GraphBuffer
[start
] = 2;
1963 GraphBuffer
[start
+1] = -2;
1969 for(bit
= 0; bit
< 64; bit
++) {
1972 for(j
= 0; j
< 16; j
++) {
1973 sum
+= GraphBuffer
[i
++];
1980 PrintToScrollback("bit %d sum %d", bit
, sum
);
1983 for(bit
= 0; bit
< 64; bit
++) {
1986 for(j
= 0; j
< 16; j
++) {
1987 sum
+= GraphBuffer
[i
++];
1989 if(sum
> 0 && bits
[bit
] != 1) {
1990 PrintToScrollback("oops1 at %d", bit
);
1992 if(sum
< 0 && bits
[bit
] != 0) {
1993 PrintToScrollback("oops2 at %d", bit
);
1997 GraphTraceLen
= 32*64;
2000 for(bit
= 0; bit
< 64; bit
++) {
2001 if(bits
[bit
] == 0) {
2007 for(j
= 0; j
< 32; j
++) {
2008 GraphBuffer
[i
++] = phase
;
2013 RepaintGraphWindow();
2017 * Generic command to demodulate ASK.
2019 * Argument is convention: positive or negative (High mod means zero
2020 * or high mod means one)
2022 * Updates the Graph trace with 0/1 values
2028 static void Cmdaskdemod(char *str
) {
2033 // TODO: complain if we do not give 2 arguments here !
2034 sscanf(str
, "%i", &c
);
2036 /* Detect high and lows and clock */
2037 for (i
= 0; i
< GraphTraceLen
; i
++)
2039 if (GraphBuffer
[i
] > high
)
2040 high
= GraphBuffer
[i
];
2041 else if (GraphBuffer
[i
] < low
)
2042 low
= GraphBuffer
[i
];
2045 if (GraphBuffer
[0] > 0) {
2046 GraphBuffer
[0] = 1-c
;
2050 for(i
=1;i
<GraphTraceLen
;i
++) {
2051 /* Transitions are detected at each peak
2052 * Transitions are either:
2053 * - we're low: transition if we hit a high
2054 * - we're high: transition if we hit a low
2055 * (we need to do it this way because some tags keep high or
2056 * low for long periods, others just reach the peak and go
2059 if ((GraphBuffer
[i
]==high
) && (GraphBuffer
[i
-1] == c
)) {
2061 } else if ((GraphBuffer
[i
]==low
) && (GraphBuffer
[i
-1] == (1-c
))){
2065 GraphBuffer
[i
] = GraphBuffer
[i
-1];
2068 RepaintGraphWindow();
2071 /* Print our clock rate */
2072 static void Cmddetectclockrate(char *str
)
2074 int clock
= detectclock(0);
2075 PrintToScrollback("Auto-detected clock rate: %d", clock
);
2081 int detectclock(int peak
)
2087 /* Detect peak if we don't have one */
2089 for (i
= 0; i
< GraphTraceLen
; i
++)
2090 if (GraphBuffer
[i
] > peak
)
2091 peak
= GraphBuffer
[i
];
2093 for (i
= 1; i
< GraphTraceLen
; i
++)
2095 /* If this is the beginning of a peak */
2096 if (GraphBuffer
[i
-1] != GraphBuffer
[i
] && GraphBuffer
[i
] == peak
)
2098 /* Find lowest difference between peaks */
2099 if (lastpeak
&& i
- lastpeak
< clock
)
2101 clock
= i
- lastpeak
;
2110 /* Get or auto-detect clock rate */
2111 int GetClock(char *str
, int peak
)
2115 sscanf(str
, "%i", &clock
);
2116 if (!strcmp(str
, ""))
2119 /* Auto-detect clock */
2122 clock
= detectclock(peak
);
2124 /* Only print this message if we're not looping something */
2126 PrintToScrollback("Auto-detected clock rate: %d", clock
);
2133 * Convert to a bitstream
2135 static void Cmdbitstream(char *str
) {
2142 int hithigh
, hitlow
, first
;
2144 /* Detect high and lows and clock */
2145 for (i
= 0; i
< GraphTraceLen
; i
++)
2147 if (GraphBuffer
[i
] > high
)
2148 high
= GraphBuffer
[i
];
2149 else if (GraphBuffer
[i
] < low
)
2150 low
= GraphBuffer
[i
];
2154 clock
= GetClock(str
, high
);
2156 gtl
= CmdClearGraph(0);
2159 for (i
= 0; i
< (int)(gtl
/ clock
); i
++)
2165 /* Find out if we hit both high and low peaks */
2166 for (j
= 0; j
< clock
; j
++)
2168 if (GraphBuffer
[(i
* clock
) + j
] == high
)
2170 else if (GraphBuffer
[(i
* clock
) + j
] == low
)
2173 /* it doesn't count if it's the first part of our read
2174 because it's really just trailing from the last sequence */
2175 if (first
&& (hithigh
|| hitlow
))
2176 hithigh
= hitlow
= 0;
2180 if (hithigh
&& hitlow
)
2184 /* If we didn't hit both high and low peaks, we had a bit transition */
2185 if (!hithigh
|| !hitlow
)
2188 CmdAppendGraph(0, clock
, bit
);
2189 // for (j = 0; j < (int)(clock/2); j++)
2190 // GraphBuffer[(i * clock) + j] = bit ^ 1;
2191 // for (j = (int)(clock/2); j < clock; j++)
2192 // GraphBuffer[(i * clock) + j] = bit;
2195 RepaintGraphWindow();
2198 /* Modulate our data into manchester */
2199 static void Cmdmanchestermod(char *str
)
2203 int bit
, lastbit
, wave
;
2206 clock
= GetClock(str
, 0);
2210 for (i
= 0; i
< (int)(GraphTraceLen
/ clock
); i
++)
2212 bit
= GraphBuffer
[i
* clock
] ^ 1;
2214 for (j
= 0; j
< (int)(clock
/2); j
++)
2215 GraphBuffer
[(i
* clock
) + j
] = bit
^ lastbit
^ wave
;
2216 for (j
= (int)(clock
/2); j
< clock
; j
++)
2217 GraphBuffer
[(i
* clock
) + j
] = bit
^ lastbit
^ wave
^ 1;
2219 /* Keep track of how we start our wave and if we changed or not this time */
2220 wave
^= bit
^ lastbit
;
2224 RepaintGraphWindow();
2228 * Manchester demodulate a bitstream. The bitstream needs to be already in
2229 * the GraphBuffer as 0 and 1 values
2231 * Give the clock rate as argument in order to help the sync - the algorithm
2232 * resyncs at each pulse anyway.
2234 * Not optimized by any means, this is the 1st time I'm writing this type of
2235 * routine, feel free to improve...
2237 * 1st argument: clock rate (as number of samples per clock rate)
2238 * Typical values can be 64, 32, 128...
2240 static void Cmdmanchesterdemod(char *str
) {
2241 int i
, j
, invert
= 0;
2247 int hithigh
, hitlow
, first
;
2253 /* check if we're inverting output */
2256 PrintToScrollback("Inverting output");
2260 while(*str
== ' '); // in case a 2nd argument was given
2263 /* Holds the decoded bitstream: each clock period contains 2 bits */
2264 /* later simplified to 1 bit after manchester decoding. */
2265 /* Add 10 bits to allow for noisy / uncertain traces without aborting */
2266 /* int BitStream[GraphTraceLen*2/clock+10]; */
2268 /* But it does not work if compiling on WIndows: therefore we just allocate a */
2270 int BitStream
[MAX_GRAPH_TRACE_LEN
];
2272 /* Detect high and lows */
2273 for (i
= 0; i
< GraphTraceLen
; i
++)
2275 if (GraphBuffer
[i
] > high
)
2276 high
= GraphBuffer
[i
];
2277 else if (GraphBuffer
[i
] < low
)
2278 low
= GraphBuffer
[i
];
2282 clock
= GetClock(str
, high
);
2284 int tolerance
= clock
/4;
2286 /* Detect first transition */
2287 /* Lo-Hi (arbitrary) */
2288 for (i
= 0; i
< GraphTraceLen
; i
++)
2290 if (GraphBuffer
[i
] == low
)
2297 /* If we're not working with 1/0s, demod based off clock */
2300 bit
= 0; /* We assume the 1st bit is zero, it may not be
2301 * the case: this routine (I think) has an init problem.
2304 for (; i
< (int)(GraphTraceLen
/ clock
); i
++)
2310 /* Find out if we hit both high and low peaks */
2311 for (j
= 0; j
< clock
; j
++)
2313 if (GraphBuffer
[(i
* clock
) + j
] == high
)
2315 else if (GraphBuffer
[(i
* clock
) + j
] == low
)
2318 /* it doesn't count if it's the first part of our read
2319 because it's really just trailing from the last sequence */
2320 if (first
&& (hithigh
|| hitlow
))
2321 hithigh
= hitlow
= 0;
2325 if (hithigh
&& hitlow
)
2329 /* If we didn't hit both high and low peaks, we had a bit transition */
2330 if (!hithigh
|| !hitlow
)
2333 BitStream
[bit2idx
++] = bit
^ invert
;
2337 /* standard 1/0 bitstream */
2341 /* Then detect duration between 2 successive transitions */
2342 for (bitidx
= 1; i
< GraphTraceLen
; i
++)
2344 if (GraphBuffer
[i
-1] != GraphBuffer
[i
])
2349 // Error check: if bitidx becomes too large, we do not
2350 // have a Manchester encoded bitstream or the clock is really
2352 if (bitidx
> (GraphTraceLen
*2/clock
+8) ) {
2353 PrintToScrollback("Error: the clock you gave is probably wrong, aborting.");
2356 // Then switch depending on lc length:
2357 // Tolerance is 1/4 of clock rate (arbitrary)
2358 if (abs(lc
-clock
/2) < tolerance
) {
2359 // Short pulse : either "1" or "0"
2360 BitStream
[bitidx
++]=GraphBuffer
[i
-1];
2361 } else if (abs(lc
-clock
) < tolerance
) {
2362 // Long pulse: either "11" or "00"
2363 BitStream
[bitidx
++]=GraphBuffer
[i
-1];
2364 BitStream
[bitidx
++]=GraphBuffer
[i
-1];
2368 PrintToScrollback("Warning: Manchester decode error for pulse width detection.");
2369 PrintToScrollback("(too many of those messages mean either the stream is not Manchester encoded, or clock is wrong)");
2373 PrintToScrollback("Error: too many detection errors, aborting.");
2380 // At this stage, we now have a bitstream of "01" ("1") or "10" ("0"), parse it into final decoded bitstream
2381 // Actually, we overwrite BitStream with the new decoded bitstream, we just need to be careful
2382 // to stop output at the final bitidx2 value, not bitidx
2383 for (i
= 0; i
< bitidx
; i
+= 2) {
2384 if ((BitStream
[i
] == 0) && (BitStream
[i
+1] == 1)) {
2385 BitStream
[bit2idx
++] = 1 ^ invert
;
2386 } else if ((BitStream
[i
] == 1) && (BitStream
[i
+1] == 0)) {
2387 BitStream
[bit2idx
++] = 0 ^ invert
;
2389 // We cannot end up in this state, this means we are unsynchronized,
2393 PrintToScrollback("Unsynchronized, resync...");
2394 PrintToScrollback("(too many of those messages mean the stream is not Manchester encoded)");
2398 PrintToScrollback("Error: too many decode errors, aborting.");
2405 PrintToScrollback("Manchester decoded bitstream");
2406 // Now output the bitstream to the scrollback by line of 16 bits
2407 for (i
= 0; i
< (bit2idx
-16); i
+=16) {
2408 PrintToScrollback("%i %i %i %i %i %i %i %i %i %i %i %i %i %i %i %i",
2433 static void CmdHiddemod(char *str
)
2435 if(GraphTraceLen
< 4800) {
2436 PrintToScrollback("too short; need at least 4800 samples");
2440 GraphTraceLen
= 4800;
2442 for(i
= 0; i
< GraphTraceLen
; i
++) {
2443 if(GraphBuffer
[i
] < 0) {
2449 RepaintGraphWindow();
2452 static void CmdPlot(char *str
)
2457 static void CmdHide(char *str
)
2462 static void CmdScale(char *str
)
2464 CursorScaleFactor
= atoi(str
);
2465 if(CursorScaleFactor
== 0) {
2466 PrintToScrollback("bad, can't have zero scale");
2467 CursorScaleFactor
= 1;
2469 RepaintGraphWindow();
2472 static void CmdSave(char *str
)
2474 FILE *f
= fopen(str
, "w");
2476 PrintToScrollback("couldn't open '%s'", str
);
2480 for(i
= 0; i
< GraphTraceLen
; i
++) {
2481 fprintf(f
, "%d\n", GraphBuffer
[i
]);
2484 PrintToScrollback("saved to '%s'", str
);
2487 static void CmdLoad(char *str
)
2489 FILE *f
= fopen(str
, "r");
2491 PrintToScrollback("couldn't open '%s'", str
);
2497 while(fgets(line
, sizeof(line
), f
)) {
2498 GraphBuffer
[GraphTraceLen
] = atoi(line
);
2502 PrintToScrollback("loaded %d samples", GraphTraceLen
);
2503 RepaintGraphWindow();
2506 static void CmdHIDsimTAG(char *str
)
2508 unsigned int hi
=0, lo
=0;
2512 while (sscanf(&str
[i
++], "%1x", &n
) == 1) {
2513 hi
=(hi
<<4)|(lo
>>28);
2517 PrintToScrollback("Emulating tag with ID %x%16x", hi
, lo
);
2519 c
.cmd
= CMD_HID_SIM_TAG
;
2522 SendCommand(&c
, FALSE
);
2525 static void CmdLcdReset(char *str
)
2528 c
.cmd
= CMD_LCD_RESET
;
2530 SendCommand(&c
, FALSE
);
2533 static void CmdLcd(char *str
)
2538 sscanf(str
, "%x %d", &i
, &j
);
2541 SendCommand(&c
, FALSE
);
2547 static void CmdTest(char *str
)
2552 * Sets the divisor for LF frequency clock: lets the user choose any LF frequency below
2555 static void CmdSetDivisor(char *str
)
2558 c
.cmd
= CMD_SET_LF_DIVISOR
;
2560 if (( c
.ext1
<0) || (c
.ext1
>255)) {
2561 PrintToScrollback("divisor must be between 19 and 255");
2563 SendCommand(&c
, FALSE
);
2564 PrintToScrollback("Divisor set, expected freq=%dHz", 12000000/(c
.ext1
+1));
2568 static void CmdSweepLF(char *str
)
2571 c
.cmd
= CMD_SWEEP_LF
;
2572 SendCommand(&c
, FALSE
);
2576 typedef void HandlerFunction(char *cmdline
);
2578 /* in alphabetic order */
2581 HandlerFunction
*handler
;
2582 int offline
; // 1 if the command can be used when in offline mode
2584 } CommandTable
[] = {
2585 "askdemod", Cmdaskdemod
,1, "<samples per bit> <0|1> -- Attempt to demodulate simple ASK tags",
2586 "autocorr", CmdAutoCorr
,1, "<window length> -- Autocorrelation over window",
2587 "bitsamples", CmdBitsamples
,0, " Get raw samples as bitstring",
2588 "bitstream", Cmdbitstream
,1, "[clock rate] -- Convert waveform into a bitstream",
2589 "buffclear", CmdBuffClear
,0, " Clear sample buffer and graph window",
2590 "dec", CmdDec
,1, " Decimate samples",
2591 "detectclock", Cmddetectclockrate
,1, " Detect clock rate",
2592 "detectreader", CmdDetectReader
,0, "['l'|'h'] -- Detect external reader field (option 'l' or 'h' to limit to LF or HF)",
2593 "em410xsim", CmdEM410xsim
,1, "<UID> -- Simulate EM410x tag",
2594 "em410xread", CmdEM410xread
,1, "[clock rate] -- Extract ID from EM410x tag",
2595 "em410xwatch", CmdEM410xwatch
,0, " Watches for EM410x tags",
2596 "em4x50read", CmdEM4x50read
,1, " Extract data from EM4x50 tag",
2597 "exit", CmdQuit
,1, " Exit program",
2598 "flexdemod", CmdFlexdemod
,1, " Demodulate samples for FlexPass",
2599 "fpgaoff", CmdFPGAOff
,0, " Set FPGA off", // ## FPGA Control
2600 "hexsamples", CmdHexsamples
,0, "<blocks> -- Dump big buffer as hex bytes",
2601 "hi14alist", CmdHi14alist
,0, " List ISO 14443a history", // ## New list command
2602 "hi14areader", CmdHi14areader
,0, " Act like an ISO14443 Type A reader", // ## New reader command
2603 "hi14asim", CmdHi14asim
,0, "<UID> -- Fake ISO 14443a tag", // ## Simulate 14443a tag
2604 "hi14asnoop", CmdHi14asnoop
,0, " Eavesdrop ISO 14443 Type A", // ## New snoop command
2605 "hi14bdemod", CmdHi14bdemod
,1, " Demodulate ISO14443 Type B from tag",
2606 "hi14list", CmdHi14list
,0, " List ISO 14443 history",
2607 "hi14read", CmdHi14read
,0, " Read HF tag (ISO 14443)",
2608 "hi14sim", CmdHi14sim
,0, " Fake ISO 14443 tag",
2609 "hi14snoop", CmdHi14snoop
,0, " Eavesdrop ISO 14443",
2610 "hi15demod", CmdHi15demod
,1, " Demodulate ISO15693 from tag",
2611 "hi15read", CmdHi15read
,0, " Read HF tag (ISO 15693)",
2612 "hi15reader", CmdHi15reader
,0, " Act like an ISO15693 reader", // new command greg
2613 "hi15sim", CmdHi15tag
,0, " Fake an ISO15693 tag", // new command greg
2614 "hiddemod", CmdHiddemod
,1, " Demodulate HID Prox Card II (not optimal)",
2615 "hide", CmdHide
,1, " Hide graph window",
2616 "hidfskdemod", CmdHIDdemodFSK
,0, " Realtime HID FSK demodulator",
2617 "hidsimtag", CmdHIDsimTAG
,0, "<ID> -- HID tag simulator",
2618 "higet", CmdHi14read_sim
,0, "<samples> -- Get samples HF, 'analog'",
2619 "hisamples", CmdHisamples
,0, " Get raw samples for HF tag",
2620 "hisampless", CmdHisampless
,0, "<samples> -- Get signed raw samples, HF tag",
2621 "hisamplest", CmdHi14readt
,0, " Get samples HF, for testing",
2622 "hisimlisten", CmdHisimlisten
,0, " Get HF samples as fake tag",
2623 "hpf", CmdHpf
,1, " Remove DC offset from trace",
2624 "indalademod", CmdIndalademod
,0, "['224'] -- Demodulate samples for Indala 64 bit UID (option '224' for 224 bit)",
2625 "lcd", CmdLcd
,0, "<HEX command> <count> -- Send command/data to LCD",
2626 "lcdreset", CmdLcdReset
,0, " Hardware reset LCD",
2627 "load", CmdLoad
,1, "<filename> -- Load trace (to graph window",
2628 "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)",
2629 "loread", CmdLoread
,0, "['h'] -- Read 125/134 kHz LF ID-only tag (option 'h' for 134)",
2630 "losamples", CmdLosamples
,0, "[128 - 16000] -- Get raw samples for LF tag",
2631 "losim", CmdLosim
,0, " Simulate LF tag",
2632 "ltrim", CmdLtrim
,1, "<samples> -- Trim samples from left of trace",
2633 "mandemod", Cmdmanchesterdemod
,1, "[i] [clock rate] -- Manchester demodulate binary stream (option 'i' to invert output)",
2634 "manmod", Cmdmanchestermod
,1, "[clock rate] -- Manchester modulate a binary stream",
2635 "norm", CmdNorm
,1, " Normalize max/min to +/-500",
2636 "plot", CmdPlot
,1, " Show graph window",
2637 "quit", CmdQuit
,1, " Quit program",
2638 "reset", CmdReset
,0, " Reset the Proxmark3",
2639 "save", CmdSave
,1, "<filename> -- Save trace (from graph window)",
2640 "scale", CmdScale
,1, "<int> -- Set cursor display scale",
2641 "setlfdivisor", CmdSetDivisor
,0, "<19 - 255> -- Drive LF antenna at 12Mhz/(divisor+1)",
2642 "sri512read", CmdSri512read
,0, "<int> -- Read contents of a SRI512 tag",
2643 "sweeplf", CmdSweepLF
,0, " Sweep through LF freq range and store results in buffer",
2644 "tibits", CmdTibits
,0, " Get raw bits for TI-type LF tag",
2645 "tidemod", CmdTidemod
,0, " Demodulate raw bits for TI-type LF tag",
2646 "tiread", CmdTiread
,0, " Read a TI-type 134 kHz tag",
2647 "tune", CmdTune
,0, " Measure antenna tuning",
2648 "vchdemod", CmdVchdemod
,0, "['clone'] -- Demodulate samples for VeriChip",
2649 "zerocrossings", CmdZerocrossings
,1, " Count time between zero-crossings",
2653 //-----------------------------------------------------------------------------
2654 // Entry point into our code: called whenever the user types a command and
2655 // then presses Enter, which the full command line that they typed.
2656 //-----------------------------------------------------------------------------
2657 void CommandReceived(char *cmd
)
2661 PrintToScrollback("> %s", cmd
);
2663 if(strcmp(cmd
, "help")==0) {
2664 if (offline
) PrintToScrollback("Operating in OFFLINE mode (no device connected)");
2665 PrintToScrollback("\r\nAvailable commands:");
2666 for(i
= 0; i
< sizeof(CommandTable
) / sizeof(CommandTable
[0]); i
++) {
2667 if (offline
&& (CommandTable
[i
].offline
==0)) continue;
2669 memset(line
, ' ', sizeof(line
));
2670 strcpy(line
+2, CommandTable
[i
].name
);
2671 line
[strlen(line
)] = ' ';
2672 sprintf(line
+15, " -- %s", CommandTable
[i
].docString
);
2673 PrintToScrollback("%s", line
);
2675 PrintToScrollback("");
2676 PrintToScrollback("and also: help, cls");
2680 for(i
= 0; i
< sizeof(CommandTable
) / sizeof(CommandTable
[0]); i
++) {
2681 char *name
= CommandTable
[i
].name
;
2682 if(memcmp(cmd
, name
, strlen(name
))==0 &&
2683 (cmd
[strlen(name
)] == ' ' || cmd
[strlen(name
)] == '\0'))
2685 cmd
+= strlen(name
);
2686 while(*cmd
== ' ') {
2689 if (offline
&& (CommandTable
[i
].offline
==0)) {
2690 PrintToScrollback("Offline mode, cannot use this command.");
2693 (CommandTable
[i
].handler
)(cmd
);
2697 PrintToScrollback(">> bad command '%s'", cmd
);
2700 //-----------------------------------------------------------------------------
2701 // Entry point into our code: called whenever we received a packet over USB
2702 // that we weren't necessarily expecting, for example a debug print.
2703 //-----------------------------------------------------------------------------
2704 void UsbCommandReceived(UsbCommand
*c
)
2707 case CMD_DEBUG_PRINT_STRING
: {
2709 if(c
->ext1
> 70 || c
->ext1
< 0) {
2712 memcpy(s
, c
->d
.asBytes
, c
->ext1
);
2714 PrintToScrollback("#db# %s", s
);
2718 case CMD_DEBUG_PRINT_INTEGERS
:
2719 PrintToScrollback("#db# %08x, %08x, %08x\r\n", c
->ext1
, c
->ext2
, c
->ext3
);
2722 case CMD_MEASURED_ANTENNA_TUNING
: {
2724 int vLf125
, vLf134
, vHf
;
2725 vLf125
= c
->ext1
& 0xffff;
2726 vLf134
= c
->ext1
>> 16;
2728 zLf
= c
->ext3
& 0xffff;
2729 zHf
= c
->ext3
>> 16;
2730 PrintToScrollback("# LF antenna @ %3d mA / %5d mV [%d ohms] 125Khz",
2731 vLf125
/zLf
, vLf125
, zLf
);
2732 PrintToScrollback("# LF antenna @ %3d mA / %5d mV [%d ohms] 134Khz",
2733 vLf134
/((zLf
*125)/134), vLf134
, (zLf
*125)/134);
2734 PrintToScrollback("# HF antenna @ %3d mA / %5d mV [%d ohms] 13.56Mhz",
2739 PrintToScrollback("unrecognized command %08x\n", c
->cmd
);