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
) 
 643         /* convert to bitstream if necessary */ 
 646         for (i 
= 0; i 
< GraphTraceLen
; i 
+= 48) { 
 649                 for(j 
= 0; j 
< 48; j
++) { 
 650                         c
.d
.asBytes
[j
] = GraphBuffer
[i
+j
]; 
 652                 c
.cmd 
= CMD_DOWNLOADED_SIM_SAMPLES_125K
; 
 654                 SendCommand(&c
, FALSE
); 
 658         c
.cmd 
= CMD_SIMULATE_TAG_125K
; 
 659         c
.ext1 
= GraphTraceLen
; 
 660         SendCommand(&c
, FALSE
); 
 663 static void CmdLoread(char *str
) 
 666         // 'h' means higher-low-frequency, 134 kHz 
 669         } else if (*str 
== '\0') { 
 672                 PrintToScrollback("use 'loread' or 'loread h'"); 
 675         c
.cmd 
= CMD_ACQUIRE_RAW_ADC_SAMPLES_125K
; 
 676         SendCommand(&c
, FALSE
); 
 679 static void CmdDetectReader(char *str
) 
 682         // 'l' means LF - 125/134 kHz 
 685         } else if (*str 
== 'h') { 
 687         } else if (*str 
!= '\0') { 
 688                 PrintToScrollback("use 'detectreader' or 'detectreader l' or 'detectreader h'"); 
 691         c
.cmd 
= CMD_LISTEN_READER_FIELD
; 
 692          SendCommand(&c
, FALSE
); 
 695 /* send a command before reading */ 
 696 static void CmdLoCommandRead(char *str
) 
 698         static char dummy
[3]; 
 703         c
.cmd 
= CMD_MOD_THEN_ACQUIRE_RAW_ADC_SAMPLES_125K
; 
 704         sscanf(str
, "%i %i %i %s %s", &c
.ext1
, &c
.ext2
, &c
.ext3
, (char *) &c
.d
.asBytes
,(char *) &dummy
+1); 
 705         // in case they specified 'h' 
 706         strcpy((char *)&c
.d
.asBytes 
+ strlen((char *)c
.d
.asBytes
), dummy
); 
 707         SendCommand(&c
, FALSE
); 
 710 static void CmdLosamples(char *str
) 
 718         if (n
>16000) n
=16000; 
 720         for(i 
= 0; i 
< n
; i 
+= 12) { 
 722                 c
.cmd 
= CMD_DOWNLOAD_RAW_ADC_SAMPLES_125K
; 
 724                 SendCommand(&c
, FALSE
); 
 726                 if(c
.cmd 
!= CMD_DOWNLOADED_RAW_ADC_SAMPLES_125K
) { 
 728                                 PrintToScrollback("bad resp"); 
 732                 for(j 
= 0; j 
< 48; j
++) { 
 733                         GraphBuffer
[cnt
++] = ((int)c
.d
.asBytes
[j
]) - 128; 
 737         RepaintGraphWindow(); 
 740 static void CmdBitsamples(char *str
) 
 747         for(i 
= 0; i 
< n
; i 
+= 12) { 
 749                 c
.cmd 
= CMD_DOWNLOAD_RAW_ADC_SAMPLES_125K
; 
 751                 SendCommand(&c
, FALSE
); 
 753                 if(c
.cmd 
!= CMD_DOWNLOADED_RAW_ADC_SAMPLES_125K
) { 
 754                         PrintToScrollback("bad resp"); 
 758                 for(j 
= 0; j 
< 48; j
++) { 
 759                         for(k 
= 0; k 
< 8; k
++) { 
 760                                 if(c
.d
.asBytes
[j
] & (1 << (7 - k
))) { 
 761                                         GraphBuffer
[cnt
++] = 1; 
 763                                         GraphBuffer
[cnt
++] = 0; 
 769         RepaintGraphWindow(); 
 772 static void CmdHisamples(char *str
) 
 778         for(i 
= 0; i 
< n
; i 
+= 12) { 
 780                 c
.cmd 
= CMD_DOWNLOAD_RAW_ADC_SAMPLES_125K
; 
 782                 SendCommand(&c
, FALSE
); 
 784                 if(c
.cmd 
!= CMD_DOWNLOADED_RAW_ADC_SAMPLES_125K
) { 
 785                         PrintToScrollback("bad resp"); 
 789                 for(j 
= 0; j 
< 48; j
++) { 
 790                         GraphBuffer
[cnt
++] = (int)((BYTE
)c
.d
.asBytes
[j
]); 
 795         RepaintGraphWindow(); 
 799 static int CmdHisamplest(char *str
, int nrlow
) 
 811         for(i 
= 0; i 
< n
; i 
+= 12) { 
 813                 c
.cmd 
= CMD_DOWNLOAD_RAW_ADC_SAMPLES_125K
; 
 815                 SendCommand(&c
, FALSE
); 
 817                 if(c
.cmd 
!= CMD_DOWNLOADED_RAW_ADC_SAMPLES_125K
) { 
 818                         PrintToScrollback("bad resp"); 
 822                 for(j 
= 0; j 
< 48; j
++) { 
 823                         t2 
= (int)((BYTE
)c
.d
.asBytes
[j
]); 
 824                         if((t2 
^ 0xC0) & 0xC0) { hasbeennull
++; } 
 830                                         t1 
= (t2 
& 0x80) ^ (t2 
& 0x20); 
 831                                         t2 
= ((t2 
<< 1) & 0x80) ^ ((t2 
<< 1) & 0x20); 
 837                                         t2 
= ((t2 
<< 1) & 0x80); 
 843                                         t2 
= ((t2 
<< 1) & 0x20); 
 847                                         // both, but tag with other algorithm 
 848                                         t1 
= (t2 
& 0x80) ^ (t2 
& 0x08); 
 849                                         t2 
= ((t2 
<< 1) & 0x80) ^ ((t2 
<< 1) & 0x08); 
 853                         GraphBuffer
[cnt
++] = t1
; 
 854                         GraphBuffer
[cnt
++] = t2
; 
 859         if(hasbeennull
>nrlow 
|| nrlow
==0) { 
 860                 PrintToScrollback("hasbeennull=%d", hasbeennull
); 
 869 static void CmdHexsamples(char *str
) 
 880         for(i 
= 0; i 
< n
; i 
+= 12) { 
 882                 c
.cmd 
= CMD_DOWNLOAD_RAW_ADC_SAMPLES_125K
; 
 884                 SendCommand(&c
, FALSE
); 
 886                 if(c
.cmd 
!= CMD_DOWNLOADED_RAW_ADC_SAMPLES_125K
) { 
 887                         PrintToScrollback("bad resp"); 
 891                 for(j 
= 0; j 
< 48; j 
+= 8) { 
 892                         PrintToScrollback("%02x %02x %02x %02x %02x %02x %02x %02x", 
 907 static void CmdHisampless(char *str
) 
 919         for(i 
= 0; i 
< n
; i 
+= 12) { 
 921                 c
.cmd 
= CMD_DOWNLOAD_RAW_ADC_SAMPLES_125K
; 
 923                 SendCommand(&c
, FALSE
); 
 925                 if(c
.cmd 
!= CMD_DOWNLOADED_RAW_ADC_SAMPLES_125K
) { 
 926                         PrintToScrollback("bad resp"); 
 930                 for(j 
= 0; j 
< 48; j
++) { 
 931                         GraphBuffer
[cnt
++] = (int)((signed char)c
.d
.asBytes
[j
]); 
 936         RepaintGraphWindow(); 
 939 static WORD 
Iso15693Crc(BYTE 
*v
, int n
) 
 945         for(i 
= 0; i 
< n
; i
++) { 
 946                 reg 
= reg 
^ ((DWORD
)v
[i
]); 
 947                 for (j 
= 0; j 
< 8; j
++) { 
 949                                 reg 
= (reg 
>> 1) ^ 0x8408; 
 959 static void CmdHi14bdemod(char *str
) 
 964         BOOL negateI
, negateQ
; 
 969         // As received, the samples are pairs, correlations against I and Q 
 970         // square waves. So estimate angle of initial carrier (or just 
 971         // quadrant, actually), and then do the demod. 
 973         // First, estimate where the tag starts modulating. 
 974         for(i 
= 0; i 
< GraphTraceLen
; i 
+= 2) { 
 975                 if(abs(GraphBuffer
[i
]) + abs(GraphBuffer
[i
+1]) > 40) { 
 979         if(i 
>= GraphTraceLen
) { 
 980                 PrintToScrollback("too weak to sync"); 
 983         PrintToScrollback("out of weak at %d", i
); 
 986         // Now, estimate the phase in the initial modulation of the tag 
 989         for(; i 
< (outOfWeakAt 
+ 16); i 
+= 2) { 
 990                 isum 
+= GraphBuffer
[i
+0]; 
 991                 qsum 
+= GraphBuffer
[i
+1]; 
 993         negateI 
= (isum 
< 0); 
 994         negateQ 
= (qsum 
< 0); 
 996         // Turn the correlation pairs into soft decisions on the bit. 
 998         for(i 
= 0; i 
< GraphTraceLen
/2; i
++) { 
 999                 int si 
= GraphBuffer
[j
]; 
1000                 int sq 
= GraphBuffer
[j
+1]; 
1001                 if(negateI
) si 
= -si
; 
1002                 if(negateQ
) sq 
= -sq
; 
1003                 GraphBuffer
[i
] = si 
+ sq
; 
1009         while(GraphBuffer
[i
] > 0 && i 
< GraphTraceLen
) 
1011         if(i 
>= GraphTraceLen
) goto demodError
; 
1014         while(GraphBuffer
[i
] < 0 && i 
< GraphTraceLen
) 
1016         if(i 
>= GraphTraceLen
) goto demodError
; 
1017         if((i 
- iold
) > 23) goto demodError
; 
1019         PrintToScrollback("make it to demod loop"); 
1023                 while(GraphBuffer
[i
] >= 0 && i 
< GraphTraceLen
) 
1025                 if(i 
>= GraphTraceLen
) goto demodError
; 
1026                 if((i 
- iold
) > 6) goto demodError
; 
1029                 if(i 
+ 20 >= GraphTraceLen
) goto demodError
; 
1031                 for(j 
= 0; j 
< 10; j
++) { 
1032                         int soft 
= GraphBuffer
[i
] + GraphBuffer
[i
+1]; 
1034                         if(abs(soft
) < ((abs(isum
) + abs(qsum
))/20)) { 
1035                                 PrintToScrollback("weak bit"); 
1039                         if(GraphBuffer
[i
] + GraphBuffer
[i
+1] >= 0) { 
1046                 if( (shiftReg 
& 0x200) && 
1047                         !(shiftReg 
& 0x001)) 
1049                         // valid data byte, start and stop bits okay 
1050                         PrintToScrollback("   %02x", (shiftReg 
>> 1) & 0xff); 
1051                         data
[dataLen
++] = (shiftReg 
>> 1) & 0xff; 
1052                         if(dataLen 
>= sizeof(data
)) { 
1055                 } else if(shiftReg 
== 0x000) { 
1064         ComputeCrc14443(CRC_14443_B
, data
, dataLen
-2, &first
, &second
); 
1065         PrintToScrollback("CRC: %02x %02x (%s)\n", first
, second
, 
1066                 (first 
== data
[dataLen
-2] && second 
== data
[dataLen
-1]) ? 
1067                         "ok" : "****FAIL****"); 
1069         RepaintGraphWindow(); 
1073         PrintToScrollback("demod error"); 
1074         RepaintGraphWindow(); 
1077 static void CmdHi14list(char *str
) 
1080         GetFromBigBuf(got
, sizeof(got
)); 
1082         PrintToScrollback("recorded activity:"); 
1083         PrintToScrollback(" time        :rssi: who bytes"); 
1084         PrintToScrollback("---------+----+----+-----------"); 
1095                 int timestamp 
= *((DWORD 
*)(got
+i
)); 
1096                 if(timestamp 
& 0x80000000) { 
1097                         timestamp 
&= 0x7fffffff; 
1102                 int metric 
= *((DWORD 
*)(got
+i
+4)); 
1109                 if(i 
+ len 
>= 900) { 
1113                 BYTE 
*frame 
= (got
+i
+9); 
1115                 char line
[1000] = ""; 
1117                 for(j 
= 0; j 
< len
; j
++) { 
1118                         sprintf(line
+(j
*3), "%02x  ", frame
[j
]); 
1124                         ComputeCrc14443(CRC_14443_B
, frame
, len
-2, &b1
, &b2
); 
1125                         if(b1 
!= frame
[len
-2] || b2 
!= frame
[len
-1]) { 
1126                                 crc 
= "**FAIL CRC**"; 
1134                 char metricString
[100]; 
1136                         sprintf(metricString
, "%3d", metric
); 
1138                         strcpy(metricString
, "   "); 
1141                 PrintToScrollback(" +%7d: %s: %s %s %s", 
1142                         (prev 
< 0 ? 0 : timestamp 
- prev
), 
1144                         (isResponse 
? "TAG" : "   "), line
, crc
); 
1151 static void CmdHi14alist(char *str
) 
1154         GetFromBigBuf(got
, sizeof(got
)); 
1156         PrintToScrollback("recorded activity:"); 
1157         PrintToScrollback(" ETU     :rssi: who bytes"); 
1158         PrintToScrollback("---------+----+----+-----------"); 
1169                 int timestamp 
= *((DWORD 
*)(got
+i
)); 
1170                 if(timestamp 
& 0x80000000) { 
1171                         timestamp 
&= 0x7fffffff; 
1178                 int parityBits 
= *((DWORD 
*)(got
+i
+4)); 
1179                 // 4 bytes of additional information... 
1180                 // maximum of 32 additional parity bit information 
1183                 // at each quarter bit period we can send power level (16 levels) 
1184                 // or each half bit period in 256 levels. 
1192                 if(i 
+ len 
>= 1900) { 
1196                 BYTE 
*frame 
= (got
+i
+9); 
1198                 // Break and stick with current result if buffer was not completely full 
1199                 if(frame
[0] == 0x44 && frame
[1] == 0x44 && frame
[3] == 0x44) { break; } 
1201                 char line
[1000] = ""; 
1203                 for(j 
= 0; j 
< len
; j
++) { 
1204                         int oddparity 
= 0x01; 
1208                                 oddparity 
^= (((frame
[j
] & 0xFF) >> k
) & 0x01); 
1211                         //if((parityBits >> (len - j - 1)) & 0x01) { 
1212                         if(isResponse 
&& (oddparity 
!= ((parityBits 
>> (len 
- j 
- 1)) & 0x01))) { 
1213                                 sprintf(line
+(j
*4), "%02x!  ", frame
[j
]); 
1216                                 sprintf(line
+(j
*4), "%02x   ", frame
[j
]); 
1224                         for(j 
= 0; j 
< (len 
- 1); j
++) { 
1225                                 // gives problems... search for the reason.. 
1226                                 /*if(frame[j] == 0xAA) { 
1227                                         switch(frame[j+1]) { 
1229                                                         crc = "[1] Two drops close after each other"; 
1232                                                         crc = "[2] Potential SOC with a drop in second half of bitperiod"; 
1235                                                         crc = "[3] Segment Z after segment X is not possible"; 
1238                                                         crc = "[4] Parity bit of a fully received byte was wrong"; 
1241                                                         crc = "[?] Unknown error"; 
1248                         if(strlen(crc
)==0) { 
1249                                 ComputeCrc14443(CRC_14443_A
, frame
, len
-2, &b1
, &b2
); 
1250                                 if(b1 
!= frame
[len
-2] || b2 
!= frame
[len
-1]) { 
1251                                         crc 
= (isResponse 
& (len 
< 6)) ? "" : " !crc"; 
1260                 char metricString
[100]; 
1262                         sprintf(metricString
, "%3d", metric
); 
1264                         strcpy(metricString
, "   "); 
1267                 PrintToScrollback(" +%7d: %s: %s %s %s", 
1268                         (prev 
< 0 ? 0 : (timestamp 
- prev
)), 
1270                         (isResponse 
? "TAG" : "   "), line
, crc
); 
1275         CommandFinished 
= 1; 
1278 static void CmdHi15demod(char *str
) 
1280         // The sampling rate is 106.353 ksps/s, for T = 18.8 us 
1283         // 1) Unmodulated time of 56.64us 
1284         // 2) 24 pulses of 423.75khz 
1285         // 3) logic '1' (unmodulated for 18.88us followed by 8 pulses of 423.75khz) 
1287         static const int FrameSOF
[] = { 
1288                 -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, 
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, 
1297         static const int Logic0
[] = { 
1303         static const int Logic1
[] = { 
1311         // 1) logic '0' (8 pulses of 423.75khz followed by unmodulated for 18.88us) 
1312         // 2) 24 pulses of 423.75khz 
1313         // 3) Unmodulated time of 56.64us 
1315         static const int FrameEOF
[] = { 
1320                  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1, 
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 
1327         int max 
= 0, maxPos
; 
1331         if(GraphTraceLen 
< 1000) return; 
1333         // First, correlate for SOF 
1334         for(i 
= 0; i 
< 100; i
++) { 
1336                 for(j 
= 0; j 
< arraylen(FrameSOF
); j 
+= skip
) { 
1337                         corr 
+= FrameSOF
[j
]*GraphBuffer
[i
+(j
/skip
)]; 
1344         PrintToScrollback("SOF at %d, correlation %d", maxPos
, 
1345                 max
/(arraylen(FrameSOF
)/skip
)); 
1347         i 
= maxPos 
+ arraylen(FrameSOF
)/skip
; 
1350         memset(outBuf
, 0, sizeof(outBuf
)); 
1353                 int corr0 
= 0, corr1 
= 0, corrEOF 
= 0; 
1354                 for(j 
= 0; j 
< arraylen(Logic0
); j 
+= skip
) { 
1355                         corr0 
+= Logic0
[j
]*GraphBuffer
[i
+(j
/skip
)]; 
1357                 for(j 
= 0; j 
< arraylen(Logic1
); j 
+= skip
) { 
1358                         corr1 
+= Logic1
[j
]*GraphBuffer
[i
+(j
/skip
)]; 
1360                 for(j 
= 0; j 
< arraylen(FrameEOF
); j 
+= skip
) { 
1361                         corrEOF 
+= FrameEOF
[j
]*GraphBuffer
[i
+(j
/skip
)]; 
1363                 // Even things out by the length of the target waveform. 
1367                 if(corrEOF 
> corr1 
&& corrEOF 
> corr0
) { 
1368                         PrintToScrollback("EOF at %d", i
); 
1370                 } else if(corr1 
> corr0
) { 
1371                         i 
+= arraylen(Logic1
)/skip
; 
1374                         i 
+= arraylen(Logic0
)/skip
; 
1381                 if((i
+(int)arraylen(FrameEOF
)) >= GraphTraceLen
) { 
1382                         PrintToScrollback("ran off end!"); 
1387                 PrintToScrollback("error, uneven octet! (discard extra bits!)"); 
1388                 PrintToScrollback("   mask=%02x", mask
); 
1390         PrintToScrollback("%d octets", k
); 
1392         for(i 
= 0; i 
< k
; i
++) { 
1393                 PrintToScrollback("# %2d: %02x ", i
, outBuf
[i
]); 
1395         PrintToScrollback("CRC=%04x", Iso15693Crc(outBuf
, k
-2)); 
1398 static void CmdTiread(char *str
) 
1401         c
.cmd 
= CMD_ACQUIRE_RAW_BITS_TI_TYPE
; 
1402         SendCommand(&c
, FALSE
); 
1405 static void CmdTibits(char *str
) 
1409         for(i 
= 0; i 
< 1536; i 
+= 12) { 
1411                 c
.cmd 
= CMD_DOWNLOAD_RAW_BITS_TI_TYPE
; 
1413                 SendCommand(&c
, FALSE
); 
1415                 if(c
.cmd 
!= CMD_DOWNLOADED_RAW_BITS_TI_TYPE
) { 
1416                         PrintToScrollback("bad resp"); 
1420                 for(j 
= 0; j 
< 12; j
++) { 
1422                         for(k 
= 31; k 
>= 0; k
--) { 
1423                                 if(c
.d
.asDwords
[j
] & (1 << k
)) { 
1424                                         GraphBuffer
[cnt
++] = 1; 
1426                                         GraphBuffer
[cnt
++] = -1; 
1431         GraphTraceLen 
= 1536*32; 
1432         RepaintGraphWindow(); 
1435 static void CmdTidemod(char *cmdline
) 
1437         /* MATLAB as follows: 
1438 f_s = 2000000;  % sampling frequency 
1439 f_l = 123200;   % low FSK tone 
1440 f_h = 134200;   % high FSK tone 
1442 T_l = 119e-6;   % low bit duration 
1443 T_h = 130e-6;   % high bit duration 
1445 l = 2*pi*ones(1, floor(f_s*T_l))*(f_l/f_s); 
1446 h = 2*pi*ones(1, floor(f_s*T_h))*(f_h/f_s); 
1448 l = sign(sin(cumsum(l))); 
1449 h = sign(sin(cumsum(h))); 
1451         static const int LowTone
[] = { 
1452                 1, 1, 1, 1, 1, 1, 1, 1, -1, -1, -1, -1, -1, -1, -1, -1, 1, 1, 1, 
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, 
1466         static const int HighTone
[] = { 
1467                 1, 1, 1, 1, 1, 1, 1, -1, -1, -1, -1, -1, -1, -1, 1, 1, 1, 1, 1, 1, 
1468                 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, 
1470                 -1, -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, 
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, 1, 1, 
1476                 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, 
1478                 -1, -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, 
1483         int convLen 
= max(arraylen(HighTone
), arraylen(LowTone
)); 
1486         for(i 
= 0; i 
< GraphTraceLen 
- convLen
; i
++) { 
1488                 int lowSum 
= 0, highSum 
= 0;; 
1489                 int lowLen 
= arraylen(LowTone
); 
1490                 int highLen 
= arraylen(HighTone
); 
1492                 for(j 
= 0; j 
< lowLen
; j
++) { 
1493                         lowSum 
+= LowTone
[j
]*GraphBuffer
[i
+j
]; 
1495                 for(j 
= 0; j 
< highLen
; j
++) { 
1496                         highSum 
+= HighTone
[j
]*GraphBuffer
[i
+j
]; 
1498                 lowSum 
= abs((100*lowSum
) / lowLen
); 
1499                 highSum 
= abs((100*highSum
) / highLen
); 
1500                 GraphBuffer
[i
] = (highSum 
<< 16) | lowSum
; 
1503         for(i 
= 0; i 
< GraphTraceLen 
- convLen 
- 16; i
++) { 
1505                 int lowTot 
= 0, highTot 
= 0; 
1506                 // 16 and 15 are f_s divided by f_l and f_h, rounded 
1507                 for(j 
= 0; j 
< 16; j
++) { 
1508                         lowTot 
+= (GraphBuffer
[i
+j
] & 0xffff); 
1510                 for(j 
= 0; j 
< 15; j
++) { 
1511                         highTot 
+= (GraphBuffer
[i
+j
] >> 16); 
1513                 GraphBuffer
[i
] = lowTot 
- highTot
; 
1516         GraphTraceLen 
-= (convLen 
+ 16); 
1518         RepaintGraphWindow(); 
1520         // Okay, so now we have unsliced soft decisions; find bit-sync, and then 
1523         int max 
= 0, maxPos 
= 0; 
1524         for(i 
= 0; i 
< 6000; i
++) { 
1527                 for(j 
= 0; j 
< 8*arraylen(LowTone
); j
++) { 
1528                         dec 
-= GraphBuffer
[i
+j
]; 
1530                 for(; j 
< 8*arraylen(LowTone
) + 8*arraylen(HighTone
); j
++) { 
1531                         dec 
+= GraphBuffer
[i
+j
]; 
1538         GraphBuffer
[maxPos
] = 800; 
1539         GraphBuffer
[maxPos
+1] = -800; 
1541         maxPos 
+= 8*arraylen(LowTone
); 
1542         GraphBuffer
[maxPos
] = 800; 
1543         GraphBuffer
[maxPos
+1] = -800; 
1544         maxPos 
+= 8*arraylen(HighTone
); 
1546         GraphBuffer
[maxPos
] = 800; 
1547         GraphBuffer
[maxPos
+1] = -800; 
1549         PrintToScrollback("actual data bits start at sample %d", maxPos
); 
1551         PrintToScrollback("length %d/%d", arraylen(HighTone
), arraylen(LowTone
)); 
1553         GraphBuffer
[maxPos
] = 800; 
1554         GraphBuffer
[maxPos
+1] = -800; 
1556         BYTE bits
[64+16+8+1]; 
1557         bits
[sizeof(bits
)-1] = '\0'; 
1559         for(i 
= 0; i 
< arraylen(bits
); i
++) { 
1563                 for(j 
= 0; j 
< arraylen(LowTone
); j
++) { 
1564                         low 
-= GraphBuffer
[maxPos
+j
]; 
1566                 for(j 
= 0; j 
< arraylen(HighTone
); j
++) { 
1567                         high 
+= GraphBuffer
[maxPos
+j
]; 
1571                         maxPos 
+= arraylen(HighTone
); 
1574                         maxPos 
+= arraylen(LowTone
); 
1576                 GraphBuffer
[maxPos
] = 800; 
1577                 GraphBuffer
[maxPos
+1] = -800; 
1579         PrintToScrollback("bits: '%s'", bits
); 
1582         for(i 
= 0; i 
< 32; i
++) { 
1583                 if(bits
[i
] == '1') { 
1587         for(i 
= 32; i 
< 64; i
++) { 
1588                 if(bits
[i
] == '1') { 
1592         PrintToScrollback("hex: %08x %08x", h
, l
); 
1595 static void CmdNorm(char *str
) 
1598         int max 
= INT_MIN
, min 
= INT_MAX
; 
1599         for(i 
= 10; i 
< GraphTraceLen
; i
++) { 
1600                 if(GraphBuffer
[i
] > max
) { 
1601                         max 
= GraphBuffer
[i
]; 
1603                 if(GraphBuffer
[i
] < min
) { 
1604                         min 
= GraphBuffer
[i
]; 
1608                 for(i 
= 0; i 
< GraphTraceLen
; i
++) { 
1609                         GraphBuffer
[i
] = (GraphBuffer
[i
] - ((max 
+ min
)/2))*1000/ 
1613         RepaintGraphWindow(); 
1616 static void CmdDec(char *str
) 
1619         for(i 
= 0; i 
< (GraphTraceLen
/2); i
++) { 
1620                 GraphBuffer
[i
] = GraphBuffer
[i
*2]; 
1623         PrintToScrollback("decimated by 2"); 
1624         RepaintGraphWindow(); 
1627 static void CmdHpf(char *str
) 
1631         for(i 
= 10; i 
< GraphTraceLen
; i
++) { 
1632                 accum 
+= GraphBuffer
[i
]; 
1634         accum 
/= (GraphTraceLen 
- 10); 
1635         for(i 
= 0; i 
< GraphTraceLen
; i
++) { 
1636                 GraphBuffer
[i
] -= accum
; 
1639         RepaintGraphWindow(); 
1642 static void CmdZerocrossings(char *str
) 
1645         // Zero-crossings aren't meaningful unless the signal is zero-mean. 
1651         for(i 
= 0; i 
< GraphTraceLen
; i
++) { 
1652                 if(GraphBuffer
[i
]*sign 
>= 0) { 
1653                         // No change in sign, reproduce the previous sample count. 
1655                         GraphBuffer
[i
] = lastZc
; 
1657                         // Change in sign, reset the sample count. 
1659                         GraphBuffer
[i
] = lastZc
; 
1667         RepaintGraphWindow(); 
1670 static void CmdLtrim(char *str
) 
1675         for(i 
= ds
; i 
< GraphTraceLen
; i
++) { 
1676                 GraphBuffer
[i
-ds
] = GraphBuffer
[i
]; 
1678         GraphTraceLen 
-= ds
; 
1680         RepaintGraphWindow(); 
1683 static void CmdAutoCorr(char *str
) 
1685         static int CorrelBuffer
[MAX_GRAPH_TRACE_LEN
]; 
1687         int window 
= atoi(str
); 
1690                 PrintToScrollback("needs a window"); 
1694         if(window 
>= GraphTraceLen
) { 
1695                 PrintToScrollback("window must be smaller than trace (%d samples)", 
1700         PrintToScrollback("performing %d correlations", GraphTraceLen 
- window
); 
1703         for(i 
= 0; i 
< GraphTraceLen 
- window
; i
++) { 
1706                 for(j 
= 0; j 
< window
; j
++) { 
1707                         sum 
+= (GraphBuffer
[j
]*GraphBuffer
[i
+j
]) / 256; 
1709                 CorrelBuffer
[i
] = sum
; 
1711         GraphTraceLen 
= GraphTraceLen 
- window
; 
1712         memcpy(GraphBuffer
, CorrelBuffer
, GraphTraceLen
*sizeof(int)); 
1714         RepaintGraphWindow(); 
1717 static void CmdVchdemod(char *str
) 
1719         // Is this the entire sync pattern, or does this also include some 
1720         // data bits that happen to be the same everywhere? That would be 
1722         static const int SyncPattern
[] = { 
1723                 1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1, 
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, 
1735         // So first, we correlate for the sync pattern, and mark that. 
1736         int bestCorrel 
= 0, bestPos 
= 0; 
1738         // It does us no good to find the sync pattern, with fewer than 
1739         // 2048 samples after it... 
1740         for(i 
= 0; i 
< (GraphTraceLen
-2048); i
++) { 
1743                 for(j 
= 0; j 
< arraylen(SyncPattern
); j
++) { 
1744                         sum 
+= GraphBuffer
[i
+j
]*SyncPattern
[j
]; 
1746                 if(sum 
> bestCorrel
) { 
1751         PrintToScrollback("best sync at %d [metric %d]", bestPos
, bestCorrel
); 
1756         int worst 
= INT_MAX
; 
1759         for(i 
= 0; i 
< 2048; i 
+= 8) { 
1762                 for(j 
= 0; j 
< 8; j
++) { 
1763                         sum 
+= GraphBuffer
[bestPos
+i
+j
]; 
1770                 if(abs(sum
) < worst
) { 
1775         PrintToScrollback("bits:"); 
1776         PrintToScrollback("%s", bits
); 
1777         PrintToScrollback("worst metric: %d at pos %d", worst
, worstPos
); 
1779         if(strcmp(str
, "clone")==0) { 
1782                 for(s 
= bits
; *s
; s
++) { 
1784                         for(j 
= 0; j 
< 16; j
++) { 
1785                                 GraphBuffer
[GraphTraceLen
++] = (*s 
== '1') ? 1 : 0; 
1788                 RepaintGraphWindow(); 
1792 static void CmdIndalademod(char *str
) 
1794         // Usage: recover 64bit UID by default, specify "224" as arg to recover a 224bit UID 
1799         // worst case with GraphTraceLen=64000 is < 4096 
1800         // under normal conditions it's < 2048 
1803         int worst 
= 0, worstPos 
= 0; 
1804         PrintToScrollback("Expecting a bit less than %d raw bits", GraphTraceLen
/32); 
1805         for(i 
= 0; i 
< GraphTraceLen
-1; i 
+= 2) { 
1807                 if((GraphBuffer
[i
] > GraphBuffer
[i 
+ 1]) && (state 
!= 1)) { 
1809                                 for(j 
= 0; j 
<  count 
- 8; j 
+= 16) { 
1810                                         rawbits
[rawbit
++] = 0; 
1812                                 if ((abs(count 
- j
)) > worst
) { 
1813                                         worst 
= abs(count 
- j
); 
1819                 } else if((GraphBuffer
[i
] < GraphBuffer
[i 
+ 1]) && (state 
!= 0)) { 
1821                                 for(j 
= 0; j 
<  count 
- 8; j 
+= 16) { 
1822                                         rawbits
[rawbit
++] = 1; 
1824                                 if ((abs(count 
- j
)) > worst
) { 
1825                                         worst 
= abs(count 
- j
); 
1833         PrintToScrollback("Recovered %d raw bits", rawbit
); 
1834         PrintToScrollback("worst metric (0=best..7=worst): %d at pos %d", worst
, worstPos
); 
1836         // Finding the start of a UID 
1837         int uidlen
, long_wait
; 
1838         if(strcmp(str
, "224") == 0) { 
1847         for(start 
= 0; start 
<= rawbit 
- uidlen
; start
++) { 
1848                 first 
= rawbits
[start
]; 
1849                 for(i 
= start
; i 
< start 
+ long_wait
; i
++) { 
1850                         if(rawbits
[i
] != first
) { 
1854                 if(i 
== (start 
+ long_wait
)) { 
1858         if(start 
== rawbit 
- uidlen 
+ 1) { 
1859                 PrintToScrollback("nothing to wait for"); 
1863         // Inverting signal if needed 
1865                 for(i 
= start
; i 
< rawbit
; i
++) { 
1866                         rawbits
[i
] = !rawbits
[i
]; 
1873         showbits
[uidlen
]='\0'; 
1877         if(uidlen 
> rawbit
) { 
1878                 PrintToScrollback("Warning: not enough raw bits to get a full UID"); 
1879                 for(bit 
= 0; bit 
< rawbit
; bit
++) { 
1880                         bits
[bit
] = rawbits
[i
++]; 
1881                         // As we cannot know the parity, let's use "." and "/" 
1882                         showbits
[bit
] = '.' + bits
[bit
]; 
1884                 showbits
[bit
+1]='\0'; 
1885                 PrintToScrollback("Partial UID=%s", showbits
); 
1888                 for(bit 
= 0; bit 
< uidlen
; bit
++) { 
1889                         bits
[bit
] = rawbits
[i
++]; 
1890                         showbits
[bit
] = '0' + bits
[bit
]; 
1894         PrintToScrollback("UID=%s", showbits
); 
1896         // Checking UID against next occurences 
1897         for(; i 
+ uidlen 
<= rawbit
;) { 
1899                 for(bit 
= 0; bit 
< uidlen
; bit
++) { 
1900                         if(bits
[bit
] != rawbits
[i
++]) { 
1910         PrintToScrollback("Occurences: %d (expected %d)", times
, (rawbit 
- start
) / uidlen
); 
1912         // Remodulating for tag cloning 
1913         GraphTraceLen 
= 32*uidlen
; 
1916         for(bit 
= 0; bit 
< uidlen
; bit
++) { 
1917                 if(bits
[bit
] == 0) { 
1923                 for(j 
= 0; j 
< 32; j
++) { 
1924                         GraphBuffer
[i
++] = phase
; 
1929         RepaintGraphWindow(); 
1932 static void CmdFlexdemod(char *str
) 
1935         for(i 
= 0; i 
< GraphTraceLen
; i
++) { 
1936                 if(GraphBuffer
[i
] < 0) { 
1937                         GraphBuffer
[i
] = -1; 
1943 #define LONG_WAIT 100 
1945         for(start 
= 0; start 
< GraphTraceLen 
- LONG_WAIT
; start
++) { 
1946                 int first 
= GraphBuffer
[start
]; 
1947                 for(i 
= start
; i 
< start 
+ LONG_WAIT
; i
++) { 
1948                         if(GraphBuffer
[i
] != first
) { 
1952                 if(i 
== (start 
+ LONG_WAIT
)) { 
1956         if(start 
== GraphTraceLen 
- LONG_WAIT
) { 
1957                 PrintToScrollback("nothing to wait for"); 
1961         GraphBuffer
[start
] = 2; 
1962         GraphBuffer
[start
+1] = -2; 
1968         for(bit 
= 0; bit 
< 64; bit
++) { 
1971                 for(j 
= 0; j 
< 16; j
++) { 
1972                         sum 
+= GraphBuffer
[i
++]; 
1979                 PrintToScrollback("bit %d sum %d", bit
, sum
); 
1982         for(bit 
= 0; bit 
< 64; bit
++) { 
1985                 for(j 
= 0; j 
< 16; j
++) { 
1986                         sum 
+= GraphBuffer
[i
++]; 
1988                 if(sum 
> 0 && bits
[bit
] != 1) { 
1989                         PrintToScrollback("oops1 at %d", bit
); 
1991                 if(sum 
< 0 && bits
[bit
] != 0) { 
1992                         PrintToScrollback("oops2 at %d", bit
); 
1996         GraphTraceLen 
= 32*64; 
1999         for(bit 
= 0; bit 
< 64; bit
++) { 
2000                 if(bits
[bit
] == 0) { 
2006                 for(j 
= 0; j 
< 32; j
++) { 
2007                         GraphBuffer
[i
++] = phase
; 
2012         RepaintGraphWindow(); 
2016  * Generic command to demodulate ASK. 
2018  * Argument is convention: positive or negative (High mod means zero 
2019  * or high mod means one) 
2021  * Updates the Graph trace with 0/1 values 
2027 static void Cmdaskdemod(char *str
) { 
2029         int c
, high 
= 0, low 
= 0; 
2031         // TODO: complain if we do not give 2 arguments here ! 
2032         sscanf(str
, "%i", &c
); 
2034         /* Detect high and lows and clock */ 
2035         for (i 
= 0; i 
< GraphTraceLen
; i
++) 
2037                 if (GraphBuffer
[i
] > high
) 
2038                         high 
= GraphBuffer
[i
]; 
2039                 else if (GraphBuffer
[i
] < low
) 
2040                         low 
= GraphBuffer
[i
]; 
2043         if (GraphBuffer
[0] > 0) { 
2044                 GraphBuffer
[0] = 1-c
; 
2048         for(i
=1;i
<GraphTraceLen
;i
++) { 
2049                 /* Transitions are detected at each peak 
2050                  * Transitions are either: 
2051                  * - we're low: transition if we hit a high 
2052                  * - we're high: transition if we hit a low 
2053                  * (we need to do it this way because some tags keep high or 
2054                  * low for long periods, others just reach the peak and go 
2057                 if ((GraphBuffer
[i
]==high
) && (GraphBuffer
[i
-1] == c
)) { 
2059                 } else if ((GraphBuffer
[i
]==low
) && (GraphBuffer
[i
-1] == (1-c
))){ 
2063                         GraphBuffer
[i
] = GraphBuffer
[i
-1]; 
2066         RepaintGraphWindow(); 
2069 /* Print our clock rate */ 
2070 static void Cmddetectclockrate(char *str
) 
2072         int clock 
= detectclock(0); 
2073         PrintToScrollback("Auto-detected clock rate: %d", clock
); 
2079 int detectclock(int peak
) 
2085         /* Detect peak if we don't have one */ 
2087                 for (i 
= 0; i 
< GraphTraceLen
; i
++) 
2088                         if (GraphBuffer
[i
] > peak
) 
2089                                 peak 
= GraphBuffer
[i
]; 
2091         for (i 
= 1; i 
< GraphTraceLen
; i
++) 
2093                 /* If this is the beginning of a peak */ 
2094                 if (GraphBuffer
[i
-1] != GraphBuffer
[i
] && GraphBuffer
[i
] == peak
) 
2096                         /* Find lowest difference between peaks */ 
2097                         if (lastpeak 
&& i 
- lastpeak 
< clock
) 
2099                                 clock 
= i 
- lastpeak
; 
2108 /* Get or auto-detect clock rate */ 
2109 int GetClock(char *str
, int peak
) 
2113         sscanf(str
, "%i", &clock
); 
2114         if (!strcmp(str
, "")) 
2117         /* Auto-detect clock */ 
2120                 clock 
= detectclock(peak
); 
2122                 /* Only print this message if we're not looping something */ 
2124                         PrintToScrollback("Auto-detected clock rate: %d", clock
); 
2131  * Convert to a bitstream 
2133 static void Cmdbitstream(char *str
) { 
2140         int hithigh
, hitlow
, first
; 
2142         /* Detect high and lows and clock */ 
2143         for (i 
= 0; i 
< GraphTraceLen
; i
++) 
2145                 if (GraphBuffer
[i
] > high
) 
2146                         high 
= GraphBuffer
[i
]; 
2147                 else if (GraphBuffer
[i
] < low
) 
2148                         low 
= GraphBuffer
[i
]; 
2152         clock 
= GetClock(str
, high
); 
2154         gtl 
= CmdClearGraph(0); 
2157         for (i 
= 0; i 
< (int)(gtl 
/ clock
); i
++) 
2163                 /* Find out if we hit both high and low peaks */ 
2164                 for (j 
= 0; j 
< clock
; j
++) 
2166                         if (GraphBuffer
[(i 
* clock
) + j
] == high
) 
2168                         else if (GraphBuffer
[(i 
* clock
) + j
] == low
) 
2171                         /* it doesn't count if it's the first part of our read 
2172                          because it's really just trailing from the last sequence */ 
2173                         if (first 
&& (hithigh 
|| hitlow
)) 
2174                                 hithigh 
= hitlow 
= 0; 
2178                         if (hithigh 
&& hitlow
) 
2182                 /* If we didn't hit both high and low peaks, we had a bit transition */ 
2183                 if (!hithigh 
|| !hitlow
) 
2186                 CmdAppendGraph(0, clock
, bit
); 
2187 //              for (j = 0; j < (int)(clock/2); j++) 
2188 //                      GraphBuffer[(i * clock) + j] = bit ^ 1; 
2189 //              for (j = (int)(clock/2); j < clock; j++) 
2190 //                      GraphBuffer[(i * clock) + j] = bit; 
2193         RepaintGraphWindow(); 
2196 /* Modulate our data into manchester */ 
2197 static void Cmdmanchestermod(char *str
) 
2201         int bit
, lastbit
, wave
; 
2204         clock 
= GetClock(str
, 0); 
2208         for (i 
= 0; i 
< (int)(GraphTraceLen 
/ clock
); i
++) 
2210                 bit 
= GraphBuffer
[i 
* clock
] ^ 1; 
2212                 for (j 
= 0; j 
< (int)(clock
/2); j
++) 
2213                         GraphBuffer
[(i 
* clock
) + j
] = bit 
^ lastbit 
^ wave
; 
2214                 for (j 
= (int)(clock
/2); j 
< clock
; j
++) 
2215                         GraphBuffer
[(i 
* clock
) + j
] = bit 
^ lastbit 
^ wave 
^ 1; 
2217                 /* Keep track of how we start our wave and if we changed or not this time */ 
2218                 wave 
^= bit 
^ lastbit
; 
2222         RepaintGraphWindow(); 
2226  * Manchester demodulate a bitstream. The bitstream needs to be already in 
2227  * the GraphBuffer as 0 and 1 values 
2229  * Give the clock rate as argument in order to help the sync - the algorithm 
2230  * resyncs at each pulse anyway. 
2232  * Not optimized by any means, this is the 1st time I'm writing this type of 
2233  * routine, feel free to improve... 
2235  * 1st argument: clock rate (as number of samples per clock rate) 
2236  *               Typical values can be 64, 32, 128... 
2238 static void Cmdmanchesterdemod(char *str
) { 
2239         int i
, j
, invert
= 0; 
2245         int hithigh
, hitlow
, first
; 
2251         /* check if we're inverting output */ 
2254                 PrintToScrollback("Inverting output"); 
2258                 while(*str 
== ' '); // in case a 2nd argument was given 
2261         /* Holds the decoded bitstream: each clock period contains 2 bits       */ 
2262         /* later simplified to 1 bit after manchester decoding.                 */ 
2263         /* Add 10 bits to allow for noisy / uncertain traces without aborting   */ 
2264         /* int BitStream[GraphTraceLen*2/clock+10]; */ 
2266         /* But it does not work if compiling on WIndows: therefore we just allocate a */ 
2268         int BitStream
[MAX_GRAPH_TRACE_LEN
]; 
2270         /* Detect high and lows */ 
2271         for (i 
= 0; i 
< GraphTraceLen
; i
++) 
2273                 if (GraphBuffer
[i
] > high
) 
2274                         high 
= GraphBuffer
[i
]; 
2275                 else if (GraphBuffer
[i
] < low
) 
2276                         low 
= GraphBuffer
[i
]; 
2280         clock 
= GetClock(str
, high
); 
2282         int tolerance 
= clock
/4; 
2284         /* Detect first transition */ 
2285         /* Lo-Hi (arbitrary)       */ 
2286         for (i 
= 0; i 
< GraphTraceLen
; i
++) 
2288                 if (GraphBuffer
[i
] == low
) 
2295         /* If we're not working with 1/0s, demod based off clock */ 
2298                 bit 
= 0; /* We assume the 1st bit is zero, it may not be 
2299                           * the case: this routine (I think) has an init problem. 
2302                 for (; i 
< (int)(GraphTraceLen 
/ clock
); i
++) 
2308                         /* Find out if we hit both high and low peaks */ 
2309                         for (j 
= 0; j 
< clock
; j
++) 
2311                                 if (GraphBuffer
[(i 
* clock
) + j
] == high
) 
2313                                 else if (GraphBuffer
[(i 
* clock
) + j
] == low
) 
2316                                 /* it doesn't count if it's the first part of our read 
2317                                    because it's really just trailing from the last sequence */ 
2318                                 if (first 
&& (hithigh 
|| hitlow
)) 
2319                                         hithigh 
= hitlow 
= 0; 
2323                                 if (hithigh 
&& hitlow
) 
2327                         /* If we didn't hit both high and low peaks, we had a bit transition */ 
2328                         if (!hithigh 
|| !hitlow
) 
2331                         BitStream
[bit2idx
++] = bit 
^ invert
; 
2335         /* standard 1/0 bitstream */ 
2339                 /* Then detect duration between 2 successive transitions */ 
2340                 for (bitidx 
= 1; i 
< GraphTraceLen
; i
++) 
2342                         if (GraphBuffer
[i
-1] != GraphBuffer
[i
]) 
2347                         // Error check: if bitidx becomes too large, we do not 
2348                         // have a Manchester encoded bitstream or the clock is really 
2350                         if (bitidx 
> (GraphTraceLen
*2/clock
+8) ) { 
2351                                 PrintToScrollback("Error: the clock you gave is probably wrong, aborting."); 
2354                         // Then switch depending on lc length: 
2355                         // Tolerance is 1/4 of clock rate (arbitrary) 
2356                         if (abs(lc
-clock
/2) < tolerance
) { 
2357                                 // Short pulse : either "1" or "0" 
2358                                 BitStream
[bitidx
++]=GraphBuffer
[i
-1]; 
2359                         } else if (abs(lc
-clock
) < tolerance
) { 
2360                                 // Long pulse: either "11" or "00" 
2361                                 BitStream
[bitidx
++]=GraphBuffer
[i
-1]; 
2362                                 BitStream
[bitidx
++]=GraphBuffer
[i
-1]; 
2366                                 PrintToScrollback("Warning: Manchester decode error for pulse width detection."); 
2367                                 PrintToScrollback("(too many of those messages mean either the stream is not Manchester encoded, or clock is wrong)"); 
2371                                                 PrintToScrollback("Error: too many detection errors, aborting."); 
2378                 // At this stage, we now have a bitstream of "01" ("1") or "10" ("0"), parse it into final decoded bitstream 
2379                 // Actually, we overwrite BitStream with the new decoded bitstream, we just need to be careful 
2380                 // to stop output at the final bitidx2 value, not bitidx 
2381                 for (i 
= 0; i 
< bitidx
; i 
+= 2) { 
2382                         if ((BitStream
[i
] == 0) && (BitStream
[i
+1] == 1)) { 
2383                                 BitStream
[bit2idx
++] = 1 ^ invert
; 
2384                 } else if ((BitStream
[i
] == 1) && (BitStream
[i
+1] == 0)) { 
2385                         BitStream
[bit2idx
++] = 0 ^ invert
; 
2387                         // We cannot end up in this state, this means we are unsynchronized, 
2391                         PrintToScrollback("Unsynchronized, resync..."); 
2392                         PrintToScrollback("(too many of those messages mean the stream is not Manchester encoded)"); 
2396                                         PrintToScrollback("Error: too many decode errors, aborting."); 
2403         PrintToScrollback("Manchester decoded bitstream"); 
2404         // Now output the bitstream to the scrollback by line of 16 bits 
2405         for (i 
= 0; i 
< (bit2idx
-16); i
+=16) { 
2406                 PrintToScrollback("%i %i %i %i %i %i %i %i %i %i %i %i %i %i %i %i", 
2431 static void CmdHiddemod(char *str
) 
2433         if(GraphTraceLen 
< 4800) { 
2434                 PrintToScrollback("too short; need at least 4800 samples"); 
2438         GraphTraceLen 
= 4800; 
2440         for(i 
= 0; i 
< GraphTraceLen
; i
++) { 
2441                 if(GraphBuffer
[i
] < 0) { 
2447         RepaintGraphWindow(); 
2450 static void CmdPlot(char *str
) 
2455 static void CmdHide(char *str
) 
2460 static void CmdScale(char *str
) 
2462         CursorScaleFactor 
= atoi(str
); 
2463         if(CursorScaleFactor 
== 0) { 
2464                 PrintToScrollback("bad, can't have zero scale"); 
2465                 CursorScaleFactor 
= 1; 
2467         RepaintGraphWindow(); 
2470 static void CmdSave(char *str
) 
2472         FILE *f 
= fopen(str
, "w"); 
2474                 PrintToScrollback("couldn't open '%s'", str
); 
2478         for(i 
= 0; i 
< GraphTraceLen
; i
++) { 
2479                 fprintf(f
, "%d\n", GraphBuffer
[i
]); 
2482         PrintToScrollback("saved to '%s'", str
); 
2485 static void CmdLoad(char *str
) 
2487         FILE *f 
= fopen(str
, "r"); 
2489                 PrintToScrollback("couldn't open '%s'", str
); 
2495         while(fgets(line
, sizeof(line
), f
)) { 
2496                 GraphBuffer
[GraphTraceLen
] = atoi(line
); 
2500         PrintToScrollback("loaded %d samples", GraphTraceLen
); 
2501         RepaintGraphWindow(); 
2504 static void CmdHIDsimTAG(char *str
) 
2506         unsigned int hi
=0, lo
=0; 
2510         while (sscanf(&str
[i
++], "%1x", &n 
) == 1) { 
2511                 hi
=(hi
<<4)|(lo
>>28); 
2515         PrintToScrollback("Emulating tag with ID %x%16x", hi
, lo
); 
2517         c
.cmd 
= CMD_HID_SIM_TAG
; 
2520         SendCommand(&c
, FALSE
); 
2523 static void CmdReadmem(char *str
) 
2526         c
.cmd 
= CMD_READ_MEM
; 
2528         SendCommand(&c
, FALSE
); 
2531 static void CmdLcdReset(char *str
) 
2534         c
.cmd 
= CMD_LCD_RESET
; 
2536         SendCommand(&c
, FALSE
); 
2539 static void CmdLcd(char *str
) 
2544         sscanf(str
, "%x %d", &i
, &j
); 
2547                 SendCommand(&c
, FALSE
); 
2553 static void CmdTest(char *str
) 
2558  * Sets the divisor for LF frequency clock: lets the user choose any LF frequency below 
2561 static void CmdSetDivisor(char *str
) 
2564         c
.cmd 
= CMD_SET_LF_DIVISOR
; 
2566         if (( c
.ext1
<0) || (c
.ext1
>255)) { 
2567                         PrintToScrollback("divisor must be between 19 and 255"); 
2569                         SendCommand(&c
, FALSE
); 
2570                         PrintToScrollback("Divisor set, expected freq=%dHz", 12000000/(c
.ext1
+1)); 
2574 static void CmdSweepLF(char *str
) 
2577         c
.cmd 
= CMD_SWEEP_LF
; 
2578         SendCommand(&c
, FALSE
); 
2582 typedef void HandlerFunction(char *cmdline
); 
2584 /* in alphabetic order */ 
2587         HandlerFunction 
*handler
; 
2588         int             offline
;  // 1 if the command can be used when in offline mode 
2590 } CommandTable
[] = { 
2591         {"askdemod",                    Cmdaskdemod
,1,          "<samples per bit> <0|1> -- Attempt to demodulate simple ASK tags"}, 
2592         {"autocorr",                    CmdAutoCorr
,1,          "<window length> -- Autocorrelation over window"}, 
2593         {"bitsamples",          CmdBitsamples
,0,        "    Get raw samples as bitstring"}, 
2594         {"bitstream",           Cmdbitstream
,1,         "[clock rate] -- Convert waveform into a bitstream"}, 
2595         {"buffclear",           CmdBuffClear
,0,         "    Clear sample buffer and graph window"}, 
2596         {"dec",                         CmdDec
,1,               "    Decimate samples"}, 
2597         {"detectclock",         Cmddetectclockrate
,1, "    Detect clock rate"}, 
2598         {"detectreader",                CmdDetectReader
,0, "['l'|'h'] -- Detect external reader field (option 'l' or 'h' to limit to LF or HF)"}, 
2599         {"em410xsim",           CmdEM410xsim
,1,         "<UID> -- Simulate EM410x tag"}, 
2600         {"em410xread",          CmdEM410xread
,1,        "[clock rate] -- Extract ID from EM410x tag"}, 
2601         {"em410xwatch",         CmdEM410xwatch
,0,       "    Watches for EM410x tags"}, 
2602         {"em4x50read",          CmdEM4x50read
,1,        "    Extract data from EM4x50 tag"}, 
2603         {"exit",                                CmdQuit
,1,                      "    Exit program"}, 
2604         {"flexdemod",           CmdFlexdemod
,1,         "    Demodulate samples for FlexPass"}, 
2605         {"fpgaoff",                     CmdFPGAOff
,0,           "    Set FPGA off"},                                                    // ## FPGA Control 
2606         {"hexsamples",          CmdHexsamples
,0,        "<blocks> -- Dump big buffer as hex bytes"}, 
2607         {"hi14alist",           CmdHi14alist
,0,         "    List ISO 14443a history"},                         // ## New list command 
2608         {"hi14areader",         CmdHi14areader
,0,       "    Act like an ISO14443 Type A reader"},      // ## New reader command 
2609         {"hi14asim",                    CmdHi14asim
,0,          "<UID> -- Fake ISO 14443a tag"},                                        // ## Simulate 14443a tag 
2610         {"hi14asnoop",          CmdHi14asnoop
,0,        "    Eavesdrop ISO 14443 Type A"},                      // ## New snoop command 
2611         {"hi14bdemod",          CmdHi14bdemod
,1,        "    Demodulate ISO14443 Type B from tag"}, 
2612         {"hi14list",                    CmdHi14list
,0,          "    List ISO 14443 history"}, 
2613         {"hi14read",                    CmdHi14read
,0,          "    Read HF tag (ISO 14443)"}, 
2614         {"hi14sim",                     CmdHi14sim
,0,           "    Fake ISO 14443 tag"}, 
2615         {"hi14snoop",           CmdHi14snoop
,0,         "    Eavesdrop ISO 14443"}, 
2616         {"hi15demod",           CmdHi15demod
,1,         "    Demodulate ISO15693 from tag"}, 
2617         {"hi15read",                    CmdHi15read
,0,          "    Read HF tag (ISO 15693)"}, 
2618         {"hi15reader",          CmdHi15reader
,0,        "    Act like an ISO15693 reader"}, // new command greg 
2619         {"hi15sim",                     CmdHi15tag
,0,           "    Fake an ISO15693 tag"}, // new command greg 
2620         {"hiddemod",                    CmdHiddemod
,1,          "    Demodulate HID Prox Card II (not optimal)"}, 
2621         {"hide",                                CmdHide
,1,              "    Hide graph window"}, 
2622         {"hidfskdemod",         CmdHIDdemodFSK
,0,       "    Realtime HID FSK demodulator"}, 
2623         {"hidsimtag",           CmdHIDsimTAG
,0,         "<ID> -- HID tag simulator"}, 
2624         {"higet",                       CmdHi14read_sim
,0,      "<samples> -- Get samples HF, 'analog'"}, 
2625         {"hisamples",           CmdHisamples
,0,         "    Get raw samples for HF tag"}, 
2626         {"hisampless",          CmdHisampless
,0,        "<samples> -- Get signed raw samples, HF tag"}, 
2627         {"hisamplest",          CmdHi14readt
,0,         "    Get samples HF, for testing"}, 
2628         {"hisimlisten",         CmdHisimlisten
,0,       "    Get HF samples as fake tag"}, 
2629         {"hpf",                         CmdHpf
,1,               "    Remove DC offset from trace"}, 
2630         {"indalademod",         CmdIndalademod
,0,         "['224'] -- Demodulate samples for Indala 64 bit UID (option '224' for 224 bit)"}, 
2631         {"lcd",                         CmdLcd
,0,                       "<HEX command> <count> -- Send command/data to LCD"}, 
2632         {"lcdreset",                    CmdLcdReset
,0,          "    Hardware reset LCD"}, 
2633         {"load",                                CmdLoad
,1,              "<filename> -- Load trace (to graph window"}, 
2634         {"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)"}, 
2635         {"loread",                      CmdLoread
,0,            "['h'] -- Read 125/134 kHz LF ID-only tag (option 'h' for 134)"}, 
2636         {"losamples",           CmdLosamples
,0,         "[128 - 16000] -- Get raw samples for LF tag"}, 
2637         {"losim",                       CmdLosim
,0,             "    Simulate LF tag"}, 
2638         {"ltrim",                       CmdLtrim
,1,             "<samples> -- Trim samples from left of trace"}, 
2639         {"mandemod",                    Cmdmanchesterdemod
,1,   "[i] [clock rate] -- Manchester demodulate binary stream (option 'i' to invert output)"}, 
2640         {"manmod",                      Cmdmanchestermod
,1,     "[clock rate] -- Manchester modulate a binary stream"}, 
2641         {"norm",                                CmdNorm
,1,              "    Normalize max/min to +/-500"}, 
2642         {"plot",                                CmdPlot
,1,              "    Show graph window"}, 
2643         {"quit",                                CmdQuit
,1,                      "    Quit program"}, 
2644         {"readmem",                     CmdReadmem
,0,                   "    [address] Read memory at decimal address from flash"}, 
2645         {"reset",                       CmdReset
,0,                     "    Reset the Proxmark3"}, 
2646         {"save",                                CmdSave
,1,              "<filename> -- Save trace (from graph window)"}, 
2647         {"scale",                       CmdScale
,1,             "<int> -- Set cursor display scale"}, 
2648         {"setlfdivisor",                CmdSetDivisor
,0,        "<19 - 255> -- Drive LF antenna at 12Mhz/(divisor+1)"}, 
2649         {"sri512read",          CmdSri512read
,0,        "<int> -- Read contents of a SRI512 tag"}, 
2650         {"sweeplf",                     CmdSweepLF
,0,           "    Sweep through LF freq range, store results in buffer and show resonant frequency of antenna"}, 
2651         {"tibits",                      CmdTibits
,0,            "    Get raw bits for TI-type LF tag"}, 
2652         {"tidemod",                     CmdTidemod
,0,           "    Demodulate raw bits for TI-type LF tag"}, 
2653         {"tiread",                      CmdTiread
,0,            "    Read a TI-type 134 kHz tag"}, 
2654         {"tune",                                CmdTune
,0,              "    Measure antenna tuning"}, 
2655         {"vchdemod",                    CmdVchdemod
,0,          "['clone'] -- Demodulate samples for VeriChip"}, 
2656         {"zerocrossings",       CmdZerocrossings
,1,     "    Count time between zero-crossings"}, 
2664         }       CommandExtendedHelp
[]= { 
2665                 {"detectreader","'l'|'h'","'l' specifies LF antenna scan only, 'h' specifies HF antenna scan only.","Monitor antenna for changes in voltage. Output is in three fields: CHANGED, CURRENT, PERIOD,\nwhere CHANGED is the value just changed from, CURRENT is the current value and PERIOD is the\nnumber of program loops since the last change.\n\nThe RED LED indicates LF field detected, and the GREEN LED indicates HF field detected."}, 
2666                 {"sweeplf","","","Drive LF antenna at all divisor range values (19 - 255) and store the results in the output\nbuffer. Issuing 'losamples' and then 'plot' commands will display the resulting peak. 12MHz\ndivided by the peak's position plus one gives the antenna's resonant frequency. For convenience,\nthis value is also printed out by the command."}, 
2669 //----------------------------------------------------------------------------- 
2670 // Entry point into our code: called whenever the user types a command and 
2671 // then presses Enter, which the full command line that they typed. 
2672 //----------------------------------------------------------------------------- 
2673 void CommandReceived(char *cmd
) 
2678         PrintToScrollback("> %s", cmd
); 
2680         if(strcmp(cmd
, "help") == 0 || strncmp(cmd
,"help ",strlen("help ")) == 0) { 
2681                 // check if we're doing extended help 
2682                 if(strlen(cmd
) > strlen("help ")) { 
2683                         cmd 
+= strlen("help "); 
2684                         for(i 
= 0; i 
< sizeof(CommandExtendedHelp
) / sizeof(CommandExtendedHelp
[0]); i
++) { 
2685                                 if(strcmp(CommandExtendedHelp
[i
].name
,cmd
) == 0) { 
2686                                         PrintToScrollback("\nExtended help for '%s':\n", cmd
); 
2687                                         PrintToScrollback("Args: %s\t- %s\n",CommandExtendedHelp
[i
].args
,CommandExtendedHelp
[i
].argshelp
); 
2688                                         PrintToScrollback(CommandExtendedHelp
[i
].description
); 
2689                                         PrintToScrollback(""); 
2693                 PrintToScrollback("No extended help available for '%s'", cmd
); 
2696                 if (offline
) PrintToScrollback("Operating in OFFLINE mode (no device connected)"); 
2697                 PrintToScrollback("\r\nAvailable commands:"); 
2698                 for(i 
= 0; i 
< sizeof(CommandTable
) / sizeof(CommandTable
[0]); i
++) { 
2699                         if (offline 
&& (CommandTable
[i
].offline
==0)) continue; 
2700                         memset(line
, ' ', sizeof(line
)); 
2701                         strcpy(line
+2, CommandTable
[i
].name
); 
2702                         line
[strlen(line
)] = ' '; 
2703                         sprintf(line
+15, " -- %s", CommandTable
[i
].docString
); 
2704                         PrintToScrollback("%s", line
); 
2706                 PrintToScrollback(""); 
2707                 PrintToScrollback("'help <command>' for extended help on that command\n"); 
2711         for(i 
= 0; i 
< sizeof(CommandTable
) / sizeof(CommandTable
[0]); i
++) { 
2712                 char *name 
= CommandTable
[i
].name
; 
2713                 if(memcmp(cmd
, name
, strlen(name
))==0 && 
2714                         (cmd
[strlen(name
)] == ' ' || cmd
[strlen(name
)] == '\0')) 
2716                         cmd 
+= strlen(name
); 
2717                         while(*cmd 
== ' ') { 
2720                         if (offline 
&& (CommandTable
[i
].offline
==0)) { 
2721                                 PrintToScrollback("Offline mode, cannot use this command."); 
2724                         (CommandTable
[i
].handler
)(cmd
); 
2728         PrintToScrollback(">> bad command '%s'", cmd
); 
2731 //----------------------------------------------------------------------------- 
2732 // Entry point into our code: called whenever we received a packet over USB 
2733 // that we weren't necessarily expecting, for example a debug print. 
2734 //----------------------------------------------------------------------------- 
2735 void UsbCommandReceived(UsbCommand 
*c
) 
2738                 case CMD_DEBUG_PRINT_STRING
: { 
2740                         if(c
->ext1 
> 70 || c
->ext1 
< 0) { 
2743                         memcpy(s
, c
->d
.asBytes
, c
->ext1
); 
2745                         PrintToScrollback("#db# %s", s
); 
2749                 case CMD_DEBUG_PRINT_INTEGERS
: 
2750                         PrintToScrollback("#db# %08x, %08x, %08x\r\n", c
->ext1
, c
->ext2
, c
->ext3
); 
2753                 case CMD_MEASURED_ANTENNA_TUNING
: { 
2755                         int vLf125
, vLf134
, vHf
; 
2756                         vLf125 
= c
->ext1 
& 0xffff; 
2757                         vLf134 
= c
->ext1 
>> 16; 
2759                         zLf 
= c
->ext3 
& 0xffff; 
2760                         zHf 
= c
->ext3 
>> 16; 
2761                         PrintToScrollback("# LF antenna @ %3d mA / %5d mV [%d ohms] 125Khz", 
2762                                 vLf125
/zLf
, vLf125
, zLf
); 
2763                         PrintToScrollback("# LF antenna @ %3d mA / %5d mV [%d ohms] 134Khz", 
2764                                 vLf134
/((zLf
*125)/134), vLf134
, (zLf
*125)/134); 
2765                         PrintToScrollback("# HF antenna @ %3d mA / %5d mV [%d ohms] 13.56Mhz", 
2770                         PrintToScrollback("unrecognized command %08x\n", c
->cmd
);