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
); 
  56 static void CmdQuit(char *str
) 
  61 static void CmdHIDdemodFSK(char *str
) 
  64         c
.cmd 
= CMD_HID_DEMOD_FSK
; 
  65         SendCommand(&c
, FALSE
); 
  68 static void CmdTune(char *str
) 
  71         c
.cmd 
= CMD_MEASURE_ANTENNA_TUNING
; 
  72         SendCommand(&c
, FALSE
); 
  75 static void CmdHi15read(char *str
) 
  78         c
.cmd 
= CMD_ACQUIRE_RAW_ADC_SAMPLES_ISO_15693
; 
  79         SendCommand(&c
, FALSE
); 
  82 static void CmdHi14read(char *str
) 
  85         c
.cmd 
= CMD_ACQUIRE_RAW_ADC_SAMPLES_ISO_14443
; 
  87         SendCommand(&c
, FALSE
); 
  91 /* New command to read the contents of a SRI512 tag 
  92  * SRI512 tags are ISO14443-B modulated memory tags, 
  93  * this command just dumps the contents of the memory/ 
  95 static void CmdSri512read(char *str
) 
  98         c
.cmd 
= CMD_READ_SRI512_TAG
; 
 100         SendCommand(&c
, FALSE
); 
 104 static void CmdHi14areader(char *str
) 
 107         c
.cmd 
= CMD_READER_ISO_14443a
; 
 109         SendCommand(&c
, FALSE
); 
 113 static void CmdHi15reader(char *str
) 
 116         c
.cmd 
= CMD_READER_ISO_15693
; 
 118         SendCommand(&c
, FALSE
); 
 122 static void CmdHi15tag(char *str
) 
 125         c
.cmd 
= CMD_SIMTAG_ISO_15693
; 
 127         SendCommand(&c
, FALSE
); 
 130 static void CmdHi14read_sim(char *str
) 
 133         c
.cmd 
= CMD_ACQUIRE_RAW_ADC_SAMPLES_ISO_14443_SIM
; 
 135         SendCommand(&c
, FALSE
); 
 138 static void CmdHi14readt(char *str
) 
 141         c
.cmd 
= CMD_ACQUIRE_RAW_ADC_SAMPLES_ISO_14443
; 
 143         SendCommand(&c
, FALSE
); 
 145         //CmdHisamplest(str); 
 146         while(CmdHisamplest(str
,atoi(str
))==0) { 
 147                 c
.cmd 
= CMD_ACQUIRE_RAW_ADC_SAMPLES_ISO_14443
; 
 149                 SendCommand(&c
, FALSE
); 
 151         RepaintGraphWindow(); 
 154 static void CmdHisimlisten(char *str
) 
 157         c
.cmd 
= CMD_SIMULATE_TAG_HF_LISTEN
; 
 158         SendCommand(&c
, FALSE
); 
 161 static void CmdHi14sim(char *str
) 
 164         c
.cmd 
= CMD_SIMULATE_TAG_ISO_14443
; 
 165         SendCommand(&c
, FALSE
); 
 168 static void CmdHi14asim(char *str
)      // ## simulate iso14443a tag 
 169 {                                       // ## greg - added ability to specify tag UID 
 171         unsigned int hi
=0, lo
=0; 
 175         while (sscanf(&str
[i
++], "%1x", &n 
) == 1) { 
 180         c
.cmd 
= CMD_SIMULATE_TAG_ISO_14443a
; 
 181         // c.ext should be set to *str or convert *str to the correct format for a uid 
 184         PrintToScrollback("Emulating 14443A TAG with UID %x%16x", hi
, lo
); 
 185         SendCommand(&c
, FALSE
); 
 188 static void CmdHi14snoop(char *str
) 
 191         c
.cmd 
= CMD_SNOOP_ISO_14443
; 
 192         SendCommand(&c
, FALSE
); 
 195 static void CmdHi14asnoop(char *str
) 
 198         c
.cmd 
= CMD_SNOOP_ISO_14443a
; 
 199         SendCommand(&c
, FALSE
); 
 202 static void CmdFPGAOff(char *str
)               // ## FPGA Control 
 205         c
.cmd 
= CMD_FPGA_MAJOR_MODE_OFF
; 
 206         SendCommand(&c
, FALSE
); 
 209 /* clear out our graph window */ 
 210 int CmdClearGraph(int redraw
) 
 212         int gtl 
= GraphTraceLen
; 
 216                 RepaintGraphWindow(); 
 221 /* write a bit to the graph */ 
 222 static void CmdAppendGraph(int redraw
, int clock
, int bit
) 
 226         for (i 
= 0; i 
< (int)(clock
/2); i
++) 
 227                 GraphBuffer
[GraphTraceLen
++] = bit 
^ 1; 
 229         for (i 
= (int)(clock
/2); i 
< clock
; i
++)         
 230                 GraphBuffer
[GraphTraceLen
++] = bit
; 
 233                 RepaintGraphWindow(); 
 236 /* Function is equivalent of loread + losamples + em410xread 
 237  * looped until an EM410x tag is detected */ 
 238 static void CmdEM410xwatch(char *str
) 
 252 /* Read the ID of an EM410x tag. 
 254  *   1111 1111 1           <-- standard non-repeatable header 
 255  *   XXXX [row parity bit] <-- 10 rows of 5 bits for our 40 bit tag ID 
 257  *   CCCC                  <-- each bit here is parity for the 10 bits above in corresponding column 
 258  *   0                     <-- stop bit, end of tag 
 260 static void CmdEM410xread(char *str
) 
 262         int i
, j
, clock
, header
, rows
, bit
, hithigh
, hitlow
, first
, bit2idx
, high
, low
; 
 265         int BitStream
[MAX_GRAPH_TRACE_LEN
]; 
 268         /* Detect high and lows and clock */ 
 269         for (i 
= 0; i 
< GraphTraceLen
; i
++) 
 271                 if (GraphBuffer
[i
] > high
) 
 272                         high 
= GraphBuffer
[i
]; 
 273                 else if (GraphBuffer
[i
] < low
) 
 274                         low 
= GraphBuffer
[i
]; 
 278         clock 
= GetClock(str
, high
); 
 280         /* parity for our 4 columns */ 
 281         parity
[0] = parity
[1] = parity
[2] = parity
[3] = 0; 
 284         /* manchester demodulate */ 
 286         for (i 
= 0; i 
< (int)(GraphTraceLen 
/ clock
); i
++) 
 292                 /* Find out if we hit both high and low peaks */ 
 293                 for (j 
= 0; j 
< clock
; j
++) 
 295                         if (GraphBuffer
[(i 
* clock
) + j
] == high
) 
 297                         else if (GraphBuffer
[(i 
* clock
) + j
] == low
) 
 300                         /* it doesn't count if it's the first part of our read 
 301                          because it's really just trailing from the last sequence */ 
 302                         if (first 
&& (hithigh 
|| hitlow
)) 
 303                                 hithigh 
= hitlow 
= 0; 
 307                         if (hithigh 
&& hitlow
) 
 311                 /* If we didn't hit both high and low peaks, we had a bit transition */ 
 312                 if (!hithigh 
|| !hitlow
) 
 315                 BitStream
[bit2idx
++] = bit
; 
 318         /* We go till 5 before the graph ends because we'll get that far below */ 
 319         for (i 
= 1; i 
< bit2idx 
- 5; i
++) 
 321                 /* Step 2: We have our header but need our tag ID */ 
 322                 if (header 
== 9 && rows 
< 10) 
 324                         /* Confirm parity is correct */ 
 325                         if ((BitStream
[i
] ^ BitStream
[i
+1] ^ BitStream
[i
+2] ^ BitStream
[i
+3]) == BitStream
[i
+4]) 
 327                                 /* Read another byte! */ 
 328                                 sprintf(id
+rows
, "%x", (8 * BitStream
[i
]) + (4 * BitStream
[i
+1]) + (2 * BitStream
[i
+2]) + (1 * BitStream
[i
+3])); 
 331                                 /* Keep parity info */ 
 332                                 parity
[0] ^= BitStream
[i
]; 
 333                                 parity
[1] ^= BitStream
[i
+1]; 
 334                                 parity
[2] ^= BitStream
[i
+2]; 
 335                                 parity
[3] ^= BitStream
[i
+3]; 
 337                                 /* Move 4 bits ahead */ 
 341                         /* Damn, something wrong! reset */ 
 344                                 PrintToScrollback("Thought we had a valid tag but failed at word %d (i=%d)", rows 
+ 1, i
); 
 346                                 /* Start back rows * 5 + 9 header bits, -1 to not start at same place */ 
 347                                 i 
-= 9 + (5 * rows
) - 5; 
 353                 /* Step 3: Got our 40 bits! confirm column parity */ 
 356                         /* We need to make sure our 4 bits of parity are correct and we have a stop bit */ 
 357                         if (BitStream
[i
] == parity
[0] && BitStream
[i
+1] == parity
[1] && 
 358                                 BitStream
[i
+2] == parity
[2] && BitStream
[i
+3] == parity
[3] && 
 362                                 PrintToScrollback("EM410x Tag ID: %s", id
); 
 369                         /* Crap! Incorrect parity or no stop bit, start all over */ 
 374                                 /* Go back 59 bits (9 header bits + 10 rows at 4+1 parity) */ 
 379                 /* Step 1: get our header */ 
 382                         /* Need 9 consecutive 1's */ 
 383                         if (BitStream
[i
] == 1) 
 386                         /* We don't have a header, not enough consecutive 1 bits */ 
 393 /* emulate an EM410X tag 
 395  *   1111 1111 1           <-- standard non-repeatable header 
 396  *   XXXX [row parity bit] <-- 10 rows of 5 bits for our 40 bit tag ID 
 398  *   CCCC                  <-- each bit here is parity for the 10 bits above in corresponding column 
 399  *   0                     <-- stop bit, end of tag 
 401 static void CmdEM410xsim(char *str
) 
 403         int i
, n
, j
, h
, binary
[4], parity
[4]; 
 406         /* clock is 64 in EM410x tags */ 
 409         /* clear our graph */ 
 412         /* write it out a few times */ 
 413         for (h 
= 0; h 
< 4; h
++) 
 415                 /* write 9 start bits */ 
 416                 for (i 
= 0; i 
< 9; i
++) 
 417                         CmdAppendGraph(0, clock
, 1); 
 419                 /* for each hex char */ 
 420                 parity
[0] = parity
[1] = parity
[2] = parity
[3] = 0; 
 421                 for (i 
= 0; i 
< 10; i
++) 
 423                         /* read each hex char */ 
 424                         sscanf(&str
[i
], "%1x", &n
); 
 425                         for (j 
= 3; j 
>= 0; j
--, n
/= 2) 
 428                         /* append each bit */ 
 429                         CmdAppendGraph(0, clock
, binary
[0]); 
 430                         CmdAppendGraph(0, clock
, binary
[1]); 
 431                         CmdAppendGraph(0, clock
, binary
[2]); 
 432                         CmdAppendGraph(0, clock
, binary
[3]); 
 434                         /* append parity bit */ 
 435                         CmdAppendGraph(0, clock
, binary
[0] ^ binary
[1] ^ binary
[2] ^ binary
[3]); 
 437                         /* keep track of column parity */ 
 438                         parity
[0] ^= binary
[0]; 
 439                         parity
[1] ^= binary
[1]; 
 440                         parity
[2] ^= binary
[2]; 
 441                         parity
[3] ^= binary
[3]; 
 445                 CmdAppendGraph(0, clock
, parity
[0]); 
 446                 CmdAppendGraph(0, clock
, parity
[1]); 
 447                 CmdAppendGraph(0, clock
, parity
[2]); 
 448                 CmdAppendGraph(0, clock
, parity
[3]); 
 451                 CmdAppendGraph(0, clock
, 0); 
 454         /* modulate that biatch */ 
 458         RepaintGraphWindow(); 
 463 static void ChkBitstream(char *str
) 
 467         /* convert to bitstream if necessary */ 
 468         for (i 
= 0; i 
< (int)(GraphTraceLen 
/ 2); i
++) 
 470                 if (GraphBuffer
[i
] > 1 || GraphBuffer
[i
] < 0) 
 478 static void CmdLosim(char *str
) 
 483         /* convert to bitstream if necessary */ 
 486         for (i 
= 0; i 
< GraphTraceLen
; i 
+= 48) { 
 489                 for(j 
= 0; j 
< 48; j
++) { 
 490                         c
.d
.asBytes
[j
] = GraphBuffer
[i
+j
]; 
 492                 c
.cmd 
= CMD_DOWNLOADED_SIM_SAMPLES_125K
; 
 494                 SendCommand(&c
, FALSE
); 
 498         c
.cmd 
= CMD_SIMULATE_TAG_125K
; 
 499         c
.ext1 
= GraphTraceLen
; 
 500         SendCommand(&c
, FALSE
); 
 503 static void CmdLoread(char *str
) 
 506         // 'h' means higher-low-frequency, 134 kHz 
 509         } else if (*str 
== '\0') { 
 512                 PrintToScrollback("use 'loread' or 'loread h'"); 
 515         c
.cmd 
= CMD_ACQUIRE_RAW_ADC_SAMPLES_125K
; 
 516         SendCommand(&c
, FALSE
); 
 519 static void CmdLosamples(char *str
) 
 527         if (n
>16000) n
=16000; 
 529         for(i 
= 0; i 
< n
; i 
+= 12) { 
 531                 c
.cmd 
= CMD_DOWNLOAD_RAW_ADC_SAMPLES_125K
; 
 533                 SendCommand(&c
, FALSE
); 
 535                 if(c
.cmd 
!= CMD_DOWNLOADED_RAW_ADC_SAMPLES_125K
) { 
 537                                 PrintToScrollback("bad resp"); 
 541                 for(j 
= 0; j 
< 48; j
++) { 
 542                         GraphBuffer
[cnt
++] = ((int)c
.d
.asBytes
[j
]) - 128; 
 546         RepaintGraphWindow(); 
 549 static void CmdBitsamples(char *str
) 
 556         for(i 
= 0; i 
< n
; i 
+= 12) { 
 558                 c
.cmd 
= CMD_DOWNLOAD_RAW_ADC_SAMPLES_125K
; 
 560                 SendCommand(&c
, FALSE
); 
 562                 if(c
.cmd 
!= CMD_DOWNLOADED_RAW_ADC_SAMPLES_125K
) { 
 563                         PrintToScrollback("bad resp"); 
 567                 for(j 
= 0; j 
< 48; j
++) { 
 568                         for(k 
= 0; k 
< 8; k
++) { 
 569                                 if(c
.d
.asBytes
[j
] & (1 << (7 - k
))) { 
 570                                         GraphBuffer
[cnt
++] = 1; 
 572                                         GraphBuffer
[cnt
++] = 0; 
 578         RepaintGraphWindow(); 
 581 static void CmdHisamples(char *str
) 
 587         for(i 
= 0; i 
< n
; i 
+= 12) { 
 589                 c
.cmd 
= CMD_DOWNLOAD_RAW_ADC_SAMPLES_125K
; 
 591                 SendCommand(&c
, FALSE
); 
 593                 if(c
.cmd 
!= CMD_DOWNLOADED_RAW_ADC_SAMPLES_125K
) { 
 594                         PrintToScrollback("bad resp"); 
 598                 for(j 
= 0; j 
< 48; j
++) { 
 599                         GraphBuffer
[cnt
++] = (int)((BYTE
)c
.d
.asBytes
[j
]); 
 604         RepaintGraphWindow(); 
 608 static int CmdHisamplest(char *str
, int nrlow
) 
 620         for(i 
= 0; i 
< n
; i 
+= 12) { 
 622                 c
.cmd 
= CMD_DOWNLOAD_RAW_ADC_SAMPLES_125K
; 
 624                 SendCommand(&c
, FALSE
); 
 626                 if(c
.cmd 
!= CMD_DOWNLOADED_RAW_ADC_SAMPLES_125K
) { 
 627                         PrintToScrollback("bad resp"); 
 631                 for(j 
= 0; j 
< 48; j
++) { 
 632                         t2 
= (int)((BYTE
)c
.d
.asBytes
[j
]); 
 633                         if((t2 
^ 0xC0) & 0xC0) { hasbeennull
++; } 
 639                                         t1 
= (t2 
& 0x80) ^ (t2 
& 0x20); 
 640                                         t2 
= ((t2 
<< 1) & 0x80) ^ ((t2 
<< 1) & 0x20); 
 646                                         t2 
= ((t2 
<< 1) & 0x80); 
 652                                         t2 
= ((t2 
<< 1) & 0x20); 
 656                                         // both, but tag with other algorithm 
 657                                         t1 
= (t2 
& 0x80) ^ (t2 
& 0x08); 
 658                                         t2 
= ((t2 
<< 1) & 0x80) ^ ((t2 
<< 1) & 0x08); 
 662                         GraphBuffer
[cnt
++] = t1
; 
 663                         GraphBuffer
[cnt
++] = t2
; 
 668         if(hasbeennull
>nrlow 
|| nrlow
==0) { 
 669                 PrintToScrollback("hasbeennull=%d", hasbeennull
); 
 678 static void CmdHexsamples(char *str
) 
 689         for(i 
= 0; i 
< n
; i 
+= 12) { 
 691                 c
.cmd 
= CMD_DOWNLOAD_RAW_ADC_SAMPLES_125K
; 
 693                 SendCommand(&c
, FALSE
); 
 695                 if(c
.cmd 
!= CMD_DOWNLOADED_RAW_ADC_SAMPLES_125K
) { 
 696                         PrintToScrollback("bad resp"); 
 700                 for(j 
= 0; j 
< 48; j 
+= 8) { 
 701                         PrintToScrollback("%02x %02x %02x %02x %02x %02x %02x %02x", 
 716 static void CmdHisampless(char *str
) 
 728         for(i 
= 0; i 
< n
; i 
+= 12) { 
 730                 c
.cmd 
= CMD_DOWNLOAD_RAW_ADC_SAMPLES_125K
; 
 732                 SendCommand(&c
, FALSE
); 
 734                 if(c
.cmd 
!= CMD_DOWNLOADED_RAW_ADC_SAMPLES_125K
) { 
 735                         PrintToScrollback("bad resp"); 
 739                 for(j 
= 0; j 
< 48; j
++) { 
 740                         GraphBuffer
[cnt
++] = (int)((signed char)c
.d
.asBytes
[j
]); 
 745         RepaintGraphWindow(); 
 748 static WORD 
Iso15693Crc(BYTE 
*v
, int n
) 
 754         for(i 
= 0; i 
< n
; i
++) { 
 755                 reg 
= reg 
^ ((DWORD
)v
[i
]); 
 756                 for (j 
= 0; j 
< 8; j
++) { 
 758                                 reg 
= (reg 
>> 1) ^ 0x8408; 
 768 static void CmdHi14bdemod(char *str
) 
 773         BOOL negateI
, negateQ
; 
 778         // As received, the samples are pairs, correlations against I and Q 
 779         // square waves. So estimate angle of initial carrier (or just 
 780         // quadrant, actually), and then do the demod. 
 782         // First, estimate where the tag starts modulating. 
 783         for(i 
= 0; i 
< GraphTraceLen
; i 
+= 2) { 
 784                 if(abs(GraphBuffer
[i
]) + abs(GraphBuffer
[i
+1]) > 40) { 
 788         if(i 
>= GraphTraceLen
) { 
 789                 PrintToScrollback("too weak to sync"); 
 792         PrintToScrollback("out of weak at %d", i
); 
 795         // Now, estimate the phase in the initial modulation of the tag 
 798         for(; i 
< (outOfWeakAt 
+ 16); i 
+= 2) { 
 799                 isum 
+= GraphBuffer
[i
+0]; 
 800                 qsum 
+= GraphBuffer
[i
+1]; 
 802         negateI 
= (isum 
< 0); 
 803         negateQ 
= (qsum 
< 0); 
 805         // Turn the correlation pairs into soft decisions on the bit. 
 807         for(i 
= 0; i 
< GraphTraceLen
/2; i
++) { 
 808                 int si 
= GraphBuffer
[j
]; 
 809                 int sq 
= GraphBuffer
[j
+1]; 
 810                 if(negateI
) si 
= -si
; 
 811                 if(negateQ
) sq 
= -sq
; 
 812                 GraphBuffer
[i
] = si 
+ sq
; 
 818         while(GraphBuffer
[i
] > 0 && i 
< GraphTraceLen
) 
 820         if(i 
>= GraphTraceLen
) goto demodError
; 
 823         while(GraphBuffer
[i
] < 0 && i 
< GraphTraceLen
) 
 825         if(i 
>= GraphTraceLen
) goto demodError
; 
 826         if((i 
- iold
) > 23) goto demodError
; 
 828         PrintToScrollback("make it to demod loop"); 
 832                 while(GraphBuffer
[i
] >= 0 && i 
< GraphTraceLen
) 
 834                 if(i 
>= GraphTraceLen
) goto demodError
; 
 835                 if((i 
- iold
) > 6) goto demodError
; 
 838                 if(i 
+ 20 >= GraphTraceLen
) goto demodError
; 
 840                 for(j 
= 0; j 
< 10; j
++) { 
 841                         int soft 
= GraphBuffer
[i
] + GraphBuffer
[i
+1]; 
 843                         if(abs(soft
) < ((abs(isum
) + abs(qsum
))/20)) { 
 844                                 PrintToScrollback("weak bit"); 
 848                         if(GraphBuffer
[i
] + GraphBuffer
[i
+1] >= 0) { 
 855                 if( (shiftReg 
& 0x200) && 
 858                         // valid data byte, start and stop bits okay 
 859                         PrintToScrollback("   %02x", (shiftReg 
>> 1) & 0xff); 
 860                         data
[dataLen
++] = (shiftReg 
>> 1) & 0xff; 
 861                         if(dataLen 
>= sizeof(data
)) { 
 864                 } else if(shiftReg 
== 0x000) { 
 873         ComputeCrc14443(CRC_14443_B
, data
, dataLen
-2, &first
, &second
); 
 874         PrintToScrollback("CRC: %02x %02x (%s)\n", first
, second
, 
 875                 (first 
== data
[dataLen
-2] && second 
== data
[dataLen
-1]) ? 
 876                         "ok" : "****FAIL****"); 
 878         RepaintGraphWindow(); 
 882         PrintToScrollback("demod error"); 
 883         RepaintGraphWindow(); 
 886 static void CmdHi14list(char *str
) 
 889         GetFromBigBuf(got
, sizeof(got
)); 
 891         PrintToScrollback("recorded activity:"); 
 892         PrintToScrollback(" time        :rssi: who bytes"); 
 893         PrintToScrollback("---------+----+----+-----------"); 
 904                 int timestamp 
= *((DWORD 
*)(got
+i
)); 
 905                 if(timestamp 
& 0x80000000) { 
 906                         timestamp 
&= 0x7fffffff; 
 911                 int metric 
= *((DWORD 
*)(got
+i
+4)); 
 922                 BYTE 
*frame 
= (got
+i
+9); 
 924                 char line
[1000] = ""; 
 926                 for(j 
= 0; j 
< len
; j
++) { 
 927                         sprintf(line
+(j
*3), "%02x  ", frame
[j
]); 
 933                         ComputeCrc14443(CRC_14443_B
, frame
, len
-2, &b1
, &b2
); 
 934                         if(b1 
!= frame
[len
-2] || b2 
!= frame
[len
-1]) { 
 935                                 crc 
= "**FAIL CRC**"; 
 943                 char metricString
[100]; 
 945                         sprintf(metricString
, "%3d", metric
); 
 947                         strcpy(metricString
, "   "); 
 950                 PrintToScrollback(" +%7d: %s: %s %s %s", 
 951                         (prev 
< 0 ? 0 : timestamp 
- prev
), 
 953                         (isResponse 
? "TAG" : "   "), line
, crc
); 
 960 static void CmdHi14alist(char *str
) 
 963         GetFromBigBuf(got
, sizeof(got
)); 
 965         PrintToScrollback("recorded activity:"); 
 966         PrintToScrollback(" ETU     :rssi: who bytes"); 
 967         PrintToScrollback("---------+----+----+-----------"); 
 978                 int timestamp 
= *((DWORD 
*)(got
+i
)); 
 979                 if(timestamp 
& 0x80000000) { 
 980                         timestamp 
&= 0x7fffffff; 
 987                 int parityBits 
= *((DWORD 
*)(got
+i
+4)); 
 988                 // 4 bytes of additional information... 
 989                 // maximum of 32 additional parity bit information 
 992                 // at each quarter bit period we can send power level (16 levels) 
 993                 // or each half bit period in 256 levels. 
1001                 if(i 
+ len 
>= 1900) { 
1005                 BYTE 
*frame 
= (got
+i
+9); 
1007                 // Break and stick with current result if buffer was not completely full 
1008                 if(frame
[0] == 0x44 && frame
[1] == 0x44 && frame
[3] == 0x44) { break; } 
1010                 char line
[1000] = ""; 
1012                 for(j 
= 0; j 
< len
; j
++) { 
1013                         int oddparity 
= 0x01; 
1017                                 oddparity 
^= (((frame
[j
] & 0xFF) >> k
) & 0x01); 
1020                         //if((parityBits >> (len - j - 1)) & 0x01) { 
1021                         if(isResponse 
&& (oddparity 
!= ((parityBits 
>> (len 
- j 
- 1)) & 0x01))) { 
1022                                 sprintf(line
+(j
*4), "%02x!  ", frame
[j
]); 
1025                                 sprintf(line
+(j
*4), "%02x   ", frame
[j
]); 
1033                         for(j 
= 0; j 
< (len 
- 1); j
++) { 
1034                                 // gives problems... search for the reason.. 
1035                                 /*if(frame[j] == 0xAA) { 
1036                                         switch(frame[j+1]) { 
1038                                                         crc = "[1] Two drops close after each other"; 
1041                                                         crc = "[2] Potential SOC with a drop in second half of bitperiod"; 
1044                                                         crc = "[3] Segment Z after segment X is not possible"; 
1047                                                         crc = "[4] Parity bit of a fully received byte was wrong"; 
1050                                                         crc = "[?] Unknown error"; 
1057                         if(strlen(crc
)==0) { 
1058                                 ComputeCrc14443(CRC_14443_A
, frame
, len
-2, &b1
, &b2
); 
1059                                 if(b1 
!= frame
[len
-2] || b2 
!= frame
[len
-1]) { 
1060                                         crc 
= (isResponse 
& (len 
< 6)) ? "" : " !crc"; 
1069                 char metricString
[100]; 
1071                         sprintf(metricString
, "%3d", metric
); 
1073                         strcpy(metricString
, "   "); 
1076                 PrintToScrollback(" +%7d: %s: %s %s %s", 
1077                         (prev 
< 0 ? 0 : (timestamp 
- prev
)), 
1079                         (isResponse 
? "TAG" : "   "), line
, crc
); 
1084         CommandFinished 
= 1; 
1087 static void CmdHi15demod(char *str
) 
1089         // The sampling rate is 106.353 ksps/s, for T = 18.8 us 
1092         // 1) Unmodulated time of 56.64us 
1093         // 2) 24 pulses of 423.75khz 
1094         // 3) logic '1' (unmodulated for 18.88us followed by 8 pulses of 423.75khz) 
1096         static const int FrameSOF
[] = { 
1097                 -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 
1098                 -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 
1099                  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1, 
1100                  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1, 
1106         static const int Logic0
[] = { 
1112         static const int Logic1
[] = { 
1120         // 1) logic '0' (8 pulses of 423.75khz followed by unmodulated for 18.88us) 
1121         // 2) 24 pulses of 423.75khz 
1122         // 3) Unmodulated time of 56.64us 
1124         static const int FrameEOF
[] = { 
1129                  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1, 
1130                  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1, 
1131                 -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 
1132                 -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 
1136         int max 
= 0, maxPos
; 
1140         if(GraphTraceLen 
< 1000) return; 
1142         // First, correlate for SOF 
1143         for(i 
= 0; i 
< 100; i
++) { 
1145                 for(j 
= 0; j 
< arraylen(FrameSOF
); j 
+= skip
) { 
1146                         corr 
+= FrameSOF
[j
]*GraphBuffer
[i
+(j
/skip
)]; 
1153         PrintToScrollback("SOF at %d, correlation %d", maxPos
, 
1154                 max
/(arraylen(FrameSOF
)/skip
)); 
1156         i 
= maxPos 
+ arraylen(FrameSOF
)/skip
; 
1159         memset(outBuf
, 0, sizeof(outBuf
)); 
1162                 int corr0 
= 0, corr1 
= 0, corrEOF 
= 0; 
1163                 for(j 
= 0; j 
< arraylen(Logic0
); j 
+= skip
) { 
1164                         corr0 
+= Logic0
[j
]*GraphBuffer
[i
+(j
/skip
)]; 
1166                 for(j 
= 0; j 
< arraylen(Logic1
); j 
+= skip
) { 
1167                         corr1 
+= Logic1
[j
]*GraphBuffer
[i
+(j
/skip
)]; 
1169                 for(j 
= 0; j 
< arraylen(FrameEOF
); j 
+= skip
) { 
1170                         corrEOF 
+= FrameEOF
[j
]*GraphBuffer
[i
+(j
/skip
)]; 
1172                 // Even things out by the length of the target waveform. 
1176                 if(corrEOF 
> corr1 
&& corrEOF 
> corr0
) { 
1177                         PrintToScrollback("EOF at %d", i
); 
1179                 } else if(corr1 
> corr0
) { 
1180                         i 
+= arraylen(Logic1
)/skip
; 
1183                         i 
+= arraylen(Logic0
)/skip
; 
1190                 if((i
+(int)arraylen(FrameEOF
)) >= GraphTraceLen
) { 
1191                         PrintToScrollback("ran off end!"); 
1196                 PrintToScrollback("error, uneven octet! (discard extra bits!)"); 
1197                 PrintToScrollback("   mask=%02x", mask
); 
1199         PrintToScrollback("%d octets", k
); 
1201         for(i 
= 0; i 
< k
; i
++) { 
1202                 PrintToScrollback("# %2d: %02x ", i
, outBuf
[i
]); 
1204         PrintToScrollback("CRC=%04x", Iso15693Crc(outBuf
, k
-2)); 
1207 static void CmdTiread(char *str
) 
1210         c
.cmd 
= CMD_ACQUIRE_RAW_BITS_TI_TYPE
; 
1211         SendCommand(&c
, FALSE
); 
1214 static void CmdTibits(char *str
) 
1218         for(i 
= 0; i 
< 1536; i 
+= 12) { 
1220                 c
.cmd 
= CMD_DOWNLOAD_RAW_BITS_TI_TYPE
; 
1222                 SendCommand(&c
, FALSE
); 
1224                 if(c
.cmd 
!= CMD_DOWNLOADED_RAW_BITS_TI_TYPE
) { 
1225                         PrintToScrollback("bad resp"); 
1229                 for(j 
= 0; j 
< 12; j
++) { 
1231                         for(k 
= 31; k 
>= 0; k
--) { 
1232                                 if(c
.d
.asDwords
[j
] & (1 << k
)) { 
1233                                         GraphBuffer
[cnt
++] = 1; 
1235                                         GraphBuffer
[cnt
++] = -1; 
1240         GraphTraceLen 
= 1536*32; 
1241         RepaintGraphWindow(); 
1244 static void CmdTidemod(char *cmdline
) 
1246         /* MATLAB as follows: 
1247 f_s = 2000000;  % sampling frequency 
1248 f_l = 123200;   % low FSK tone 
1249 f_h = 134200;   % high FSK tone 
1251 T_l = 119e-6;   % low bit duration 
1252 T_h = 130e-6;   % high bit duration 
1254 l = 2*pi*ones(1, floor(f_s*T_l))*(f_l/f_s); 
1255 h = 2*pi*ones(1, floor(f_s*T_h))*(f_h/f_s); 
1257 l = sign(sin(cumsum(l))); 
1258 h = sign(sin(cumsum(h))); 
1260         static const int LowTone
[] = { 
1261                 1, 1, 1, 1, 1, 1, 1, 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, -1, 1, 1, 1, 1, 1, 1, 
1263                 1, 1, -1, -1, -1, -1, -1, -1, -1, -1, 1, 1, 1, 1, 1, 1, 1, 1, -1, 
1264                 -1, -1, -1, -1, -1, -1, -1, 1, 1, 1, 1, 1, 1, 1, 1, 1, -1, -1, -1, 
1265                 -1, -1, -1, -1, -1, 1, 1, 1, 1, 1, 1, 1, 1, -1, -1, -1, -1, -1, -1, 
1266                 -1, -1, 1, 1, 1, 1, 1, 1, 1, 1, -1, -1, -1, -1, -1, -1, -1, -1, 1, 
1267                 1, 1, 1, 1, 1, 1, 1, -1, -1, -1, -1, -1, -1, -1, -1, 1, 1, 1, 1, 
1268                 1, 1, 1, 1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 1, 1, 1, 1, 1, 1, 
1269                 1, 1, -1, -1, -1, -1, -1, -1, -1, -1, 1, 1, 1, 1, 1, 1, 1, 1, -1, 
1270                 -1, -1, -1, -1, -1, -1, -1, 1, 1, 1, 1, 1, 1, 1, 1, -1, -1, -1, -1, 
1271                 -1, -1, -1, -1, 1, 1, 1, 1, 1, 1, 1, 1, -1, -1, -1, -1, -1, -1, -1, 
1272                 -1, -1, 1, 1, 1, 1, 1, 1, 1, 1, -1, -1, -1, -1, -1, -1, -1, -1, 1, 
1273                 1, 1, 1, 1, 1, 1, 1, -1, -1, -1, 
1275         static const int HighTone
[] = { 
1276                 1, 1, 1, 1, 1, 1, 1, -1, -1, -1, -1, -1, -1, -1, 1, 1, 1, 1, 1, 1, 
1277                 1, 1, -1, -1, -1, -1, -1, -1, -1, 1, 1, 1, 1, 1, 1, 1, 1, -1, -1, 
1278                 -1, -1, -1, -1, -1, 1, 1, 1, 1, 1, 1, 1, 1, -1, -1, -1, -1, -1, 
1279                 -1, -1, 1, 1, 1, 1, 1, 1, 1, 1, -1, -1, -1, -1, -1, -1, -1, 1, 1, 
1280                 1, 1, 1, 1, 1, -1, -1, -1, -1, -1, -1, -1, -1, 1, 1, 1, 1, 1, 1, 
1281                 1, -1, -1, -1, -1, -1, -1, -1, -1, 1, 1, 1, 1, 1, 1, 1, -1, -1, 
1282                 -1, -1, -1, -1, -1, -1, 1, 1, 1, 1, 1, 1, 1, -1, -1, -1, -1, -1, 
1283                 -1, -1, -1, 1, 1, 1, 1, 1, 1, 1, -1, -1, -1, -1, -1, -1, -1, -1, 
1284                 1, 1, 1, 1, 1, 1, 1, -1, -1, -1, -1, -1, -1, -1, 1, 1, 1, 1, 1, 1, 
1285                 1, 1, -1, -1, -1, -1, -1, -1, -1, 1, 1, 1, 1, 1, 1, 1, 1, -1, -1, 
1286                 -1, -1, -1, -1, -1, 1, 1, 1, 1, 1, 1, 1, 1, -1, -1, -1, -1, -1, 
1287                 -1, -1, 1, 1, 1, 1, 1, 1, 1, 1, -1, -1, -1, -1, -1, -1, -1, 1, 1, 
1288                 1, 1, 1, 1, 1, -1, -1, -1, -1, -1, -1, -1, -1, 1, 1, 1, 1, 1, 1, 
1289                 1, -1, -1, -1, -1, -1, -1, -1, -1, 1, 1, 1, 1, 1, 1, 1, 
1292         int convLen 
= max(arraylen(HighTone
), arraylen(LowTone
)); 
1295         for(i 
= 0; i 
< GraphTraceLen 
- convLen
; i
++) { 
1297                 int lowSum 
= 0, highSum 
= 0;; 
1298                 int lowLen 
= arraylen(LowTone
); 
1299                 int highLen 
= arraylen(HighTone
); 
1301                 for(j 
= 0; j 
< lowLen
; j
++) { 
1302                         lowSum 
+= LowTone
[j
]*GraphBuffer
[i
+j
]; 
1304                 for(j 
= 0; j 
< highLen
; j
++) { 
1305                         highSum 
+= HighTone
[j
]*GraphBuffer
[i
+j
]; 
1307                 lowSum 
= abs((100*lowSum
) / lowLen
); 
1308                 highSum 
= abs((100*highSum
) / highLen
); 
1309                 GraphBuffer
[i
] = (highSum 
<< 16) | lowSum
; 
1312         for(i 
= 0; i 
< GraphTraceLen 
- convLen 
- 16; i
++) { 
1314                 int lowTot 
= 0, highTot 
= 0; 
1315                 // 16 and 15 are f_s divided by f_l and f_h, rounded 
1316                 for(j 
= 0; j 
< 16; j
++) { 
1317                         lowTot 
+= (GraphBuffer
[i
+j
] & 0xffff); 
1319                 for(j 
= 0; j 
< 15; j
++) { 
1320                         highTot 
+= (GraphBuffer
[i
+j
] >> 16); 
1322                 GraphBuffer
[i
] = lowTot 
- highTot
; 
1325         GraphTraceLen 
-= (convLen 
+ 16); 
1327         RepaintGraphWindow(); 
1329         // Okay, so now we have unsliced soft decisions; find bit-sync, and then 
1332         int max 
= 0, maxPos 
= 0; 
1333         for(i 
= 0; i 
< 6000; i
++) { 
1336                 for(j 
= 0; j 
< 8*arraylen(LowTone
); j
++) { 
1337                         dec 
-= GraphBuffer
[i
+j
]; 
1339                 for(; j 
< 8*arraylen(LowTone
) + 8*arraylen(HighTone
); j
++) { 
1340                         dec 
+= GraphBuffer
[i
+j
]; 
1347         GraphBuffer
[maxPos
] = 800; 
1348         GraphBuffer
[maxPos
+1] = -800; 
1350         maxPos 
+= 8*arraylen(LowTone
); 
1351         GraphBuffer
[maxPos
] = 800; 
1352         GraphBuffer
[maxPos
+1] = -800; 
1353         maxPos 
+= 8*arraylen(HighTone
); 
1355         GraphBuffer
[maxPos
] = 800; 
1356         GraphBuffer
[maxPos
+1] = -800; 
1358         PrintToScrollback("actual data bits start at sample %d", maxPos
); 
1360         PrintToScrollback("length %d/%d", arraylen(HighTone
), arraylen(LowTone
)); 
1362         GraphBuffer
[maxPos
] = 800; 
1363         GraphBuffer
[maxPos
+1] = -800; 
1365         BYTE bits
[64+16+8+1]; 
1366         bits
[sizeof(bits
)-1] = '\0'; 
1368         for(i 
= 0; i 
< arraylen(bits
); i
++) { 
1372                 for(j 
= 0; j 
< arraylen(LowTone
); j
++) { 
1373                         low 
-= GraphBuffer
[maxPos
+j
]; 
1375                 for(j 
= 0; j 
< arraylen(HighTone
); j
++) { 
1376                         high 
+= GraphBuffer
[maxPos
+j
]; 
1380                         maxPos 
+= arraylen(HighTone
); 
1383                         maxPos 
+= arraylen(LowTone
); 
1385                 GraphBuffer
[maxPos
] = 800; 
1386                 GraphBuffer
[maxPos
+1] = -800; 
1388         PrintToScrollback("bits: '%s'", bits
); 
1391         for(i 
= 0; i 
< 32; i
++) { 
1392                 if(bits
[i
] == '1') { 
1396         for(i 
= 32; i 
< 64; i
++) { 
1397                 if(bits
[i
] == '1') { 
1401         PrintToScrollback("hex: %08x %08x", h
, l
); 
1404 static void CmdNorm(char *str
) 
1407         int max 
= INT_MIN
, min 
= INT_MAX
; 
1408         for(i 
= 10; i 
< GraphTraceLen
; i
++) { 
1409                 if(GraphBuffer
[i
] > max
) { 
1410                         max 
= GraphBuffer
[i
]; 
1412                 if(GraphBuffer
[i
] < min
) { 
1413                         min 
= GraphBuffer
[i
]; 
1417                 for(i 
= 0; i 
< GraphTraceLen
; i
++) { 
1418                         GraphBuffer
[i
] = (GraphBuffer
[i
] - ((max 
+ min
)/2))*1000/ 
1422         RepaintGraphWindow(); 
1425 static void CmdDec(char *str
) 
1428         for(i 
= 0; i 
< (GraphTraceLen
/2); i
++) { 
1429                 GraphBuffer
[i
] = GraphBuffer
[i
*2]; 
1432         PrintToScrollback("decimated by 2"); 
1433         RepaintGraphWindow(); 
1436 static void CmdHpf(char *str
) 
1440         for(i 
= 10; i 
< GraphTraceLen
; i
++) { 
1441                 accum 
+= GraphBuffer
[i
]; 
1443         accum 
/= (GraphTraceLen 
- 10); 
1444         for(i 
= 0; i 
< GraphTraceLen
; i
++) { 
1445                 GraphBuffer
[i
] -= accum
; 
1448         RepaintGraphWindow(); 
1451 static void CmdZerocrossings(char *str
) 
1454         // Zero-crossings aren't meaningful unless the signal is zero-mean. 
1460         for(i 
= 0; i 
< GraphTraceLen
; i
++) { 
1461                 if(GraphBuffer
[i
]*sign 
>= 0) { 
1462                         // No change in sign, reproduce the previous sample count. 
1464                         GraphBuffer
[i
] = lastZc
; 
1466                         // Change in sign, reset the sample count. 
1468                         GraphBuffer
[i
] = lastZc
; 
1476         RepaintGraphWindow(); 
1479 static void CmdLtrim(char *str
) 
1484         for(i 
= ds
; i 
< GraphTraceLen
; i
++) { 
1485                 GraphBuffer
[i
-ds
] = GraphBuffer
[i
]; 
1487         GraphTraceLen 
-= ds
; 
1489         RepaintGraphWindow(); 
1492 static void CmdAutoCorr(char *str
) 
1494         static int CorrelBuffer
[MAX_GRAPH_TRACE_LEN
]; 
1496         int window 
= atoi(str
); 
1499                 PrintToScrollback("needs a window"); 
1503         if(window 
>= GraphTraceLen
) { 
1504                 PrintToScrollback("window must be smaller than trace (%d samples)", 
1509         PrintToScrollback("performing %d correlations", GraphTraceLen 
- window
); 
1512         for(i 
= 0; i 
< GraphTraceLen 
- window
; i
++) { 
1515                 for(j 
= 0; j 
< window
; j
++) { 
1516                         sum 
+= (GraphBuffer
[j
]*GraphBuffer
[i
+j
]) / 256; 
1518                 CorrelBuffer
[i
] = sum
; 
1520         GraphTraceLen 
= GraphTraceLen 
- window
; 
1521         memcpy(GraphBuffer
, CorrelBuffer
, GraphTraceLen
*sizeof(int)); 
1523         RepaintGraphWindow(); 
1526 static void CmdVchdemod(char *str
) 
1528         // Is this the entire sync pattern, or does this also include some 
1529         // data bits that happen to be the same everywhere? That would be 
1531         static const int SyncPattern
[] = { 
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, 
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, 
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, 
1544         // So first, we correlate for the sync pattern, and mark that. 
1545         int bestCorrel 
= 0, bestPos 
= 0; 
1547         // It does us no good to find the sync pattern, with fewer than 
1548         // 2048 samples after it... 
1549         for(i 
= 0; i 
< (GraphTraceLen
-2048); i
++) { 
1552                 for(j 
= 0; j 
< arraylen(SyncPattern
); j
++) { 
1553                         sum 
+= GraphBuffer
[i
+j
]*SyncPattern
[j
]; 
1555                 if(sum 
> bestCorrel
) { 
1560         PrintToScrollback("best sync at %d [metric %d]", bestPos
, bestCorrel
); 
1565         int worst 
= INT_MAX
; 
1568         for(i 
= 0; i 
< 2048; i 
+= 8) { 
1571                 for(j 
= 0; j 
< 8; j
++) { 
1572                         sum 
+= GraphBuffer
[bestPos
+i
+j
]; 
1579                 if(abs(sum
) < worst
) { 
1584         PrintToScrollback("bits:"); 
1585         PrintToScrollback("%s", bits
); 
1586         PrintToScrollback("worst metric: %d at pos %d", worst
, worstPos
); 
1588         if(strcmp(str
, "clone")==0) { 
1591                 for(s 
= bits
; *s
; s
++) { 
1593                         for(j 
= 0; j 
< 16; j
++) { 
1594                                 GraphBuffer
[GraphTraceLen
++] = (*s 
== '1') ? 1 : 0; 
1597                 RepaintGraphWindow(); 
1601 static void CmdIndalademod(char *str
) 
1603         // Usage: recover 64bit UID by default, specify "224" as arg to recover a 224bit UID 
1608         // worst case with GraphTraceLen=64000 is < 4096 
1609         // under normal conditions it's < 2048 
1612         int worst 
= 0, worstPos 
= 0; 
1613         PrintToScrollback("Expecting a bit less than %d raw bits", GraphTraceLen
/32); 
1614         for(i 
= 0; i 
< GraphTraceLen
-1; i 
+= 2) { 
1616                 if((GraphBuffer
[i
] > GraphBuffer
[i 
+ 1]) && (state 
!= 1)) { 
1618                                 for(j 
= 0; j 
<  count 
- 8; j 
+= 16) { 
1619                                         rawbits
[rawbit
++] = 0; 
1621                                 if ((abs(count 
- j
)) > worst
) { 
1622                                         worst 
= abs(count 
- j
); 
1628                 } else if((GraphBuffer
[i
] < GraphBuffer
[i 
+ 1]) && (state 
!= 0)) { 
1630                                 for(j 
= 0; j 
<  count 
- 8; j 
+= 16) { 
1631                                         rawbits
[rawbit
++] = 1; 
1633                                 if ((abs(count 
- j
)) > worst
) { 
1634                                         worst 
= abs(count 
- j
); 
1642         PrintToScrollback("Recovered %d raw bits", rawbit
); 
1643         PrintToScrollback("worst metric (0=best..7=worst): %d at pos %d", worst
, worstPos
); 
1645         // Finding the start of a UID 
1646         int uidlen
, long_wait
; 
1647         if(strcmp(str
, "224") == 0) { 
1656         for(start 
= 0; start 
<= rawbit 
- uidlen
; start
++) { 
1657                 first 
= rawbits
[start
]; 
1658                 for(i 
= start
; i 
< start 
+ long_wait
; i
++) { 
1659                         if(rawbits
[i
] != first
) { 
1663                 if(i 
== (start 
+ long_wait
)) { 
1667         if(start 
== rawbit 
- uidlen 
+ 1) { 
1668                 PrintToScrollback("nothing to wait for"); 
1672         // Inverting signal if needed 
1674                 for(i 
= start
; i 
< rawbit
; i
++) { 
1675                         rawbits
[i
] = !rawbits
[i
]; 
1682         showbits
[uidlen
]='\0'; 
1686         if(uidlen 
> rawbit
) { 
1687                 PrintToScrollback("Warning: not enough raw bits to get a full UID"); 
1688                 for(bit 
= 0; bit 
< rawbit
; bit
++) { 
1689                         bits
[bit
] = rawbits
[i
++]; 
1690                         // As we cannot know the parity, let's use "." and "/" 
1691                         showbits
[bit
] = '.' + bits
[bit
]; 
1693                 showbits
[bit
+1]='\0'; 
1694                 PrintToScrollback("Partial UID=%s", showbits
); 
1697                 for(bit 
= 0; bit 
< uidlen
; bit
++) { 
1698                         bits
[bit
] = rawbits
[i
++]; 
1699                         showbits
[bit
] = '0' + bits
[bit
]; 
1703         PrintToScrollback("UID=%s", showbits
); 
1705         // Checking UID against next occurences 
1706         for(; i 
+ uidlen 
<= rawbit
;) { 
1708                 for(bit 
= 0; bit 
< uidlen
; bit
++) { 
1709                         if(bits
[bit
] != rawbits
[i
++]) { 
1719         PrintToScrollback("Occurences: %d (expected %d)", times
, (rawbit 
- start
) / uidlen
); 
1721         // Remodulating for tag cloning 
1722         GraphTraceLen 
= 32*uidlen
; 
1725         for(bit 
= 0; bit 
< uidlen
; bit
++) { 
1726                 if(bits
[bit
] == 0) { 
1732                 for(j 
= 0; j 
< 32; j
++) { 
1733                         GraphBuffer
[i
++] = phase
; 
1738         RepaintGraphWindow(); 
1741 static void CmdFlexdemod(char *str
) 
1744         for(i 
= 0; i 
< GraphTraceLen
; i
++) { 
1745                 if(GraphBuffer
[i
] < 0) { 
1746                         GraphBuffer
[i
] = -1; 
1752 #define LONG_WAIT 100 
1754         for(start 
= 0; start 
< GraphTraceLen 
- LONG_WAIT
; start
++) { 
1755                 int first 
= GraphBuffer
[start
]; 
1756                 for(i 
= start
; i 
< start 
+ LONG_WAIT
; i
++) { 
1757                         if(GraphBuffer
[i
] != first
) { 
1761                 if(i 
== (start 
+ LONG_WAIT
)) { 
1765         if(start 
== GraphTraceLen 
- LONG_WAIT
) { 
1766                 PrintToScrollback("nothing to wait for"); 
1770         GraphBuffer
[start
] = 2; 
1771         GraphBuffer
[start
+1] = -2; 
1777         for(bit 
= 0; bit 
< 64; bit
++) { 
1780                 for(j 
= 0; j 
< 16; j
++) { 
1781                         sum 
+= GraphBuffer
[i
++]; 
1788                 PrintToScrollback("bit %d sum %d", bit
, sum
); 
1791         for(bit 
= 0; bit 
< 64; bit
++) { 
1794                 for(j 
= 0; j 
< 16; j
++) { 
1795                         sum 
+= GraphBuffer
[i
++]; 
1797                 if(sum 
> 0 && bits
[bit
] != 1) { 
1798                         PrintToScrollback("oops1 at %d", bit
); 
1800                 if(sum 
< 0 && bits
[bit
] != 0) { 
1801                         PrintToScrollback("oops2 at %d", bit
); 
1805         GraphTraceLen 
= 32*64; 
1808         for(bit 
= 0; bit 
< 64; bit
++) { 
1809                 if(bits
[bit
] == 0) { 
1815                 for(j 
= 0; j 
< 32; j
++) { 
1816                         GraphBuffer
[i
++] = phase
; 
1821         RepaintGraphWindow(); 
1825  * Generic command to demodulate ASK. bit length in argument. 
1826  * Giving the bit length helps discriminate ripple effects 
1827  * upon zero crossing for noisy traces. 
1829  * Second is convention: positive or negative (High mod means zero 
1830  * or high mod means one) 
1832  * Updates the Graph trace with 0/1 values 
1835  * sl : bit length in terms of number of samples per bit 
1836  *      (use yellow/purple markers to compute). 
1840 static void Cmdaskdemod(char *str
) { 
1847         // TODO: complain if we do not give 2 arguments here ! 
1848         sscanf(str
, "%i %i", &n
, &c
); 
1855         if (GraphBuffer
[0]*c 
> 0) { 
1860         for(i
=1;i
<GraphTraceLen
;i
++) { 
1861                 /* Analyse signal within the symbol length */ 
1862                 /* Decide if we crossed a zero */ 
1863                 if (GraphBuffer
[i
]*sign 
< 0) { 
1864                          /* Crossed a zero, check if this is a ripple or not */ 
1865                         if ( (i
-t1
) > n
/4 ) { 
1868                                 if (GraphBuffer
[i
]*c 
> 0){ 
1874                         /* This is a ripple, set the current sample value 
1875                            to the same as previous */ 
1876                                 GraphBuffer
[i
] = GraphBuffer
[i
-1]; 
1879                         GraphBuffer
[i
] = GraphBuffer
[i
-1]; 
1882         RepaintGraphWindow(); 
1885 /* Print our clock rate */ 
1886 static void Cmddetectclockrate(char *str
) 
1888         int clock 
= detectclock(0); 
1889         PrintToScrollback("Auto-detected clock rate: %d", clock
); 
1895 int detectclock(int peak
) 
1901         /* Detect peak if we don't have one */ 
1903                 for (i 
= 0; i 
< GraphTraceLen
; i
++) 
1904                         if (GraphBuffer
[i
] > peak
) 
1905                                 peak 
= GraphBuffer
[i
]; 
1907         for (i 
= 1; i 
< GraphTraceLen
; i
++) 
1909                 /* If this is the beginning of a peak */ 
1910                 if (GraphBuffer
[i
-1] != GraphBuffer
[i
] && GraphBuffer
[i
] == peak
) 
1912                         /* Find lowest difference between peaks */ 
1913                         if (lastpeak 
&& i 
- lastpeak 
< clock
) 
1915                                 clock 
= i 
- lastpeak
; 
1924 /* Get or auto-detect clock rate */ 
1925 int GetClock(char *str
, int peak
) 
1929         sscanf(str
, "%i", &clock
); 
1930         if (!strcmp(str
, "")) 
1933         /* Auto-detect clock */ 
1936                 clock 
= detectclock(peak
); 
1938                 /* Only print this message if we're not looping something */ 
1940                         PrintToScrollback("Auto-detected clock rate: %d", clock
); 
1947  * Convert to a bitstream 
1949 static void Cmdbitstream(char *str
) { 
1956         int hithigh
, hitlow
, first
; 
1958         /* Detect high and lows and clock */ 
1959         for (i 
= 0; i 
< GraphTraceLen
; i
++) 
1961                 if (GraphBuffer
[i
] > high
) 
1962                         high 
= GraphBuffer
[i
]; 
1963                 else if (GraphBuffer
[i
] < low
) 
1964                         low 
= GraphBuffer
[i
]; 
1968         clock 
= GetClock(str
, high
); 
1970         gtl 
= CmdClearGraph(0); 
1973         for (i 
= 0; i 
< (int)(gtl 
/ clock
); i
++) 
1979                 /* Find out if we hit both high and low peaks */ 
1980                 for (j 
= 0; j 
< clock
; j
++) 
1982                         if (GraphBuffer
[(i 
* clock
) + j
] == high
) 
1984                         else if (GraphBuffer
[(i 
* clock
) + j
] == low
) 
1987                         /* it doesn't count if it's the first part of our read 
1988                          because it's really just trailing from the last sequence */ 
1989                         if (first 
&& (hithigh 
|| hitlow
)) 
1990                                 hithigh 
= hitlow 
= 0; 
1994                         if (hithigh 
&& hitlow
) 
1998                 /* If we didn't hit both high and low peaks, we had a bit transition */ 
1999                 if (!hithigh 
|| !hitlow
) 
2002                 CmdAppendGraph(0, clock
, bit
); 
2003 //              for (j = 0; j < (int)(clock/2); j++) 
2004 //                      GraphBuffer[(i * clock) + j] = bit ^ 1; 
2005 //              for (j = (int)(clock/2); j < clock; j++) 
2006 //                      GraphBuffer[(i * clock) + j] = bit; 
2009         RepaintGraphWindow(); 
2012 /* Modulate our data into manchester */ 
2013 static void Cmdmanchestermod(char *str
) 
2017         int bit
, lastbit
, wave
; 
2020         clock 
= GetClock(str
, 0); 
2024         for (i 
= 0; i 
< (int)(GraphTraceLen 
/ clock
); i
++) 
2026                 bit 
= GraphBuffer
[i 
* clock
] ^ 1; 
2028                 for (j 
= 0; j 
< (int)(clock
/2); j
++) 
2029                         GraphBuffer
[(i 
* clock
) + j
] = bit 
^ lastbit 
^ wave
; 
2030                 for (j 
= (int)(clock
/2); j 
< clock
; j
++) 
2031                         GraphBuffer
[(i 
* clock
) + j
] = bit 
^ lastbit 
^ wave 
^ 1; 
2033                 /* Keep track of how we start our wave and if we changed or not this time */ 
2034                 wave 
^= bit 
^ lastbit
; 
2038         RepaintGraphWindow(); 
2042  * Manchester demodulate a bitstream. The bitstream needs to be already in 
2043  * the GraphBuffer as 0 and 1 values 
2045  * Give the clock rate as argument in order to help the sync - the algorithm 
2046  * resyncs at each pulse anyway. 
2048  * Not optimized by any means, this is the 1st time I'm writing this type of 
2049  * routine, feel free to improve... 
2051  * 1st argument: clock rate (as number of samples per clock rate) 
2052  *               Typical values can be 64, 32, 128... 
2054 static void Cmdmanchesterdemod(char *str
) { 
2061         int hithigh
, hitlow
, first
; 
2067         /* Holds the decoded bitstream: each clock period contains 2 bits       */ 
2068         /* later simplified to 1 bit after manchester decoding.                 */ 
2069         /* Add 10 bits to allow for noisy / uncertain traces without aborting   */ 
2070         /* int BitStream[GraphTraceLen*2/clock+10]; */ 
2072         /* But it does not work if compiling on WIndows: therefore we just allocate a */ 
2074         int BitStream
[MAX_GRAPH_TRACE_LEN
]; 
2076         /* Detect high and lows */ 
2077         for (i 
= 0; i 
< GraphTraceLen
; i
++) 
2079                 if (GraphBuffer
[i
] > high
) 
2080                         high 
= GraphBuffer
[i
]; 
2081                 else if (GraphBuffer
[i
] < low
) 
2082                         low 
= GraphBuffer
[i
]; 
2086         clock 
= GetClock(str
, high
); 
2088         int tolerance 
= clock
/4; 
2090         /* Detect first transition */ 
2091         /* Lo-Hi (arbitrary)       */ 
2092         for (i 
= 0; i 
< GraphTraceLen
; i
++) 
2094                 if (GraphBuffer
[i
] == low
) 
2101         /* If we're not working with 1/0s, demod based off clock */ 
2105                 for (i 
= 0; i 
< (int)(GraphTraceLen 
/ clock
); i
++) 
2111                         /* Find out if we hit both high and low peaks */ 
2112                         for (j 
= 0; j 
< clock
; j
++) 
2114                                 if (GraphBuffer
[(i 
* clock
) + j
] == high
) 
2116                                 else if (GraphBuffer
[(i 
* clock
) + j
] == low
) 
2119                                 /* it doesn't count if it's the first part of our read 
2120                                    because it's really just trailing from the last sequence */ 
2121                                 if (first 
&& (hithigh 
|| hitlow
)) 
2122                                         hithigh 
= hitlow 
= 0; 
2126                                 if (hithigh 
&& hitlow
) 
2130                         /* If we didn't hit both high and low peaks, we had a bit transition */ 
2131                         if (!hithigh 
|| !hitlow
) 
2134                         BitStream
[bit2idx
++] = bit
; 
2138         /* standard 1/0 bitstream */ 
2142         /* Then detect duration between 2 successive transitions */ 
2143                 for (bitidx 
= 1; i 
< GraphTraceLen
; i
++) 
2145                         if (GraphBuffer
[i
-1] != GraphBuffer
[i
]) 
2150                         // Error check: if bitidx becomes too large, we do not 
2151                         // have a Manchester encoded bitstream or the clock is really 
2153                         if (bitidx 
> (GraphTraceLen
*2/clock
+8) ) { 
2154                                 PrintToScrollback("Error: the clock you gave is probably wrong, aborting."); 
2157                         // Then switch depending on lc length: 
2158                         // Tolerance is 1/4 of clock rate (arbitrary) 
2159                         if (abs(lc
-clock
/2) < tolerance
) { 
2160                                 // Short pulse : either "1" or "0" 
2161                                 BitStream
[bitidx
++]=GraphBuffer
[i
-1]; 
2162                         } else if (abs(lc
-clock
) < tolerance
) { 
2163                                 // Long pulse: either "11" or "00" 
2164                                 BitStream
[bitidx
++]=GraphBuffer
[i
-1]; 
2165                                 BitStream
[bitidx
++]=GraphBuffer
[i
-1]; 
2169                                 PrintToScrollback("Warning: Manchester decode error for pulse width detection."); 
2170                                 PrintToScrollback("(too many of those messages mean either the stream is not Manchester encoded, or clock is wrong)"); 
2174                                                 PrintToScrollback("Error: too many detection errors, aborting."); 
2181         // At this stage, we now have a bitstream of "01" ("1") or "10" ("0"), parse it into final decoded bitstream 
2182         // Actually, we overwrite BitStream with the new decoded bitstream, we just need to be careful 
2183         // to stop output at the final bitidx2 value, not bitidx 
2184         for (i 
= 0; i 
< bitidx
; i 
+= 2) { 
2185                 if ((BitStream
[i
] == 0) && (BitStream
[i
+1] == 1)) { 
2186                         BitStream
[bit2idx
++] = 1; 
2187                 } else if ((BitStream
[i
] == 1) && (BitStream
[i
+1] == 0)) { 
2188                         BitStream
[bit2idx
++] = 0; 
2190                         // We cannot end up in this state, this means we are unsynchronized, 
2194                         PrintToScrollback("Unsynchronized, resync..."); 
2195                         PrintToScrollback("(too many of those messages mean the stream is not Manchester encoded)"); 
2199                                         PrintToScrollback("Error: too many decode errors, aborting."); 
2206         PrintToScrollback("Manchester decoded bitstream"); 
2207         // Now output the bitstream to the scrollback by line of 16 bits 
2208         for (i 
= 0; i 
< (bit2idx
-16); i
+=16) { 
2209                 PrintToScrollback("%i %i %i %i %i %i %i %i %i %i %i %i %i %i %i %i", 
2234 static void CmdHiddemod(char *str
) 
2236         if(GraphTraceLen 
< 4800) { 
2237                 PrintToScrollback("too short; need at least 4800 samples"); 
2241         GraphTraceLen 
= 4800; 
2243         for(i 
= 0; i 
< GraphTraceLen
; i
++) { 
2244                 if(GraphBuffer
[i
] < 0) { 
2250         RepaintGraphWindow(); 
2253 static void CmdPlot(char *str
) 
2258 static void CmdHide(char *str
) 
2263 static void CmdScale(char *str
) 
2265         CursorScaleFactor 
= atoi(str
); 
2266         if(CursorScaleFactor 
== 0) { 
2267                 PrintToScrollback("bad, can't have zero scale"); 
2268                 CursorScaleFactor 
= 1; 
2270         RepaintGraphWindow(); 
2273 static void CmdSave(char *str
) 
2275         FILE *f 
= fopen(str
, "w"); 
2277                 PrintToScrollback("couldn't open '%s'", str
); 
2281         for(i 
= 0; i 
< GraphTraceLen
; i
++) { 
2282                 fprintf(f
, "%d\n", GraphBuffer
[i
]); 
2285         PrintToScrollback("saved to '%s'", str
); 
2288 static void CmdLoad(char *str
) 
2290         FILE *f 
= fopen(str
, "r"); 
2292                 PrintToScrollback("couldn't open '%s'", str
); 
2298         while(fgets(line
, sizeof(line
), f
)) { 
2299                 GraphBuffer
[GraphTraceLen
] = atoi(line
); 
2303         PrintToScrollback("loaded %d samples", GraphTraceLen
); 
2304         RepaintGraphWindow(); 
2307 static void CmdHIDsimTAG(char *str
) 
2309         unsigned int hi
=0, lo
=0; 
2313         while (sscanf(&str
[i
++], "%1x", &n 
) == 1) { 
2314                 hi
=(hi
<<4)|(lo
>>28); 
2318         PrintToScrollback("Emulating tag with ID %x%16x", hi
, lo
); 
2320         c
.cmd 
= CMD_HID_SIM_TAG
; 
2323         SendCommand(&c
, FALSE
); 
2326 static void CmdLcdReset(char *str
) 
2329         c
.cmd 
= CMD_LCD_RESET
; 
2331         SendCommand(&c
, FALSE
); 
2334 static void CmdLcd(char *str
) 
2339         sscanf(str
, "%x %d", &i
, &j
); 
2342                 SendCommand(&c
, FALSE
); 
2348 static void CmdTest(char *str
) 
2353  * Sets the divisor for LF frequency clock: lets the user choose any LF frequency below 
2356 static void CmdSetDivisor(char *str
) 
2359         c
.cmd 
= CMD_SET_LF_DIVISOR
; 
2361         if (( c
.ext1
<0) || (c
.ext1
>255)) { 
2362                         PrintToScrollback("divisor must be between 19 and 255"); 
2364                         SendCommand(&c
, FALSE
); 
2365                         PrintToScrollback("Divisor set, expected freq=%dHz", 12000000/(c
.ext1
+1)); 
2369 static void CmdSweepLF(char *str
) 
2372         c
.cmd 
= CMD_SWEEP_LF
; 
2373         SendCommand(&c
, FALSE
); 
2377 typedef void HandlerFunction(char *cmdline
); 
2379 /* in alphabetic order */ 
2382         HandlerFunction 
*handler
; 
2383         int             offline
;  // 1 if the command can be used when in offline mode 
2385 } CommandTable
[] = { 
2386         "askdemod",                     Cmdaskdemod
,1,          "<samples per bit> <0|1> -- Attempt to demodulate simple ASK tags", 
2387         "autocorr",                     CmdAutoCorr
,1,          "<window length> -- Autocorrelation over window", 
2388         "bitsamples",           CmdBitsamples
,0,        "    Get raw samples as bitstring", 
2389         "bitstream",            Cmdbitstream
,1,         "[clock rate] -- Convert waveform into a bitstream", 
2390         "dec",                          CmdDec
,1,               "    Decimate samples", 
2391         "detectclock",          Cmddetectclockrate
,1, "    Detect clock rate", 
2392         "em410xsim",            CmdEM410xsim
,1,         "<UID> -- Simulate EM410x tag", 
2393         "em410xread",           CmdEM410xread
,1,        "[clock rate] -- Extract ID from EM410x tag", 
2394         "em410xwatch",          CmdEM410xwatch
,0,       "    Watches for EM410x tags", 
2395         "exit",                         CmdQuit
,1,                      "    Exit program", 
2396         "flexdemod",            CmdFlexdemod
,1,         "    Demodulate samples for FlexPass", 
2397         "fpgaoff",                      CmdFPGAOff
,0,           "    Set FPGA off",                                                     // ## FPGA Control 
2398         "hexsamples",           CmdHexsamples
,0,        "<blocks> -- Dump big buffer as hex bytes", 
2399         "hi14alist",            CmdHi14alist
,0,         "    List ISO 14443a history",                          // ## New list command 
2400         "hi14areader",          CmdHi14areader
,0,       "    Act like an ISO14443 Type A reader",       // ## New reader command 
2401         "hi14asim",                     CmdHi14asim
,0,          "<UID> -- Fake ISO 14443a tag",                                 // ## Simulate 14443a tag 
2402         "hi14asnoop",           CmdHi14asnoop
,0,        "    Eavesdrop ISO 14443 Type A",                       // ## New snoop command 
2403         "hi14bdemod",           CmdHi14bdemod
,1,        "    Demodulate ISO14443 Type B from tag", 
2404         "hi14list",                     CmdHi14list
,0,          "    List ISO 14443 history", 
2405         "hi14read",                     CmdHi14read
,0,          "    Read HF tag (ISO 14443)", 
2406         "hi14sim",                      CmdHi14sim
,0,           "    Fake ISO 14443 tag", 
2407         "hi14snoop",            CmdHi14snoop
,0,         "    Eavesdrop ISO 14443", 
2408         "hi15demod",            CmdHi15demod
,1,         "    Demodulate ISO15693 from tag", 
2409         "hi15read",                     CmdHi15read
,0,          "    Read HF tag (ISO 15693)", 
2410         "hi15reader",           CmdHi15reader
,0,        "    Act like an ISO15693 reader", // new command greg 
2411         "hi15sim",                      CmdHi15tag
,0,           "    Fake an ISO15693 tag", // new command greg 
2412         "hiddemod",                     CmdHiddemod
,1,          "    Demodulate HID Prox Card II (not optimal)", 
2413         "hide",                         CmdHide
,1,              "    Hide graph window", 
2414         "hidfskdemod",          CmdHIDdemodFSK
,0,       "    Realtime HID FSK demodulator", 
2415         "hidsimtag",            CmdHIDsimTAG
,0,         "<ID> -- HID tag simulator", 
2416         "higet",                        CmdHi14read_sim
,0,      "<samples> -- Get samples HF, 'analog'", 
2417         "hisamples",            CmdHisamples
,0,         "    Get raw samples for HF tag", 
2418         "hisampless",           CmdHisampless
,0,        "<samples> -- Get signed raw samples, HF tag", 
2419         "hisamplest",           CmdHi14readt
,0,         "    Get samples HF, for testing", 
2420         "hisimlisten",          CmdHisimlisten
,0,       "    Get HF samples as fake tag", 
2421         "hpf",                          CmdHpf
,1,               "    Remove DC offset from trace", 
2422         "indalademod",          CmdIndalademod
,0,         "['224'] -- Demodulate samples for Indala", 
2423         "lcd",                          CmdLcd
,0,                       "<HEX command> <count> -- Send command/data to LCD", 
2424         "lcdreset",                     CmdLcdReset
,0,          "    Hardware reset LCD", 
2425         "load",                         CmdLoad
,1,              "<filename> -- Load trace (to graph window", 
2426         "loread",                       CmdLoread
,0,            "['h'] -- Read 125/134 kHz LF ID-only tag (option 'h' for 134)", 
2427         "losamples",            CmdLosamples
,0,         "[128 - 16000] -- Get raw samples for LF tag", 
2428         "losim",                        CmdLosim
,0,             "    Simulate LF tag", 
2429         "ltrim",                        CmdLtrim
,1,             "<samples> -- Trim samples from left of trace", 
2430         "mandemod",                     Cmdmanchesterdemod
,1,   "[clock rate] -- Try a Manchester demodulation on a binary stream", 
2431         "manmod",                       Cmdmanchestermod
,1,     "[clock rate] -- Manchester modulate a binary stream", 
2432         "norm",                         CmdNorm
,1,              "    Normalize max/min to +/-500", 
2433         "plot",                         CmdPlot
,1,              "    Show graph window", 
2434         "quit",                         CmdQuit
,1,                      "    Quit program", 
2435         "reset",                        CmdReset
,0,                     "    Reset the Proxmark3", 
2436         "save",                         CmdSave
,1,              "<filename> -- Save trace (from graph window)", 
2437         "scale",                        CmdScale
,1,             "<int> -- Set cursor display scale", 
2438         "setlfdivisor",         CmdSetDivisor
,0,        "<19 - 255> -- Drive LF antenna at 12Mhz/(divisor+1)", 
2439         "sri512read",           CmdSri512read
,0,        "<int> -- Read contents of a SRI512 tag", 
2440         "sweeplf",                      CmdSweepLF
,0,           "    Sweep through LF freq range and store results in buffer", 
2441         "tibits",                       CmdTibits
,0,            "    Get raw bits for TI-type LF tag", 
2442         "tidemod",                      CmdTidemod
,0,           "    Demodulate raw bits for TI-type LF tag", 
2443         "tiread",                       CmdTiread
,0,            "    Read a TI-type 134 kHz tag", 
2444         "tune",                         CmdTune
,0,              "    Measure antenna tuning", 
2445         "vchdemod",                     CmdVchdemod
,0,          "['clone'] -- Demodulate samples for VeriChip", 
2446         "zerocrossings",        CmdZerocrossings
,1,     "    Count time between zero-crossings", 
2450 //----------------------------------------------------------------------------- 
2451 // Entry point into our code: called whenever the user types a command and 
2452 // then presses Enter, which the full command line that they typed. 
2453 //----------------------------------------------------------------------------- 
2454 void CommandReceived(char *cmd
) 
2458         PrintToScrollback("> %s", cmd
); 
2460         if(strcmp(cmd
, "help")==0) { 
2461                 if (offline
) PrintToScrollback("Operating in OFFLINE mode (no device connected)"); 
2462                 PrintToScrollback("\r\nAvailable commands:"); 
2463                 for(i 
= 0; i 
< sizeof(CommandTable
) / sizeof(CommandTable
[0]); i
++) { 
2464                         if (offline 
&& (CommandTable
[i
].offline
==0)) continue; 
2466                         memset(line
, ' ', sizeof(line
)); 
2467                         strcpy(line
+2, CommandTable
[i
].name
); 
2468                         line
[strlen(line
)] = ' '; 
2469                         sprintf(line
+15, " -- %s", CommandTable
[i
].docString
); 
2470                         PrintToScrollback("%s", line
); 
2472                 PrintToScrollback(""); 
2473                 PrintToScrollback("and also: help, cls"); 
2477         for(i 
= 0; i 
< sizeof(CommandTable
) / sizeof(CommandTable
[0]); i
++) { 
2478                 char *name 
= CommandTable
[i
].name
; 
2479                 if(memcmp(cmd
, name
, strlen(name
))==0 && 
2480                         (cmd
[strlen(name
)] == ' ' || cmd
[strlen(name
)] == '\0')) 
2482                         cmd 
+= strlen(name
); 
2483                         while(*cmd 
== ' ') { 
2486                         if (offline 
&& (CommandTable
[i
].offline
==0)) { 
2487                                 PrintToScrollback("Offline mode, cannot use this command."); 
2490                         (CommandTable
[i
].handler
)(cmd
); 
2494         PrintToScrollback(">> bad command '%s'", cmd
); 
2497 //----------------------------------------------------------------------------- 
2498 // Entry point into our code: called whenever we received a packet over USB 
2499 // that we weren't necessarily expecting, for example a debug print. 
2500 //----------------------------------------------------------------------------- 
2501 void UsbCommandReceived(UsbCommand 
*c
) 
2504                 case CMD_DEBUG_PRINT_STRING
: { 
2506                         if(c
->ext1 
> 70 || c
->ext1 
< 0) { 
2509                         memcpy(s
, c
->d
.asBytes
, c
->ext1
); 
2511                         PrintToScrollback("#db# %s", s
); 
2515                 case CMD_DEBUG_PRINT_INTEGERS
: 
2516                         PrintToScrollback("#db# %08x, %08x, %08x\r\n", c
->ext1
, c
->ext2
, c
->ext3
); 
2519                 case CMD_MEASURED_ANTENNA_TUNING
: { 
2521                         int vLf125
, vLf134
, vHf
; 
2522                         vLf125 
= c
->ext1 
& 0xffff; 
2523                         vLf134 
= c
->ext1 
>> 16; 
2525                         zLf 
= c
->ext3 
& 0xffff; 
2526                         zHf 
= c
->ext3 
>> 16; 
2527                         PrintToScrollback("# LF antenna @ %3d mA / %5d mV [%d ohms] 125Khz", 
2528                                 vLf125
/zLf
, vLf125
, zLf
); 
2529                         PrintToScrollback("# LF antenna @ %3d mA / %5d mV [%d ohms] 134Khz", 
2530                                 vLf134
/((zLf
*125)/134), vLf134
, (zLf
*125)/134); 
2531                         PrintToScrollback("# HF antenna @ %3d mA / %5d mV [%d ohms] 13.56Mhz", 
2536                         PrintToScrollback("unrecognized command %08x\n", c
->cmd
);