1 //----------------------------------------------------------------------------- 
   2 // The actual command interpeter for what the user types at the command line. 
   3 // Jonathan Westhues, Sept 2005 
   4 // Edits by Gerhard de Koning Gans, Sep 2007 (##) 
   5 //----------------------------------------------------------------------------- 
  17 #include "../common/iso14443_crc.c" 
  18 #include "../common/crc16.c" 
  19 #include "../include/usb_cmd.h" 
  21 #define arraylen(x) (sizeof(x)/sizeof((x)[0])) 
  22 #define BIT(x) GraphBuffer[x * clock] 
  23 #define BITS (GraphTraceLen / clock) 
  24 #define SAMPLE_BUFFER_SIZE 64 // XXX check this 
  27 static int CmdHisamplest(char *str
, int nrlow
); 
  28 unsigned int current_command 
= CMD_UNKNOWN
; 
  29 unsigned int received_command 
= CMD_UNKNOWN
; 
  30 static uint8_t sample_buf
[SAMPLE_BUFFER_SIZE
]; 
  32 void wait_for_response(uint32_t response_type
) 
  34         while (received_command 
!= response_type
) { 
  37                 if (ReceiveCommandPoll(&c
)) 
  38                         UsbCommandReceived(&c
); 
  41                 usleep(10000); // XXX ugh 
  44         received_command 
= CMD_UNKNOWN
; 
  47 static void GetFromBigBuf(uint8_t *dest
, int bytes
) 
  52                 PrintToScrollback("bad len in GetFromBigBuf"); 
  57         for(i 
= 0; i 
< n
; i 
+= 12) { 
  58                 UsbCommand c 
= {CMD_DOWNLOAD_RAW_ADC_SAMPLES_125K
, {i
, 0, 0}}; 
  60                 wait_for_response(CMD_DOWNLOADED_RAW_ADC_SAMPLES_125K
); 
  62                 memcpy(dest
+(i
*4), sample_buf
, 48); 
  66 static void CmdReset(char *str
) 
  68         UsbCommand c 
= {CMD_HARDWARE_RESET
}; 
  72 static void CmdBuffClear(char *str
) 
  74         UsbCommand c 
= {CMD_BUFF_CLEAR
}; 
  79 static void CmdQuit(char *str
) 
  84 static void CmdHIDdemodFSK(char *str
) 
  86         UsbCommand c
={CMD_HID_DEMOD_FSK
}; 
  90 static void CmdTune(char *str
) 
  92         UsbCommand c
={CMD_MEASURE_ANTENNA_TUNING
}; 
  96 static void CmdHi15read(char *str
) 
  98         UsbCommand c
={CMD_ACQUIRE_RAW_ADC_SAMPLES_ISO_15693
}; 
 102 static void CmdHi14read(char *str
) 
 104         UsbCommand c 
= {CMD_ACQUIRE_RAW_ADC_SAMPLES_ISO_14443
, {strtol(str
, NULL
, 0), 0, 0}}; 
 109 /* New command to read the contents of a SRI512 tag 
 110  * SRI512 tags are ISO14443-B modulated memory tags, 
 111  * this command just dumps the contents of the memory 
 113 static void CmdSri512read(char *str
) 
 115         UsbCommand c
={CMD_READ_SRI512_TAG
, {strtol(str
, NULL
, 0), 0, 0}}; 
 119 /* New command to read the contents of a SRIX4K tag 
 120  * SRIX4K tags are ISO14443-B modulated memory tags, 
 121  * this command just dumps the contents of the memory/ 
 123 static void CmdSrix4kread(char *str
) 
 125         UsbCommand c
={CMD_READ_SRIX4K_TAG
, {strtol(str
, NULL
, 0), 0, 0}}; 
 129 static void CmdHi14areader(char *str
) 
 131         UsbCommand c
={CMD_READER_ISO_14443a
, {strtol(str
, NULL
, 0), 0, 0}}; 
 135 static void CmdHi15reader(char *str
) 
 137         UsbCommand c
={CMD_READER_ISO_15693
, {strtol(str
, NULL
, 0), 0, 0}}; 
 141 static void CmdHi15tag(char *str
) 
 143         UsbCommand c
={CMD_SIMTAG_ISO_15693
, {strtol(str
, NULL
, 0), 0, 0}}; 
 147 static void CmdHi14read_sim(char *str
) 
 149         UsbCommand c
={CMD_ACQUIRE_RAW_ADC_SAMPLES_ISO_14443_SIM
, {strtol(str
, NULL
, 0), 0, 0}}; 
 153 static void CmdHi14readt(char *str
) 
 155         UsbCommand c
={CMD_ACQUIRE_RAW_ADC_SAMPLES_ISO_14443
, {strtol(str
, NULL
, 0), 0, 0}}; 
 158         //CmdHisamplest(str); 
 159         while(CmdHisamplest(str
,strtol(str
, NULL
, 0))==0) { 
 162         RepaintGraphWindow(); 
 165 static void CmdHisimlisten(char *str
) 
 167         UsbCommand c
={CMD_SIMULATE_TAG_HF_LISTEN
}; 
 171 static void CmdHi14sim(char *str
) 
 173         UsbCommand c
={CMD_SIMULATE_TAG_ISO_14443
}; 
 177 static void CmdHi14asim(char *str
)      // ## simulate iso14443a tag 
 178 {                                       // ## greg - added ability to specify tag UID 
 180         unsigned int hi
=0, lo
=0; 
 182         while (sscanf(&str
[i
++], "%1x", &n 
) == 1) { 
 187         // c.arg should be set to *str or convert *str to the correct format for a uid 
 188         UsbCommand c 
= {CMD_SIMULATE_TAG_ISO_14443a
, {hi
, lo
, 0}}; 
 189         PrintToScrollback("Emulating 14443A TAG with UID %x%16x", hi
, lo
); 
 193 static void CmdHi14snoop(char *str
) 
 195         UsbCommand c
={CMD_SNOOP_ISO_14443
}; 
 199 static void CmdHi14asnoop(char *str
) 
 201         UsbCommand c
={CMD_SNOOP_ISO_14443a
}; 
 205 static void CmdLegicRfRead(char *str
) 
 207         UsbCommand c
={CMD_READER_LEGIC_RF
}; 
 211 static void CmdFPGAOff(char *str
)               // ## FPGA Control 
 213         UsbCommand c
={CMD_FPGA_MAJOR_MODE_OFF
}; 
 217 /* clear out our graph window */ 
 218 int CmdClearGraph(int redraw
) 
 220         int gtl 
= GraphTraceLen
; 
 224                 RepaintGraphWindow(); 
 229 /* write a bit to the graph */ 
 230 static void CmdAppendGraph(int redraw
, int clock
, int bit
) 
 234         for (i 
= 0; i 
< (int)(clock
/2); i
++) 
 235                 GraphBuffer
[GraphTraceLen
++] = bit 
^ 1; 
 237         for (i 
= (int)(clock
/2); i 
< clock
; i
++) 
 238                 GraphBuffer
[GraphTraceLen
++] = bit
; 
 241                 RepaintGraphWindow(); 
 244 /* Function is equivalent of loread + losamples + em410xread 
 245  * looped until an EM410x tag is detected */ 
 246 static void CmdEM410xwatch(char *str
) 
 260 /* Read the transmitted data of an EM4x50 tag 
 263  *  XXXXXXXX [row parity bit (even)] <- 8 bits plus parity 
 264  *  XXXXXXXX [row parity bit (even)] <- 8 bits plus parity 
 265  *  XXXXXXXX [row parity bit (even)] <- 8 bits plus parity 
 266  *  XXXXXXXX [row parity bit (even)] <- 8 bits plus parity 
 267  *  CCCCCCCC                         <- column parity bits 
 269  *  LW                               <- Listen Window 
 271  * This pattern repeats for every block of data being transmitted. 
 272  * Transmission starts with two Listen Windows (LW - a modulated 
 273  * pattern of 320 cycles each (32/32/128/64/64)). 
 275  * Note that this data may or may not be the UID. It is whatever data 
 276  * is stored in the blocks defined in the control word First and Last 
 277  * Word Read values. UID is stored in block 32. 
 279 static void CmdEM4x50read(char *str
) 
 281         int i
, j
, startblock
, clock
, skip
, block
, start
, end
, low
, high
; 
 282         bool complete
= false; 
 283         int tmpbuff
[MAX_GRAPH_TRACE_LEN 
/ 64]; 
 289         /* first get high and low values */ 
 290         for (i 
= 0; i 
< GraphTraceLen
; i
++) 
 292                 if (GraphBuffer
[i
] > high
) 
 293                         high 
= GraphBuffer
[i
]; 
 294                 else if (GraphBuffer
[i
] < low
) 
 295                         low 
= GraphBuffer
[i
]; 
 298         /* populate a buffer with pulse lengths */ 
 301         while(i 
< GraphTraceLen
) 
 303                 // measure from low to low 
 304                 while((GraphBuffer
[i
] > low
) && (i
<GraphTraceLen
)) 
 307                 while((GraphBuffer
[i
] < high
) && (i
<GraphTraceLen
)) 
 309                 while((GraphBuffer
[i
] > low
) && (i
<GraphTraceLen
)) 
 311                 if (j
>(MAX_GRAPH_TRACE_LEN
/64)) { 
 314                 tmpbuff
[j
++]= i 
- start
; 
 317         /* look for data start - should be 2 pairs of LW (pulses of 192,128) */ 
 320         for (i
= 0; i 
< j 
- 4 ; ++i
) 
 323                 if (tmpbuff
[i
] >= 190 && tmpbuff
[i
] <= 194) 
 324                         if (tmpbuff
[i
+1] >= 126 && tmpbuff
[i
+1] <= 130) 
 325                                 if (tmpbuff
[i
+2] >= 190 && tmpbuff
[i
+2] <= 194) 
 326                                         if (tmpbuff
[i
+3] >= 126 && tmpbuff
[i
+3] <= 130) 
 334         /* skip over the remainder of the LW */ 
 335         skip 
+= tmpbuff
[i
+1]+tmpbuff
[i
+2]; 
 336         while(skip 
< MAX_GRAPH_TRACE_LEN 
&& GraphBuffer
[skip
] > low
) 
 340         /* now do it again to find the end */ 
 342         for (i 
+= 3; i 
< j 
- 4 ; ++i
) 
 345                 if (tmpbuff
[i
] >= 190 && tmpbuff
[i
] <= 194) 
 346                         if (tmpbuff
[i
+1] >= 126 && tmpbuff
[i
+1] <= 130) 
 347                                 if (tmpbuff
[i
+2] >= 190 && tmpbuff
[i
+2] <= 194) 
 348                                         if (tmpbuff
[i
+3] >= 126 && tmpbuff
[i
+3] <= 130) 
 356                 PrintToScrollback("Found data at sample: %i",skip
); 
 359                 PrintToScrollback("No data found!"); 
 360                 PrintToScrollback("Try again with more samples."); 
 366                 PrintToScrollback("*** Warning!"); 
 367                 PrintToScrollback("Partial data - no end found!"); 
 368                 PrintToScrollback("Try again with more samples."); 
 371         /* get rid of leading crap */ 
 372         sprintf(tmp
,"%i",skip
); 
 375         /* now work through remaining buffer printing out data blocks */ 
 380                 PrintToScrollback("Block %i:", block
); 
 381                 // mandemod routine needs to be split so we can call it for data 
 382                 // just print for now for debugging 
 383                 Cmdmanchesterdemod("i 64"); 
 385                 /* look for LW before start of next block */ 
 386                 for ( ; i 
< j 
- 4 ; ++i
) 
 389                         if (tmpbuff
[i
] >= 190 && tmpbuff
[i
] <= 194) 
 390                                 if (tmpbuff
[i
+1] >= 126 && tmpbuff
[i
+1] <= 130) 
 393                 while(GraphBuffer
[skip
] > low
) 
 396                 sprintf(tmp
,"%i",skip
); 
 404 /* Read the ID of an EM410x tag. 
 406  *   1111 1111 1           <-- standard non-repeatable header 
 407  *   XXXX [row parity bit] <-- 10 rows of 5 bits for our 40 bit tag ID 
 409  *   CCCC                  <-- each bit here is parity for the 10 bits above in corresponding column 
 410  *   0                     <-- stop bit, end of tag 
 412 static void CmdEM410xread(char *str
) 
 414         int i
, j
, clock
, header
, rows
, bit
, hithigh
, hitlow
, first
, bit2idx
, high
, low
; 
 418         int BitStream
[MAX_GRAPH_TRACE_LEN
]; 
 421         /* Detect high and lows and clock */ 
 422         for (i 
= 0; i 
< GraphTraceLen
; i
++) 
 424                 if (GraphBuffer
[i
] > high
) 
 425                         high 
= GraphBuffer
[i
]; 
 426                 else if (GraphBuffer
[i
] < low
) 
 427                         low 
= GraphBuffer
[i
]; 
 431         clock 
= GetClock(str
, high
); 
 433         /* parity for our 4 columns */ 
 434         parity
[0] = parity
[1] = parity
[2] = parity
[3] = 0; 
 437         /* manchester demodulate */ 
 439         for (i 
= 0; i 
< (int)(GraphTraceLen 
/ clock
); i
++) 
 445                 /* Find out if we hit both high and low peaks */ 
 446                 for (j 
= 0; j 
< clock
; j
++) 
 448                         if (GraphBuffer
[(i 
* clock
) + j
] == high
) 
 450                         else if (GraphBuffer
[(i 
* clock
) + j
] == low
) 
 453                         /* it doesn't count if it's the first part of our read 
 454                          because it's really just trailing from the last sequence */ 
 455                         if (first 
&& (hithigh 
|| hitlow
)) 
 456                                 hithigh 
= hitlow 
= 0; 
 460                         if (hithigh 
&& hitlow
) 
 464                 /* If we didn't hit both high and low peaks, we had a bit transition */ 
 465                 if (!hithigh 
|| !hitlow
) 
 468                 BitStream
[bit2idx
++] = bit
; 
 472         /* We go till 5 before the graph ends because we'll get that far below */ 
 473         for (i 
= 1; i 
< bit2idx 
- 5; i
++) 
 475                 /* Step 2: We have our header but need our tag ID */ 
 476                 if (header 
== 9 && rows 
< 10) 
 478                         /* Confirm parity is correct */ 
 479                         if ((BitStream
[i
] ^ BitStream
[i
+1] ^ BitStream
[i
+2] ^ BitStream
[i
+3]) == BitStream
[i
+4]) 
 481                                 /* Read another byte! */ 
 482                                 sprintf(id
+rows
, "%x", (8 * BitStream
[i
]) + (4 * BitStream
[i
+1]) + (2 * BitStream
[i
+2]) + (1 * BitStream
[i
+3])); 
 485                                 /* Keep parity info */ 
 486                                 parity
[0] ^= BitStream
[i
]; 
 487                                 parity
[1] ^= BitStream
[i
+1]; 
 488                                 parity
[2] ^= BitStream
[i
+2]; 
 489                                 parity
[3] ^= BitStream
[i
+3]; 
 491                                 /* Move 4 bits ahead */ 
 495                         /* Damn, something wrong! reset */ 
 498                                 PrintToScrollback("Thought we had a valid tag but failed at word %d (i=%d)", rows 
+ 1, i
); 
 500                                 /* Start back rows * 5 + 9 header bits, -1 to not start at same place */ 
 501                                 i 
-= 9 + (5 * rows
) - 5; 
 507                 /* Step 3: Got our 40 bits! confirm column parity */ 
 510                         /* We need to make sure our 4 bits of parity are correct and we have a stop bit */ 
 511                         if (BitStream
[i
] == parity
[0] && BitStream
[i
+1] == parity
[1] && 
 512                                 BitStream
[i
+2] == parity
[2] && BitStream
[i
+3] == parity
[3] && 
 516                                 PrintToScrollback("EM410x Tag ID: %s", id
); 
 523                         /* Crap! Incorrect parity or no stop bit, start all over */ 
 528                                 /* Go back 59 bits (9 header bits + 10 rows at 4+1 parity) */ 
 533                 /* Step 1: get our header */ 
 536                         /* Need 9 consecutive 1's */ 
 537                         if (BitStream
[i
] == 1) 
 540                         /* We don't have a header, not enough consecutive 1 bits */ 
 546         /* if we've already retested after flipping bits, return */ 
 550         /* if this didn't work, try flipping bits */ 
 551         for (i 
= 0; i 
< bit2idx
; i
++) 
 557 /* emulate an EM410X tag 
 559  *   1111 1111 1           <-- standard non-repeatable header 
 560  *   XXXX [row parity bit] <-- 10 rows of 5 bits for our 40 bit tag ID 
 562  *   CCCC                  <-- each bit here is parity for the 10 bits above in corresponding column 
 563  *   0                     <-- stop bit, end of tag 
 565 static void CmdEM410xsim(char *str
) 
 567         int i
, n
, j
, h
, binary
[4], parity
[4]; 
 570         /* clock is 64 in EM410x tags */ 
 573         /* clear our graph */ 
 576         /* write it out a few times */ 
 577         for (h 
= 0; h 
< 4; h
++) 
 579                 /* write 9 start bits */ 
 580                 for (i 
= 0; i 
< 9; i
++) 
 581                         CmdAppendGraph(0, clock
, 1); 
 583                 /* for each hex char */ 
 584                 parity
[0] = parity
[1] = parity
[2] = parity
[3] = 0; 
 585                 for (i 
= 0; i 
< 10; i
++) 
 587                         /* read each hex char */ 
 588                         sscanf(&str
[i
], "%1x", &n
); 
 589                         for (j 
= 3; j 
>= 0; j
--, n
/= 2) 
 592                         /* append each bit */ 
 593                         CmdAppendGraph(0, clock
, binary
[0]); 
 594                         CmdAppendGraph(0, clock
, binary
[1]); 
 595                         CmdAppendGraph(0, clock
, binary
[2]); 
 596                         CmdAppendGraph(0, clock
, binary
[3]); 
 598                         /* append parity bit */ 
 599                         CmdAppendGraph(0, clock
, binary
[0] ^ binary
[1] ^ binary
[2] ^ binary
[3]); 
 601                         /* keep track of column parity */ 
 602                         parity
[0] ^= binary
[0]; 
 603                         parity
[1] ^= binary
[1]; 
 604                         parity
[2] ^= binary
[2]; 
 605                         parity
[3] ^= binary
[3]; 
 609                 CmdAppendGraph(0, clock
, parity
[0]); 
 610                 CmdAppendGraph(0, clock
, parity
[1]); 
 611                 CmdAppendGraph(0, clock
, parity
[2]); 
 612                 CmdAppendGraph(0, clock
, parity
[3]); 
 615                 CmdAppendGraph(0, clock
, 0); 
 618         /* modulate that biatch */ 
 622         RepaintGraphWindow(); 
 627 static void ChkBitstream(char *str
) 
 631         /* convert to bitstream if necessary */ 
 632         for (i 
= 0; i 
< (int)(GraphTraceLen 
/ 2); i
++) 
 634                 if (GraphBuffer
[i
] > 1 || GraphBuffer
[i
] < 0) 
 642 static void CmdLosim(char *str
) 
 646         /* convert to bitstream if necessary */ 
 649         for (i 
= 0; i 
< GraphTraceLen
; i 
+= 48) { 
 650                 UsbCommand c
={CMD_DOWNLOADED_SIM_SAMPLES_125K
, {i
, 0, 0}}; 
 652                 for(j 
= 0; j 
< 48; j
++) { 
 653                         c
.d
.asBytes
[j
] = GraphBuffer
[i
+j
]; 
 658         UsbCommand c
={CMD_SIMULATE_TAG_125K
, {GraphTraceLen
, 0, 0}}; 
 662 static void CmdLosimBidir(char *str
) 
 664         /* Set ADC to twice the carrier for a slight supersampling */ 
 665         UsbCommand c
={CMD_LF_SIMULATE_BIDIR
, {47, 384, 0}}; 
 669 static void CmdLoread(char *str
) 
 671         UsbCommand c
={CMD_ACQUIRE_RAW_ADC_SAMPLES_125K
}; 
 672         // 'h' means higher-low-frequency, 134 kHz 
 675         } else if (*str 
== '\0') { 
 678                 PrintToScrollback("use 'loread' or 'loread h'"); 
 684 static void CmdDetectReader(char *str
) 
 686         UsbCommand c
={CMD_LISTEN_READER_FIELD
}; 
 687         // 'l' means LF - 125/134 kHz 
 690         } else if (*str 
== 'h') { 
 692         } else if (*str 
!= '\0') { 
 693                 PrintToScrollback("use 'detectreader' or 'detectreader l' or 'detectreader h'"); 
 699 /* send a command before reading */ 
 700 static void CmdLoCommandRead(char *str
) 
 702         static char dummy
[3]; 
 706         UsbCommand c
={CMD_MOD_THEN_ACQUIRE_RAW_ADC_SAMPLES_125K
}; 
 707         sscanf(str
, "%i %i %i %s %s", &c
.arg
[0], &c
.arg
[1], &c
.arg
[2], (char *) &c
.d
.asBytes
,(char *) &dummy
+1); 
 708         // in case they specified 'h' 
 709         strcpy((char *)&c
.d
.asBytes 
+ strlen((char *)c
.d
.asBytes
), dummy
); 
 713 static void CmdLosamples(char *str
) 
 718         n
=strtol(str
, NULL
, 0); 
 720         if (n
>16000) n
=16000; 
 722         PrintToScrollback("Reading %d samples\n", n
); 
 723         for(i 
= 0; i 
< n
; i 
+= 12) { 
 724                 UsbCommand c 
= {CMD_DOWNLOAD_RAW_ADC_SAMPLES_125K
, {i
, 0, 0}}; 
 726                 wait_for_response(CMD_DOWNLOADED_RAW_ADC_SAMPLES_125K
); 
 727                 for(j 
= 0; j 
< 48; j
++) { 
 728                         GraphBuffer
[cnt
++] = ((int)sample_buf
[j
]) - 128; 
 731         PrintToScrollback("Done!\n"); 
 733         RepaintGraphWindow(); 
 736 static void CmdBitsamples(char *str
) 
 742         for(i 
= 0; i 
< n
; i 
+= 12) { 
 743                 UsbCommand c 
= {CMD_DOWNLOAD_RAW_ADC_SAMPLES_125K
, {i
, 0, 0}}; 
 745                 wait_for_response(CMD_DOWNLOADED_RAW_ADC_SAMPLES_125K
); 
 747                 for(j 
= 0; j 
< 48; j
++) { 
 748                         for(k 
= 0; k 
< 8; k
++) { 
 749                                 if(sample_buf
[j
] & (1 << (7 - k
))) { 
 750                                         GraphBuffer
[cnt
++] = 1; 
 752                                         GraphBuffer
[cnt
++] = 0; 
 758         RepaintGraphWindow(); 
 761 static void CmdHisamples(char *str
) 
 767         for(i 
= 0; i 
< n
; i 
+= 12) { 
 768                 UsbCommand c 
= {CMD_DOWNLOAD_RAW_ADC_SAMPLES_125K
, {i
, 0, 0}}; 
 770                 wait_for_response(CMD_DOWNLOADED_RAW_ADC_SAMPLES_125K
); 
 771                 for(j 
= 0; j 
< 48; j
++) { 
 772                         GraphBuffer
[cnt
++] = (int)(sample_buf
[j
]); 
 777         RepaintGraphWindow(); 
 780 static int CmdHisamplest(char *str
, int nrlow
) 
 790         for(i 
= 0; i 
< n
; i 
+= 12) { 
 791                 UsbCommand c 
= {CMD_DOWNLOAD_RAW_ADC_SAMPLES_125K
, {i
, 0, 0}}; 
 793                 wait_for_response(CMD_DOWNLOADED_RAW_ADC_SAMPLES_125K
); 
 794                 for(j 
= 0; j 
< 48; j
++) { 
 795                         t2 
= (int)(sample_buf
[j
]); 
 796                         if((t2 
^ 0xC0) & 0xC0) { hasbeennull
++; } 
 802                                         t1 
= (t2 
& 0x80) ^ (t2 
& 0x20); 
 803                                         t2 
= ((t2 
<< 1) & 0x80) ^ ((t2 
<< 1) & 0x20); 
 809                                         t2 
= ((t2 
<< 1) & 0x80); 
 815                                         t2 
= ((t2 
<< 1) & 0x20); 
 819                                         // both, but tag with other algorithm 
 820                                         t1 
= (t2 
& 0x80) ^ (t2 
& 0x08); 
 821                                         t2 
= ((t2 
<< 1) & 0x80) ^ ((t2 
<< 1) & 0x08); 
 825                         GraphBuffer
[cnt
++] = t1
; 
 826                         GraphBuffer
[cnt
++] = t2
; 
 831         if(hasbeennull
>nrlow 
|| nrlow
==0) { 
 832                 PrintToScrollback("hasbeennull=%d", hasbeennull
); 
 841 static void CmdHexsamples(char *str
) 
 844         int requested 
= strtol(str
, NULL
, 0); 
 847         if (requested 
== 0) { 
 854         for(i 
= 0; i 
< n
; i 
+= 12) { 
 855                 UsbCommand c 
= {CMD_DOWNLOAD_RAW_ADC_SAMPLES_125K
, {i
, 0, 0}}; 
 857                 wait_for_response(CMD_DOWNLOADED_RAW_ADC_SAMPLES_125K
); 
 858                 for (j 
= 0; j 
< 48; j 
+= 8) { 
 859                         PrintToScrollback("%02x %02x %02x %02x %02x %02x %02x %02x", 
 871                         if (delivered 
>= requested
) 
 874                 if (delivered 
>= requested
) 
 879 static void CmdHisampless(char *str
) 
 883         int n 
= strtol(str
, NULL
, 0); 
 891         for(i 
= 0; i 
< n
; i 
+= 12) { 
 892                 UsbCommand c 
= {CMD_DOWNLOAD_RAW_ADC_SAMPLES_125K
, {i
, 0, 0}}; 
 894                 wait_for_response(CMD_DOWNLOADED_RAW_ADC_SAMPLES_125K
); 
 895                 for(j 
= 0; j 
< 48; j
++) { 
 896                         GraphBuffer
[cnt
++] = (int)(sample_buf
[j
]); 
 901         RepaintGraphWindow(); 
 904 static uint16_t Iso15693Crc(uint8_t *v
, int n
) 
 910         for(i 
= 0; i 
< n
; i
++) { 
 911                 reg 
= reg 
^ ((uint32_t)v
[i
]); 
 912                 for (j 
= 0; j 
< 8; j
++) { 
 914                                 reg 
= (reg 
>> 1) ^ 0x8408; 
 921         return (uint16_t)~reg
; 
 924 static void CmdHi14bdemod(char *str
) 
 929         bool negateI
, negateQ
; 
 934         // As received, the samples are pairs, correlations against I and Q 
 935         // square waves. So estimate angle of initial carrier (or just 
 936         // quadrant, actually), and then do the demod. 
 938         // First, estimate where the tag starts modulating. 
 939         for(i 
= 0; i 
< GraphTraceLen
; i 
+= 2) { 
 940                 if(abs(GraphBuffer
[i
]) + abs(GraphBuffer
[i
+1]) > 40) { 
 944         if(i 
>= GraphTraceLen
) { 
 945                 PrintToScrollback("too weak to sync"); 
 948         PrintToScrollback("out of weak at %d", i
); 
 951         // Now, estimate the phase in the initial modulation of the tag 
 954         for(; i 
< (outOfWeakAt 
+ 16); i 
+= 2) { 
 955                 isum 
+= GraphBuffer
[i
+0]; 
 956                 qsum 
+= GraphBuffer
[i
+1]; 
 958         negateI 
= (isum 
< 0); 
 959         negateQ 
= (qsum 
< 0); 
 961         // Turn the correlation pairs into soft decisions on the bit. 
 963         for(i 
= 0; i 
< GraphTraceLen
/2; i
++) { 
 964                 int si 
= GraphBuffer
[j
]; 
 965                 int sq 
= GraphBuffer
[j
+1]; 
 966                 if(negateI
) si 
= -si
; 
 967                 if(negateQ
) sq 
= -sq
; 
 968                 GraphBuffer
[i
] = si 
+ sq
; 
 974         while(GraphBuffer
[i
] > 0 && i 
< GraphTraceLen
) 
 976         if(i 
>= GraphTraceLen
) goto demodError
; 
 979         while(GraphBuffer
[i
] < 0 && i 
< GraphTraceLen
) 
 981         if(i 
>= GraphTraceLen
) goto demodError
; 
 982         if((i 
- iold
) > 23) goto demodError
; 
 984         PrintToScrollback("make it to demod loop"); 
 988                 while(GraphBuffer
[i
] >= 0 && i 
< GraphTraceLen
) 
 990                 if(i 
>= GraphTraceLen
) goto demodError
; 
 991                 if((i 
- iold
) > 6) goto demodError
; 
 993                 uint16_t shiftReg 
= 0; 
 994                 if(i 
+ 20 >= GraphTraceLen
) goto demodError
; 
 996                 for(j 
= 0; j 
< 10; j
++) { 
 997                         int soft 
= GraphBuffer
[i
] + GraphBuffer
[i
+1]; 
 999                         if(abs(soft
) < ((abs(isum
) + abs(qsum
))/20)) { 
1000                                 PrintToScrollback("weak bit"); 
1004                         if(GraphBuffer
[i
] + GraphBuffer
[i
+1] >= 0) { 
1011                 if( (shiftReg 
& 0x200) && 
1012                         !(shiftReg 
& 0x001)) 
1014                         // valid data byte, start and stop bits okay 
1015                         PrintToScrollback("   %02x", (shiftReg 
>> 1) & 0xff); 
1016                         data
[dataLen
++] = (shiftReg 
>> 1) & 0xff; 
1017                         if(dataLen 
>= sizeof(data
)) { 
1020                 } else if(shiftReg 
== 0x000) { 
1028         uint8_t first
, second
; 
1029         ComputeCrc14443(CRC_14443_B
, data
, dataLen
-2, &first
, &second
); 
1030         PrintToScrollback("CRC: %02x %02x (%s)\n", first
, second
, 
1031                 (first 
== data
[dataLen
-2] && second 
== data
[dataLen
-1]) ? 
1032                         "ok" : "****FAIL****"); 
1034         RepaintGraphWindow(); 
1038         PrintToScrollback("demod error"); 
1039         RepaintGraphWindow(); 
1042 static void CmdHi14list(char *str
) 
1045         GetFromBigBuf(got
, sizeof(got
)); 
1047         PrintToScrollback("recorded activity:"); 
1048         PrintToScrollback(" time        :rssi: who bytes"); 
1049         PrintToScrollback("---------+----+----+-----------"); 
1060                 int timestamp 
= *((uint32_t *)(got
+i
)); 
1061                 if(timestamp 
& 0x80000000) { 
1062                         timestamp 
&= 0x7fffffff; 
1067                 int metric 
= *((uint32_t *)(got
+i
+4)); 
1074                 if(i 
+ len 
>= 900) { 
1078                 uint8_t *frame 
= (got
+i
+9); 
1080                 char line
[1000] = ""; 
1082                 for(j 
= 0; j 
< len
; j
++) { 
1083                         sprintf(line
+(j
*3), "%02x  ", frame
[j
]); 
1089                         ComputeCrc14443(CRC_14443_B
, frame
, len
-2, &b1
, &b2
); 
1090                         if(b1 
!= frame
[len
-2] || b2 
!= frame
[len
-1]) { 
1091                                 crc 
= "**FAIL CRC**"; 
1099                 char metricString
[100]; 
1101                         sprintf(metricString
, "%3d", metric
); 
1103                         strcpy(metricString
, "   "); 
1106                 PrintToScrollback(" +%7d: %s: %s %s %s", 
1107                         (prev 
< 0 ? 0 : timestamp 
- prev
), 
1109                         (isResponse 
? "TAG" : "   "), line
, crc
); 
1116 static void CmdHi14alist(char *str
) 
1119         GetFromBigBuf(got
, sizeof(got
)); 
1121         PrintToScrollback("recorded activity:"); 
1122         PrintToScrollback(" ETU     :rssi: who bytes"); 
1123         PrintToScrollback("---------+----+----+-----------"); 
1134                 int timestamp 
= *((uint32_t *)(got
+i
)); 
1135                 if(timestamp 
& 0x80000000) { 
1136                         timestamp 
&= 0x7fffffff; 
1143                 int parityBits 
= *((uint32_t *)(got
+i
+4)); 
1144                 // 4 bytes of additional information... 
1145                 // maximum of 32 additional parity bit information 
1148                 // at each quarter bit period we can send power level (16 levels) 
1149                 // or each half bit period in 256 levels. 
1157                 if(i 
+ len 
>= 1900) { 
1161                 uint8_t *frame 
= (got
+i
+9); 
1163                 // Break and stick with current result if buffer was not completely full 
1164                 if(frame
[0] == 0x44 && frame
[1] == 0x44 && frame
[3] == 0x44) { break; } 
1166                 char line
[1000] = ""; 
1168                 for(j 
= 0; j 
< len
; j
++) { 
1169                         int oddparity 
= 0x01; 
1173                                 oddparity 
^= (((frame
[j
] & 0xFF) >> k
) & 0x01); 
1176                         //if((parityBits >> (len - j - 1)) & 0x01) { 
1177                         if(isResponse 
&& (oddparity 
!= ((parityBits 
>> (len 
- j 
- 1)) & 0x01))) { 
1178                                 sprintf(line
+(j
*4), "%02x!  ", frame
[j
]); 
1181                                 sprintf(line
+(j
*4), "%02x   ", frame
[j
]); 
1189                         for(j 
= 0; j 
< (len 
- 1); j
++) { 
1190                                 // gives problems... search for the reason.. 
1191                                 /*if(frame[j] == 0xAA) { 
1192                                         switch(frame[j+1]) { 
1194                                                         crc = "[1] Two drops close after each other"; 
1197                                                         crc = "[2] Potential SOC with a drop in second half of bitperiod"; 
1200                                                         crc = "[3] Segment Z after segment X is not possible"; 
1203                                                         crc = "[4] Parity bit of a fully received byte was wrong"; 
1206                                                         crc = "[?] Unknown error"; 
1213                         if(strlen(crc
)==0) { 
1214                                 ComputeCrc14443(CRC_14443_A
, frame
, len
-2, &b1
, &b2
); 
1215                                 if(b1 
!= frame
[len
-2] || b2 
!= frame
[len
-1]) { 
1216                                         crc 
= (isResponse 
& (len 
< 6)) ? "" : " !crc"; 
1225                 char metricString
[100]; 
1227                         sprintf(metricString
, "%3d", metric
); 
1229                         strcpy(metricString
, "   "); 
1232                 PrintToScrollback(" +%7d: %s: %s %s %s", 
1233                         (prev 
< 0 ? 0 : (timestamp 
- prev
)), 
1235                         (isResponse 
? "TAG" : "   "), line
, crc
); 
1240         CommandFinished 
= 1; 
1243 static void CmdHi15demod(char *str
) 
1245         // The sampling rate is 106.353 ksps/s, for T = 18.8 us 
1248         // 1) Unmodulated time of 56.64us 
1249         // 2) 24 pulses of 423.75khz 
1250         // 3) logic '1' (unmodulated for 18.88us followed by 8 pulses of 423.75khz) 
1252         static const int FrameSOF
[] = { 
1253                 -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 
1254                 -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 
1255                  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1, 
1256                  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1, 
1262         static const int Logic0
[] = { 
1268         static const int Logic1
[] = { 
1276         // 1) logic '0' (8 pulses of 423.75khz followed by unmodulated for 18.88us) 
1277         // 2) 24 pulses of 423.75khz 
1278         // 3) Unmodulated time of 56.64us 
1280         static const int FrameEOF
[] = { 
1285                  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1, 
1286                  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1, 
1287                 -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 
1288                 -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 
1292         int max 
= 0, maxPos
; 
1296         if(GraphTraceLen 
< 1000) return; 
1298         // First, correlate for SOF 
1299         for(i 
= 0; i 
< 100; i
++) { 
1301                 for(j 
= 0; j 
< arraylen(FrameSOF
); j 
+= skip
) { 
1302                         corr 
+= FrameSOF
[j
]*GraphBuffer
[i
+(j
/skip
)]; 
1309         PrintToScrollback("SOF at %d, correlation %d", maxPos
, 
1310                 max
/(arraylen(FrameSOF
)/skip
)); 
1312         i 
= maxPos 
+ arraylen(FrameSOF
)/skip
; 
1315         memset(outBuf
, 0, sizeof(outBuf
)); 
1316         uint8_t mask 
= 0x01; 
1318                 int corr0 
= 0, corr1 
= 0, corrEOF 
= 0; 
1319                 for(j 
= 0; j 
< arraylen(Logic0
); j 
+= skip
) { 
1320                         corr0 
+= Logic0
[j
]*GraphBuffer
[i
+(j
/skip
)]; 
1322                 for(j 
= 0; j 
< arraylen(Logic1
); j 
+= skip
) { 
1323                         corr1 
+= Logic1
[j
]*GraphBuffer
[i
+(j
/skip
)]; 
1325                 for(j 
= 0; j 
< arraylen(FrameEOF
); j 
+= skip
) { 
1326                         corrEOF 
+= FrameEOF
[j
]*GraphBuffer
[i
+(j
/skip
)]; 
1328                 // Even things out by the length of the target waveform. 
1332                 if(corrEOF 
> corr1 
&& corrEOF 
> corr0
) { 
1333                         PrintToScrollback("EOF at %d", i
); 
1335                 } else if(corr1 
> corr0
) { 
1336                         i 
+= arraylen(Logic1
)/skip
; 
1339                         i 
+= arraylen(Logic0
)/skip
; 
1346                 if((i
+(int)arraylen(FrameEOF
)) >= GraphTraceLen
) { 
1347                         PrintToScrollback("ran off end!"); 
1352                 PrintToScrollback("error, uneven octet! (discard extra bits!)"); 
1353                 PrintToScrollback("   mask=%02x", mask
); 
1355         PrintToScrollback("%d octets", k
); 
1357         for(i 
= 0; i 
< k
; i
++) { 
1358                 PrintToScrollback("# %2d: %02x ", i
, outBuf
[i
]); 
1360         PrintToScrollback("CRC=%04x", Iso15693Crc(outBuf
, k
-2)); 
1363 static void CmdFSKdemod(char *cmdline
) 
1365         static const int LowTone
[]  = { 
1366                 1,  1,  1,  1,  1, -1, -1, -1, -1, -1, 
1367                 1,  1,  1,  1,  1, -1, -1, -1, -1, -1, 
1368                 1,  1,  1,  1,  1, -1, -1, -1, -1, -1, 
1369                 1,  1,  1,  1,  1, -1, -1, -1, -1, -1, 
1370                 1,  1,  1,  1,  1, -1, -1, -1, -1, -1 
1372         static const int HighTone
[] = { 
1373                 1,  1,  1,  1,  1,     -1, -1, -1, -1, 
1374                 1,  1,  1,  1,         -1, -1, -1, -1, 
1375                 1,  1,  1,  1,         -1, -1, -1, -1, 
1376                 1,  1,  1,  1,         -1, -1, -1, -1, 
1377                 1,  1,  1,  1,         -1, -1, -1, -1, 
1378                 1,  1,  1,  1,     -1, -1, -1, -1, -1, 
1381         int lowLen 
= sizeof(LowTone
)/sizeof(int); 
1382         int highLen 
= sizeof(HighTone
)/sizeof(int); 
1383         int convLen 
= (highLen
>lowLen
)?highLen
:lowLen
; 
1384         uint32_t hi 
= 0, lo 
= 0; 
1387         int minMark
=0, maxMark
=0; 
1389         for(i 
= 0; i 
< GraphTraceLen 
- convLen
; i
++) { 
1390                 int lowSum 
= 0, highSum 
= 0; 
1392                 for(j 
= 0; j 
< lowLen
; j
++) { 
1393                         lowSum 
+= LowTone
[j
]*GraphBuffer
[i
+j
]; 
1395                 for(j 
= 0; j 
< highLen
; j
++) { 
1396                         highSum 
+= HighTone
[j
]*GraphBuffer
[i
+j
]; 
1398                 lowSum 
= abs((100*lowSum
) / lowLen
); 
1399                 highSum 
= abs((100*highSum
) / highLen
); 
1400                 GraphBuffer
[i
] = (highSum 
<< 16) | lowSum
; 
1403         for(i 
= 0; i 
< GraphTraceLen 
- convLen 
- 16; i
++) { 
1405                 int lowTot 
= 0, highTot 
= 0; 
1406                 // 10 and 8 are f_s divided by f_l and f_h, rounded 
1407                 for(j 
= 0; j 
< 10; j
++) { 
1408                         lowTot 
+= (GraphBuffer
[i
+j
] & 0xffff); 
1410                 for(j 
= 0; j 
< 8; j
++) { 
1411                         highTot 
+= (GraphBuffer
[i
+j
] >> 16); 
1413                 GraphBuffer
[i
] = lowTot 
- highTot
; 
1414                 if (GraphBuffer
[i
]>maxMark
) maxMark
=GraphBuffer
[i
]; 
1415                 if (GraphBuffer
[i
]<minMark
) minMark
=GraphBuffer
[i
]; 
1418         GraphTraceLen 
-= (convLen 
+ 16); 
1420         RepaintGraphWindow(); 
1422         // Find bit-sync (3 lo followed by 3 high) 
1423         int max 
= 0, maxPos 
= 0; 
1424         for(i 
= 0; i 
< 6000; i
++) { 
1426                 for(j 
= 0; j 
< 3*lowLen
; j
++) { 
1427                         dec 
-= GraphBuffer
[i
+j
]; 
1429                 for(; j 
< 3*(lowLen 
+ highLen 
); j
++) { 
1430                         dec 
+= GraphBuffer
[i
+j
]; 
1438         // place start of bit sync marker in graph 
1439         GraphBuffer
[maxPos
] = maxMark
; 
1440         GraphBuffer
[maxPos
+1] = minMark
; 
1444         // place end of bit sync marker in graph 
1445         GraphBuffer
[maxPos
] = maxMark
; 
1446         GraphBuffer
[maxPos
+1] = minMark
; 
1448         PrintToScrollback("actual data bits start at sample %d", maxPos
); 
1449         PrintToScrollback("length %d/%d", highLen
, lowLen
); 
1452         bits
[sizeof(bits
)-1] = '\0'; 
1454         // find bit pairs and manchester decode them 
1455         for(i 
= 0; i 
< arraylen(bits
)-1; i
++) { 
1457                 for(j 
= 0; j 
< lowLen
; j
++) { 
1458                         dec 
-= GraphBuffer
[maxPos
+j
]; 
1460                 for(; j 
< lowLen 
+ highLen
; j
++) { 
1461                         dec 
+= GraphBuffer
[maxPos
+j
]; 
1464                 // place inter bit marker in graph 
1465                 GraphBuffer
[maxPos
] = maxMark
; 
1466                 GraphBuffer
[maxPos
+1] = minMark
; 
1468                 // hi and lo form a 64 bit pair 
1469                 hi 
= (hi
<<1)|(lo
>>31); 
1471                 // store decoded bit as binary (in hi/lo) and text (in bits[]) 
1479         PrintToScrollback("bits: '%s'", bits
); 
1480         PrintToScrollback("hex: %08x %08x", hi
, lo
); 
1483 // read a TI tag and return its ID 
1484 static void CmdTIRead(char *str
) 
1486         UsbCommand c
={CMD_READ_TI_TYPE
}; 
1490 // write new data to a r/w TI tag 
1491 static void CmdTIWrite(char *str
) 
1493         UsbCommand c
={CMD_WRITE_TI_TYPE
}; 
1496         res 
= sscanf(str
, "0x%x 0x%x 0x%x ", &c
.arg
[0], &c
.arg
[1], &c
.arg
[2]); 
1497         if (res 
== 2) c
.arg
[2]=0; 
1499                 PrintToScrollback("Please specify the data as two hex strings, optionally the CRC as a third"); 
1504 static void CmdTIDemod(char *cmdline
) 
1506         /* MATLAB as follows: 
1507 f_s = 2000000;  % sampling frequency 
1508 f_l = 123200;   % low FSK tone 
1509 f_h = 134200;   % high FSK tone 
1511 T_l = 119e-6;   % low bit duration 
1512 T_h = 130e-6;   % high bit duration 
1514 l = 2*pi*ones(1, floor(f_s*T_l))*(f_l/f_s); 
1515 h = 2*pi*ones(1, floor(f_s*T_h))*(f_h/f_s); 
1517 l = sign(sin(cumsum(l))); 
1518 h = sign(sin(cumsum(h))); 
1521 // 2M*16/134.2k = 238 
1522  static const int LowTone
[] = { 
1523         1, 1, 1, 1, 1, 1, 1, 1, 1, -1, -1, -1, -1, -1, -1, -1, -1, 
1524         1, 1, 1, 1, 1, 1, 1, 1,          -1, -1, -1, -1, -1, -1, -1, -1, 
1525         1, 1, 1, 1, 1, 1, 1, 1,          -1, -1, -1, -1, -1, -1, -1, -1, 
1526         1, 1, 1, 1, 1, 1, 1, 1,          -1, -1, -1, -1, -1, -1, -1, -1, 
1527         1, 1, 1, 1, 1, 1, 1, 1, 1, -1, -1, -1, -1, -1, -1, -1, -1, 
1528         1, 1, 1, 1, 1, 1, 1, 1,          -1, -1, -1, -1, -1, -1, -1, -1, 
1529         1, 1, 1, 1, 1, 1, 1, 1,          -1, -1, -1, -1, -1, -1, -1, -1, 
1530         1, 1, 1, 1, 1, 1, 1, 1,          -1, -1, -1, -1, -1, -1, -1, -1, 
1531         1, 1, 1, 1, 1, 1, 1, 1, 1, -1, -1, -1, -1, -1, -1, -1, -1, 
1532         1, 1, 1, 1, 1, 1, 1, 1,          -1, -1, -1, -1, -1, -1, -1, -1, 
1533         1, 1, 1, 1, 1, 1, 1, 1,          -1, -1, -1, -1, -1, -1, -1, -1, 
1534         1, 1, 1, 1, 1, 1, 1, 1,          -1, -1, -1, -1, -1, -1, -1, -1, 
1535         1, 1, 1, 1, 1, 1, 1, 1, 1, -1, -1, -1, -1, -1, -1, -1, -1, 
1536         1, 1, 1, 1, 1, 1, 1, 1,          -1, -1, -1, -1, -1, -1, -1, -1, 
1537         1, 1, 1, 1, 1, 1, 1, 1,          -1, -1 
1539 // 2M*16/123.2k = 260 
1540  static const int HighTone
[] = { 
1541         1, 1, 1, 1, 1, 1, 1, 1,         -1, -1, -1, -1, -1, -1, -1, 
1542         1, 1, 1, 1, 1, 1, 1, 1,         -1, -1, -1, -1, -1, -1, -1, 
1543         1, 1, 1, 1, 1, 1, 1,                    -1, -1, -1, -1, -1, -1, -1, -1, 
1544         1, 1, 1, 1, 1, 1, 1,                    -1, -1, -1, -1, -1, -1, -1, -1, 
1545         1, 1, 1, 1, 1, 1, 1,                    -1, -1, -1, -1, -1, -1, -1, -1, 
1546         1, 1, 1, 1, 1, 1, 1,                    -1, -1, -1, -1, -1, -1, -1, 
1547         1, 1, 1, 1, 1, 1, 1, 1,         -1, -1, -1, -1, -1, -1, -1, 
1548         1, 1, 1, 1, 1, 1, 1, 1,         -1, -1, -1, -1, -1, -1, -1, 
1549         1, 1, 1, 1, 1, 1, 1,                    -1, -1, -1, -1, -1, -1, -1, -1, 
1550         1, 1, 1, 1, 1, 1, 1,                    -1, -1, -1, -1, -1, -1, -1, -1, 
1551         1, 1, 1, 1, 1, 1, 1,                    -1, -1, -1, -1, -1, -1, -1, 
1552         1, 1, 1, 1, 1, 1, 1, 1,         -1, -1, -1, -1, -1, -1, -1, 
1553         1, 1, 1, 1, 1, 1, 1, 1,         -1, -1, -1, -1, -1, -1, -1, 
1554         1, 1, 1, 1, 1, 1, 1, 1,         -1, -1, -1, -1, -1, -1, -1, 
1555         1, 1, 1, 1, 1, 1, 1,                    -1, -1, -1, -1, -1, -1, -1, -1, 
1556         1, 1, 1, 1, 1, 1, 1,                    -1, -1, -1, -1, -1, -1, -1, -1, 
1557         1, 1, 1, 1, 1, 1, 1,                    -1, -1, -1, -1, -1, -1, -1, 
1558         1, 1, 1, 1, 1, 1, 1, 1 
1560         int lowLen 
= sizeof(LowTone
)/sizeof(int); 
1561         int highLen 
= sizeof(HighTone
)/sizeof(int); 
1562         int convLen 
= (highLen
>lowLen
)?highLen
:lowLen
; 
1565         int lowSum 
= 0, highSum 
= 0;; 
1566         int lowTot 
= 0, highTot 
= 0; 
1568         for(i 
= 0; i 
< GraphTraceLen 
- convLen
; i
++) { 
1572                 for(j 
= 0; j 
< lowLen
; j
++) { 
1573                         lowSum 
+= LowTone
[j
]*GraphBuffer
[i
+j
]; 
1575                 for(j 
= 0; j 
< highLen
; j
++) { 
1576                         highSum 
+= HighTone
[j
]*GraphBuffer
[i
+j
]; 
1578                 lowSum 
= abs((100*lowSum
) / lowLen
); 
1579                 highSum 
= abs((100*highSum
) / highLen
); 
1580                 lowSum 
= (lowSum
<0)?-lowSum
:lowSum
; 
1581                 highSum 
= (highSum
<0)?-highSum
:highSum
; 
1583                 GraphBuffer
[i
] = (highSum 
<< 16) | lowSum
; 
1586         for(i 
= 0; i 
< GraphTraceLen 
- convLen 
- 16; i
++) { 
1589                 // 16 and 15 are f_s divided by f_l and f_h, rounded 
1590                 for(j 
= 0; j 
< 16; j
++) { 
1591                         lowTot 
+= (GraphBuffer
[i
+j
] & 0xffff); 
1593                 for(j 
= 0; j 
< 15; j
++) { 
1594                         highTot 
+= (GraphBuffer
[i
+j
] >> 16); 
1596                 GraphBuffer
[i
] = lowTot 
- highTot
; 
1599         GraphTraceLen 
-= (convLen 
+ 16); 
1601         RepaintGraphWindow(); 
1603         // TI tag data format is 16 prebits, 8 start bits, 64 data bits, 
1604         // 16 crc CCITT bits, 8 stop bits, 15 end bits 
1606         // the 16 prebits are always low 
1607         // the 8 start and stop bits of a tag must match 
1608         // the start/stop prebits of a ro tag are 01111110 
1609         // the start/stop prebits of a rw tag are 11111110 
1610   // the 15 end bits of a ro tag are all low 
1611   // the 15 end bits of a rw tag match bits 15-1 of the data bits 
1613         // Okay, so now we have unsliced soft decisions; 
1614         // find bit-sync, and then get some bits. 
1615         // look for 17 low bits followed by 6 highs (common pattern for ro and rw tags) 
1616         int max 
= 0, maxPos 
= 0; 
1617         for(i 
= 0; i 
< 6000; i
++) { 
1620                 // searching 17 consecutive lows 
1621                 for(j 
= 0; j 
< 17*lowLen
; j
++) { 
1622                         dec 
-= GraphBuffer
[i
+j
]; 
1624                 // searching 7 consecutive highs 
1625                 for(; j 
< 17*lowLen 
+ 6*highLen
; j
++) { 
1626                         dec 
+= GraphBuffer
[i
+j
]; 
1634         // place a marker in the buffer to visually aid location 
1635         // of the start of sync 
1636         GraphBuffer
[maxPos
] = 800; 
1637         GraphBuffer
[maxPos
+1] = -800; 
1639         // advance pointer to start of actual data stream (after 16 pre and 8 start bits) 
1640         maxPos 
+= 17*lowLen
; 
1641         maxPos 
+= 6*highLen
; 
1643         // place a marker in the buffer to visually aid location 
1644         // of the end of sync 
1645         GraphBuffer
[maxPos
] = 800; 
1646         GraphBuffer
[maxPos
+1] = -800; 
1648         PrintToScrollback("actual data bits start at sample %d", maxPos
); 
1650         PrintToScrollback("length %d/%d", highLen
, lowLen
); 
1652         uint8_t bits
[1+64+16+8+16]; 
1653         bits
[sizeof(bits
)-1] = '\0'; 
1655         uint32_t shift3 
= 0x7e000000, shift2 
= 0, shift1 
= 0, shift0 
= 0; 
1657         for(i 
= 0; i 
< arraylen(bits
)-1; i
++) { 
1661                 for(j 
= 0; j 
< lowLen
; j
++) { 
1662                         low 
-= GraphBuffer
[maxPos
+j
]; 
1664                 for(j 
= 0; j 
< highLen
; j
++) { 
1665                         high 
+= GraphBuffer
[maxPos
+j
]; 
1671                         // bitstream arrives lsb first so shift right 
1678                 // 128 bit right shift register 
1679           shift0 
= (shift0
>>1) | (shift1 
<< 31); 
1680           shift1 
= (shift1
>>1) | (shift2 
<< 31); 
1681           shift2 
= (shift2
>>1) | (shift3 
<< 31); 
1684                 // place a marker in the buffer between bits to visually aid location 
1685                 GraphBuffer
[maxPos
] = 800; 
1686                 GraphBuffer
[maxPos
+1] = -800; 
1688         PrintToScrollback("Info: raw tag bits = %s", bits
); 
1690         TagType 
= (shift3
>>8)&0xff; 
1691         if ( TagType 
!= ((shift0
>>16)&0xff) ) { 
1692                 PrintToScrollback("Error: start and stop bits do not match!"); 
1695         else if (TagType 
== 0x7e) { 
1696                 PrintToScrollback("Info: Readonly TI tag detected."); 
1699         else if (TagType 
== 0xfe) { 
1700                 PrintToScrollback("Info: Rewriteable TI tag detected."); 
1702           // put 64 bit data into shift1 and shift0 
1703           shift0 
= (shift0
>>24) | (shift1 
<< 8); 
1704           shift1 
= (shift1
>>24) | (shift2 
<< 8); 
1706                 // align 16 bit crc into lower half of shift2 
1707           shift2 
= ((shift2
>>24) | (shift3 
<< 8)) & 0x0ffff; 
1709                 // align 16 bit "end bits" or "ident" into lower half of shift3 
1712                 // only 15 bits compare, last bit of ident is not valid 
1713                 if ( (shift3
^shift0
)&0x7fff ) { 
1714                         PrintToScrollback("Error: Ident mismatch!"); 
1716                 // WARNING the order of the bytes in which we calc crc below needs checking 
1717                 // i'm 99% sure the crc algorithm is correct, but it may need to eat the 
1718                 // bytes in reverse or something 
1721                 crc 
= update_crc16(crc
, (shift0
)&0xff); 
1722                 crc 
= update_crc16(crc
, (shift0
>>8)&0xff); 
1723                 crc 
= update_crc16(crc
, (shift0
>>16)&0xff); 
1724                 crc 
= update_crc16(crc
, (shift0
>>24)&0xff); 
1725                 crc 
= update_crc16(crc
, (shift1
)&0xff); 
1726                 crc 
= update_crc16(crc
, (shift1
>>8)&0xff); 
1727                 crc 
= update_crc16(crc
, (shift1
>>16)&0xff); 
1728                 crc 
= update_crc16(crc
, (shift1
>>24)&0xff); 
1729                 PrintToScrollback("Info: Tag data = %08X%08X", shift1
, shift0
); 
1730                 if (crc 
!= (shift2
&0xffff)) { 
1731                         PrintToScrollback("Error: CRC mismatch, calculated %04X, got ^04X", crc
, shift2
&0xffff); 
1733                         PrintToScrollback("Info: CRC %04X is good", crc
); 
1737                 PrintToScrollback("Unknown tag type."); 
1742 static void CmdNorm(char *str
) 
1745         int max 
= INT_MIN
, min 
= INT_MAX
; 
1746         for(i 
= 10; i 
< GraphTraceLen
; i
++) { 
1747                 if(GraphBuffer
[i
] > max
) { 
1748                         max 
= GraphBuffer
[i
]; 
1750                 if(GraphBuffer
[i
] < min
) { 
1751                         min 
= GraphBuffer
[i
]; 
1755                 for(i 
= 0; i 
< GraphTraceLen
; i
++) { 
1756                         GraphBuffer
[i
] = (GraphBuffer
[i
] - ((max 
+ min
)/2))*1000/ 
1760         RepaintGraphWindow(); 
1763 static void CmdAmp(char *str
) 
1765         int i
, rising
, falling
; 
1766         int max 
= INT_MIN
, min 
= INT_MAX
; 
1767         for(i 
= 10; i 
< GraphTraceLen
; i
++) { 
1768                 if(GraphBuffer
[i
] > max
) { 
1769                         max 
= GraphBuffer
[i
]; 
1771                 if(GraphBuffer
[i
] < min
) { 
1772                         min 
= GraphBuffer
[i
]; 
1777                 for(i 
= 0; i 
< GraphTraceLen
; i
++) { 
1778                         if(GraphBuffer
[i
+1] < GraphBuffer
[i
]) { 
1780                                         GraphBuffer
[i
]= max
; 
1785                         if(GraphBuffer
[i
+1] > GraphBuffer
[i
]) { 
1787                                         GraphBuffer
[i
]= min
; 
1794         RepaintGraphWindow(); 
1797 static void CmdDec(char *str
) 
1800         for(i 
= 0; i 
< (GraphTraceLen
/2); i
++) { 
1801                 GraphBuffer
[i
] = GraphBuffer
[i
*2]; 
1804         PrintToScrollback("decimated by 2"); 
1805         RepaintGraphWindow(); 
1808 static void CmdHpf(char *str
) 
1812         for(i 
= 10; i 
< GraphTraceLen
; i
++) { 
1813                 accum 
+= GraphBuffer
[i
]; 
1815         accum 
/= (GraphTraceLen 
- 10); 
1816         for(i 
= 0; i 
< GraphTraceLen
; i
++) { 
1817                 GraphBuffer
[i
] -= accum
; 
1820         RepaintGraphWindow(); 
1823 static void CmdZerocrossings(char *str
) 
1826         // Zero-crossings aren't meaningful unless the signal is zero-mean. 
1832         for(i 
= 0; i 
< GraphTraceLen
; i
++) { 
1833                 if(GraphBuffer
[i
]*sign 
>= 0) { 
1834                         // No change in sign, reproduce the previous sample count. 
1836                         GraphBuffer
[i
] = lastZc
; 
1838                         // Change in sign, reset the sample count. 
1840                         GraphBuffer
[i
] = lastZc
; 
1848         RepaintGraphWindow(); 
1851 static void CmdThreshold(char *str
) 
1854         int threshold 
= atoi(str
); 
1856         for(i 
= 0; i 
< GraphTraceLen
; i
++) { 
1857                 if(GraphBuffer
[i
]>= threshold
) 
1862         RepaintGraphWindow(); 
1865 static void CmdLtrim(char *str
) 
1870         for(i 
= ds
; i 
< GraphTraceLen
; i
++) { 
1871                 GraphBuffer
[i
-ds
] = GraphBuffer
[i
]; 
1873         GraphTraceLen 
-= ds
; 
1875         RepaintGraphWindow(); 
1878 static void CmdAutoCorr(char *str
) 
1880         static int CorrelBuffer
[MAX_GRAPH_TRACE_LEN
]; 
1882         int window 
= atoi(str
); 
1885                 PrintToScrollback("needs a window"); 
1889         if(window 
>= GraphTraceLen
) { 
1890                 PrintToScrollback("window must be smaller than trace (%d samples)", 
1895         PrintToScrollback("performing %d correlations", GraphTraceLen 
- window
); 
1898         for(i 
= 0; i 
< GraphTraceLen 
- window
; i
++) { 
1901                 for(j 
= 0; j 
< window
; j
++) { 
1902                         sum 
+= (GraphBuffer
[j
]*GraphBuffer
[i
+j
]) / 256; 
1904                 CorrelBuffer
[i
] = sum
; 
1906         GraphTraceLen 
= GraphTraceLen 
- window
; 
1907         memcpy(GraphBuffer
, CorrelBuffer
, GraphTraceLen
*sizeof(int)); 
1909         RepaintGraphWindow(); 
1912 static void CmdVchdemod(char *str
) 
1914         // Is this the entire sync pattern, or does this also include some 
1915         // data bits that happen to be the same everywhere? That would be 
1917         static const int SyncPattern
[] = { 
1918                 1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1, 
1919                 1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 
1920                 1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1, 
1921                 1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 
1922                 1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1, 
1923                 1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 
1924                 1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1, 
1925                 1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 
1926                 1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1, 
1927                 1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 
1930         // So first, we correlate for the sync pattern, and mark that. 
1931         int bestCorrel 
= 0, bestPos 
= 0; 
1933         // It does us no good to find the sync pattern, with fewer than 
1934         // 2048 samples after it... 
1935         for(i 
= 0; i 
< (GraphTraceLen
-2048); i
++) { 
1938                 for(j 
= 0; j 
< arraylen(SyncPattern
); j
++) { 
1939                         sum 
+= GraphBuffer
[i
+j
]*SyncPattern
[j
]; 
1941                 if(sum 
> bestCorrel
) { 
1946         PrintToScrollback("best sync at %d [metric %d]", bestPos
, bestCorrel
); 
1951         int worst 
= INT_MAX
; 
1954         for(i 
= 0; i 
< 2048; i 
+= 8) { 
1957                 for(j 
= 0; j 
< 8; j
++) { 
1958                         sum 
+= GraphBuffer
[bestPos
+i
+j
]; 
1965                 if(abs(sum
) < worst
) { 
1970         PrintToScrollback("bits:"); 
1971         PrintToScrollback("%s", bits
); 
1972         PrintToScrollback("worst metric: %d at pos %d", worst
, worstPos
); 
1974         if(strcmp(str
, "clone")==0) { 
1977                 for(s 
= bits
; *s
; s
++) { 
1979                         for(j 
= 0; j 
< 16; j
++) { 
1980                                 GraphBuffer
[GraphTraceLen
++] = (*s 
== '1') ? 1 : 0; 
1983                 RepaintGraphWindow(); 
1987 static void CmdIndalademod(char *str
) 
1989         // Usage: recover 64bit UID by default, specify "224" as arg to recover a 224bit UID 
1994         // worst case with GraphTraceLen=64000 is < 4096 
1995         // under normal conditions it's < 2048 
1996         uint8_t rawbits
[4096]; 
1998         int worst 
= 0, worstPos 
= 0; 
1999         PrintToScrollback("Expecting a bit less than %d raw bits", GraphTraceLen
/32); 
2000         for(i 
= 0; i 
< GraphTraceLen
-1; i 
+= 2) { 
2002                 if((GraphBuffer
[i
] > GraphBuffer
[i 
+ 1]) && (state 
!= 1)) { 
2004                                 for(j 
= 0; j 
<  count 
- 8; j 
+= 16) { 
2005                                         rawbits
[rawbit
++] = 0; 
2007                                 if ((abs(count 
- j
)) > worst
) { 
2008                                         worst 
= abs(count 
- j
); 
2014                 } else if((GraphBuffer
[i
] < GraphBuffer
[i 
+ 1]) && (state 
!= 0)) { 
2016                                 for(j 
= 0; j 
<  count 
- 8; j 
+= 16) { 
2017                                         rawbits
[rawbit
++] = 1; 
2019                                 if ((abs(count 
- j
)) > worst
) { 
2020                                         worst 
= abs(count 
- j
); 
2028         PrintToScrollback("Recovered %d raw bits", rawbit
); 
2029         PrintToScrollback("worst metric (0=best..7=worst): %d at pos %d", worst
, worstPos
); 
2031         // Finding the start of a UID 
2032         int uidlen
, long_wait
; 
2033         if(strcmp(str
, "224") == 0) { 
2042         for(start 
= 0; start 
<= rawbit 
- uidlen
; start
++) { 
2043                 first 
= rawbits
[start
]; 
2044                 for(i 
= start
; i 
< start 
+ long_wait
; i
++) { 
2045                         if(rawbits
[i
] != first
) { 
2049                 if(i 
== (start 
+ long_wait
)) { 
2053         if(start 
== rawbit 
- uidlen 
+ 1) { 
2054                 PrintToScrollback("nothing to wait for"); 
2058         // Inverting signal if needed 
2060                 for(i 
= start
; i 
< rawbit
; i
++) { 
2061                         rawbits
[i
] = !rawbits
[i
]; 
2068         showbits
[uidlen
]='\0'; 
2072         if(uidlen 
> rawbit
) { 
2073                 PrintToScrollback("Warning: not enough raw bits to get a full UID"); 
2074                 for(bit 
= 0; bit 
< rawbit
; bit
++) { 
2075                         bits
[bit
] = rawbits
[i
++]; 
2076                         // As we cannot know the parity, let's use "." and "/" 
2077                         showbits
[bit
] = '.' + bits
[bit
]; 
2079                 showbits
[bit
+1]='\0'; 
2080                 PrintToScrollback("Partial UID=%s", showbits
); 
2083                 for(bit 
= 0; bit 
< uidlen
; bit
++) { 
2084                         bits
[bit
] = rawbits
[i
++]; 
2085                         showbits
[bit
] = '0' + bits
[bit
]; 
2089         PrintToScrollback("UID=%s", showbits
); 
2091         // Checking UID against next occurences 
2092         for(; i 
+ uidlen 
<= rawbit
;) { 
2094                 for(bit 
= 0; bit 
< uidlen
; bit
++) { 
2095                         if(bits
[bit
] != rawbits
[i
++]) { 
2105         PrintToScrollback("Occurences: %d (expected %d)", times
, (rawbit 
- start
) / uidlen
); 
2107         // Remodulating for tag cloning 
2108         GraphTraceLen 
= 32*uidlen
; 
2111         for(bit 
= 0; bit 
< uidlen
; bit
++) { 
2112                 if(bits
[bit
] == 0) { 
2118                 for(j 
= 0; j 
< 32; j
++) { 
2119                         GraphBuffer
[i
++] = phase
; 
2124         RepaintGraphWindow(); 
2127 static void CmdFlexdemod(char *str
) 
2130         for(i 
= 0; i 
< GraphTraceLen
; i
++) { 
2131                 if(GraphBuffer
[i
] < 0) { 
2132                         GraphBuffer
[i
] = -1; 
2138 #define LONG_WAIT 100 
2140         for(start 
= 0; start 
< GraphTraceLen 
- LONG_WAIT
; start
++) { 
2141                 int first 
= GraphBuffer
[start
]; 
2142                 for(i 
= start
; i 
< start 
+ LONG_WAIT
; i
++) { 
2143                         if(GraphBuffer
[i
] != first
) { 
2147                 if(i 
== (start 
+ LONG_WAIT
)) { 
2151         if(start 
== GraphTraceLen 
- LONG_WAIT
) { 
2152                 PrintToScrollback("nothing to wait for"); 
2156         GraphBuffer
[start
] = 2; 
2157         GraphBuffer
[start
+1] = -2; 
2163         for(bit 
= 0; bit 
< 64; bit
++) { 
2166                 for(j 
= 0; j 
< 16; j
++) { 
2167                         sum 
+= GraphBuffer
[i
++]; 
2174                 PrintToScrollback("bit %d sum %d", bit
, sum
); 
2177         for(bit 
= 0; bit 
< 64; bit
++) { 
2180                 for(j 
= 0; j 
< 16; j
++) { 
2181                         sum 
+= GraphBuffer
[i
++]; 
2183                 if(sum 
> 0 && bits
[bit
] != 1) { 
2184                         PrintToScrollback("oops1 at %d", bit
); 
2186                 if(sum 
< 0 && bits
[bit
] != 0) { 
2187                         PrintToScrollback("oops2 at %d", bit
); 
2191         GraphTraceLen 
= 32*64; 
2194         for(bit 
= 0; bit 
< 64; bit
++) { 
2195                 if(bits
[bit
] == 0) { 
2201                 for(j 
= 0; j 
< 32; j
++) { 
2202                         GraphBuffer
[i
++] = phase
; 
2207         RepaintGraphWindow(); 
2211  * Generic command to demodulate ASK. 
2213  * Argument is convention: positive or negative (High mod means zero 
2214  * or high mod means one) 
2216  * Updates the Graph trace with 0/1 values 
2222 static void Cmdaskdemod(char *str
) { 
2224         int c
, high 
= 0, low 
= 0; 
2226         // TODO: complain if we do not give 2 arguments here ! 
2227         // (AL - this doesn't make sense! we're only using one argument!!!) 
2228         sscanf(str
, "%i", &c
); 
2230         /* Detect high and lows and clock */ 
2232         for (i 
= 0; i 
< GraphTraceLen
; i
++) 
2234                 if (GraphBuffer
[i
] > high
) 
2235                         high 
= GraphBuffer
[i
]; 
2236                 else if (GraphBuffer
[i
] < low
) 
2237                         low 
= GraphBuffer
[i
]; 
2239         if(c 
!= 0 && c 
!= 1) { 
2240                 PrintToScrollback("Invalid argument: %s",str
); 
2244         if (GraphBuffer
[0] > 0) { 
2245                 GraphBuffer
[0] = 1-c
; 
2249         for(i
=1;i
<GraphTraceLen
;i
++) { 
2250                 /* Transitions are detected at each peak 
2251                  * Transitions are either: 
2252                  * - we're low: transition if we hit a high 
2253                  * - we're high: transition if we hit a low 
2254                  * (we need to do it this way because some tags keep high or 
2255                  * low for long periods, others just reach the peak and go 
2258                 if ((GraphBuffer
[i
]==high
) && (GraphBuffer
[i
-1] == c
)) { 
2260                 } else if ((GraphBuffer
[i
]==low
) && (GraphBuffer
[i
-1] == (1-c
))){ 
2264                         GraphBuffer
[i
] = GraphBuffer
[i
-1]; 
2267         RepaintGraphWindow(); 
2270 /* Print our clock rate */ 
2271 static void Cmddetectclockrate(char *str
) 
2273         int clock 
= detectclock(0); 
2274         PrintToScrollback("Auto-detected clock rate: %d", clock
); 
2280 int detectclock(int peak
) 
2286         /* Detect peak if we don't have one */ 
2288                 for (i 
= 0; i 
< GraphTraceLen
; i
++) 
2289                         if (GraphBuffer
[i
] > peak
) 
2290                                 peak 
= GraphBuffer
[i
]; 
2292         for (i 
= 1; i 
< GraphTraceLen
; i
++) 
2294                 /* If this is the beginning of a peak */ 
2295                 if (GraphBuffer
[i
-1] != GraphBuffer
[i
] && GraphBuffer
[i
] == peak
) 
2297                         /* Find lowest difference between peaks */ 
2298                         if (lastpeak 
&& i 
- lastpeak 
< clock
) 
2300                                 clock 
= i 
- lastpeak
; 
2309 /* Get or auto-detect clock rate */ 
2310 int GetClock(char *str
, int peak
) 
2314         sscanf(str
, "%i", &clock
); 
2315         if (!strcmp(str
, "")) 
2318         /* Auto-detect clock */ 
2321                 clock 
= detectclock(peak
); 
2323                 /* Only print this message if we're not looping something */ 
2325                         PrintToScrollback("Auto-detected clock rate: %d", clock
); 
2332  * Convert to a bitstream 
2334 static void Cmdbitstream(char *str
) { 
2341         int hithigh
, hitlow
, first
; 
2343         /* Detect high and lows and clock */ 
2344         for (i 
= 0; i 
< GraphTraceLen
; i
++) 
2346                 if (GraphBuffer
[i
] > high
) 
2347                         high 
= GraphBuffer
[i
]; 
2348                 else if (GraphBuffer
[i
] < low
) 
2349                         low 
= GraphBuffer
[i
]; 
2353         clock 
= GetClock(str
, high
); 
2355         gtl 
= CmdClearGraph(0); 
2358         for (i 
= 0; i 
< (int)(gtl 
/ clock
); i
++) 
2364                 /* Find out if we hit both high and low peaks */ 
2365                 for (j 
= 0; j 
< clock
; j
++) 
2367                         if (GraphBuffer
[(i 
* clock
) + j
] == high
) 
2369                         else if (GraphBuffer
[(i 
* clock
) + j
] == low
) 
2372                         /* it doesn't count if it's the first part of our read 
2373                          because it's really just trailing from the last sequence */ 
2374                         if (first 
&& (hithigh 
|| hitlow
)) 
2375                                 hithigh 
= hitlow 
= 0; 
2379                         if (hithigh 
&& hitlow
) 
2383                 /* If we didn't hit both high and low peaks, we had a bit transition */ 
2384                 if (!hithigh 
|| !hitlow
) 
2387                 CmdAppendGraph(0, clock
, bit
); 
2388 //              for (j = 0; j < (int)(clock/2); j++) 
2389 //                      GraphBuffer[(i * clock) + j] = bit ^ 1; 
2390 //              for (j = (int)(clock/2); j < clock; j++) 
2391 //                      GraphBuffer[(i * clock) + j] = bit; 
2394         RepaintGraphWindow(); 
2397 /* Modulate our data into manchester */ 
2398 static void Cmdmanchestermod(char *str
) 
2402         int bit
, lastbit
, wave
; 
2405         clock 
= GetClock(str
, 0); 
2409         for (i 
= 0; i 
< (int)(GraphTraceLen 
/ clock
); i
++) 
2411                 bit 
= GraphBuffer
[i 
* clock
] ^ 1; 
2413                 for (j 
= 0; j 
< (int)(clock
/2); j
++) 
2414                         GraphBuffer
[(i 
* clock
) + j
] = bit 
^ lastbit 
^ wave
; 
2415                 for (j 
= (int)(clock
/2); j 
< clock
; j
++) 
2416                         GraphBuffer
[(i 
* clock
) + j
] = bit 
^ lastbit 
^ wave 
^ 1; 
2418                 /* Keep track of how we start our wave and if we changed or not this time */ 
2419                 wave 
^= bit 
^ lastbit
; 
2423         RepaintGraphWindow(); 
2427  * Manchester demodulate a bitstream. The bitstream needs to be already in 
2428  * the GraphBuffer as 0 and 1 values 
2430  * Give the clock rate as argument in order to help the sync - the algorithm 
2431  * resyncs at each pulse anyway. 
2433  * Not optimized by any means, this is the 1st time I'm writing this type of 
2434  * routine, feel free to improve... 
2436  * 1st argument: clock rate (as number of samples per clock rate) 
2437  *               Typical values can be 64, 32, 128... 
2439 static void Cmdmanchesterdemod(char *str
) { 
2440         int i
, j
, invert
= 0; 
2446         int hithigh
, hitlow
, first
; 
2452         /* check if we're inverting output */ 
2455                 PrintToScrollback("Inverting output"); 
2459                 while(*str 
== ' '); // in case a 2nd argument was given 
2462         /* Holds the decoded bitstream: each clock period contains 2 bits       */ 
2463         /* later simplified to 1 bit after manchester decoding.                 */ 
2464         /* Add 10 bits to allow for noisy / uncertain traces without aborting   */ 
2465         /* int BitStream[GraphTraceLen*2/clock+10]; */ 
2467         /* But it does not work if compiling on WIndows: therefore we just allocate a */ 
2469         int BitStream
[MAX_GRAPH_TRACE_LEN
]; 
2471         /* Detect high and lows */ 
2472         for (i 
= 0; i 
< GraphTraceLen
; i
++) 
2474                 if (GraphBuffer
[i
] > high
) 
2475                         high 
= GraphBuffer
[i
]; 
2476                 else if (GraphBuffer
[i
] < low
) 
2477                         low 
= GraphBuffer
[i
]; 
2481         clock 
= GetClock(str
, high
); 
2483         int tolerance 
= clock
/4; 
2485         /* Detect first transition */ 
2486         /* Lo-Hi (arbitrary)       */ 
2487         /* skip to the first high */ 
2488         for (i
= 0; i 
< GraphTraceLen
; i
++) 
2489                 if(GraphBuffer
[i
] == high
) 
2491         /* now look for the first low */ 
2492         for (; i 
< GraphTraceLen
; i
++) 
2494                 if (GraphBuffer
[i
] == low
) 
2501         /* If we're not working with 1/0s, demod based off clock */ 
2504                 bit 
= 0; /* We assume the 1st bit is zero, it may not be 
2505                           * the case: this routine (I think) has an init problem. 
2508                 for (; i 
< (int)(GraphTraceLen 
/ clock
); i
++) 
2514                         /* Find out if we hit both high and low peaks */ 
2515                         for (j 
= 0; j 
< clock
; j
++) 
2517                                 if (GraphBuffer
[(i 
* clock
) + j
] == high
) 
2519                                 else if (GraphBuffer
[(i 
* clock
) + j
] == low
) 
2522                                 /* it doesn't count if it's the first part of our read 
2523                                    because it's really just trailing from the last sequence */ 
2524                                 if (first 
&& (hithigh 
|| hitlow
)) 
2525                                         hithigh 
= hitlow 
= 0; 
2529                                 if (hithigh 
&& hitlow
) 
2533                         /* If we didn't hit both high and low peaks, we had a bit transition */ 
2534                         if (!hithigh 
|| !hitlow
) 
2537                         BitStream
[bit2idx
++] = bit 
^ invert
; 
2541         /* standard 1/0 bitstream */ 
2545                 /* Then detect duration between 2 successive transitions */ 
2546                 for (bitidx 
= 1; i 
< GraphTraceLen
; i
++) 
2548                         if (GraphBuffer
[i
-1] != GraphBuffer
[i
]) 
2553                         // Error check: if bitidx becomes too large, we do not 
2554                         // have a Manchester encoded bitstream or the clock is really 
2556                         if (bitidx 
> (GraphTraceLen
*2/clock
+8) ) { 
2557                                 PrintToScrollback("Error: the clock you gave is probably wrong, aborting."); 
2560                         // Then switch depending on lc length: 
2561                         // Tolerance is 1/4 of clock rate (arbitrary) 
2562                         if (abs(lc
-clock
/2) < tolerance
) { 
2563                                 // Short pulse : either "1" or "0" 
2564                                 BitStream
[bitidx
++]=GraphBuffer
[i
-1]; 
2565                         } else if (abs(lc
-clock
) < tolerance
) { 
2566                                 // Long pulse: either "11" or "00" 
2567                                 BitStream
[bitidx
++]=GraphBuffer
[i
-1]; 
2568                                 BitStream
[bitidx
++]=GraphBuffer
[i
-1]; 
2572                                 PrintToScrollback("Warning: Manchester decode error for pulse width detection."); 
2573                                 PrintToScrollback("(too many of those messages mean either the stream is not Manchester encoded, or clock is wrong)"); 
2577                                                 PrintToScrollback("Error: too many detection errors, aborting."); 
2584                 // At this stage, we now have a bitstream of "01" ("1") or "10" ("0"), parse it into final decoded bitstream 
2585                 // Actually, we overwrite BitStream with the new decoded bitstream, we just need to be careful 
2586                 // to stop output at the final bitidx2 value, not bitidx 
2587                 for (i 
= 0; i 
< bitidx
; i 
+= 2) { 
2588                         if ((BitStream
[i
] == 0) && (BitStream
[i
+1] == 1)) { 
2589                                 BitStream
[bit2idx
++] = 1 ^ invert
; 
2590                 } else if ((BitStream
[i
] == 1) && (BitStream
[i
+1] == 0)) { 
2591                         BitStream
[bit2idx
++] = 0 ^ invert
; 
2593                         // We cannot end up in this state, this means we are unsynchronized, 
2597                         PrintToScrollback("Unsynchronized, resync..."); 
2598                         PrintToScrollback("(too many of those messages mean the stream is not Manchester encoded)"); 
2602                                         PrintToScrollback("Error: too many decode errors, aborting."); 
2609         PrintToScrollback("Manchester decoded bitstream"); 
2610         // Now output the bitstream to the scrollback by line of 16 bits 
2611         for (i 
= 0; i 
< (bit2idx
-16); i
+=16) { 
2612                 PrintToScrollback("%i %i %i %i %i %i %i %i %i %i %i %i %i %i %i %i", 
2635 static void CmdHiddemod(char *str
) 
2637         if(GraphTraceLen 
< 4800) { 
2638                 PrintToScrollback("too short; need at least 4800 samples"); 
2642         GraphTraceLen 
= 4800; 
2644         for(i 
= 0; i 
< GraphTraceLen
; i
++) { 
2645                 if(GraphBuffer
[i
] < 0) { 
2651         RepaintGraphWindow(); 
2654 static void CmdPlot(char *str
) 
2659 static void CmdGrid(char *str
) 
2661         sscanf(str
, "%i %i", &PlotGridX
, &PlotGridY
); 
2662         RepaintGraphWindow(); 
2665 static void CmdHide(char *str
) 
2670 static void CmdScale(char *str
) 
2672         CursorScaleFactor 
= atoi(str
); 
2673         if(CursorScaleFactor 
== 0) { 
2674                 PrintToScrollback("bad, can't have zero scale"); 
2675                 CursorScaleFactor 
= 1; 
2677         RepaintGraphWindow(); 
2680 static void CmdSave(char *str
) 
2682         FILE *f 
= fopen(str
, "w"); 
2684                 PrintToScrollback("couldn't open '%s'", str
); 
2688         for(i 
= 0; i 
< GraphTraceLen
; i
++) { 
2689                 fprintf(f
, "%d\n", GraphBuffer
[i
]); 
2692         PrintToScrollback("saved to '%s'", str
); 
2695 static void CmdLoad(char *str
) 
2697         FILE *f 
= fopen(str
, "r"); 
2699                 PrintToScrollback("couldn't open '%s'", str
); 
2705         while(fgets(line
, sizeof(line
), f
)) { 
2706                 GraphBuffer
[GraphTraceLen
] = atoi(line
); 
2710         PrintToScrollback("loaded %d samples", GraphTraceLen
); 
2711         RepaintGraphWindow(); 
2714 static void CmdHIDsimTAG(char *str
) 
2716         unsigned int hi
=0, lo
=0; 
2719         while (sscanf(&str
[i
++], "%1x", &n 
) == 1) { 
2720                 hi
=(hi
<<4)|(lo
>>28); 
2724         PrintToScrollback("Emulating tag with ID %x%16x", hi
, lo
); 
2726         UsbCommand c
={CMD_HID_SIM_TAG
, {hi
, lo
, 0}}; 
2730 static void CmdReadmem(char *str
) 
2732         UsbCommand c
={CMD_READ_MEM
, {strtol(str
, NULL
, 0), 0, 0}}; 
2736 static void CmdVersion(char *str
) 
2738         UsbCommand c
={CMD_VERSION
}; 
2742 static void CmdLcdReset(char *str
) 
2744         UsbCommand c
={CMD_LCD_RESET
, {strtol(str
, NULL
, 0), 0, 0}}; 
2748 static void CmdLcd(char *str
) 
2751         UsbCommand c
={CMD_LCD
}; 
2752         sscanf(str
, "%x %d", &i
, &j
); 
2760  * Sets the divisor for LF frequency clock: lets the user choose any LF frequency below 
2763 static void CmdSetDivisor(char *str
) 
2765         UsbCommand c
={CMD_SET_LF_DIVISOR
, {strtol(str
, NULL
, 0), 0, 0}}; 
2766         if (( c
.arg
[0]<0) || (c
.arg
[0]>255)) { 
2767                         PrintToScrollback("divisor must be between 19 and 255"); 
2770                         PrintToScrollback("Divisor set, expected freq=%dHz", 12000000/(c
.arg
[0]+1)); 
2774 static void CmdSetMux(char *str
) 
2776         UsbCommand c
={CMD_SET_ADC_MUX
}; 
2777         if(strcmp(str
, "lopkd") == 0) { 
2779         } else if(strcmp(str
, "loraw") == 0) { 
2781         } else if(strcmp(str
, "hipkd") == 0) { 
2783         } else if(strcmp(str
, "hiraw") == 0) { 
2789 typedef void HandlerFunction(char *cmdline
); 
2791 /* in alphabetic order */ 
2794         HandlerFunction 
*handler
; 
2795         int             offline
;  // 1 if the command can be used when in offline mode 
2797 } CommandTable
[] = { 
2798         {"amp",                 CmdAmp
,                 1, "Amplify peaks"}, 
2799         {"askdemod",            Cmdaskdemod
,            1, "<0|1> -- Attempt to demodulate simple ASK tags"}, 
2800         {"autocorr",            CmdAutoCorr
,            1, "<window length> -- Autocorrelation over window"}, 
2801         {"bitsamples",          CmdBitsamples
,          0, "Get raw samples as bitstring"}, 
2802         {"bitstream",           Cmdbitstream
,           1, "[clock rate] -- Convert waveform into a bitstream"}, 
2803         {"buffclear",           CmdBuffClear
,           1, "Clear sample buffer and graph window"}, 
2804         {"dec",                 CmdDec
,                 1, "Decimate samples"}, 
2805         {"detectclock",         Cmddetectclockrate
,     1, "Detect clock rate"}, 
2806         {"detectreader",        CmdDetectReader
,        0, "['l'|'h'] -- Detect external reader field (option 'l' or 'h' to limit to LF or HF)"}, 
2807         {"em410xsim",           CmdEM410xsim
,           1, "<UID> -- Simulate EM410x tag"}, 
2808         {"em410xread",          CmdEM410xread
,          1, "[clock rate] -- Extract ID from EM410x tag"}, 
2809         {"em410xwatch",         CmdEM410xwatch
,         0, "Watches for EM410x tags"}, 
2810         {"em4x50read",          CmdEM4x50read
,          1, "Extract data from EM4x50 tag"}, 
2811         {"exit",                CmdQuit
,                1, "Exit program"}, 
2812         {"flexdemod",           CmdFlexdemod
,           1, "Demodulate samples for FlexPass"}, 
2813         {"fpgaoff",             CmdFPGAOff
,             0, "Set FPGA off"}, 
2814         {"fskdemod",            CmdFSKdemod
,            1, "Demodulate graph window as a HID FSK"}, 
2815         {"grid",                CmdGrid
,                1, "<x> <y> -- overlay grid on graph window, use zero value to turn off either"}, 
2816         {"hexsamples",          CmdHexsamples
,          0, "<blocks> -- Dump big buffer as hex bytes"}, 
2817         {"hi14alist",           CmdHi14alist
,           0, "List ISO 14443a history"}, 
2818         {"hi14areader",         CmdHi14areader
,         0, "Act like an ISO14443 Type A reader"}, 
2819         {"hi14asim",            CmdHi14asim
,            0, "<UID> -- Fake ISO 14443a tag"}, 
2820         {"hi14asnoop",          CmdHi14asnoop
,          0, "Eavesdrop ISO 14443 Type A"}, 
2821         {"hi14bdemod",          CmdHi14bdemod
,          1, "Demodulate ISO14443 Type B from tag"}, 
2822         {"hi14list",            CmdHi14list
,            0, "List ISO 14443 history"}, 
2823         {"hi14read",            CmdHi14read
,            0, "Read HF tag (ISO 14443)"}, 
2824         {"hi14sim",             CmdHi14sim
,             0, "Fake ISO 14443 tag"}, 
2825         {"hi14snoop",           CmdHi14snoop
,           0, "Eavesdrop ISO 14443"}, 
2826         {"hi15demod",           CmdHi15demod
,           1, "Demodulate ISO15693 from tag"}, 
2827         {"hi15read",            CmdHi15read
,            0, "Read HF tag (ISO 15693)"}, 
2828         {"hi15reader",          CmdHi15reader
,          0, "Act like an ISO15693 reader"}, 
2829         {"hi15sim",             CmdHi15tag
,             0, "Fake an ISO15693 tag"}, 
2830         {"hiddemod",            CmdHiddemod
,            1, "Demodulate HID Prox Card II (not optimal)"}, 
2831         {"hide",                CmdHide
,                1, "Hide graph window"}, 
2832         {"hidfskdemod",         CmdHIDdemodFSK
,         0, "Realtime HID FSK demodulator"}, 
2833         {"hidsimtag",           CmdHIDsimTAG
,           0, "<ID> -- HID tag simulator"}, 
2834         {"higet",               CmdHi14read_sim
,        0, "<samples> -- Get samples HF, 'analog'"}, 
2835         {"hisamples",           CmdHisamples
,           0, "Get raw samples for HF tag"}, 
2836         {"hisampless",          CmdHisampless
,          0, "<samples> -- Get signed raw samples, HF tag"}, 
2837         {"hisamplest",          CmdHi14readt
,           0, "Get samples HF, for testing"}, 
2838         {"hisimlisten",         CmdHisimlisten
,         0, "Get HF samples as fake tag"}, 
2839         {"hpf",                 CmdHpf
,                 1, "Remove DC offset from trace"}, 
2840         {"indalademod",         CmdIndalademod
,         0, "['224'] -- Demodulate samples for Indala 64 bit UID (option '224' for 224 bit)"}, 
2841         {"lcd",                 CmdLcd
,                 0, "<HEX command> <count> -- Send command/data to LCD"}, 
2842         {"lcdreset",            CmdLcdReset
,            0, "Hardware reset LCD"}, 
2843         {"legicrfread",         CmdLegicRfRead
,         0, "Start the LEGIC RF reader"}, 
2844         {"load",                CmdLoad
,                1, "<filename> -- Load trace (to graph window"}, 
2845         {"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)"}, 
2846         {"loread",              CmdLoread
,              0, "['h'] -- Read 125/134 kHz LF ID-only tag (option 'h' for 134)"}, 
2847         {"losamples",           CmdLosamples
,           0, "[128 - 16000] -- Get raw samples for LF tag"}, 
2848         {"losim",               CmdLosim
,               0, "Simulate LF tag"}, 
2849         {"losimbidir",          CmdLosimBidir
,          0, "Simulate LF tag (with bidirectional data transmission between reader and tag)"}, 
2850         {"ltrim",               CmdLtrim
,               1, "<samples> -- Trim samples from left of trace"}, 
2851         {"mandemod",            Cmdmanchesterdemod
,     1, "[i] [clock rate] -- Manchester demodulate binary stream (option 'i' to invert output)"}, 
2852         {"manmod",              Cmdmanchestermod
,       1, "[clock rate] -- Manchester modulate a binary stream"}, 
2853         {"norm",                CmdNorm
,                1, "Normalize max/min to +/-500"}, 
2854         {"plot",                CmdPlot
,                1, "Show graph window"}, 
2855         {"quit",                CmdQuit
,                1, "Quit program"}, 
2856         {"readmem",             CmdReadmem
,             0, "[address] -- Read memory at decimal address from flash"}, 
2857         {"reset",               CmdReset
,               0, "Reset the Proxmark3"}, 
2858         {"save",                CmdSave
,                1, "<filename> -- Save trace (from graph window)"}, 
2859         {"scale",               CmdScale
,               1, "<int> -- Set cursor display scale"}, 
2860         {"setlfdivisor",        CmdSetDivisor
,          0, "<19 - 255> -- Drive LF antenna at 12Mhz/(divisor+1)"}, 
2861         {"setmux",              CmdSetMux
,              0, "<loraw|hiraw|lopkd|hipkd> -- Set the ADC mux to a specific value"}, 
2862         {"sri512read",          CmdSri512read
,          0, "<int> -- Read contents of a SRI512 tag"}, 
2863         {"srix4kread",          CmdSrix4kread
,          0, "<int> -- Read contents of a SRIX4K tag"}, 
2864         {"tidemod",             CmdTIDemod
,             1, "Demodulate raw bits for TI-type LF tag"}, 
2865         {"tiread",              CmdTIRead
,              0, "Read and decode a TI 134 kHz tag"}, 
2866         {"tiwrite",             CmdTIWrite
,             0, "Write new data to a r/w TI 134 kHz tag"}, 
2867         {"threshold",           CmdThreshold
,           1, "Maximize/minimize every value in the graph window depending on threshold"}, 
2868         {"tune",                CmdTune
,                0, "Measure antenna tuning"}, 
2869         {"vchdemod",            CmdVchdemod
,            0, "['clone'] -- Demodulate samples for VeriChip"}, 
2870         {"version",             CmdVersion
,             0, "Show version inforation about the connected Proxmark"}, 
2871         {"zerocrossings",       CmdZerocrossings
,       1, "Count time between zero-crossings"}, 
2879         }       CommandExtendedHelp
[]= { 
2880                 {"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."}, 
2881                 {"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."}, 
2884 //----------------------------------------------------------------------------- 
2885 // Entry point into our code: called whenever the user types a command and 
2886 // then presses Enter, which the full command line that they typed. 
2887 //----------------------------------------------------------------------------- 
2888 void CommandReceived(char *cmd
) 
2893         PrintToScrollback("> %s", cmd
); 
2895         if(strcmp(cmd
, "help") == 0 || strncmp(cmd
,"help ",strlen("help ")) == 0) { 
2896                 // check if we're doing extended help 
2897                 if(strlen(cmd
) > strlen("help ")) { 
2898                         cmd 
+= strlen("help "); 
2899                         for(i 
= 0; i 
< sizeof(CommandExtendedHelp
) / sizeof(CommandExtendedHelp
[0]); i
++) { 
2900                                 if(strcmp(CommandExtendedHelp
[i
].name
,cmd
) == 0) { 
2901                                         PrintToScrollback("\nExtended help for '%s':\n", cmd
); 
2902                                         PrintToScrollback("Args: %s\t- %s\n",CommandExtendedHelp
[i
].args
,CommandExtendedHelp
[i
].argshelp
); 
2903                                         PrintToScrollback(CommandExtendedHelp
[i
].description
); 
2904                                         PrintToScrollback(""); 
2908                 PrintToScrollback("No extended help available for '%s'", cmd
); 
2911                 if (offline
) PrintToScrollback("Operating in OFFLINE mode (no device connected)"); 
2912                 PrintToScrollback("\r\nAvailable commands:"); 
2913                 for(i 
= 0; i 
< sizeof(CommandTable
) / sizeof(CommandTable
[0]); i
++) { 
2914                         if (offline 
&& (CommandTable
[i
].offline
==0)) continue; 
2915                         memset(line
, ' ', sizeof(line
)); 
2916                         strcpy(line
+2, CommandTable
[i
].name
); 
2917                         line
[strlen(line
)] = ' '; 
2918                         sprintf(line
+15, " -- %s", CommandTable
[i
].docString
); 
2919                         PrintToScrollback("%s", line
); 
2921                 PrintToScrollback(""); 
2922                 PrintToScrollback("'help <command>' for extended help on that command\n"); 
2926         for(i 
= 0; i 
< sizeof(CommandTable
) / sizeof(CommandTable
[0]); i
++) { 
2927                 char *name 
= CommandTable
[i
].name
; 
2928                 if(memcmp(cmd
, name
, strlen(name
))==0 && 
2929                         (cmd
[strlen(name
)] == ' ' || cmd
[strlen(name
)] == '\0')) 
2931                         cmd 
+= strlen(name
); 
2932                         while(*cmd 
== ' ') { 
2935                         if (offline 
&& (CommandTable
[i
].offline
==0)) { 
2936                                 PrintToScrollback("Offline mode, cannot use this command."); 
2939                         (CommandTable
[i
].handler
)(cmd
); 
2943         PrintToScrollback(">> bad command '%s'", cmd
); 
2946 //----------------------------------------------------------------------------- 
2947 // Entry point into our code: called whenever we received a packet over USB 
2948 // that we weren't necessarily expecting, for example a debug print. 
2949 //----------------------------------------------------------------------------- 
2950 void UsbCommandReceived(UsbCommand 
*c
) 
2952 //      printf("%s(%x) current cmd = %x\n", __FUNCTION__, c->cmd, current_command); 
2953 /* If we recognize a response, return to avoid further processing */ 
2955                 case CMD_DEBUG_PRINT_STRING
: { 
2957                         if(c
->arg
[0] > 70 || c
->arg
[0] < 0) { 
2960                         memcpy(s
, c
->d
.asBytes
, c
->arg
[0]); 
2961                         s
[c
->arg
[0]] = '\0'; 
2962                         PrintToScrollback("#db# %s", s
); 
2966                 case CMD_DEBUG_PRINT_INTEGERS
: 
2967                         PrintToScrollback("#db# %08x, %08x, %08x\r\n", c
->arg
[0], c
->arg
[1], c
->arg
[2]); 
2970                 case CMD_MEASURED_ANTENNA_TUNING
: { 
2972                         int vLf125
, vLf134
, vHf
; 
2973                         vLf125 
= c
->arg
[0] & 0xffff; 
2974                         vLf134 
= c
->arg
[0] >> 16; 
2975                         vHf 
= c
->arg
[1] & 0xffff;; 
2976                         peakf 
= c
->arg
[2] & 0xffff; 
2977                         peakv 
= c
->arg
[2] >> 16; 
2978                         PrintToScrollback(""); 
2979                         PrintToScrollback(""); 
2980                         PrintToScrollback("# LF antenna: %5.2f V @   125.00 kHz", vLf125
/1000.0); 
2981                         PrintToScrollback("# LF antenna: %5.2f V @   134.00 kHz", vLf134
/1000.0); 
2982                         PrintToScrollback("# LF optimal: %5.2f V @%9.2f kHz", peakv
/1000.0, 12000.0/(peakf
+1)); 
2983                         PrintToScrollback("# HF antenna: %5.2f V @    13.56 MHz", vHf
/1000.0); 
2985                                 PrintToScrollback("# Your LF antenna is unusable."); 
2986                         else if (peakv
<10000) 
2987                                 PrintToScrollback("# Your LF antenna is marginal."); 
2989                                 PrintToScrollback("# Your HF antenna is unusable."); 
2991                                 PrintToScrollback("# Your HF antenna is marginal."); 
2997         /* Maybe it's a response: */ 
2998         switch(current_command
) { 
2999                 case CMD_DOWNLOAD_RAW_ADC_SAMPLES_125K
: 
3000                 if (c
->cmd 
!= CMD_DOWNLOADED_RAW_ADC_SAMPLES_125K
) goto unexpected_response
; 
3002                 for(i
=0; i
<48; i
++) sample_buf
[i
] = c
->d
.asBytes
[i
]; 
3003                 received_command 
= c
->cmd
; 
3006         unexpected_response
: 
3007                 PrintToScrollback("unrecognized command %08x\n", c
->cmd
);