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" 
  15 #include "../common/crc16.c" 
  17 #define arraylen(x) (sizeof(x)/sizeof((x)[0])) 
  18 #define BIT(x) GraphBuffer[x * clock] 
  19 #define BITS (GraphTraceLen / clock) 
  22 static int CmdHisamplest(char *str
, int nrlow
); 
  24 static void GetFromBigBuf(BYTE 
*dest
, int bytes
) 
  29                 PrintToScrollback("bad len in GetFromBigBuf"); 
  34         for(i 
= 0; i 
< n
; i 
+= 12) { 
  36                 c
.cmd 
= CMD_DOWNLOAD_RAW_ADC_SAMPLES_125K
; 
  38                 SendCommand(&c
, FALSE
); 
  40                 if(c
.cmd 
!= CMD_DOWNLOADED_RAW_ADC_SAMPLES_125K
) { 
  41                         PrintToScrollback("bad resp"); 
  45                 memcpy(dest
+(i
*4), c
.d
.asBytes
, 48); 
  49 static void CmdReset(char *str
) 
  52         c
.cmd 
= CMD_HARDWARE_RESET
; 
  53         SendCommand(&c
, FALSE
); 
  56 static void CmdBuffClear(char *str
) 
  59         c
.cmd 
= CMD_BUFF_CLEAR
; 
  60         SendCommand(&c
, FALSE
); 
  64 static void CmdQuit(char *str
) 
  69 static void CmdHIDdemodFSK(char *str
) 
  72         c
.cmd 
= CMD_HID_DEMOD_FSK
; 
  73         SendCommand(&c
, FALSE
); 
  76 static void CmdTune(char *str
) 
  79         c
.cmd 
= CMD_MEASURE_ANTENNA_TUNING
; 
  80         SendCommand(&c
, FALSE
); 
  83 static void CmdHi15read(char *str
) 
  86         c
.cmd 
= CMD_ACQUIRE_RAW_ADC_SAMPLES_ISO_15693
; 
  87         SendCommand(&c
, FALSE
); 
  90 static void CmdHi14read(char *str
) 
  93         c
.cmd 
= CMD_ACQUIRE_RAW_ADC_SAMPLES_ISO_14443
; 
  95         SendCommand(&c
, FALSE
); 
  99 /* New command to read the contents of a SRI512 tag 
 100  * SRI512 tags are ISO14443-B modulated memory tags, 
 101  * this command just dumps the contents of the memory/ 
 103 static void CmdSri512read(char *str
) 
 106         c
.cmd 
= CMD_READ_SRI512_TAG
; 
 108         SendCommand(&c
, FALSE
); 
 111 /* New command to read the contents of a SRIX4K tag 
 112  * SRIX4K tags are ISO14443-B modulated memory tags, 
 113  * this command just dumps the contents of the memory/ 
 115 static void CmdSrix4kread(char *str
) 
 118         c
.cmd 
= CMD_READ_SRIX4K_TAG
; 
 120         SendCommand(&c
, FALSE
); 
 126 static void CmdHi14areader(char *str
) 
 129         c
.cmd 
= CMD_READER_ISO_14443a
; 
 131         SendCommand(&c
, FALSE
); 
 135 static void CmdHi15reader(char *str
) 
 138         c
.cmd 
= CMD_READER_ISO_15693
; 
 140         SendCommand(&c
, FALSE
); 
 144 static void CmdHi15tag(char *str
) 
 147         c
.cmd 
= CMD_SIMTAG_ISO_15693
; 
 149         SendCommand(&c
, FALSE
); 
 152 static void CmdHi14read_sim(char *str
) 
 155         c
.cmd 
= CMD_ACQUIRE_RAW_ADC_SAMPLES_ISO_14443_SIM
; 
 157         SendCommand(&c
, FALSE
); 
 160 static void CmdHi14readt(char *str
) 
 163         c
.cmd 
= CMD_ACQUIRE_RAW_ADC_SAMPLES_ISO_14443
; 
 165         SendCommand(&c
, FALSE
); 
 167         //CmdHisamplest(str); 
 168         while(CmdHisamplest(str
,atoi(str
))==0) { 
 169                 c
.cmd 
= CMD_ACQUIRE_RAW_ADC_SAMPLES_ISO_14443
; 
 171                 SendCommand(&c
, FALSE
); 
 173         RepaintGraphWindow(); 
 176 static void CmdHisimlisten(char *str
) 
 179         c
.cmd 
= CMD_SIMULATE_TAG_HF_LISTEN
; 
 180         SendCommand(&c
, FALSE
); 
 183 static void CmdHi14sim(char *str
) 
 186         c
.cmd 
= CMD_SIMULATE_TAG_ISO_14443
; 
 187         SendCommand(&c
, FALSE
); 
 190 static void CmdHi14asim(char *str
)      // ## simulate iso14443a tag 
 191 {                                       // ## greg - added ability to specify tag UID 
 193         unsigned int hi
=0, lo
=0; 
 197         while (sscanf(&str
[i
++], "%1x", &n 
) == 1) { 
 202         c
.cmd 
= CMD_SIMULATE_TAG_ISO_14443a
; 
 203         // c.ext should be set to *str or convert *str to the correct format for a uid 
 206         PrintToScrollback("Emulating 14443A TAG with UID %x%16x", hi
, lo
); 
 207         SendCommand(&c
, FALSE
); 
 210 static void CmdHi14snoop(char *str
) 
 213         c
.cmd 
= CMD_SNOOP_ISO_14443
; 
 214         SendCommand(&c
, FALSE
); 
 217 static void CmdHi14asnoop(char *str
) 
 220         c
.cmd 
= CMD_SNOOP_ISO_14443a
; 
 221         SendCommand(&c
, FALSE
); 
 224 static void CmdLegicRfSim(char *str
) 
 227         c
.cmd 
= CMD_SIMULATE_TAG_LEGIC_RF
; 
 228         SendCommand(&c
, FALSE
); 
 231 static void CmdLegicRfRead(char *str
) 
 234         c
.cmd 
= CMD_READER_LEGIC_RF
; 
 235         SendCommand(&c
, FALSE
); 
 238 static void CmdFPGAOff(char *str
)               // ## FPGA Control 
 241         c
.cmd 
= CMD_FPGA_MAJOR_MODE_OFF
; 
 242         SendCommand(&c
, FALSE
); 
 245 /* clear out our graph window */ 
 246 int CmdClearGraph(int redraw
) 
 248         int gtl 
= GraphTraceLen
; 
 252                 RepaintGraphWindow(); 
 257 /* write a bit to the graph */ 
 258 static void CmdAppendGraph(int redraw
, int clock
, int bit
) 
 262         for (i 
= 0; i 
< (int)(clock
/2); i
++) 
 263                 GraphBuffer
[GraphTraceLen
++] = bit 
^ 1; 
 265         for (i 
= (int)(clock
/2); i 
< clock
; i
++) 
 266                 GraphBuffer
[GraphTraceLen
++] = bit
; 
 269                 RepaintGraphWindow(); 
 272 /* Function is equivalent of loread + losamples + em410xread 
 273  * looped until an EM410x tag is detected */ 
 274 static void CmdEM410xwatch(char *str
) 
 288 /* Read the transmitted data of an EM4x50 tag 
 291  *  XXXXXXXX [row parity bit (even)] <- 8 bits plus parity 
 292  *  XXXXXXXX [row parity bit (even)] <- 8 bits plus parity 
 293  *  XXXXXXXX [row parity bit (even)] <- 8 bits plus parity 
 294  *  XXXXXXXX [row parity bit (even)] <- 8 bits plus parity 
 295  *  CCCCCCCC                         <- column parity bits 
 297  *  LW                               <- Listen Window 
 299  * This pattern repeats for every block of data being transmitted. 
 300  * Transmission starts with two Listen Windows (LW - a modulated 
 301  * pattern of 320 cycles each (32/32/128/64/64)). 
 303  * Note that this data may or may not be the UID. It is whatever data 
 304  * is stored in the blocks defined in the control word First and Last 
 305  * Word Read values. UID is stored in block 32. 
 307 static void CmdEM4x50read(char *str
) 
 309         int i
, j
, startblock
, clock
, skip
, block
, start
, end
, low
, high
; 
 310         BOOL complete
= FALSE
; 
 311         int tmpbuff
[MAX_GRAPH_TRACE_LEN 
/ 64]; 
 317         /* first get high and low values */ 
 318         for (i 
= 0; i 
< GraphTraceLen
; i
++) 
 320                 if (GraphBuffer
[i
] > high
) 
 321                         high 
= GraphBuffer
[i
]; 
 322                 else if (GraphBuffer
[i
] < low
) 
 323                         low 
= GraphBuffer
[i
]; 
 326         /* populate a buffer with pulse lengths */ 
 329         while(i 
< GraphTraceLen
) 
 331                 // measure from low to low 
 332                 while((GraphBuffer
[i
] > low
) && (i
<GraphTraceLen
)) 
 335                 while((GraphBuffer
[i
] < high
) && (i
<GraphTraceLen
)) 
 337                 while((GraphBuffer
[i
] > low
) && (i
<GraphTraceLen
)) 
 339                 if (j
>(MAX_GRAPH_TRACE_LEN
/64)) { 
 342                 tmpbuff
[j
++]= i 
- start
; 
 345         /* look for data start - should be 2 pairs of LW (pulses of 192,128) */ 
 348         for (i
= 0; i 
< j 
- 4 ; ++i
) 
 351                 if (tmpbuff
[i
] >= 190 && tmpbuff
[i
] <= 194) 
 352                         if (tmpbuff
[i
+1] >= 126 && tmpbuff
[i
+1] <= 130) 
 353                                 if (tmpbuff
[i
+2] >= 190 && tmpbuff
[i
+2] <= 194) 
 354                                         if (tmpbuff
[i
+3] >= 126 && tmpbuff
[i
+3] <= 130) 
 362         /* skip over the remainder of the LW */ 
 363         skip 
+= tmpbuff
[i
+1]+tmpbuff
[i
+2]; 
 364         while(skip 
< MAX_GRAPH_TRACE_LEN 
&& GraphBuffer
[skip
] > low
) 
 368         /* now do it again to find the end */ 
 370         for (i 
+= 3; i 
< j 
- 4 ; ++i
) 
 373                 if (tmpbuff
[i
] >= 190 && tmpbuff
[i
] <= 194) 
 374                         if (tmpbuff
[i
+1] >= 126 && tmpbuff
[i
+1] <= 130) 
 375                                 if (tmpbuff
[i
+2] >= 190 && tmpbuff
[i
+2] <= 194) 
 376                                         if (tmpbuff
[i
+3] >= 126 && tmpbuff
[i
+3] <= 130) 
 384                 PrintToScrollback("Found data at sample: %i",skip
); 
 387                 PrintToScrollback("No data found!"); 
 388                 PrintToScrollback("Try again with more samples."); 
 394                 PrintToScrollback("*** Warning!"); 
 395                 PrintToScrollback("Partial data - no end found!"); 
 396                 PrintToScrollback("Try again with more samples."); 
 399         /* get rid of leading crap */ 
 400         sprintf(tmp
,"%i",skip
); 
 403         /* now work through remaining buffer printing out data blocks */ 
 408                 PrintToScrollback("Block %i:", block
); 
 409                 // mandemod routine needs to be split so we can call it for data 
 410                 // just print for now for debugging 
 411                 Cmdmanchesterdemod("i 64"); 
 413                 /* look for LW before start of next block */ 
 414                 for ( ; i 
< j 
- 4 ; ++i
) 
 417                         if (tmpbuff
[i
] >= 190 && tmpbuff
[i
] <= 194) 
 418                                 if (tmpbuff
[i
+1] >= 126 && tmpbuff
[i
+1] <= 130) 
 421                 while(GraphBuffer
[skip
] > low
) 
 424                 sprintf(tmp
,"%i",skip
); 
 432 /* Read the ID of an EM410x tag. 
 434  *   1111 1111 1           <-- standard non-repeatable header 
 435  *   XXXX [row parity bit] <-- 10 rows of 5 bits for our 40 bit tag ID 
 437  *   CCCC                  <-- each bit here is parity for the 10 bits above in corresponding column 
 438  *   0                     <-- stop bit, end of tag 
 440 static void CmdEM410xread(char *str
) 
 442         int i
, j
, clock
, header
, rows
, bit
, hithigh
, hitlow
, first
, bit2idx
, high
, low
; 
 446         int BitStream
[MAX_GRAPH_TRACE_LEN
]; 
 449         /* Detect high and lows and clock */ 
 450         for (i 
= 0; i 
< GraphTraceLen
; i
++) 
 452                 if (GraphBuffer
[i
] > high
) 
 453                         high 
= GraphBuffer
[i
]; 
 454                 else if (GraphBuffer
[i
] < low
) 
 455                         low 
= GraphBuffer
[i
]; 
 459         clock 
= GetClock(str
, high
); 
 461         /* parity for our 4 columns */ 
 462         parity
[0] = parity
[1] = parity
[2] = parity
[3] = 0; 
 465         /* manchester demodulate */ 
 467         for (i 
= 0; i 
< (int)(GraphTraceLen 
/ clock
); i
++) 
 473                 /* Find out if we hit both high and low peaks */ 
 474                 for (j 
= 0; j 
< clock
; j
++) 
 476                         if (GraphBuffer
[(i 
* clock
) + j
] == high
) 
 478                         else if (GraphBuffer
[(i 
* clock
) + j
] == low
) 
 481                         /* it doesn't count if it's the first part of our read 
 482                          because it's really just trailing from the last sequence */ 
 483                         if (first 
&& (hithigh 
|| hitlow
)) 
 484                                 hithigh 
= hitlow 
= 0; 
 488                         if (hithigh 
&& hitlow
) 
 492                 /* If we didn't hit both high and low peaks, we had a bit transition */ 
 493                 if (!hithigh 
|| !hitlow
) 
 496                 BitStream
[bit2idx
++] = bit
; 
 500         /* We go till 5 before the graph ends because we'll get that far below */ 
 501         for (i 
= 1; i 
< bit2idx 
- 5; i
++) 
 503                 /* Step 2: We have our header but need our tag ID */ 
 504                 if (header 
== 9 && rows 
< 10) 
 506                         /* Confirm parity is correct */ 
 507                         if ((BitStream
[i
] ^ BitStream
[i
+1] ^ BitStream
[i
+2] ^ BitStream
[i
+3]) == BitStream
[i
+4]) 
 509                                 /* Read another byte! */ 
 510                                 sprintf(id
+rows
, "%x", (8 * BitStream
[i
]) + (4 * BitStream
[i
+1]) + (2 * BitStream
[i
+2]) + (1 * BitStream
[i
+3])); 
 513                                 /* Keep parity info */ 
 514                                 parity
[0] ^= BitStream
[i
]; 
 515                                 parity
[1] ^= BitStream
[i
+1]; 
 516                                 parity
[2] ^= BitStream
[i
+2]; 
 517                                 parity
[3] ^= BitStream
[i
+3]; 
 519                                 /* Move 4 bits ahead */ 
 523                         /* Damn, something wrong! reset */ 
 526                                 PrintToScrollback("Thought we had a valid tag but failed at word %d (i=%d)", rows 
+ 1, i
); 
 528                                 /* Start back rows * 5 + 9 header bits, -1 to not start at same place */ 
 529                                 i 
-= 9 + (5 * rows
) - 5; 
 535                 /* Step 3: Got our 40 bits! confirm column parity */ 
 538                         /* We need to make sure our 4 bits of parity are correct and we have a stop bit */ 
 539                         if (BitStream
[i
] == parity
[0] && BitStream
[i
+1] == parity
[1] && 
 540                                 BitStream
[i
+2] == parity
[2] && BitStream
[i
+3] == parity
[3] && 
 544                                 PrintToScrollback("EM410x Tag ID: %s", id
); 
 551                         /* Crap! Incorrect parity or no stop bit, start all over */ 
 556                                 /* Go back 59 bits (9 header bits + 10 rows at 4+1 parity) */ 
 561                 /* Step 1: get our header */ 
 564                         /* Need 9 consecutive 1's */ 
 565                         if (BitStream
[i
] == 1) 
 568                         /* We don't have a header, not enough consecutive 1 bits */ 
 574         /* if we've already retested after flipping bits, return */ 
 578         /* if this didn't work, try flipping bits */ 
 579         for (i 
= 0; i 
< bit2idx
; i
++) 
 585 /* emulate an EM410X tag 
 587  *   1111 1111 1           <-- standard non-repeatable header 
 588  *   XXXX [row parity bit] <-- 10 rows of 5 bits for our 40 bit tag ID 
 590  *   CCCC                  <-- each bit here is parity for the 10 bits above in corresponding column 
 591  *   0                     <-- stop bit, end of tag 
 593 static void CmdEM410xsim(char *str
) 
 595         int i
, n
, j
, h
, binary
[4], parity
[4]; 
 598         /* clock is 64 in EM410x tags */ 
 601         /* clear our graph */ 
 604         /* write it out a few times */ 
 605         for (h 
= 0; h 
< 4; h
++) 
 607                 /* write 9 start bits */ 
 608                 for (i 
= 0; i 
< 9; i
++) 
 609                         CmdAppendGraph(0, clock
, 1); 
 611                 /* for each hex char */ 
 612                 parity
[0] = parity
[1] = parity
[2] = parity
[3] = 0; 
 613                 for (i 
= 0; i 
< 10; i
++) 
 615                         /* read each hex char */ 
 616                         sscanf(&str
[i
], "%1x", &n
); 
 617                         for (j 
= 3; j 
>= 0; j
--, n
/= 2) 
 620                         /* append each bit */ 
 621                         CmdAppendGraph(0, clock
, binary
[0]); 
 622                         CmdAppendGraph(0, clock
, binary
[1]); 
 623                         CmdAppendGraph(0, clock
, binary
[2]); 
 624                         CmdAppendGraph(0, clock
, binary
[3]); 
 626                         /* append parity bit */ 
 627                         CmdAppendGraph(0, clock
, binary
[0] ^ binary
[1] ^ binary
[2] ^ binary
[3]); 
 629                         /* keep track of column parity */ 
 630                         parity
[0] ^= binary
[0]; 
 631                         parity
[1] ^= binary
[1]; 
 632                         parity
[2] ^= binary
[2]; 
 633                         parity
[3] ^= binary
[3]; 
 637                 CmdAppendGraph(0, clock
, parity
[0]); 
 638                 CmdAppendGraph(0, clock
, parity
[1]); 
 639                 CmdAppendGraph(0, clock
, parity
[2]); 
 640                 CmdAppendGraph(0, clock
, parity
[3]); 
 643                 CmdAppendGraph(0, clock
, 0); 
 646         /* modulate that biatch */ 
 650         RepaintGraphWindow(); 
 655 static void ChkBitstream(char *str
) 
 659         /* convert to bitstream if necessary */ 
 660         for (i 
= 0; i 
< (int)(GraphTraceLen 
/ 2); i
++) 
 662                 if (GraphBuffer
[i
] > 1 || GraphBuffer
[i
] < 0) 
 670 static void CmdLosim(char *str
) 
 674         /* convert to bitstream if necessary */ 
 677         for (i 
= 0; i 
< GraphTraceLen
; i 
+= 48) { 
 680                 for(j 
= 0; j 
< 48; j
++) { 
 681                         c
.d
.asBytes
[j
] = GraphBuffer
[i
+j
]; 
 683                 c
.cmd 
= CMD_DOWNLOADED_SIM_SAMPLES_125K
; 
 685                 SendCommand(&c
, FALSE
); 
 689         c
.cmd 
= CMD_SIMULATE_TAG_125K
; 
 690         c
.ext1 
= GraphTraceLen
; 
 691         SendCommand(&c
, FALSE
); 
 694 static void CmdLosimBidir(char *str
) 
 697         c
.cmd 
= CMD_LF_SIMULATE_BIDIR
; 
 698         c
.ext1 
= 47; /* Set ADC to twice the carrier for a slight supersampling */ 
 700         SendCommand(&c
, FALSE
); 
 703 static void CmdLoread(char *str
) 
 706         // 'h' means higher-low-frequency, 134 kHz 
 709         } else if (*str 
== '\0') { 
 712                 PrintToScrollback("use 'loread' or 'loread h'"); 
 715         c
.cmd 
= CMD_ACQUIRE_RAW_ADC_SAMPLES_125K
; 
 716         SendCommand(&c
, FALSE
); 
 719 static void CmdDetectReader(char *str
) 
 722         // 'l' means LF - 125/134 kHz 
 725         } else if (*str 
== 'h') { 
 727         } else if (*str 
!= '\0') { 
 728                 PrintToScrollback("use 'detectreader' or 'detectreader l' or 'detectreader h'"); 
 731         c
.cmd 
= CMD_LISTEN_READER_FIELD
; 
 732          SendCommand(&c
, FALSE
); 
 735 /* send a command before reading */ 
 736 static void CmdLoCommandRead(char *str
) 
 738         static char dummy
[3]; 
 743         c
.cmd 
= CMD_MOD_THEN_ACQUIRE_RAW_ADC_SAMPLES_125K
; 
 744         sscanf(str
, "%i %i %i %s %s", &c
.ext1
, &c
.ext2
, &c
.ext3
, (char *) &c
.d
.asBytes
,(char *) &dummy
+1); 
 745         // in case they specified 'h' 
 746         strcpy((char *)&c
.d
.asBytes 
+ strlen((char *)c
.d
.asBytes
), dummy
); 
 747         SendCommand(&c
, FALSE
); 
 750 static void CmdLosamples(char *str
) 
 758         if (n
>16000) n
=16000; 
 760         for(i 
= 0; i 
< n
; i 
+= 12) { 
 762                 c
.cmd 
= CMD_DOWNLOAD_RAW_ADC_SAMPLES_125K
; 
 764                 SendCommand(&c
, FALSE
); 
 766                 if(c
.cmd 
!= CMD_DOWNLOADED_RAW_ADC_SAMPLES_125K
) { 
 768                                 PrintToScrollback("bad resp"); 
 772                 for(j 
= 0; j 
< 48; j
++) { 
 773                         GraphBuffer
[cnt
++] = ((int)c
.d
.asBytes
[j
]) - 128; 
 777         RepaintGraphWindow(); 
 780 static void CmdBitsamples(char *str
) 
 787         for(i 
= 0; i 
< n
; i 
+= 12) { 
 789                 c
.cmd 
= CMD_DOWNLOAD_RAW_ADC_SAMPLES_125K
; 
 791                 SendCommand(&c
, FALSE
); 
 793                 if(c
.cmd 
!= CMD_DOWNLOADED_RAW_ADC_SAMPLES_125K
) { 
 794                         PrintToScrollback("bad resp"); 
 798                 for(j 
= 0; j 
< 48; j
++) { 
 799                         for(k 
= 0; k 
< 8; k
++) { 
 800                                 if(c
.d
.asBytes
[j
] & (1 << (7 - k
))) { 
 801                                         GraphBuffer
[cnt
++] = 1; 
 803                                         GraphBuffer
[cnt
++] = 0; 
 809         RepaintGraphWindow(); 
 812 static void CmdHisamples(char *str
) 
 818         for(i 
= 0; i 
< n
; i 
+= 12) { 
 820                 c
.cmd 
= CMD_DOWNLOAD_RAW_ADC_SAMPLES_125K
; 
 822                 SendCommand(&c
, FALSE
); 
 824                 if(c
.cmd 
!= CMD_DOWNLOADED_RAW_ADC_SAMPLES_125K
) { 
 825                         PrintToScrollback("bad resp"); 
 829                 for(j 
= 0; j 
< 48; j
++) { 
 830                         GraphBuffer
[cnt
++] = (int)((BYTE
)c
.d
.asBytes
[j
]); 
 835         RepaintGraphWindow(); 
 838 static int CmdHisamplest(char *str
, int nrlow
) 
 850         for(i 
= 0; i 
< n
; i 
+= 12) { 
 852                 c
.cmd 
= CMD_DOWNLOAD_RAW_ADC_SAMPLES_125K
; 
 854                 SendCommand(&c
, FALSE
); 
 856                 if(c
.cmd 
!= CMD_DOWNLOADED_RAW_ADC_SAMPLES_125K
) { 
 857                         PrintToScrollback("bad resp"); 
 861                 for(j 
= 0; j 
< 48; j
++) { 
 862                         t2 
= (int)((BYTE
)c
.d
.asBytes
[j
]); 
 863                         if((t2 
^ 0xC0) & 0xC0) { hasbeennull
++; } 
 869                                         t1 
= (t2 
& 0x80) ^ (t2 
& 0x20); 
 870                                         t2 
= ((t2 
<< 1) & 0x80) ^ ((t2 
<< 1) & 0x20); 
 876                                         t2 
= ((t2 
<< 1) & 0x80); 
 882                                         t2 
= ((t2 
<< 1) & 0x20); 
 886                                         // both, but tag with other algorithm 
 887                                         t1 
= (t2 
& 0x80) ^ (t2 
& 0x08); 
 888                                         t2 
= ((t2 
<< 1) & 0x80) ^ ((t2 
<< 1) & 0x08); 
 892                         GraphBuffer
[cnt
++] = t1
; 
 893                         GraphBuffer
[cnt
++] = t2
; 
 898         if(hasbeennull
>nrlow 
|| nrlow
==0) { 
 899                 PrintToScrollback("hasbeennull=%d", hasbeennull
); 
 908 static void CmdHexsamples(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 
+= 8) { 
 931                         PrintToScrollback("%02x %02x %02x %02x %02x %02x %02x %02x", 
 946 static void CmdHisampless(char *str
) 
 958         for(i 
= 0; i 
< n
; i 
+= 12) { 
 960                 c
.cmd 
= CMD_DOWNLOAD_RAW_ADC_SAMPLES_125K
; 
 962                 SendCommand(&c
, FALSE
); 
 964                 if(c
.cmd 
!= CMD_DOWNLOADED_RAW_ADC_SAMPLES_125K
) { 
 965                         PrintToScrollback("bad resp"); 
 969                 for(j 
= 0; j 
< 48; j
++) { 
 970                         GraphBuffer
[cnt
++] = (int)((signed char)c
.d
.asBytes
[j
]); 
 975         RepaintGraphWindow(); 
 978 static WORD 
Iso15693Crc(BYTE 
*v
, int n
) 
 984         for(i 
= 0; i 
< n
; i
++) { 
 985                 reg 
= reg 
^ ((DWORD
)v
[i
]); 
 986                 for (j 
= 0; j 
< 8; j
++) { 
 988                                 reg 
= (reg 
>> 1) ^ 0x8408; 
 998 static void CmdHi14bdemod(char *str
) 
1003         BOOL negateI
, negateQ
; 
1008         // As received, the samples are pairs, correlations against I and Q 
1009         // square waves. So estimate angle of initial carrier (or just 
1010         // quadrant, actually), and then do the demod. 
1012         // First, estimate where the tag starts modulating. 
1013         for(i 
= 0; i 
< GraphTraceLen
; i 
+= 2) { 
1014                 if(abs(GraphBuffer
[i
]) + abs(GraphBuffer
[i
+1]) > 40) { 
1018         if(i 
>= GraphTraceLen
) { 
1019                 PrintToScrollback("too weak to sync"); 
1022         PrintToScrollback("out of weak at %d", i
); 
1025         // Now, estimate the phase in the initial modulation of the tag 
1028         for(; i 
< (outOfWeakAt 
+ 16); i 
+= 2) { 
1029                 isum 
+= GraphBuffer
[i
+0]; 
1030                 qsum 
+= GraphBuffer
[i
+1]; 
1032         negateI 
= (isum 
< 0); 
1033         negateQ 
= (qsum 
< 0); 
1035         // Turn the correlation pairs into soft decisions on the bit. 
1037         for(i 
= 0; i 
< GraphTraceLen
/2; i
++) { 
1038                 int si 
= GraphBuffer
[j
]; 
1039                 int sq 
= GraphBuffer
[j
+1]; 
1040                 if(negateI
) si 
= -si
; 
1041                 if(negateQ
) sq 
= -sq
; 
1042                 GraphBuffer
[i
] = si 
+ sq
; 
1048         while(GraphBuffer
[i
] > 0 && i 
< GraphTraceLen
) 
1050         if(i 
>= GraphTraceLen
) goto demodError
; 
1053         while(GraphBuffer
[i
] < 0 && i 
< GraphTraceLen
) 
1055         if(i 
>= GraphTraceLen
) goto demodError
; 
1056         if((i 
- iold
) > 23) goto demodError
; 
1058         PrintToScrollback("make it to demod loop"); 
1062                 while(GraphBuffer
[i
] >= 0 && i 
< GraphTraceLen
) 
1064                 if(i 
>= GraphTraceLen
) goto demodError
; 
1065                 if((i 
- iold
) > 6) goto demodError
; 
1068                 if(i 
+ 20 >= GraphTraceLen
) goto demodError
; 
1070                 for(j 
= 0; j 
< 10; j
++) { 
1071                         int soft 
= GraphBuffer
[i
] + GraphBuffer
[i
+1]; 
1073                         if(abs(soft
) < ((abs(isum
) + abs(qsum
))/20)) { 
1074                                 PrintToScrollback("weak bit"); 
1078                         if(GraphBuffer
[i
] + GraphBuffer
[i
+1] >= 0) { 
1085                 if( (shiftReg 
& 0x200) && 
1086                         !(shiftReg 
& 0x001)) 
1088                         // valid data byte, start and stop bits okay 
1089                         PrintToScrollback("   %02x", (shiftReg 
>> 1) & 0xff); 
1090                         data
[dataLen
++] = (shiftReg 
>> 1) & 0xff; 
1091                         if(dataLen 
>= sizeof(data
)) { 
1094                 } else if(shiftReg 
== 0x000) { 
1103         ComputeCrc14443(CRC_14443_B
, data
, dataLen
-2, &first
, &second
); 
1104         PrintToScrollback("CRC: %02x %02x (%s)\n", first
, second
, 
1105                 (first 
== data
[dataLen
-2] && second 
== data
[dataLen
-1]) ? 
1106                         "ok" : "****FAIL****"); 
1108         RepaintGraphWindow(); 
1112         PrintToScrollback("demod error"); 
1113         RepaintGraphWindow(); 
1116 static void CmdHi14list(char *str
) 
1119         GetFromBigBuf(got
, sizeof(got
)); 
1121         PrintToScrollback("recorded activity:"); 
1122         PrintToScrollback(" time        :rssi: who bytes"); 
1123         PrintToScrollback("---------+----+----+-----------"); 
1134                 int timestamp 
= *((DWORD 
*)(got
+i
)); 
1135                 if(timestamp 
& 0x80000000) { 
1136                         timestamp 
&= 0x7fffffff; 
1141                 int metric 
= *((DWORD 
*)(got
+i
+4)); 
1148                 if(i 
+ len 
>= 900) { 
1152                 BYTE 
*frame 
= (got
+i
+9); 
1154                 char line
[1000] = ""; 
1156                 for(j 
= 0; j 
< len
; j
++) { 
1157                         sprintf(line
+(j
*3), "%02x  ", frame
[j
]); 
1163                         ComputeCrc14443(CRC_14443_B
, frame
, len
-2, &b1
, &b2
); 
1164                         if(b1 
!= frame
[len
-2] || b2 
!= frame
[len
-1]) { 
1165                                 crc 
= "**FAIL CRC**"; 
1173                 char metricString
[100]; 
1175                         sprintf(metricString
, "%3d", metric
); 
1177                         strcpy(metricString
, "   "); 
1180                 PrintToScrollback(" +%7d: %s: %s %s %s", 
1181                         (prev 
< 0 ? 0 : timestamp 
- prev
), 
1183                         (isResponse 
? "TAG" : "   "), line
, crc
); 
1190 static void CmdHi14alist(char *str
) 
1193         GetFromBigBuf(got
, sizeof(got
)); 
1195         PrintToScrollback("recorded activity:"); 
1196         PrintToScrollback(" ETU     :rssi: who bytes"); 
1197         PrintToScrollback("---------+----+----+-----------"); 
1208                 int timestamp 
= *((DWORD 
*)(got
+i
)); 
1209                 if(timestamp 
& 0x80000000) { 
1210                         timestamp 
&= 0x7fffffff; 
1217                 int parityBits 
= *((DWORD 
*)(got
+i
+4)); 
1218                 // 4 bytes of additional information... 
1219                 // maximum of 32 additional parity bit information 
1222                 // at each quarter bit period we can send power level (16 levels) 
1223                 // or each half bit period in 256 levels. 
1231                 if(i 
+ len 
>= 1900) { 
1235                 BYTE 
*frame 
= (got
+i
+9); 
1237                 // Break and stick with current result if buffer was not completely full 
1238                 if(frame
[0] == 0x44 && frame
[1] == 0x44 && frame
[3] == 0x44) { break; } 
1240                 char line
[1000] = ""; 
1242                 for(j 
= 0; j 
< len
; j
++) { 
1243                         int oddparity 
= 0x01; 
1247                                 oddparity 
^= (((frame
[j
] & 0xFF) >> k
) & 0x01); 
1250                         //if((parityBits >> (len - j - 1)) & 0x01) { 
1251                         if(isResponse 
&& (oddparity 
!= ((parityBits 
>> (len 
- j 
- 1)) & 0x01))) { 
1252                                 sprintf(line
+(j
*4), "%02x!  ", frame
[j
]); 
1255                                 sprintf(line
+(j
*4), "%02x   ", frame
[j
]); 
1263                         for(j 
= 0; j 
< (len 
- 1); j
++) { 
1264                                 // gives problems... search for the reason.. 
1265                                 /*if(frame[j] == 0xAA) { 
1266                                         switch(frame[j+1]) { 
1268                                                         crc = "[1] Two drops close after each other"; 
1271                                                         crc = "[2] Potential SOC with a drop in second half of bitperiod"; 
1274                                                         crc = "[3] Segment Z after segment X is not possible"; 
1277                                                         crc = "[4] Parity bit of a fully received byte was wrong"; 
1280                                                         crc = "[?] Unknown error"; 
1287                         if(strlen(crc
)==0) { 
1288                                 ComputeCrc14443(CRC_14443_A
, frame
, len
-2, &b1
, &b2
); 
1289                                 if(b1 
!= frame
[len
-2] || b2 
!= frame
[len
-1]) { 
1290                                         crc 
= (isResponse 
& (len 
< 6)) ? "" : " !crc"; 
1299                 char metricString
[100]; 
1301                         sprintf(metricString
, "%3d", metric
); 
1303                         strcpy(metricString
, "   "); 
1306                 PrintToScrollback(" +%7d: %s: %s %s %s", 
1307                         (prev 
< 0 ? 0 : (timestamp 
- prev
)), 
1309                         (isResponse 
? "TAG" : "   "), line
, crc
); 
1314         CommandFinished 
= 1; 
1317 static void CmdHi15demod(char *str
) 
1319         // The sampling rate is 106.353 ksps/s, for T = 18.8 us 
1322         // 1) Unmodulated time of 56.64us 
1323         // 2) 24 pulses of 423.75khz 
1324         // 3) logic '1' (unmodulated for 18.88us followed by 8 pulses of 423.75khz) 
1326         static const int FrameSOF
[] = { 
1327                 -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 
1328                 -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 
1329                  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1, 
1330                  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1, 
1336         static const int Logic0
[] = { 
1342         static const int Logic1
[] = { 
1350         // 1) logic '0' (8 pulses of 423.75khz followed by unmodulated for 18.88us) 
1351         // 2) 24 pulses of 423.75khz 
1352         // 3) Unmodulated time of 56.64us 
1354         static const int FrameEOF
[] = { 
1359                  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1, 
1360                  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1, 
1361                 -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 
1362                 -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 
1366         int max 
= 0, maxPos
; 
1370         if(GraphTraceLen 
< 1000) return; 
1372         // First, correlate for SOF 
1373         for(i 
= 0; i 
< 100; i
++) { 
1375                 for(j 
= 0; j 
< arraylen(FrameSOF
); j 
+= skip
) { 
1376                         corr 
+= FrameSOF
[j
]*GraphBuffer
[i
+(j
/skip
)]; 
1383         PrintToScrollback("SOF at %d, correlation %d", maxPos
, 
1384                 max
/(arraylen(FrameSOF
)/skip
)); 
1386         i 
= maxPos 
+ arraylen(FrameSOF
)/skip
; 
1389         memset(outBuf
, 0, sizeof(outBuf
)); 
1392                 int corr0 
= 0, corr1 
= 0, corrEOF 
= 0; 
1393                 for(j 
= 0; j 
< arraylen(Logic0
); j 
+= skip
) { 
1394                         corr0 
+= Logic0
[j
]*GraphBuffer
[i
+(j
/skip
)]; 
1396                 for(j 
= 0; j 
< arraylen(Logic1
); j 
+= skip
) { 
1397                         corr1 
+= Logic1
[j
]*GraphBuffer
[i
+(j
/skip
)]; 
1399                 for(j 
= 0; j 
< arraylen(FrameEOF
); j 
+= skip
) { 
1400                         corrEOF 
+= FrameEOF
[j
]*GraphBuffer
[i
+(j
/skip
)]; 
1402                 // Even things out by the length of the target waveform. 
1406                 if(corrEOF 
> corr1 
&& corrEOF 
> corr0
) { 
1407                         PrintToScrollback("EOF at %d", i
); 
1409                 } else if(corr1 
> corr0
) { 
1410                         i 
+= arraylen(Logic1
)/skip
; 
1413                         i 
+= arraylen(Logic0
)/skip
; 
1420                 if((i
+(int)arraylen(FrameEOF
)) >= GraphTraceLen
) { 
1421                         PrintToScrollback("ran off end!"); 
1426                 PrintToScrollback("error, uneven octet! (discard extra bits!)"); 
1427                 PrintToScrollback("   mask=%02x", mask
); 
1429         PrintToScrollback("%d octets", k
); 
1431         for(i 
= 0; i 
< k
; i
++) { 
1432                 PrintToScrollback("# %2d: %02x ", i
, outBuf
[i
]); 
1434         PrintToScrollback("CRC=%04x", Iso15693Crc(outBuf
, k
-2)); 
1437 static void CmdFSKdemod(char *cmdline
) 
1439         static const int LowTone
[]  = { 
1440                 1,  1,  1,  1,  1, -1, -1, -1, -1, -1, 
1441                 1,  1,  1,  1,  1, -1, -1, -1, -1, -1, 
1442                 1,  1,  1,  1,  1, -1, -1, -1, -1, -1, 
1443                 1,  1,  1,  1,  1, -1, -1, -1, -1, -1, 
1444                 1,  1,  1,  1,  1, -1, -1, -1, -1, -1 
1446         static const int HighTone
[] = { 
1447                 1,  1,  1,  1,  1,     -1, -1, -1, -1, 
1448                 1,  1,  1,  1,         -1, -1, -1, -1, 
1449                 1,  1,  1,  1,         -1, -1, -1, -1, 
1450                 1,  1,  1,  1,         -1, -1, -1, -1, 
1451                 1,  1,  1,  1,         -1, -1, -1, -1, 
1452                 1,  1,  1,  1,     -1, -1, -1, -1, -1, 
1455         int lowLen 
= sizeof(LowTone
)/sizeof(int); 
1456         int highLen 
= sizeof(HighTone
)/sizeof(int); 
1457         int convLen 
= (highLen
>lowLen
)?highLen
:lowLen
; 
1458         DWORD hi 
= 0, lo 
= 0; 
1461         int minMark
=0, maxMark
=0; 
1463         for(i 
= 0; i 
< GraphTraceLen 
- convLen
; i
++) { 
1464                 int lowSum 
= 0, highSum 
= 0; 
1466                 for(j 
= 0; j 
< lowLen
; j
++) { 
1467                         lowSum 
+= LowTone
[j
]*GraphBuffer
[i
+j
]; 
1469                 for(j 
= 0; j 
< highLen
; j
++) { 
1470                         highSum 
+= HighTone
[j
]*GraphBuffer
[i
+j
]; 
1472                 lowSum 
= abs((100*lowSum
) / lowLen
); 
1473                 highSum 
= abs((100*highSum
) / highLen
); 
1474                 GraphBuffer
[i
] = (highSum 
<< 16) | lowSum
; 
1477         for(i 
= 0; i 
< GraphTraceLen 
- convLen 
- 16; i
++) { 
1479                 int lowTot 
= 0, highTot 
= 0; 
1480                 // 10 and 8 are f_s divided by f_l and f_h, rounded 
1481                 for(j 
= 0; j 
< 10; j
++) { 
1482                         lowTot 
+= (GraphBuffer
[i
+j
] & 0xffff); 
1484                 for(j 
= 0; j 
< 8; j
++) { 
1485                         highTot 
+= (GraphBuffer
[i
+j
] >> 16); 
1487                 GraphBuffer
[i
] = lowTot 
- highTot
; 
1488                 if (GraphBuffer
[i
]>maxMark
) maxMark
=GraphBuffer
[i
]; 
1489                 if (GraphBuffer
[i
]<minMark
) minMark
=GraphBuffer
[i
]; 
1492         GraphTraceLen 
-= (convLen 
+ 16); 
1494         RepaintGraphWindow(); 
1496         // Find bit-sync (3 lo followed by 3 high) 
1497         int max 
= 0, maxPos 
= 0; 
1498         for(i 
= 0; i 
< 6000; i
++) { 
1500                 for(j 
= 0; j 
< 3*lowLen
; j
++) { 
1501                         dec 
-= GraphBuffer
[i
+j
]; 
1503                 for(; j 
< 3*(lowLen 
+ highLen 
); j
++) { 
1504                         dec 
+= GraphBuffer
[i
+j
]; 
1512         // place start of bit sync marker in graph 
1513         GraphBuffer
[maxPos
] = maxMark
; 
1514         GraphBuffer
[maxPos
+1] = minMark
; 
1518         // place end of bit sync marker in graph 
1519         GraphBuffer
[maxPos
] = maxMark
; 
1520         GraphBuffer
[maxPos
+1] = minMark
; 
1522         PrintToScrollback("actual data bits start at sample %d", maxPos
); 
1523         PrintToScrollback("length %d/%d", highLen
, lowLen
); 
1526         bits
[sizeof(bits
)-1] = '\0'; 
1528         // find bit pairs and manchester decode them 
1529         for(i 
= 0; i 
< arraylen(bits
)-1; i
++) { 
1531                 for(j 
= 0; j 
< lowLen
; j
++) { 
1532                         dec 
-= GraphBuffer
[maxPos
+j
]; 
1534                 for(; j 
< lowLen 
+ highLen
; j
++) { 
1535                         dec 
+= GraphBuffer
[maxPos
+j
]; 
1538                 // place inter bit marker in graph 
1539                 GraphBuffer
[maxPos
] = maxMark
; 
1540                 GraphBuffer
[maxPos
+1] = minMark
; 
1542                 // hi and lo form a 64 bit pair 
1543                 hi 
= (hi
<<1)|(lo
>>31); 
1545                 // store decoded bit as binary (in hi/lo) and text (in bits[]) 
1553         PrintToScrollback("bits: '%s'", bits
); 
1554         PrintToScrollback("hex: %08x %08x", hi
, lo
); 
1557 // read a TI tag and return its ID 
1558 static void CmdTIRead(char *str
) 
1561         c
.cmd 
= CMD_READ_TI_TYPE
; 
1562         SendCommand(&c
, FALSE
); 
1565 // write new data to a r/w TI tag 
1566 static void CmdTIWrite(char *str
) 
1571         c
.cmd 
= CMD_WRITE_TI_TYPE
; 
1572         res 
= sscanf(str
, "0x%x 0x%x 0x%x ", &c
.ext1
, &c
.ext2
, &c
.ext3
); 
1573         if (res 
== 2) c
.ext3
=0; 
1575                 PrintToScrollback("Please specify the data as two hex strings, optionally the CRC as a third"); 
1577                 SendCommand(&c
, FALSE
); 
1580 static void CmdTIDemod(char *cmdline
) 
1582         /* MATLAB as follows: 
1583 f_s = 2000000;  % sampling frequency 
1584 f_l = 123200;   % low FSK tone 
1585 f_h = 134200;   % high FSK tone 
1587 T_l = 119e-6;   % low bit duration 
1588 T_h = 130e-6;   % high bit duration 
1590 l = 2*pi*ones(1, floor(f_s*T_l))*(f_l/f_s); 
1591 h = 2*pi*ones(1, floor(f_s*T_h))*(f_h/f_s); 
1593 l = sign(sin(cumsum(l))); 
1594 h = sign(sin(cumsum(h))); 
1597 // 2M*16/134.2k = 238 
1598  static const int LowTone
[] = { 
1599         1, 1, 1, 1, 1, 1, 1, 1, 1, -1, -1, -1, -1, -1, -1, -1, -1, 
1600         1, 1, 1, 1, 1, 1, 1, 1,          -1, -1, -1, -1, -1, -1, -1, -1, 
1601         1, 1, 1, 1, 1, 1, 1, 1,          -1, -1, -1, -1, -1, -1, -1, -1, 
1602         1, 1, 1, 1, 1, 1, 1, 1,          -1, -1, -1, -1, -1, -1, -1, -1, 
1603         1, 1, 1, 1, 1, 1, 1, 1, 1, -1, -1, -1, -1, -1, -1, -1, -1, 
1604         1, 1, 1, 1, 1, 1, 1, 1,          -1, -1, -1, -1, -1, -1, -1, -1, 
1605         1, 1, 1, 1, 1, 1, 1, 1,          -1, -1, -1, -1, -1, -1, -1, -1, 
1606         1, 1, 1, 1, 1, 1, 1, 1,          -1, -1, -1, -1, -1, -1, -1, -1, 
1607         1, 1, 1, 1, 1, 1, 1, 1, 1, -1, -1, -1, -1, -1, -1, -1, -1, 
1608         1, 1, 1, 1, 1, 1, 1, 1,          -1, -1, -1, -1, -1, -1, -1, -1, 
1609         1, 1, 1, 1, 1, 1, 1, 1,          -1, -1, -1, -1, -1, -1, -1, -1, 
1610         1, 1, 1, 1, 1, 1, 1, 1,          -1, -1, -1, -1, -1, -1, -1, -1, 
1611         1, 1, 1, 1, 1, 1, 1, 1, 1, -1, -1, -1, -1, -1, -1, -1, -1, 
1612         1, 1, 1, 1, 1, 1, 1, 1,          -1, -1, -1, -1, -1, -1, -1, -1, 
1613         1, 1, 1, 1, 1, 1, 1, 1,          -1, -1 
1615 // 2M*16/123.2k = 260 
1616  static const int HighTone
[] = { 
1617         1, 1, 1, 1, 1, 1, 1, 1,         -1, -1, -1, -1, -1, -1, -1, 
1618         1, 1, 1, 1, 1, 1, 1, 1,         -1, -1, -1, -1, -1, -1, -1, 
1619         1, 1, 1, 1, 1, 1, 1,                    -1, -1, -1, -1, -1, -1, -1, -1, 
1620         1, 1, 1, 1, 1, 1, 1,                    -1, -1, -1, -1, -1, -1, -1, -1, 
1621         1, 1, 1, 1, 1, 1, 1,                    -1, -1, -1, -1, -1, -1, -1, -1, 
1622         1, 1, 1, 1, 1, 1, 1,                    -1, -1, -1, -1, -1, -1, -1, 
1623         1, 1, 1, 1, 1, 1, 1, 1,         -1, -1, -1, -1, -1, -1, -1, 
1624         1, 1, 1, 1, 1, 1, 1, 1,         -1, -1, -1, -1, -1, -1, -1, 
1625         1, 1, 1, 1, 1, 1, 1,                    -1, -1, -1, -1, -1, -1, -1, -1, 
1626         1, 1, 1, 1, 1, 1, 1,                    -1, -1, -1, -1, -1, -1, -1, -1, 
1627         1, 1, 1, 1, 1, 1, 1,                    -1, -1, -1, -1, -1, -1, -1, 
1628         1, 1, 1, 1, 1, 1, 1, 1,         -1, -1, -1, -1, -1, -1, -1, 
1629         1, 1, 1, 1, 1, 1, 1, 1,         -1, -1, -1, -1, -1, -1, -1, 
1630         1, 1, 1, 1, 1, 1, 1, 1,         -1, -1, -1, -1, -1, -1, -1, 
1631         1, 1, 1, 1, 1, 1, 1,                    -1, -1, -1, -1, -1, -1, -1, -1, 
1632         1, 1, 1, 1, 1, 1, 1,                    -1, -1, -1, -1, -1, -1, -1, -1, 
1633         1, 1, 1, 1, 1, 1, 1,                    -1, -1, -1, -1, -1, -1, -1, 
1634         1, 1, 1, 1, 1, 1, 1, 1 
1636         int lowLen 
= sizeof(LowTone
)/sizeof(int); 
1637         int highLen 
= sizeof(HighTone
)/sizeof(int); 
1638         int convLen 
= (highLen
>lowLen
)?highLen
:lowLen
; 
1641         int lowSum 
= 0, highSum 
= 0;; 
1642         int lowTot 
= 0, highTot 
= 0; 
1644         for(i 
= 0; i 
< GraphTraceLen 
- convLen
; i
++) { 
1648                 for(j 
= 0; j 
< lowLen
; j
++) { 
1649                         lowSum 
+= LowTone
[j
]*GraphBuffer
[i
+j
]; 
1651                 for(j 
= 0; j 
< highLen
; j
++) { 
1652                         highSum 
+= HighTone
[j
]*GraphBuffer
[i
+j
]; 
1654                 lowSum 
= abs((100*lowSum
) / lowLen
); 
1655                 highSum 
= abs((100*highSum
) / highLen
); 
1656                 lowSum 
= (lowSum
<0)?-lowSum
:lowSum
; 
1657                 highSum 
= (highSum
<0)?-highSum
:highSum
; 
1659                 GraphBuffer
[i
] = (highSum 
<< 16) | lowSum
; 
1662         for(i 
= 0; i 
< GraphTraceLen 
- convLen 
- 16; i
++) { 
1665                 // 16 and 15 are f_s divided by f_l and f_h, rounded 
1666                 for(j 
= 0; j 
< 16; j
++) { 
1667                         lowTot 
+= (GraphBuffer
[i
+j
] & 0xffff); 
1669                 for(j 
= 0; j 
< 15; j
++) { 
1670                         highTot 
+= (GraphBuffer
[i
+j
] >> 16); 
1672                 GraphBuffer
[i
] = lowTot 
- highTot
; 
1675         GraphTraceLen 
-= (convLen 
+ 16); 
1677         RepaintGraphWindow(); 
1679         // TI tag data format is 16 prebits, 8 start bits, 64 data bits, 
1680         // 16 crc CCITT bits, 8 stop bits, 15 end bits 
1682         // the 16 prebits are always low 
1683         // the 8 start and stop bits of a tag must match 
1684         // the start/stop prebits of a ro tag are 01111110 
1685         // the start/stop prebits of a rw tag are 11111110 
1686   // the 15 end bits of a ro tag are all low 
1687   // the 15 end bits of a rw tag match bits 15-1 of the data bits 
1689         // Okay, so now we have unsliced soft decisions; 
1690         // find bit-sync, and then get some bits. 
1691         // look for 17 low bits followed by 6 highs (common pattern for ro and rw tags) 
1692         int max 
= 0, maxPos 
= 0; 
1693         for(i 
= 0; i 
< 6000; i
++) { 
1696                 // searching 17 consecutive lows 
1697                 for(j 
= 0; j 
< 17*lowLen
; j
++) { 
1698                         dec 
-= GraphBuffer
[i
+j
]; 
1700                 // searching 7 consecutive highs 
1701                 for(; j 
< 17*lowLen 
+ 6*highLen
; j
++) { 
1702                         dec 
+= GraphBuffer
[i
+j
]; 
1710         // place a marker in the buffer to visually aid location 
1711         // of the start of sync 
1712         GraphBuffer
[maxPos
] = 800; 
1713         GraphBuffer
[maxPos
+1] = -800; 
1715         // advance pointer to start of actual data stream (after 16 pre and 8 start bits) 
1716         maxPos 
+= 17*lowLen
; 
1717         maxPos 
+= 6*highLen
; 
1719         // place a marker in the buffer to visually aid location 
1720         // of the end of sync 
1721         GraphBuffer
[maxPos
] = 800; 
1722         GraphBuffer
[maxPos
+1] = -800; 
1724         PrintToScrollback("actual data bits start at sample %d", maxPos
); 
1726         PrintToScrollback("length %d/%d", highLen
, lowLen
); 
1728         BYTE bits
[1+64+16+8+16]; 
1729         bits
[sizeof(bits
)-1] = '\0'; 
1731         DWORD shift3 
= 0x7e000000, shift2 
= 0, shift1 
= 0, shift0 
= 0; 
1733         for(i 
= 0; i 
< arraylen(bits
)-1; i
++) { 
1737                 for(j 
= 0; j 
< lowLen
; j
++) { 
1738                         low 
-= GraphBuffer
[maxPos
+j
]; 
1740                 for(j 
= 0; j 
< highLen
; j
++) { 
1741                         high 
+= GraphBuffer
[maxPos
+j
]; 
1747                         // bitstream arrives lsb first so shift right 
1754                 // 128 bit right shift register 
1755           shift0 
= (shift0
>>1) | (shift1 
<< 31); 
1756           shift1 
= (shift1
>>1) | (shift2 
<< 31); 
1757           shift2 
= (shift2
>>1) | (shift3 
<< 31); 
1760                 // place a marker in the buffer between bits to visually aid location 
1761                 GraphBuffer
[maxPos
] = 800; 
1762                 GraphBuffer
[maxPos
+1] = -800; 
1764         PrintToScrollback("Info: raw tag bits = %s", bits
); 
1766         TagType 
= (shift3
>>8)&0xff; 
1767         if ( TagType 
!= ((shift0
>>16)&0xff) ) { 
1768                 PrintToScrollback("Error: start and stop bits do not match!"); 
1771         else if (TagType 
== 0x7e) { 
1772                 PrintToScrollback("Info: Readonly TI tag detected."); 
1775         else if (TagType 
== 0xfe) { 
1776                 PrintToScrollback("Info: Rewriteable TI tag detected."); 
1778           // put 64 bit data into shift1 and shift0 
1779           shift0 
= (shift0
>>24) | (shift1 
<< 8); 
1780           shift1 
= (shift1
>>24) | (shift2 
<< 8); 
1782                 // align 16 bit crc into lower half of shift2 
1783           shift2 
= ((shift2
>>24) | (shift3 
<< 8)) & 0x0ffff; 
1785                 // align 16 bit "end bits" or "ident" into lower half of shift3 
1788                 // only 15 bits compare, last bit of ident is not valid 
1789                 if ( (shift3
^shift0
)&0x7fff ) { 
1790                         PrintToScrollback("Error: Ident mismatch!"); 
1792                 // WARNING the order of the bytes in which we calc crc below needs checking 
1793                 // i'm 99% sure the crc algorithm is correct, but it may need to eat the 
1794                 // bytes in reverse or something 
1797                 crc 
= update_crc16(crc
, (shift0
)&0xff); 
1798                 crc 
= update_crc16(crc
, (shift0
>>8)&0xff); 
1799                 crc 
= update_crc16(crc
, (shift0
>>16)&0xff); 
1800                 crc 
= update_crc16(crc
, (shift0
>>24)&0xff); 
1801                 crc 
= update_crc16(crc
, (shift1
)&0xff); 
1802                 crc 
= update_crc16(crc
, (shift1
>>8)&0xff); 
1803                 crc 
= update_crc16(crc
, (shift1
>>16)&0xff); 
1804                 crc 
= update_crc16(crc
, (shift1
>>24)&0xff); 
1805                 PrintToScrollback("Info: Tag data = %08X%08X", shift1
, shift0
); 
1806                 if (crc 
!= (shift2
&0xffff)) { 
1807                         PrintToScrollback("Error: CRC mismatch, calculated %04X, got ^04X", crc
, shift2
&0xffff); 
1809                         PrintToScrollback("Info: CRC %04X is good", crc
); 
1813                 PrintToScrollback("Unknown tag type."); 
1818 static void CmdNorm(char *str
) 
1821         int max 
= INT_MIN
, min 
= INT_MAX
; 
1822         for(i 
= 10; i 
< GraphTraceLen
; i
++) { 
1823                 if(GraphBuffer
[i
] > max
) { 
1824                         max 
= GraphBuffer
[i
]; 
1826                 if(GraphBuffer
[i
] < min
) { 
1827                         min 
= GraphBuffer
[i
]; 
1831                 for(i 
= 0; i 
< GraphTraceLen
; i
++) { 
1832                         GraphBuffer
[i
] = (GraphBuffer
[i
] - ((max 
+ min
)/2))*1000/ 
1836         RepaintGraphWindow(); 
1839 static void CmdAmp(char *str
) 
1841         int i
, rising
, falling
; 
1842         int max 
= INT_MIN
, min 
= INT_MAX
; 
1843         for(i 
= 10; i 
< GraphTraceLen
; i
++) { 
1844                 if(GraphBuffer
[i
] > max
) { 
1845                         max 
= GraphBuffer
[i
]; 
1847                 if(GraphBuffer
[i
] < min
) { 
1848                         min 
= GraphBuffer
[i
]; 
1853                 for(i 
= 0; i 
< GraphTraceLen
; i
++) { 
1854                         if(GraphBuffer
[i
+1] < GraphBuffer
[i
]) { 
1856                                         GraphBuffer
[i
]= max
; 
1861                         if(GraphBuffer
[i
+1] > GraphBuffer
[i
]) { 
1863                                         GraphBuffer
[i
]= min
; 
1870         RepaintGraphWindow(); 
1873 static void CmdDec(char *str
) 
1876         for(i 
= 0; i 
< (GraphTraceLen
/2); i
++) { 
1877                 GraphBuffer
[i
] = GraphBuffer
[i
*2]; 
1880         PrintToScrollback("decimated by 2"); 
1881         RepaintGraphWindow(); 
1884 static void CmdHpf(char *str
) 
1888         for(i 
= 10; i 
< GraphTraceLen
; i
++) { 
1889                 accum 
+= GraphBuffer
[i
]; 
1891         accum 
/= (GraphTraceLen 
- 10); 
1892         for(i 
= 0; i 
< GraphTraceLen
; i
++) { 
1893                 GraphBuffer
[i
] -= accum
; 
1896         RepaintGraphWindow(); 
1899 static void CmdZerocrossings(char *str
) 
1902         // Zero-crossings aren't meaningful unless the signal is zero-mean. 
1908         for(i 
= 0; i 
< GraphTraceLen
; i
++) { 
1909                 if(GraphBuffer
[i
]*sign 
>= 0) { 
1910                         // No change in sign, reproduce the previous sample count. 
1912                         GraphBuffer
[i
] = lastZc
; 
1914                         // Change in sign, reset the sample count. 
1916                         GraphBuffer
[i
] = lastZc
; 
1924         RepaintGraphWindow(); 
1927 static void CmdThreshold(char *str
) 
1930         int threshold 
= atoi(str
); 
1932         for(i 
= 0; i 
< GraphTraceLen
; i
++) { 
1933                 if(GraphBuffer
[i
]>= threshold
) 
1938         RepaintGraphWindow(); 
1941 static void CmdLtrim(char *str
) 
1946         for(i 
= ds
; i 
< GraphTraceLen
; i
++) { 
1947                 GraphBuffer
[i
-ds
] = GraphBuffer
[i
]; 
1949         GraphTraceLen 
-= ds
; 
1951         RepaintGraphWindow(); 
1954 static void CmdAutoCorr(char *str
) 
1956         static int CorrelBuffer
[MAX_GRAPH_TRACE_LEN
]; 
1958         int window 
= atoi(str
); 
1961                 PrintToScrollback("needs a window"); 
1965         if(window 
>= GraphTraceLen
) { 
1966                 PrintToScrollback("window must be smaller than trace (%d samples)", 
1971         PrintToScrollback("performing %d correlations", GraphTraceLen 
- window
); 
1974         for(i 
= 0; i 
< GraphTraceLen 
- window
; i
++) { 
1977                 for(j 
= 0; j 
< window
; j
++) { 
1978                         sum 
+= (GraphBuffer
[j
]*GraphBuffer
[i
+j
]) / 256; 
1980                 CorrelBuffer
[i
] = sum
; 
1982         GraphTraceLen 
= GraphTraceLen 
- window
; 
1983         memcpy(GraphBuffer
, CorrelBuffer
, GraphTraceLen
*sizeof(int)); 
1985         RepaintGraphWindow(); 
1988 static void CmdVchdemod(char *str
) 
1990         // Is this the entire sync pattern, or does this also include some 
1991         // data bits that happen to be the same everywhere? That would be 
1993         static const int SyncPattern
[] = { 
1994                 1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1, 
1995                 1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 
1996                 1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1, 
1997                 1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 
1998                 1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1, 
1999                 1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 
2000                 1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1, 
2001                 1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 
2002                 1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1, 
2003                 1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 
2006         // So first, we correlate for the sync pattern, and mark that. 
2007         int bestCorrel 
= 0, bestPos 
= 0; 
2009         // It does us no good to find the sync pattern, with fewer than 
2010         // 2048 samples after it... 
2011         for(i 
= 0; i 
< (GraphTraceLen
-2048); i
++) { 
2014                 for(j 
= 0; j 
< arraylen(SyncPattern
); j
++) { 
2015                         sum 
+= GraphBuffer
[i
+j
]*SyncPattern
[j
]; 
2017                 if(sum 
> bestCorrel
) { 
2022         PrintToScrollback("best sync at %d [metric %d]", bestPos
, bestCorrel
); 
2027         int worst 
= INT_MAX
; 
2030         for(i 
= 0; i 
< 2048; i 
+= 8) { 
2033                 for(j 
= 0; j 
< 8; j
++) { 
2034                         sum 
+= GraphBuffer
[bestPos
+i
+j
]; 
2041                 if(abs(sum
) < worst
) { 
2046         PrintToScrollback("bits:"); 
2047         PrintToScrollback("%s", bits
); 
2048         PrintToScrollback("worst metric: %d at pos %d", worst
, worstPos
); 
2050         if(strcmp(str
, "clone")==0) { 
2053                 for(s 
= bits
; *s
; s
++) { 
2055                         for(j 
= 0; j 
< 16; j
++) { 
2056                                 GraphBuffer
[GraphTraceLen
++] = (*s 
== '1') ? 1 : 0; 
2059                 RepaintGraphWindow(); 
2063 static void CmdIndalademod(char *str
) 
2065         // Usage: recover 64bit UID by default, specify "224" as arg to recover a 224bit UID 
2070         // worst case with GraphTraceLen=64000 is < 4096 
2071         // under normal conditions it's < 2048 
2074         int worst 
= 0, worstPos 
= 0; 
2075         PrintToScrollback("Expecting a bit less than %d raw bits", GraphTraceLen
/32); 
2076         for(i 
= 0; i 
< GraphTraceLen
-1; i 
+= 2) { 
2078                 if((GraphBuffer
[i
] > GraphBuffer
[i 
+ 1]) && (state 
!= 1)) { 
2080                                 for(j 
= 0; j 
<  count 
- 8; j 
+= 16) { 
2081                                         rawbits
[rawbit
++] = 0; 
2083                                 if ((abs(count 
- j
)) > worst
) { 
2084                                         worst 
= abs(count 
- j
); 
2090                 } else if((GraphBuffer
[i
] < GraphBuffer
[i 
+ 1]) && (state 
!= 0)) { 
2092                                 for(j 
= 0; j 
<  count 
- 8; j 
+= 16) { 
2093                                         rawbits
[rawbit
++] = 1; 
2095                                 if ((abs(count 
- j
)) > worst
) { 
2096                                         worst 
= abs(count 
- j
); 
2104         PrintToScrollback("Recovered %d raw bits", rawbit
); 
2105         PrintToScrollback("worst metric (0=best..7=worst): %d at pos %d", worst
, worstPos
); 
2107         // Finding the start of a UID 
2108         int uidlen
, long_wait
; 
2109         if(strcmp(str
, "224") == 0) { 
2118         for(start 
= 0; start 
<= rawbit 
- uidlen
; start
++) { 
2119                 first 
= rawbits
[start
]; 
2120                 for(i 
= start
; i 
< start 
+ long_wait
; i
++) { 
2121                         if(rawbits
[i
] != first
) { 
2125                 if(i 
== (start 
+ long_wait
)) { 
2129         if(start 
== rawbit 
- uidlen 
+ 1) { 
2130                 PrintToScrollback("nothing to wait for"); 
2134         // Inverting signal if needed 
2136                 for(i 
= start
; i 
< rawbit
; i
++) { 
2137                         rawbits
[i
] = !rawbits
[i
]; 
2144         showbits
[uidlen
]='\0'; 
2148         if(uidlen 
> rawbit
) { 
2149                 PrintToScrollback("Warning: not enough raw bits to get a full UID"); 
2150                 for(bit 
= 0; bit 
< rawbit
; bit
++) { 
2151                         bits
[bit
] = rawbits
[i
++]; 
2152                         // As we cannot know the parity, let's use "." and "/" 
2153                         showbits
[bit
] = '.' + bits
[bit
]; 
2155                 showbits
[bit
+1]='\0'; 
2156                 PrintToScrollback("Partial UID=%s", showbits
); 
2159                 for(bit 
= 0; bit 
< uidlen
; bit
++) { 
2160                         bits
[bit
] = rawbits
[i
++]; 
2161                         showbits
[bit
] = '0' + bits
[bit
]; 
2165         PrintToScrollback("UID=%s", showbits
); 
2167         // Checking UID against next occurences 
2168         for(; i 
+ uidlen 
<= rawbit
;) { 
2170                 for(bit 
= 0; bit 
< uidlen
; bit
++) { 
2171                         if(bits
[bit
] != rawbits
[i
++]) { 
2181         PrintToScrollback("Occurences: %d (expected %d)", times
, (rawbit 
- start
) / uidlen
); 
2183         // Remodulating for tag cloning 
2184         GraphTraceLen 
= 32*uidlen
; 
2187         for(bit 
= 0; bit 
< uidlen
; bit
++) { 
2188                 if(bits
[bit
] == 0) { 
2194                 for(j 
= 0; j 
< 32; j
++) { 
2195                         GraphBuffer
[i
++] = phase
; 
2200         RepaintGraphWindow(); 
2203 static void CmdFlexdemod(char *str
) 
2206         for(i 
= 0; i 
< GraphTraceLen
; i
++) { 
2207                 if(GraphBuffer
[i
] < 0) { 
2208                         GraphBuffer
[i
] = -1; 
2214 #define LONG_WAIT 100 
2216         for(start 
= 0; start 
< GraphTraceLen 
- LONG_WAIT
; start
++) { 
2217                 int first 
= GraphBuffer
[start
]; 
2218                 for(i 
= start
; i 
< start 
+ LONG_WAIT
; i
++) { 
2219                         if(GraphBuffer
[i
] != first
) { 
2223                 if(i 
== (start 
+ LONG_WAIT
)) { 
2227         if(start 
== GraphTraceLen 
- LONG_WAIT
) { 
2228                 PrintToScrollback("nothing to wait for"); 
2232         GraphBuffer
[start
] = 2; 
2233         GraphBuffer
[start
+1] = -2; 
2239         for(bit 
= 0; bit 
< 64; bit
++) { 
2242                 for(j 
= 0; j 
< 16; j
++) { 
2243                         sum 
+= GraphBuffer
[i
++]; 
2250                 PrintToScrollback("bit %d sum %d", bit
, sum
); 
2253         for(bit 
= 0; bit 
< 64; bit
++) { 
2256                 for(j 
= 0; j 
< 16; j
++) { 
2257                         sum 
+= GraphBuffer
[i
++]; 
2259                 if(sum 
> 0 && bits
[bit
] != 1) { 
2260                         PrintToScrollback("oops1 at %d", bit
); 
2262                 if(sum 
< 0 && bits
[bit
] != 0) { 
2263                         PrintToScrollback("oops2 at %d", bit
); 
2267         GraphTraceLen 
= 32*64; 
2270         for(bit 
= 0; bit 
< 64; bit
++) { 
2271                 if(bits
[bit
] == 0) { 
2277                 for(j 
= 0; j 
< 32; j
++) { 
2278                         GraphBuffer
[i
++] = phase
; 
2283         RepaintGraphWindow(); 
2287  * Generic command to demodulate ASK. 
2289  * Argument is convention: positive or negative (High mod means zero 
2290  * or high mod means one) 
2292  * Updates the Graph trace with 0/1 values 
2298 static void Cmdaskdemod(char *str
) { 
2300         int c
, high 
= 0, low 
= 0; 
2302         // TODO: complain if we do not give 2 arguments here ! 
2303         // (AL - this doesn't make sense! we're only using one argument!!!) 
2304         sscanf(str
, "%i", &c
); 
2306         /* Detect high and lows and clock */ 
2308         for (i 
= 0; i 
< GraphTraceLen
; i
++) 
2310                 if (GraphBuffer
[i
] > high
) 
2311                         high 
= GraphBuffer
[i
]; 
2312                 else if (GraphBuffer
[i
] < low
) 
2313                         low 
= GraphBuffer
[i
]; 
2315         if(c 
!= 0 && c 
!= 1) { 
2316                 PrintToScrollback("Invalid argument: %s",str
); 
2320         if (GraphBuffer
[0] > 0) { 
2321                 GraphBuffer
[0] = 1-c
; 
2325         for(i
=1;i
<GraphTraceLen
;i
++) { 
2326                 /* Transitions are detected at each peak 
2327                  * Transitions are either: 
2328                  * - we're low: transition if we hit a high 
2329                  * - we're high: transition if we hit a low 
2330                  * (we need to do it this way because some tags keep high or 
2331                  * low for long periods, others just reach the peak and go 
2334                 if ((GraphBuffer
[i
]==high
) && (GraphBuffer
[i
-1] == c
)) { 
2336                 } else if ((GraphBuffer
[i
]==low
) && (GraphBuffer
[i
-1] == (1-c
))){ 
2340                         GraphBuffer
[i
] = GraphBuffer
[i
-1]; 
2343         RepaintGraphWindow(); 
2346 /* Print our clock rate */ 
2347 static void Cmddetectclockrate(char *str
) 
2349         int clock 
= detectclock(0); 
2350         PrintToScrollback("Auto-detected clock rate: %d", clock
); 
2356 int detectclock(int peak
) 
2362         /* Detect peak if we don't have one */ 
2364                 for (i 
= 0; i 
< GraphTraceLen
; i
++) 
2365                         if (GraphBuffer
[i
] > peak
) 
2366                                 peak 
= GraphBuffer
[i
]; 
2368         for (i 
= 1; i 
< GraphTraceLen
; i
++) 
2370                 /* If this is the beginning of a peak */ 
2371                 if (GraphBuffer
[i
-1] != GraphBuffer
[i
] && GraphBuffer
[i
] == peak
) 
2373                         /* Find lowest difference between peaks */ 
2374                         if (lastpeak 
&& i 
- lastpeak 
< clock
) 
2376                                 clock 
= i 
- lastpeak
; 
2385 /* Get or auto-detect clock rate */ 
2386 int GetClock(char *str
, int peak
) 
2390         sscanf(str
, "%i", &clock
); 
2391         if (!strcmp(str
, "")) 
2394         /* Auto-detect clock */ 
2397                 clock 
= detectclock(peak
); 
2399                 /* Only print this message if we're not looping something */ 
2401                         PrintToScrollback("Auto-detected clock rate: %d", clock
); 
2408  * Convert to a bitstream 
2410 static void Cmdbitstream(char *str
) { 
2417         int hithigh
, hitlow
, first
; 
2419         /* Detect high and lows and clock */ 
2420         for (i 
= 0; i 
< GraphTraceLen
; i
++) 
2422                 if (GraphBuffer
[i
] > high
) 
2423                         high 
= GraphBuffer
[i
]; 
2424                 else if (GraphBuffer
[i
] < low
) 
2425                         low 
= GraphBuffer
[i
]; 
2429         clock 
= GetClock(str
, high
); 
2431         gtl 
= CmdClearGraph(0); 
2434         for (i 
= 0; i 
< (int)(gtl 
/ clock
); i
++) 
2440                 /* Find out if we hit both high and low peaks */ 
2441                 for (j 
= 0; j 
< clock
; j
++) 
2443                         if (GraphBuffer
[(i 
* clock
) + j
] == high
) 
2445                         else if (GraphBuffer
[(i 
* clock
) + j
] == low
) 
2448                         /* it doesn't count if it's the first part of our read 
2449                          because it's really just trailing from the last sequence */ 
2450                         if (first 
&& (hithigh 
|| hitlow
)) 
2451                                 hithigh 
= hitlow 
= 0; 
2455                         if (hithigh 
&& hitlow
) 
2459                 /* If we didn't hit both high and low peaks, we had a bit transition */ 
2460                 if (!hithigh 
|| !hitlow
) 
2463                 CmdAppendGraph(0, clock
, bit
); 
2464 //              for (j = 0; j < (int)(clock/2); j++) 
2465 //                      GraphBuffer[(i * clock) + j] = bit ^ 1; 
2466 //              for (j = (int)(clock/2); j < clock; j++) 
2467 //                      GraphBuffer[(i * clock) + j] = bit; 
2470         RepaintGraphWindow(); 
2473 /* Modulate our data into manchester */ 
2474 static void Cmdmanchestermod(char *str
) 
2478         int bit
, lastbit
, wave
; 
2481         clock 
= GetClock(str
, 0); 
2485         for (i 
= 0; i 
< (int)(GraphTraceLen 
/ clock
); i
++) 
2487                 bit 
= GraphBuffer
[i 
* clock
] ^ 1; 
2489                 for (j 
= 0; j 
< (int)(clock
/2); j
++) 
2490                         GraphBuffer
[(i 
* clock
) + j
] = bit 
^ lastbit 
^ wave
; 
2491                 for (j 
= (int)(clock
/2); j 
< clock
; j
++) 
2492                         GraphBuffer
[(i 
* clock
) + j
] = bit 
^ lastbit 
^ wave 
^ 1; 
2494                 /* Keep track of how we start our wave and if we changed or not this time */ 
2495                 wave 
^= bit 
^ lastbit
; 
2499         RepaintGraphWindow(); 
2503  * Manchester demodulate a bitstream. The bitstream needs to be already in 
2504  * the GraphBuffer as 0 and 1 values 
2506  * Give the clock rate as argument in order to help the sync - the algorithm 
2507  * resyncs at each pulse anyway. 
2509  * Not optimized by any means, this is the 1st time I'm writing this type of 
2510  * routine, feel free to improve... 
2512  * 1st argument: clock rate (as number of samples per clock rate) 
2513  *               Typical values can be 64, 32, 128... 
2515 static void Cmdmanchesterdemod(char *str
) { 
2516         int i
, j
, invert
= 0; 
2522         int hithigh
, hitlow
, first
; 
2528         /* check if we're inverting output */ 
2531                 PrintToScrollback("Inverting output"); 
2535                 while(*str 
== ' '); // in case a 2nd argument was given 
2538         /* Holds the decoded bitstream: each clock period contains 2 bits       */ 
2539         /* later simplified to 1 bit after manchester decoding.                 */ 
2540         /* Add 10 bits to allow for noisy / uncertain traces without aborting   */ 
2541         /* int BitStream[GraphTraceLen*2/clock+10]; */ 
2543         /* But it does not work if compiling on WIndows: therefore we just allocate a */ 
2545         int BitStream
[MAX_GRAPH_TRACE_LEN
]; 
2547         /* Detect high and lows */ 
2548         for (i 
= 0; i 
< GraphTraceLen
; i
++) 
2550                 if (GraphBuffer
[i
] > high
) 
2551                         high 
= GraphBuffer
[i
]; 
2552                 else if (GraphBuffer
[i
] < low
) 
2553                         low 
= GraphBuffer
[i
]; 
2557         clock 
= GetClock(str
, high
); 
2559         int tolerance 
= clock
/4; 
2561         /* Detect first transition */ 
2562         /* Lo-Hi (arbitrary)       */ 
2563         /* skip to the first high */ 
2564         for (i
= 0; i 
< GraphTraceLen
; i
++) 
2565                 if(GraphBuffer
[i
] == high
) 
2567         /* now look for the first low */ 
2568         for (; i 
< GraphTraceLen
; i
++) 
2570                 if (GraphBuffer
[i
] == low
) 
2577         /* If we're not working with 1/0s, demod based off clock */ 
2580                 bit 
= 0; /* We assume the 1st bit is zero, it may not be 
2581                           * the case: this routine (I think) has an init problem. 
2584                 for (; i 
< (int)(GraphTraceLen 
/ clock
); i
++) 
2590                         /* Find out if we hit both high and low peaks */ 
2591                         for (j 
= 0; j 
< clock
; j
++) 
2593                                 if (GraphBuffer
[(i 
* clock
) + j
] == high
) 
2595                                 else if (GraphBuffer
[(i 
* clock
) + j
] == low
) 
2598                                 /* it doesn't count if it's the first part of our read 
2599                                    because it's really just trailing from the last sequence */ 
2600                                 if (first 
&& (hithigh 
|| hitlow
)) 
2601                                         hithigh 
= hitlow 
= 0; 
2605                                 if (hithigh 
&& hitlow
) 
2609                         /* If we didn't hit both high and low peaks, we had a bit transition */ 
2610                         if (!hithigh 
|| !hitlow
) 
2613                         BitStream
[bit2idx
++] = bit 
^ invert
; 
2617         /* standard 1/0 bitstream */ 
2621                 /* Then detect duration between 2 successive transitions */ 
2622                 for (bitidx 
= 1; i 
< GraphTraceLen
; i
++) 
2624                         if (GraphBuffer
[i
-1] != GraphBuffer
[i
]) 
2629                         // Error check: if bitidx becomes too large, we do not 
2630                         // have a Manchester encoded bitstream or the clock is really 
2632                         if (bitidx 
> (GraphTraceLen
*2/clock
+8) ) { 
2633                                 PrintToScrollback("Error: the clock you gave is probably wrong, aborting."); 
2636                         // Then switch depending on lc length: 
2637                         // Tolerance is 1/4 of clock rate (arbitrary) 
2638                         if (abs(lc
-clock
/2) < tolerance
) { 
2639                                 // Short pulse : either "1" or "0" 
2640                                 BitStream
[bitidx
++]=GraphBuffer
[i
-1]; 
2641                         } else if (abs(lc
-clock
) < tolerance
) { 
2642                                 // Long pulse: either "11" or "00" 
2643                                 BitStream
[bitidx
++]=GraphBuffer
[i
-1]; 
2644                                 BitStream
[bitidx
++]=GraphBuffer
[i
-1]; 
2648                                 PrintToScrollback("Warning: Manchester decode error for pulse width detection."); 
2649                                 PrintToScrollback("(too many of those messages mean either the stream is not Manchester encoded, or clock is wrong)"); 
2653                                                 PrintToScrollback("Error: too many detection errors, aborting."); 
2660                 // At this stage, we now have a bitstream of "01" ("1") or "10" ("0"), parse it into final decoded bitstream 
2661                 // Actually, we overwrite BitStream with the new decoded bitstream, we just need to be careful 
2662                 // to stop output at the final bitidx2 value, not bitidx 
2663                 for (i 
= 0; i 
< bitidx
; i 
+= 2) { 
2664                         if ((BitStream
[i
] == 0) && (BitStream
[i
+1] == 1)) { 
2665                                 BitStream
[bit2idx
++] = 1 ^ invert
; 
2666                 } else if ((BitStream
[i
] == 1) && (BitStream
[i
+1] == 0)) { 
2667                         BitStream
[bit2idx
++] = 0 ^ invert
; 
2669                         // We cannot end up in this state, this means we are unsynchronized, 
2673                         PrintToScrollback("Unsynchronized, resync..."); 
2674                         PrintToScrollback("(too many of those messages mean the stream is not Manchester encoded)"); 
2678                                         PrintToScrollback("Error: too many decode errors, aborting."); 
2685         PrintToScrollback("Manchester decoded bitstream"); 
2686         // Now output the bitstream to the scrollback by line of 16 bits 
2687         for (i 
= 0; i 
< (bit2idx
-16); i
+=16) { 
2688                 PrintToScrollback("%i %i %i %i %i %i %i %i %i %i %i %i %i %i %i %i", 
2711 static void CmdHiddemod(char *str
) 
2713         if(GraphTraceLen 
< 4800) { 
2714                 PrintToScrollback("too short; need at least 4800 samples"); 
2718         GraphTraceLen 
= 4800; 
2720         for(i 
= 0; i 
< GraphTraceLen
; i
++) { 
2721                 if(GraphBuffer
[i
] < 0) { 
2727         RepaintGraphWindow(); 
2730 static void CmdPlot(char *str
) 
2735 static void CmdGrid(char *str
) 
2737         sscanf(str
, "%i %i", &PlotGridX
, &PlotGridY
); 
2738         RepaintGraphWindow(); 
2741 static void CmdHide(char *str
) 
2746 static void CmdScale(char *str
) 
2748         CursorScaleFactor 
= atoi(str
); 
2749         if(CursorScaleFactor 
== 0) { 
2750                 PrintToScrollback("bad, can't have zero scale"); 
2751                 CursorScaleFactor 
= 1; 
2753         RepaintGraphWindow(); 
2756 static void CmdSave(char *str
) 
2758         FILE *f 
= fopen(str
, "w"); 
2760                 PrintToScrollback("couldn't open '%s'", str
); 
2764         for(i 
= 0; i 
< GraphTraceLen
; i
++) { 
2765                 fprintf(f
, "%d\n", GraphBuffer
[i
]); 
2768         PrintToScrollback("saved to '%s'", str
); 
2771 static void CmdLoad(char *str
) 
2773         FILE *f 
= fopen(str
, "r"); 
2775                 PrintToScrollback("couldn't open '%s'", str
); 
2781         while(fgets(line
, sizeof(line
), f
)) { 
2782                 GraphBuffer
[GraphTraceLen
] = atoi(line
); 
2786         PrintToScrollback("loaded %d samples", GraphTraceLen
); 
2787         RepaintGraphWindow(); 
2790 static void CmdHIDsimTAG(char *str
) 
2792         unsigned int hi
=0, lo
=0; 
2796         while (sscanf(&str
[i
++], "%1x", &n 
) == 1) { 
2797                 hi
=(hi
<<4)|(lo
>>28); 
2801         PrintToScrollback("Emulating tag with ID %x%16x", hi
, lo
); 
2803         c
.cmd 
= CMD_HID_SIM_TAG
; 
2806         SendCommand(&c
, FALSE
); 
2809 static void CmdReadmem(char *str
) 
2812         c
.cmd 
= CMD_READ_MEM
; 
2814         SendCommand(&c
, FALSE
); 
2817 static void CmdVersion(char *str
) 
2820         c
.cmd 
= CMD_VERSION
; 
2821         SendCommand(&c
, FALSE
); 
2824 static void CmdLcdReset(char *str
) 
2827         c
.cmd 
= CMD_LCD_RESET
; 
2829         SendCommand(&c
, FALSE
); 
2832 static void CmdLcd(char *str
) 
2837         sscanf(str
, "%x %d", &i
, &j
); 
2840                 SendCommand(&c
, FALSE
); 
2845  * Sets the divisor for LF frequency clock: lets the user choose any LF frequency below 
2848 static void CmdSetDivisor(char *str
) 
2851         c
.cmd 
= CMD_SET_LF_DIVISOR
; 
2853         if (( c
.ext1
<0) || (c
.ext1
>255)) { 
2854                         PrintToScrollback("divisor must be between 19 and 255"); 
2856                         SendCommand(&c
, FALSE
); 
2857                         PrintToScrollback("Divisor set, expected freq=%dHz", 12000000/(c
.ext1
+1)); 
2861 static void CmdSetMux(char *str
) 
2864         c
.cmd 
= CMD_SET_ADC_MUX
; 
2865         if(strcmp(str
, "lopkd") == 0) { 
2867         } else if(strcmp(str
, "loraw") == 0) { 
2869         } else if(strcmp(str
, "hipkd") == 0) { 
2871         } else if(strcmp(str
, "hiraw") == 0) { 
2874         SendCommand(&c
, FALSE
); 
2877 typedef void HandlerFunction(char *cmdline
); 
2879 /* in alphabetic order */ 
2882         HandlerFunction 
*handler
; 
2883         int             offline
;  // 1 if the command can be used when in offline mode 
2885 } CommandTable
[] = { 
2886         {"amp",                                 CmdAmp
,                                         1, "Amplify peaks"}, 
2887         {"askdemod",                    Cmdaskdemod
,                            1, "<0|1> -- Attempt to demodulate simple ASK tags"}, 
2888         {"autocorr",                    CmdAutoCorr
,                            1, "<window length> -- Autocorrelation over window"}, 
2889         {"bitsamples",          CmdBitsamples
,                  0, "Get raw samples as bitstring"}, 
2890         {"bitstream",                   Cmdbitstream
,                           1, "[clock rate] -- Convert waveform into a bitstream"}, 
2891         {"buffclear",                   CmdBuffClear
,                           1, "Clear sample buffer and graph window"}, 
2892         {"dec",                                         CmdDec
,                                                 1, "Decimate samples"}, 
2893         {"detectclock",         Cmddetectclockrate
,     1, "Detect clock rate"}, 
2894         {"detectreader",        CmdDetectReader
,                0, "['l'|'h'] -- Detect external reader field (option 'l' or 'h' to limit to LF or HF)"}, 
2895         {"em410xsim",                   CmdEM410xsim
,                           1, "<UID> -- Simulate EM410x tag"}, 
2896         {"em410xread",          CmdEM410xread
,                  1, "[clock rate] -- Extract ID from EM410x tag"}, 
2897         {"em410xwatch",         CmdEM410xwatch
,                 0, "Watches for EM410x tags"}, 
2898         {"em4x50read",          CmdEM4x50read
,                  1, "Extract data from EM4x50 tag"}, 
2899         {"exit",                                        CmdQuit
,                                                1, "Exit program"}, 
2900         {"flexdemod",                   CmdFlexdemod
,                           1, "Demodulate samples for FlexPass"}, 
2901         {"fpgaoff",                             CmdFPGAOff
,                                     0, "Set FPGA off"}, 
2902         {"fskdemod",                    CmdFSKdemod
,                            1, "Demodulate graph window as a HID FSK"}, 
2903         {"grid",                                        CmdGrid
,                                                1, "<x> <y> -- overlay grid on graph window, use zero value to turn off either"}, 
2904         {"hexsamples",          CmdHexsamples
,                  0, "<blocks> -- Dump big buffer as hex bytes"}, 
2905         {"hi14alist",                   CmdHi14alist
,                           0, "List ISO 14443a history"}, 
2906         {"hi14areader",         CmdHi14areader
,                 0, "Act like an ISO14443 Type A reader"}, 
2907         {"hi14asim",                    CmdHi14asim
,                            0, "<UID> -- Fake ISO 14443a tag"}, 
2908         {"hi14asnoop",          CmdHi14asnoop
,                  0, "Eavesdrop ISO 14443 Type A"}, 
2909         {"hi14bdemod",          CmdHi14bdemod
,                  1, "Demodulate ISO14443 Type B from tag"}, 
2910         {"hi14list",                    CmdHi14list
,                            0, "List ISO 14443 history"}, 
2911         {"hi14read",                    CmdHi14read
,                            0, "Read HF tag (ISO 14443)"}, 
2912         {"hi14sim",                             CmdHi14sim
,                                     0, "Fake ISO 14443 tag"}, 
2913         {"hi14snoop",                   CmdHi14snoop
,                           0, "Eavesdrop ISO 14443"}, 
2914         {"hi15demod",                   CmdHi15demod
,                           1, "Demodulate ISO15693 from tag"}, 
2915         {"hi15read",                    CmdHi15read
,                            0, "Read HF tag (ISO 15693)"}, 
2916         {"hi15reader",          CmdHi15reader
,                  0, "Act like an ISO15693 reader"}, 
2917         {"hi15sim",                             CmdHi15tag
,                                     0, "Fake an ISO15693 tag"}, 
2918         {"hiddemod",                    CmdHiddemod
,                            1, "Demodulate HID Prox Card II (not optimal)"}, 
2919         {"hide",                                        CmdHide
,                                                1, "Hide graph window"}, 
2920         {"hidfskdemod",         CmdHIDdemodFSK
,                 0, "Realtime HID FSK demodulator"}, 
2921         {"hidsimtag",                   CmdHIDsimTAG
,                           0, "<ID> -- HID tag simulator"}, 
2922         {"higet",                                       CmdHi14read_sim
,                0, "<samples> -- Get samples HF, 'analog'"}, 
2923         {"hisamples",                   CmdHisamples
,                           0, "Get raw samples for HF tag"}, 
2924         {"hisampless",          CmdHisampless
,                  0, "<samples> -- Get signed raw samples, HF tag"}, 
2925         {"hisamplest",          CmdHi14readt
,                           0, "Get samples HF, for testing"}, 
2926         {"hisimlisten",         CmdHisimlisten
,                 0, "Get HF samples as fake tag"}, 
2927         {"hpf",                                         CmdHpf
,                                                 1, "Remove DC offset from trace"}, 
2928         {"indalademod",         CmdIndalademod
,                 0, "['224'] -- Demodulate samples for Indala 64 bit UID (option '224' for 224 bit)"}, 
2929         {"lcd",                                         CmdLcd
,                                                 0, "<HEX command> <count> -- Send command/data to LCD"}, 
2930         {"lcdreset",                    CmdLcdReset
,                            0, "Hardware reset LCD"}, 
2931         {"legicrfsim",                  CmdLegicRfSim
,                                                  0, "Start the LEGIC RF tag simulator"}, 
2932         {"legicrfread",                 CmdLegicRfRead
,                                                 0, "Start the LEGIC RF reader"}, 
2933         {"load",                                        CmdLoad
,                                                1, "<filename> -- Load trace (to graph window"}, 
2934         {"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)"}, 
2935         {"loread",                              CmdLoread
,                                      0, "['h'] -- Read 125/134 kHz LF ID-only tag (option 'h' for 134)"}, 
2936         {"losamples",                   CmdLosamples
,                           0, "[128 - 16000] -- Get raw samples for LF tag"}, 
2937         {"losim",                                       CmdLosim
,                                               0, "Simulate LF tag"}, 
2938         {"losimbidir",                                  CmdLosimBidir
,                                          0, "Simulate LF tag (with bidirectional data transmission between reader and tag)"}, 
2939         {"ltrim",                                       CmdLtrim
,                                               1, "<samples> -- Trim samples from left of trace"}, 
2940         {"mandemod",                    Cmdmanchesterdemod
,     1, "[i] [clock rate] -- Manchester demodulate binary stream (option 'i' to invert output)"}, 
2941         {"manmod",                              Cmdmanchestermod
,               1, "[clock rate] -- Manchester modulate a binary stream"}, 
2942         {"norm",                                        CmdNorm
,                                                1, "Normalize max/min to +/-500"}, 
2943         {"plot",                                        CmdPlot
,                                                1, "Show graph window"}, 
2944         {"quit",                                        CmdQuit
,                                                1, "Quit program"}, 
2945         {"readmem",                             CmdReadmem
,                                     0, "[address] -- Read memory at decimal address from flash"}, 
2946         {"reset",                                       CmdReset
,                                               0, "Reset the Proxmark3"}, 
2947         {"save",                                        CmdSave
,                                                1, "<filename> -- Save trace (from graph window)"}, 
2948         {"scale",                                       CmdScale
,                                               1, "<int> -- Set cursor display scale"}, 
2949         {"setlfdivisor",        CmdSetDivisor
,                  0, "<19 - 255> -- Drive LF antenna at 12Mhz/(divisor+1)"}, 
2950         {"setmux",              CmdSetMux
,                      0, "<loraw|hiraw|lopkd|hipkd> -- Set the ADC mux to a specific value"}, 
2951         {"sri512read",          CmdSri512read
,                  0, "<int> -- Read contents of a SRI512 tag"}, 
2952         {"srix4kread",          CmdSrix4kread
,                  0, "<int> -- Read contents of a SRIX4K tag"}, 
2953         {"tidemod",                             CmdTIDemod
,                                     1, "Demodulate raw bits for TI-type LF tag"}, 
2954         {"tiread",                              CmdTIRead
,                                      0, "Read and decode a TI 134 kHz tag"}, 
2955         {"tiwrite",                             CmdTIWrite
,                                     0, "Write new data to a r/w TI 134 kHz tag"}, 
2956         {"threshold",                   CmdThreshold
,                           1, "Maximize/minimize every value in the graph window depending on threshold"}, 
2957         {"tune",                                        CmdTune
,                                                0, "Measure antenna tuning"}, 
2958         {"vchdemod",                    CmdVchdemod
,                            0, "['clone'] -- Demodulate samples for VeriChip"}, 
2959         {"version",                     CmdVersion
,                             0, "Show version inforation about the connected Proxmark"}, 
2960         {"zerocrossings",       CmdZerocrossings
,               1, "Count time between zero-crossings"}, 
2968         }       CommandExtendedHelp
[]= { 
2969                 {"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."}, 
2970                 {"tune","","","Drive LF antenna at all divisor range values (19 - 255) and store the results in the output\nbuffer. Issuing 'losamples' and then 'plot' commands will display the resulting peak. 12MHz\ndivided by the peak's position plus one gives the antenna's resonant frequency. For convenience,\nthis value is also printed out by the command."}, 
2973 //----------------------------------------------------------------------------- 
2974 // Entry point into our code: called whenever the user types a command and 
2975 // then presses Enter, which the full command line that they typed. 
2976 //----------------------------------------------------------------------------- 
2977 void CommandReceived(char *cmd
) 
2982         PrintToScrollback("> %s", cmd
); 
2984         if(strcmp(cmd
, "help") == 0 || strncmp(cmd
,"help ",strlen("help ")) == 0) { 
2985                 // check if we're doing extended help 
2986                 if(strlen(cmd
) > strlen("help ")) { 
2987                         cmd 
+= strlen("help "); 
2988                         for(i 
= 0; i 
< sizeof(CommandExtendedHelp
) / sizeof(CommandExtendedHelp
[0]); i
++) { 
2989                                 if(strcmp(CommandExtendedHelp
[i
].name
,cmd
) == 0) { 
2990                                         PrintToScrollback("\nExtended help for '%s':\n", cmd
); 
2991                                         PrintToScrollback("Args: %s\t- %s\n",CommandExtendedHelp
[i
].args
,CommandExtendedHelp
[i
].argshelp
); 
2992                                         PrintToScrollback(CommandExtendedHelp
[i
].description
); 
2993                                         PrintToScrollback(""); 
2997                 PrintToScrollback("No extended help available for '%s'", cmd
); 
3000                 if (offline
) PrintToScrollback("Operating in OFFLINE mode (no device connected)"); 
3001                 PrintToScrollback("\r\nAvailable commands:"); 
3002                 for(i 
= 0; i 
< sizeof(CommandTable
) / sizeof(CommandTable
[0]); i
++) { 
3003                         if (offline 
&& (CommandTable
[i
].offline
==0)) continue; 
3004                         memset(line
, ' ', sizeof(line
)); 
3005                         strcpy(line
+2, CommandTable
[i
].name
); 
3006                         line
[strlen(line
)] = ' '; 
3007                         sprintf(line
+15, " -- %s", CommandTable
[i
].docString
); 
3008                         PrintToScrollback("%s", line
); 
3010                 PrintToScrollback(""); 
3011                 PrintToScrollback("'help <command>' for extended help on that command\n"); 
3015         for(i 
= 0; i 
< sizeof(CommandTable
) / sizeof(CommandTable
[0]); i
++) { 
3016                 char *name 
= CommandTable
[i
].name
; 
3017                 if(memcmp(cmd
, name
, strlen(name
))==0 && 
3018                         (cmd
[strlen(name
)] == ' ' || cmd
[strlen(name
)] == '\0')) 
3020                         cmd 
+= strlen(name
); 
3021                         while(*cmd 
== ' ') { 
3024                         if (offline 
&& (CommandTable
[i
].offline
==0)) { 
3025                                 PrintToScrollback("Offline mode, cannot use this command."); 
3028                         (CommandTable
[i
].handler
)(cmd
); 
3032         PrintToScrollback(">> bad command '%s'", cmd
); 
3035 //----------------------------------------------------------------------------- 
3036 // Entry point into our code: called whenever we received a packet over USB 
3037 // that we weren't necessarily expecting, for example a debug print. 
3038 //----------------------------------------------------------------------------- 
3039 void UsbCommandReceived(UsbCommand 
*c
) 
3042                 case CMD_DEBUG_PRINT_STRING
: { 
3044                         if(c
->ext1 
> 70 || c
->ext1 
< 0) { 
3047                         memcpy(s
, c
->d
.asBytes
, c
->ext1
); 
3049                         PrintToScrollback("#db# %s", s
); 
3053                 case CMD_DEBUG_PRINT_INTEGERS
: 
3054                         PrintToScrollback("#db# %08x, %08x, %08x\r\n", c
->ext1
, c
->ext2
, c
->ext3
); 
3057                 case CMD_MEASURED_ANTENNA_TUNING
: { 
3059                         int vLf125
, vLf134
, vHf
; 
3060                         vLf125 
= c
->ext1 
& 0xffff; 
3061                         vLf134 
= c
->ext1 
>> 16; 
3062                         vHf 
= c
->ext2 
& 0xffff;; 
3063                         peakf 
= c
->ext3 
& 0xffff; 
3064                         peakv 
= c
->ext3 
>> 16; 
3065                         PrintToScrollback(""); 
3066                         PrintToScrollback(""); 
3067                         PrintToScrollback("# LF antenna: %5.2f V @   125.00 kHz", vLf125
/1000.0); 
3068                         PrintToScrollback("# LF antenna: %5.2f V @   134.00 kHz", vLf134
/1000.0); 
3069                         PrintToScrollback("# LF optimal: %5.2f V @%9.2f kHz", peakv
/1000.0, 12000.0/(peakf
+1)); 
3070                         PrintToScrollback("# HF antenna: %5.2f V @    13.56 MHz", vHf
/1000.0); 
3072                                 PrintToScrollback("# Your LF antenna is unusable."); 
3073                         else if (peakv
<10000) 
3074                                 PrintToScrollback("# Your LF antenna is marginal."); 
3076                                 PrintToScrollback("# Your HF antenna is unusable."); 
3078                                 PrintToScrollback("# Your HF antenna is marginal."); 
3082                         PrintToScrollback("unrecognized command %08x\n", c
->cmd
);