1 //----------------------------------------------------------------------------- 
   2 // Copyright (C) 2010 iZsh <izsh at fail0verflow.com> 
   4 // This code is licensed to you under the terms of the GNU GPL, version 2 or, 
   5 // at your option, any later version. See the LICENSE.txt file for the text of 
   7 //----------------------------------------------------------------------------- 
   8 // Data and Graph commands 
   9 //----------------------------------------------------------------------------- 
  15 #include "proxmark3.h" 
  19 #include "cmdparser.h" 
  25 static int CmdHelp(const char *Cmd
); 
  27 int CmdAmp(const char *Cmd
) 
  29   int i
, rising
, falling
; 
  30   int max 
= INT_MIN
, min 
= INT_MAX
; 
  32   for (i 
= 10; i 
< GraphTraceLen
; ++i
) { 
  33     if (GraphBuffer
[i
] > max
) 
  35     if (GraphBuffer
[i
] < min
) 
  41     for (i 
= 0; i 
< GraphTraceLen
; ++i
) { 
  42       if (GraphBuffer
[i 
+ 1] < GraphBuffer
[i
]) { 
  49       if (GraphBuffer
[i 
+ 1] > GraphBuffer
[i
]) { 
  63  * Generic command to demodulate ASK. 
  65  * Argument is convention: positive or negative (High mod means zero 
  66  * or high mod means one) 
  68  * Updates the Graph trace with 0/1 values 
  73  //this method is dependant on all highs and lows to be the same(or clipped)  this creates issues[marshmellow] it also ignores the clock 
  74 int Cmdaskdemod(const char *Cmd
) 
  77   int c
, high 
= 0, low 
= 0; 
  79   sscanf(Cmd
, "%i", &c
); 
  81   /* Detect high and lows and clock */ 
  83   for (i 
= 0; i 
< GraphTraceLen
; ++i
) 
  85     if (GraphBuffer
[i
] > high
) 
  86       high 
= GraphBuffer
[i
]; 
  87     else if (GraphBuffer
[i
] < low
) 
  92   if (c 
!= 0 && c 
!= 1) { 
  93     PrintAndLog("Invalid argument: %s", Cmd
); 
  97   if (GraphBuffer
[0] > 0) { 
 102   for (i 
= 1; i 
< GraphTraceLen
; ++i
) { 
 103     /* Transitions are detected at each peak 
 104      * Transitions are either: 
 105      * - we're low: transition if we hit a high 
 106      * - we're high: transition if we hit a low 
 107      * (we need to do it this way because some tags keep high or 
 108      * low for long periods, others just reach the peak and go 
 111     if ((GraphBuffer
[i
] == high
) && (GraphBuffer
[i 
- 1] == c
)) { 
 112       GraphBuffer
[i
] = 1 - c
; 
 113     } else if ((GraphBuffer
[i
] == low
) && (GraphBuffer
[i 
- 1] == (1 - c
))){ 
 117       GraphBuffer
[i
] = GraphBuffer
[i 
- 1]; 
 120   RepaintGraphWindow(); 
 124 void printBitStream(uint8_t BitStream
[], uint32_t bitLen
){ 
 127     PrintAndLog("Too few bits found: %d",bitLen
); 
 130   if (bitLen
>512) bitLen
=512; 
 131    for (i 
= 0; i 
<= (bitLen
-16); i
+=16) { 
 132     PrintAndLog("%i%i%i%i%i%i%i%i%i%i%i%i%i%i%i%i", 
 152 void printEM410x(uint64_t id
) 
 156       uint64_t id2lo
=0; //id2hi=0, 
 159       for (ii
=5; ii
>0;ii
--){ 
 161           id2lo
=(id2lo
<<1LL)|((id 
& (iii
<<(i
+((ii
-1)*8))))>>(i
+((ii
-1)*8))); 
 165       PrintAndLog("EM TAG ID    : %010llx", id
); 
 166       PrintAndLog("Unique TAG ID: %010llx",  id2lo
); //id2hi, 
 167       PrintAndLog("DEZ 8        : %08lld",id 
& 0xFFFFFF); 
 168       PrintAndLog("DEZ 10       : %010lld",id 
& 0xFFFFFF); 
 169       PrintAndLog("DEZ 5.5      : %05lld.%05lld",(id
>>16LL) & 0xFFFF,(id 
& 0xFFFF)); 
 170       PrintAndLog("DEZ 3.5A     : %03lld.%05lld",(id
>>32ll),(id 
& 0xFFFF)); 
 171       PrintAndLog("DEZ 14/IK2   : %014lld",id
); 
 172       PrintAndLog("DEZ 15/IK3   : %015lld",id2lo
); 
 173       PrintAndLog("Other        : %05lld_%03lld_%08lld",(id
&0xFFFF),((id
>>16LL) & 0xFF),(id 
& 0xFFFFFF)); 
 178 int CmdEm410xDecode(const char *Cmd
) 
 181   uint8_t BitStream
[MAX_GRAPH_TRACE_LEN
]={0}; 
 183   i
=getFromGraphBuf(BitStream
); 
 184   id 
= Em410xDecode(BitStream
,i
); 
 191 //takes 2 arguments - clock and invert both as integers  
 192 //attempts to demodulate ask while decoding manchester  
 193 //prints binary found and saves in graphbuffer for further commands 
 194 int Cmdaskmandemod(const char *Cmd
) 
 198   uint8_t BitStream
[MAX_GRAPH_TRACE_LEN
]={0}; 
 199   sscanf(Cmd
, "%i %i", &clk
, &invert
);     
 200   if (invert 
!= 0 && invert 
!= 1) { 
 201     PrintAndLog("Invalid argument: %s", Cmd
); 
 204   uint32_t BitLen 
= getFromGraphBuf(BitStream
); 
 207    errCnt 
= askmandemod(BitStream
, &BitLen
,&clk
,&invert
); 
 208   if (errCnt
<0){  //if fatal error (or -1) 
 209     // PrintAndLog("no data found %d, errors:%d, bitlen:%d, clock:%d",errCnt,invert,BitLen,clk);  
 212   if (BitLen
<16) return 0; 
 213   PrintAndLog("\nUsing Clock: %d - Invert: %d - Bits Found: %d",clk
,invert
,BitLen
); 
 216     PrintAndLog("# Errors during Demoding (shown as 77 in bit stream): %d",errCnt
); 
 218   PrintAndLog("ASK/Manchester decoded bitstream:"); 
 219   // Now output the bitstream to the scrollback by line of 16 bits 
 220   printBitStream(BitStream
,BitLen
); 
 222   lo 
= Em410xDecode(BitStream
,BitLen
); 
 224     //set GraphBuffer for clone or sim command 
 225     setGraphBuf(BitStream
,BitLen
);  
 226     PrintAndLog("EM410x pattern found: "); 
 229   if (BitLen
>16) return 1; 
 235 //stricktly take 10 and 01 and convert to 0 and 1 
 236 int Cmdmandecoderaw(const char *Cmd
) 
 241   uint8_t BitStream
[MAX_GRAPH_TRACE_LEN
]={0}; 
 242   int high 
= 0, low 
= 0; 
 243   for (;i
<GraphTraceLen
;++i
){ 
 244     if (GraphBuffer
[i
]>high
) high
=GraphBuffer
[i
]; 
 245     else if(GraphBuffer
[i
]<low
) low
=GraphBuffer
[i
]; 
 246     BitStream
[i
]=GraphBuffer
[i
]; 
 248   if (high
>1 || low 
<0 ){ 
 249     PrintAndLog("Error: please raw demod the wave first then mancheseter raw decode"); 
 253   errCnt
=manrawdecode(BitStream
,&bitnum
); 
 255     PrintAndLog("Too many errors: %d",errCnt
); 
 258   PrintAndLog("Manchester Decoded - # errors:%d - data:",errCnt
); 
 259   printBitStream(BitStream
,bitnum
); 
 261     //put back in graphbuffer 
 263     for (i
=0; i 
< bitnum
; ++i
){ 
 264       GraphBuffer
[i
]=BitStream
[i
]; 
 266     GraphTraceLen
=bitnum
; 
 267     RepaintGraphWindow(); 
 269     id 
= Em410xDecode(BitStream
,i
); 
 277 //take 01 or 10 = 0 and 11 or 00 = 1 
 278 //takes 1 argument "offset" default = 0 if 1 it will shift the decode by one bit 
 279 //  since it is not like manchester and doesn't have an incorrect bit pattern we  
 280 //  cannot determine if our decode is correct or if it should be shifted by one bit 
 281 //  the argument offset allows us to manually shift if the output is incorrect 
 282 //  (better would be to demod and decode at the same time so we can distinguish large 
 283 //    width waves vs small width waves to help the decode positioning) or askbiphdemod 
 284 int CmdBiphaseDecodeRaw(const char *Cmd
) 
 291   sscanf(Cmd
, "%i", &offset
);     
 292   uint8_t BitStream
[MAX_GRAPH_TRACE_LEN
]={0}; 
 293   //get graphbuffer & high and low 
 294   for (;i
<GraphTraceLen
;++i
){ 
 295     if(GraphBuffer
[i
]>high
)high
=GraphBuffer
[i
]; 
 296     else if(GraphBuffer
[i
]<low
)low
=GraphBuffer
[i
]; 
 297     BitStream
[i
]=GraphBuffer
[i
]; 
 299   if (high
>1 || low 
<0){ 
 300     PrintAndLog("Error: please raw demod the wave first then decode"); 
 304   errCnt
=BiphaseRawDecode(BitStream
,&bitnum
, offset
); 
 306     PrintAndLog("Too many errors attempting to decode: %d",errCnt
); 
 309   PrintAndLog("Biphase Decoded using offset: %d - # errors:%d - data:",offset
,errCnt
); 
 310   printBitStream(BitStream
,bitnum
); 
 311   PrintAndLog("\nif bitstream does not look right try offset=1"); 
 317 //takes 2 arguments - clock and invert both as integers 
 318 //attempts to demodulate ask only 
 319 //prints binary found and saves in graphbuffer for further commands 
 320 int Cmdaskrawdemod(const char *Cmd
) 
 325   uint8_t BitStream
[MAX_GRAPH_TRACE_LEN
]={0}; 
 326   sscanf(Cmd
, "%i %i", &clk
, &invert
);     
 327   if (invert 
!= 0 && invert 
!= 1) { 
 328     PrintAndLog("Invalid argument: %s", Cmd
); 
 331   int BitLen 
= getFromGraphBuf(BitStream
); 
 333   errCnt 
= askrawdemod(BitStream
, &BitLen
,&clk
,&invert
); 
 334   if (errCnt
==-1){  //throw away static - allow 1 and -1 (in case of threshold command first) 
 335     PrintAndLog("no data found");  
 338   if (BitLen
<16) return 0; 
 339   PrintAndLog("Using Clock: %d - invert: %d - Bits Found: %d",clk
,invert
,BitLen
); 
 340     //PrintAndLog("Data start pos:%d, lastBit:%d, stop pos:%d, numBits:%d",iii,lastBit,i,bitnum); 
 341     //move BitStream back to GraphBuffer 
 344   for (i
=0; i 
< BitLen
; ++i
){ 
 345     GraphBuffer
[i
]=BitStream
[i
]; 
 347   GraphTraceLen
=BitLen
; 
 348   RepaintGraphWindow(); 
 352       PrintAndLog("# Errors during Demoding (shown as 77 in bit stream): %d",errCnt
); 
 354   PrintAndLog("ASK demoded bitstream:"); 
 355     // Now output the bitstream to the scrollback by line of 16 bits 
 356   printBitStream(BitStream
,BitLen
); 
 361 int CmdAutoCorr(const char *Cmd
) 
 363   static int CorrelBuffer
[MAX_GRAPH_TRACE_LEN
]; 
 365   int window 
= atoi(Cmd
); 
 368     PrintAndLog("needs a window"); 
 371   if (window 
>= GraphTraceLen
) { 
 372     PrintAndLog("window must be smaller than trace (%d samples)", 
 377   PrintAndLog("performing %d correlations", GraphTraceLen 
- window
); 
 379   for (int i 
= 0; i 
< GraphTraceLen 
- window
; ++i
) { 
 381     for (int j 
= 0; j 
< window
; ++j
) { 
 382       sum 
+= (GraphBuffer
[j
]*GraphBuffer
[i 
+ j
]) / 256; 
 384     CorrelBuffer
[i
] = sum
; 
 386   GraphTraceLen 
= GraphTraceLen 
- window
; 
 387   memcpy(GraphBuffer
, CorrelBuffer
, GraphTraceLen 
* sizeof (int)); 
 389   RepaintGraphWindow(); 
 393 int CmdBitsamples(const char *Cmd
) 
 398   GetFromBigBuf(got
,sizeof(got
),0); 
 399   WaitForResponse(CMD_ACK
,NULL
); 
 401     for (int j 
= 0; j 
< sizeof(got
); j
++) { 
 402       for (int k 
= 0; k 
< 8; k
++) { 
 403         if(got
[j
] & (1 << (7 - k
))) { 
 404           GraphBuffer
[cnt
++] = 1; 
 406           GraphBuffer
[cnt
++] = 0; 
 411   RepaintGraphWindow(); 
 416  * Convert to a bitstream 
 418 int CmdBitstream(const char *Cmd
) 
 426   int hithigh
, hitlow
, first
; 
 428   /* Detect high and lows and clock */ 
 429   for (i 
= 0; i 
< GraphTraceLen
; ++i
) 
 431     if (GraphBuffer
[i
] > high
) 
 432       high 
= GraphBuffer
[i
]; 
 433     else if (GraphBuffer
[i
] < low
) 
 434       low 
= GraphBuffer
[i
]; 
 438   clock 
= GetClock(Cmd
, high
, 1); 
 442   for (i 
= 0; i 
< (int)(gtl 
/ clock
); ++i
) 
 447     /* Find out if we hit both high and low peaks */ 
 448     for (j 
= 0; j 
< clock
; ++j
) 
 450       if (GraphBuffer
[(i 
* clock
) + j
] == high
) 
 452       else if (GraphBuffer
[(i 
* clock
) + j
] == low
) 
 454       /* it doesn't count if it's the first part of our read 
 455          because it's really just trailing from the last sequence */ 
 456       if (first 
&& (hithigh 
|| hitlow
)) 
 457         hithigh 
= hitlow 
= 0; 
 461       if (hithigh 
&& hitlow
) 
 465     /* If we didn't hit both high and low peaks, we had a bit transition */ 
 466     if (!hithigh 
|| !hitlow
) 
 469     AppendGraph(0, clock
, bit
); 
 470 //    for (j = 0; j < (int)(clock/2); j++) 
 471 //      GraphBuffer[(i * clock) + j] = bit ^ 1; 
 472 //    for (j = (int)(clock/2); j < clock; j++) 
 473 //      GraphBuffer[(i * clock) + j] = bit; 
 476   RepaintGraphWindow(); 
 480 int CmdBuffClear(const char *Cmd
) 
 482   UsbCommand c 
= {CMD_BUFF_CLEAR
}; 
 488 int CmdDec(const char *Cmd
) 
 490   for (int i 
= 0; i 
< (GraphTraceLen 
/ 2); ++i
) 
 491     GraphBuffer
[i
] = GraphBuffer
[i 
* 2]; 
 493   PrintAndLog("decimated by 2"); 
 494   RepaintGraphWindow(); 
 498 /* Print our clock rate */ 
 499 // uses data from graphbuffer  
 500 int CmdDetectClockRate(const char *Cmd
) 
 507 //fsk raw demod and print binary 
 508 //takes 4 arguments - Clock, invert, rchigh, rclow 
 509 //defaults: clock = 50, invert=0, rchigh=10, rclow=8 (RF/10 RF/8 (fsk2a)) 
 510 int CmdFSKrawdemod(const char *Cmd
) 
 512   //raw fsk demod no manchester decoding no start bit finding just get binary from wave 
 518   //set options from parameters entered with the command 
 519   sscanf(Cmd
, "%i %i %i %i", &rfLen
, &invert
, &fchigh
, &fclow
);     
 521   if (strlen(Cmd
)>0 && strlen(Cmd
)<=2) { 
 522      //rfLen=param_get8(Cmd, 0); //if rfLen option only is used 
 524       invert
=1;   //if invert option only is used 
 526      } else if(rfLen
==0) rfLen
=50; 
 528   PrintAndLog("Args invert: %d - Clock:%d - fchigh:%d - fclow: %d",invert
,rfLen
,fchigh
, fclow
); 
 530   uint8_t BitStream
[MAX_GRAPH_TRACE_LEN
]={0}; 
 531   uint32_t BitLen 
= getFromGraphBuf(BitStream
); 
 532   int size  
= fskdemod(BitStream
,BitLen
,(uint8_t)rfLen
,(uint8_t)invert
,(uint8_t)fchigh
,(uint8_t)fclow
);  
 534   PrintAndLog("FSK decoded bitstream:"); 
 536   for (i
=0;i
<size
;++i
){ 
 537     GraphBuffer
[i
]=BitStream
[i
]; 
 540   RepaintGraphWindow(); 
 542   // Now output the bitstream to the scrollback by line of 16 bits 
 543   if(size 
> (8*32)+2) size 
= (8*32)+2; //only output a max of 8 blocks of 32 bits  most tags will have full bit stream inside that sample size 
 544   printBitStream(BitStream
,size
); 
 546     PrintAndLog("no FSK data found"); 
 551 //by marshmellow (based on existing demod + holiman's refactor) 
 552 //HID Prox demod - FSK RF/50 with preamble of 00011101 (then manchester encoded) 
 553 //print full HID Prox ID and some bit format details if found 
 554 int CmdFSKdemodHID(const char *Cmd
) 
 556   //raw fsk demod no manchester decoding no start bit finding just get binary from wave 
 557   uint32_t hi2
=0, hi
=0, lo
=0; 
 559   uint8_t BitStream
[MAX_GRAPH_TRACE_LEN
]={0}; 
 560   uint32_t BitLen 
= getFromGraphBuf(BitStream
); 
 561   //get binary from fsk wave 
 562   size_t size  
= HIDdemodFSK(BitStream
,BitLen
,&hi2
,&hi
,&lo
);  
 564     PrintAndLog("Error demoding fsk"); 
 567   if (hi2
==0 && hi
==0 && lo
==0) return 0; 
 568           if (hi2 
!= 0){ //extra large HID tags 
 569             PrintAndLog("TAG ID: %x%08x%08x (%d)", 
 570                (unsigned int) hi2
, (unsigned int) hi
, (unsigned int) lo
, (unsigned int) (lo
>>1) & 0xFFFF); 
 571     setGraphBuf(BitStream
,BitLen
); 
 574           else {  //standard HID tags <38 bits 
 575             //Dbprintf("TAG ID: %x%08x (%d)",(unsigned int) hi, (unsigned int) lo, (unsigned int) (lo>>1) & 0xFFFF); //old print cmd 
 578             uint32_t cardnum 
= 0; 
 579             if (((hi
>>5)&1)==1){//if bit 38 is set then < 37 bit format is used 
 581               lo2
=(((hi 
& 15) << 12) | (lo
>>20)); //get bits 21-37 to check for format len bit 
 583               while(lo2
>1){ //find last bit set to 1 (format len bit) 
 591                 cardnum 
= (lo
>>1)&0xFFFF; 
 595                 cardnum 
= (lo
>>1)&0x7FFFF; 
 596                 fc 
= ((hi
&0xF)<<12)|(lo
>>20); 
 599                 cardnum 
= (lo
>>1)&0xFFFF; 
 600                 fc
= ((hi
&1)<<15)|(lo
>>17); 
 603                 cardnum 
= (lo
>>1)&0xFFFFF; 
 604                 fc 
= ((hi
&1)<<11)|(lo
>>21); 
 607             else { //if bit 38 is not set then 37 bit format is used 
 612                 cardnum 
= (lo
>>1)&0x7FFFF; 
 613                 fc 
= ((hi
&0xF)<<12)|(lo
>>20); 
 616             PrintAndLog("TAG ID: %x%08x (%d) - Format Len: %dbit - FC: %d - Card: %d", 
 617               (unsigned int) hi
, (unsigned int) lo
, (unsigned int) (lo
>>1) & 0xFFFF, 
 618       (unsigned int) fmtLen
, (unsigned int) fc
, (unsigned int) cardnum
); 
 619     setGraphBuf(BitStream
,BitLen
); 
 626 //IO-Prox demod - FSK RF/64 with preamble of 000000001 
 627 //print ioprox ID and some format details 
 628 int CmdFSKdemodIO(const char *Cmd
) 
 630   //raw fsk demod no manchester decoding no start bit finding just get binary from wave 
 633   //something in graphbuffer 
 634   if (GraphTraceLen 
< 65) return 0; 
 635   uint8_t BitStream
[MAX_GRAPH_TRACE_LEN
]={0}; 
 636   uint32_t BitLen 
= getFromGraphBuf(BitStream
); 
 637   //get binary from fsk wave 
 638   idx 
= IOdemodFSK(BitStream
,BitLen
);  
 640     //PrintAndLog("Error demoding fsk"); 
 644     //PrintAndLog("IO Prox Data not found - FSK Data:"); 
 645     //if (BitLen > 92) printBitStream(BitStream,92); 
 649     //0           10          20          30          40          50          60 
 651     //01234567 8 90123456 7 89012345 6 78901234 5 67890123 4 56789012 3 45678901 23 
 652     //----------------------------------------------------------------------------- 
 653     //00000000 0 11110000 1 facility 1 version* 1 code*one 1 code*two 1 ???????? 11 
 655     //XSF(version)facility:codeone+codetwo (raw) 
 657   if (idx
+64>BitLen
) return 0; 
 658   PrintAndLog("%d%d%d%d%d%d%d%d %d",BitStream
[idx
],    BitStream
[idx
+1],  BitStream
[idx
+2], BitStream
[idx
+3], BitStream
[idx
+4], BitStream
[idx
+5], BitStream
[idx
+6], BitStream
[idx
+7], BitStream
[idx
+8]); 
 659   PrintAndLog("%d%d%d%d%d%d%d%d %d",BitStream
[idx
+9],  BitStream
[idx
+10], BitStream
[idx
+11],BitStream
[idx
+12],BitStream
[idx
+13],BitStream
[idx
+14],BitStream
[idx
+15],BitStream
[idx
+16],BitStream
[idx
+17]);        
 660   PrintAndLog("%d%d%d%d%d%d%d%d %d facility",BitStream
[idx
+18], BitStream
[idx
+19], BitStream
[idx
+20],BitStream
[idx
+21],BitStream
[idx
+22],BitStream
[idx
+23],BitStream
[idx
+24],BitStream
[idx
+25],BitStream
[idx
+26]); 
 661   PrintAndLog("%d%d%d%d%d%d%d%d %d version",BitStream
[idx
+27], BitStream
[idx
+28], BitStream
[idx
+29],BitStream
[idx
+30],BitStream
[idx
+31],BitStream
[idx
+32],BitStream
[idx
+33],BitStream
[idx
+34],BitStream
[idx
+35]); 
 662   PrintAndLog("%d%d%d%d%d%d%d%d %d code1",BitStream
[idx
+36], BitStream
[idx
+37], BitStream
[idx
+38],BitStream
[idx
+39],BitStream
[idx
+40],BitStream
[idx
+41],BitStream
[idx
+42],BitStream
[idx
+43],BitStream
[idx
+44]); 
 663   PrintAndLog("%d%d%d%d%d%d%d%d %d code2",BitStream
[idx
+45], BitStream
[idx
+46], BitStream
[idx
+47],BitStream
[idx
+48],BitStream
[idx
+49],BitStream
[idx
+50],BitStream
[idx
+51],BitStream
[idx
+52],BitStream
[idx
+53]); 
 664   PrintAndLog("%d%d%d%d%d%d%d%d %d%d checksum",BitStream
[idx
+54],BitStream
[idx
+55],BitStream
[idx
+56],BitStream
[idx
+57],BitStream
[idx
+58],BitStream
[idx
+59],BitStream
[idx
+60],BitStream
[idx
+61],BitStream
[idx
+62],BitStream
[idx
+63]); 
 666   uint32_t code 
= bytebits_to_byte(BitStream
+idx
,32); 
 667   uint32_t code2 
= bytebits_to_byte(BitStream
+idx
+32,32);  
 668   uint8_t version 
= bytebits_to_byte(BitStream
+idx
+27,8); //14,4 
 669   uint8_t facilitycode 
= bytebits_to_byte(BitStream
+idx
+18,8) ; 
 670   uint16_t number 
= (bytebits_to_byte(BitStream
+idx
+36,8)<<8)|(bytebits_to_byte(BitStream
+idx
+45,8)); //36,9 
 672   PrintAndLog("XSF(%02d)%02x:%05d (%08x%08x)",version
,facilitycode
,number
,code
,code2
);     
 673   setGraphBuf(BitStream
,BitLen
); 
 677 int CmdFSKdemod(const char *Cmd
) //old CmdFSKdemod needs updating 
 679   static const int LowTone
[]  = { 
 680     1,  1,  1,  1,  1, -1, -1, -1, -1, -1, 
 681     1,  1,  1,  1,  1, -1, -1, -1, -1, -1, 
 682     1,  1,  1,  1,  1, -1, -1, -1, -1, -1, 
 683     1,  1,  1,  1,  1, -1, -1, -1, -1, -1, 
 684     1,  1,  1,  1,  1, -1, -1, -1, -1, -1 
 686   static const int HighTone
[] = { 
 687     1,  1,  1,  1,  1,     -1, -1, -1, -1, 
 688     1,  1,  1,  1,         -1, -1, -1, -1, 
 689     1,  1,  1,  1,         -1, -1, -1, -1, 
 690     1,  1,  1,  1,         -1, -1, -1, -1, 
 691     1,  1,  1,  1,         -1, -1, -1, -1, 
 692     1,  1,  1,  1,     -1, -1, -1, -1, -1, 
 695   int lowLen 
= sizeof (LowTone
) / sizeof (int); 
 696   int highLen 
= sizeof (HighTone
) / sizeof (int); 
 697   int convLen 
= (highLen 
> lowLen
) ? highLen 
: lowLen
; 
 698   uint32_t hi 
= 0, lo 
= 0; 
 701   int minMark 
= 0, maxMark 
= 0; 
 703   for (i 
= 0; i 
< GraphTraceLen 
- convLen
; ++i
) { 
 704     int lowSum 
= 0, highSum 
= 0; 
 706     for (j 
= 0; j 
< lowLen
; ++j
) { 
 707       lowSum 
+= LowTone
[j
]*GraphBuffer
[i
+j
]; 
 709     for (j 
= 0; j 
< highLen
; ++j
) { 
 710       highSum 
+= HighTone
[j
] * GraphBuffer
[i 
+ j
]; 
 712     lowSum 
= abs(100 * lowSum 
/ lowLen
); 
 713     highSum 
= abs(100 * highSum 
/ highLen
); 
 714     GraphBuffer
[i
] = (highSum 
<< 16) | lowSum
; 
 717   for(i 
= 0; i 
< GraphTraceLen 
- convLen 
- 16; ++i
) { 
 718     int lowTot 
= 0, highTot 
= 0; 
 719     // 10 and 8 are f_s divided by f_l and f_h, rounded 
 720     for (j 
= 0; j 
< 10; ++j
) { 
 721       lowTot 
+= (GraphBuffer
[i
+j
] & 0xffff); 
 723     for (j 
= 0; j 
< 8; j
++) { 
 724       highTot 
+= (GraphBuffer
[i 
+ j
] >> 16); 
 726     GraphBuffer
[i
] = lowTot 
- highTot
; 
 727     if (GraphBuffer
[i
] > maxMark
) maxMark 
= GraphBuffer
[i
]; 
 728     if (GraphBuffer
[i
] < minMark
) minMark 
= GraphBuffer
[i
]; 
 731   GraphTraceLen 
-= (convLen 
+ 16); 
 732   RepaintGraphWindow(); 
 734   // Find bit-sync (3 lo followed by 3 high) (HID ONLY) 
 735   int max 
= 0, maxPos 
= 0; 
 736   for (i 
= 0; i 
< 6000; ++i
) { 
 738     for (j 
= 0; j 
< 3 * lowLen
; ++j
) { 
 739       dec 
-= GraphBuffer
[i 
+ j
]; 
 741     for (; j 
< 3 * (lowLen 
+ highLen 
); ++j
) { 
 742       dec 
+= GraphBuffer
[i 
+ j
]; 
 750   // place start of bit sync marker in graph 
 751   GraphBuffer
[maxPos
] = maxMark
; 
 752   GraphBuffer
[maxPos 
+ 1] = minMark
; 
 756   // place end of bit sync marker in graph 
 757   GraphBuffer
[maxPos
] = maxMark
; 
 758   GraphBuffer
[maxPos
+1] = minMark
; 
 760   PrintAndLog("actual data bits start at sample %d", maxPos
); 
 761   PrintAndLog("length %d/%d", highLen
, lowLen
); 
 764   bits
[sizeof(bits
)-1] = '\0'; 
 766   // find bit pairs and manchester decode them 
 767   for (i 
= 0; i 
< arraylen(bits
) - 1; ++i
) { 
 769     for (j 
= 0; j 
< lowLen
; ++j
) { 
 770       dec 
-= GraphBuffer
[maxPos 
+ j
]; 
 772     for (; j 
< lowLen 
+ highLen
; ++j
) { 
 773       dec 
+= GraphBuffer
[maxPos 
+ j
]; 
 776     // place inter bit marker in graph 
 777     GraphBuffer
[maxPos
] = maxMark
; 
 778     GraphBuffer
[maxPos 
+ 1] = minMark
; 
 780     // hi and lo form a 64 bit pair 
 781     hi 
= (hi 
<< 1) | (lo 
>> 31); 
 783     // store decoded bit as binary (in hi/lo) and text (in bits[]) 
 791   PrintAndLog("bits: '%s'", bits
); 
 792   PrintAndLog("hex: %08x %08x", hi
, lo
); 
 796 int CmdGrid(const char *Cmd
) 
 798   sscanf(Cmd
, "%i %i", &PlotGridX
, &PlotGridY
); 
 799   PlotGridXdefault
= PlotGridX
; 
 800   PlotGridYdefault
= PlotGridY
; 
 801   RepaintGraphWindow(); 
 805 int CmdHexsamples(const char *Cmd
) 
 811   char* string_ptr 
= string_buf
; 
 814   sscanf(Cmd
, "%i %i", &requested
, &offset
); 
 816   /* if no args send something */ 
 817   if (requested 
== 0) { 
 820   if (offset 
+ requested 
> sizeof(got
)) { 
 821     PrintAndLog("Tried to read past end of buffer, <bytes> + <offset> > 40000"); 
 825   GetFromBigBuf(got
,requested
,offset
); 
 826   WaitForResponse(CMD_ACK
,NULL
); 
 829   for (j 
= 0; j 
< requested
; j
++) { 
 831     string_ptr 
+= sprintf(string_ptr
, "%02x ", got
[j
]); 
 833       *(string_ptr 
- 1) = '\0';    // remove the trailing space 
 834       PrintAndLog("%s", string_buf
); 
 835       string_buf
[0] = '\0'; 
 836       string_ptr 
= string_buf
; 
 839     if (j 
== requested 
- 1 && string_buf
[0] != '\0') { // print any remaining bytes 
 840       *(string_ptr 
- 1) = '\0'; 
 841       PrintAndLog("%s", string_buf
); 
 842       string_buf
[0] = '\0'; 
 848 int CmdHide(const char *Cmd
) 
 854 int CmdHpf(const char *Cmd
) 
 859   for (i 
= 10; i 
< GraphTraceLen
; ++i
) 
 860     accum 
+= GraphBuffer
[i
]; 
 861   accum 
/= (GraphTraceLen 
- 10); 
 862   for (i 
= 0; i 
< GraphTraceLen
; ++i
) 
 863     GraphBuffer
[i
] -= accum
; 
 865   RepaintGraphWindow(); 
 869 int CmdSamples(const char *Cmd
) 
 871         uint8_t got
[36440] = {0x00}; 
 873         int n 
= strtol(Cmd
, NULL
, 0); 
 879         PrintAndLog("Reading %d samples from device memory\n", n
); 
 880         GetFromBigBuf(got
,n
,3560); 
 881         WaitForResponse(CMD_ACK
,NULL
); 
 882         for (int j 
= 0; j 
< n
; ++j
) { 
 883                 GraphBuffer
[j
] = ((int)got
[j
]) - 128; 
 886         RepaintGraphWindow(); 
 890 int CmdTuneSamples(const char *Cmd
) 
 893         printf("\nMeasuring antenna characteristics, please wait..."); 
 895         UsbCommand c 
= {CMD_MEASURE_ANTENNA_TUNING
}; 
 899         while(!WaitForResponseTimeout(CMD_MEASURED_ANTENNA_TUNING
,&resp
,1000)) { 
 903                         PrintAndLog("\nNo response from Proxmark. Aborting..."); 
 909         int vLf125
, vLf134
, vHf
; 
 910         vLf125 
= resp
.arg
[0] & 0xffff; 
 911         vLf134 
= resp
.arg
[0] >> 16; 
 912         vHf 
= resp
.arg
[1] & 0xffff;; 
 913         peakf 
= resp
.arg
[2] & 0xffff; 
 914         peakv 
= resp
.arg
[2] >> 16; 
 916         PrintAndLog("# LF antenna: %5.2f V @   125.00 kHz", vLf125
/1000.0); 
 917         PrintAndLog("# LF antenna: %5.2f V @   134.00 kHz", vLf134
/1000.0); 
 918         PrintAndLog("# LF optimal: %5.2f V @%9.2f kHz", peakv
/1000.0, 12000.0/(peakf
+1)); 
 919         PrintAndLog("# HF antenna: %5.2f V @    13.56 MHz", vHf
/1000.0); 
 921                 PrintAndLog("# Your LF antenna is unusable."); 
 922         else if (peakv
<10000) 
 923                 PrintAndLog("# Your LF antenna is marginal."); 
 925                 PrintAndLog("# Your HF antenna is unusable."); 
 927                 PrintAndLog("# Your HF antenna is marginal."); 
 929         for (int i 
= 0; i 
< 256; i
++) { 
 930                 GraphBuffer
[i
] = resp
.d
.asBytes
[i
] - 128; 
 933         PrintAndLog("Done! Divisor 89 is 134khz, 95 is 125khz.\n"); 
 941 int CmdLoad(const char *Cmd
) 
 943    char filename
[FILE_PATH_SIZE
] = {0x00}; 
 947    if (len 
> FILE_PATH_SIZE
) len 
= FILE_PATH_SIZE
; 
 948    memcpy(filename
, Cmd
, len
); 
 950    FILE *f 
= fopen(filename
, "r"); 
 952      PrintAndLog("couldn't open '%s'", filename
); 
 958   while (fgets(line
, sizeof (line
), f
)) { 
 959     GraphBuffer
[GraphTraceLen
] = atoi(line
); 
 963   PrintAndLog("loaded %d samples", GraphTraceLen
); 
 964   RepaintGraphWindow(); 
 968 int CmdLtrim(const char *Cmd
) 
 972   for (int i 
= ds
; i 
< GraphTraceLen
; ++i
) 
 973     GraphBuffer
[i
-ds
] = GraphBuffer
[i
]; 
 976   RepaintGraphWindow(); 
 981  * Manchester demodulate a bitstream. The bitstream needs to be already in 
 982  * the GraphBuffer as 0 and 1 values 
 984  * Give the clock rate as argument in order to help the sync - the algorithm 
 985  * resyncs at each pulse anyway. 
 987  * Not optimized by any means, this is the 1st time I'm writing this type of 
 988  * routine, feel free to improve... 
 990  * 1st argument: clock rate (as number of samples per clock rate) 
 991  *               Typical values can be 64, 32, 128... 
 993 int CmdManchesterDemod(const char *Cmd
) 
1001   int hithigh
, hitlow
, first
; 
1007   /* check if we're inverting output */ 
1010     PrintAndLog("Inverting output"); 
1015     while(*Cmd 
== ' '); // in case a 2nd argument was given 
1018   /* Holds the decoded bitstream: each clock period contains 2 bits       */ 
1019   /* later simplified to 1 bit after manchester decoding.                 */ 
1020   /* Add 10 bits to allow for noisy / uncertain traces without aborting   */ 
1021   /* int BitStream[GraphTraceLen*2/clock+10]; */ 
1023   /* But it does not work if compiling on WIndows: therefore we just allocate a */ 
1025   uint8_t BitStream
[MAX_GRAPH_TRACE_LEN
] = {0x00}; 
1027   /* Detect high and lows */ 
1028   for (i 
= 0; i 
< GraphTraceLen
; i
++) 
1030     if (GraphBuffer
[i
] > high
) 
1031       high 
= GraphBuffer
[i
]; 
1032     else if (GraphBuffer
[i
] < low
) 
1033       low 
= GraphBuffer
[i
]; 
1037   clock 
= GetClock(Cmd
, high
, 1);  
1038   int tolerance 
= clock
/4; 
1040   /* Detect first transition */ 
1041   /* Lo-Hi (arbitrary)       */ 
1042   /* skip to the first high */ 
1043   for (i
= 0; i 
< GraphTraceLen
; i
++) 
1044     if (GraphBuffer
[i
] == high
) 
1046   /* now look for the first low */ 
1047   for (; i 
< GraphTraceLen
; i
++) 
1049     if (GraphBuffer
[i
] == low
) 
1056   /* If we're not working with 1/0s, demod based off clock */ 
1059     bit 
= 0; /* We assume the 1st bit is zero, it may not be 
1060               * the case: this routine (I think) has an init problem. 
1063     for (; i 
< (int)(GraphTraceLen 
/ clock
); i
++) 
1069       /* Find out if we hit both high and low peaks */ 
1070       for (j 
= 0; j 
< clock
; j
++) 
1072         if (GraphBuffer
[(i 
* clock
) + j
] == high
) 
1074         else if (GraphBuffer
[(i 
* clock
) + j
] == low
) 
1077         /* it doesn't count if it's the first part of our read 
1078            because it's really just trailing from the last sequence */ 
1079         if (first 
&& (hithigh 
|| hitlow
)) 
1080           hithigh 
= hitlow 
= 0; 
1084         if (hithigh 
&& hitlow
) 
1088       /* If we didn't hit both high and low peaks, we had a bit transition */ 
1089       if (!hithigh 
|| !hitlow
) 
1092       BitStream
[bit2idx
++] = bit 
^ invert
; 
1096   /* standard 1/0 bitstream */ 
1100     /* Then detect duration between 2 successive transitions */ 
1101     for (bitidx 
= 1; i 
< GraphTraceLen
; i
++) 
1103       if (GraphBuffer
[i
-1] != GraphBuffer
[i
]) 
1108       // Error check: if bitidx becomes too large, we do not 
1109       // have a Manchester encoded bitstream or the clock is really 
1111       if (bitidx 
> (GraphTraceLen
*2/clock
+8) ) { 
1112         PrintAndLog("Error: the clock you gave is probably wrong, aborting."); 
1115       // Then switch depending on lc length: 
1116       // Tolerance is 1/4 of clock rate (arbitrary) 
1117       if (abs(lc
-clock
/2) < tolerance
) { 
1118         // Short pulse : either "1" or "0" 
1119         BitStream
[bitidx
++]=GraphBuffer
[i
-1]; 
1120       } else if (abs(lc
-clock
) < tolerance
) { 
1121         // Long pulse: either "11" or "00" 
1122         BitStream
[bitidx
++]=GraphBuffer
[i
-1]; 
1123         BitStream
[bitidx
++]=GraphBuffer
[i
-1]; 
1127         PrintAndLog("Warning: Manchester decode error for pulse width detection."); 
1128         PrintAndLog("(too many of those messages mean either the stream is not Manchester encoded, or clock is wrong)"); 
1132             PrintAndLog("Error: too many detection errors, aborting."); 
1139     // At this stage, we now have a bitstream of "01" ("1") or "10" ("0"), parse it into final decoded bitstream 
1140     // Actually, we overwrite BitStream with the new decoded bitstream, we just need to be careful 
1141     // to stop output at the final bitidx2 value, not bitidx 
1143         //http://www.proxmark.org/forum/viewtopic.php?id=403 
1144     for (i 
= 1; i 
< bitidx
; i 
+= 2) { 
1145       if ((BitStream
[i
] == 0) && (BitStream
[i
+1] == 1)) { 
1146         BitStream
[bit2idx
++] = 1 ^ invert
; 
1147     } else if ((BitStream
[i
] == 1) && (BitStream
[i
+1] == 0)) { 
1148       BitStream
[bit2idx
++] = 0 ^ invert
; 
1150       // We cannot end up in this state, this means we are unsynchronized, 
1154       PrintAndLog("Unsynchronized, resync..."); 
1155       PrintAndLog("(too many of those messages mean the stream is not Manchester encoded)"); 
1159           PrintAndLog("Error: too many decode errors, aborting."); 
1166   PrintAndLog("Manchester decoded bitstream"); 
1167   // Now output the bitstream to the scrollback by line of 16 bits 
1168   for (i 
= 0; i 
< (bit2idx
-16); i
+=16) { 
1169     PrintAndLog("%i %i %i %i %i %i %i %i %i %i %i %i %i %i %i %i", 
1190 /* Modulate our data into manchester */ 
1191 int CmdManchesterMod(const char *Cmd
) 
1194   int bit
, lastbit
, wave
; 
1195   int clock 
= GetClock(Cmd
, 0, 1); 
1196   int clock1 
= GetT55x7Clock( GraphBuffer
, GraphTraceLen
, 0 ); 
1197   PrintAndLog("MAN MOD CLOCKS:  %d  ice %d", clock
,clock1
); 
1199   int half 
= (int)(clock
/2); 
1203   for (i 
= 0; i 
< (int)(GraphTraceLen 
/ clock
); i
++) 
1205     bit 
= GraphBuffer
[i 
* clock
] ^ 1; 
1207     for (j 
= 0; j 
< half
; ++j
) 
1208       GraphBuffer
[(i 
* clock
) + j
] = bit 
^ lastbit 
^ wave
; 
1209     for (j 
= half
; j 
< clock
; ++j
) 
1210       GraphBuffer
[(i 
* clock
) + j
] = bit 
^ lastbit 
^ wave 
^ 1; 
1212     /* Keep track of how we start our wave and if we changed or not this time */ 
1213     wave 
^= bit 
^ lastbit
; 
1217   RepaintGraphWindow(); 
1221 int CmdNorm(const char *Cmd
) 
1224   int max 
= INT_MIN
, min 
= INT_MAX
; 
1226   for (i 
= 10; i 
< GraphTraceLen
; ++i
) { 
1227     if (GraphBuffer
[i
] > max
) 
1228       max 
= GraphBuffer
[i
]; 
1229     if (GraphBuffer
[i
] < min
) 
1230       min 
= GraphBuffer
[i
]; 
1234     for (i 
= 0; i 
< GraphTraceLen
; ++i
) { 
1235       GraphBuffer
[i
] = (GraphBuffer
[i
] - ((max 
+ min
) / 2)) * 1000 / 
1239   RepaintGraphWindow(); 
1243 int CmdPlot(const char *Cmd
) 
1249 int CmdSave(const char *Cmd
) 
1251    char filename
[FILE_PATH_SIZE
] = {0x00}; 
1255    if (len 
> FILE_PATH_SIZE
) len 
= FILE_PATH_SIZE
; 
1256    memcpy(filename
, Cmd
, len
); 
1259   FILE *f 
= fopen(filename
, "w"); 
1261     PrintAndLog("couldn't open '%s'", filename
); 
1265   for (i 
= 0; i 
< GraphTraceLen
; i
++) { 
1266     fprintf(f
, "%d\n", GraphBuffer
[i
]); 
1269   PrintAndLog("saved to '%s'", Cmd
); 
1273 int CmdScale(const char *Cmd
) 
1275   CursorScaleFactor 
= atoi(Cmd
); 
1276   if (CursorScaleFactor 
== 0) { 
1277     PrintAndLog("bad, can't have zero scale"); 
1278     CursorScaleFactor 
= 1; 
1280   RepaintGraphWindow(); 
1284 int CmdThreshold(const char *Cmd
) 
1286   int threshold 
= atoi(Cmd
); 
1288   for (int i 
= 0; i 
< GraphTraceLen
; ++i
) { 
1289     if (GraphBuffer
[i
] >= threshold
) 
1292       GraphBuffer
[i
] = -1; 
1294   RepaintGraphWindow(); 
1298 int CmdDirectionalThreshold(const char *Cmd
) 
1300         int8_t upThres 
= param_get8(Cmd
, 0); 
1301         int8_t downThres 
= param_get8(Cmd
, 1); 
1303   printf("Applying Up Threshold: %d, Down Threshold: %d\n", upThres
, downThres
); 
1305   int lastValue 
= GraphBuffer
[0]; 
1306   GraphBuffer
[0] = 0; // Will be changed at the end, but init 0 as we adjust to last samples value if no threshold kicks in. 
1308   for (int i 
= 1; i 
< GraphTraceLen
; ++i
) { 
1309     // Apply first threshold to samples heading up 
1310     if (GraphBuffer
[i
] >= upThres 
&& GraphBuffer
[i
] > lastValue
) 
1312       lastValue 
= GraphBuffer
[i
]; // Buffer last value as we overwrite it. 
1315     // Apply second threshold to samples heading down 
1316     else if (GraphBuffer
[i
] <= downThres 
&& GraphBuffer
[i
] < lastValue
) 
1318       lastValue 
= GraphBuffer
[i
]; // Buffer last value as we overwrite it. 
1319       GraphBuffer
[i
] = -1; 
1323       lastValue 
= GraphBuffer
[i
]; // Buffer last value as we overwrite it. 
1324       GraphBuffer
[i
] = GraphBuffer
[i
-1]; 
1328   GraphBuffer
[0] = GraphBuffer
[1]; // Aline with first edited sample. 
1329   RepaintGraphWindow(); 
1333 int CmdZerocrossings(const char *Cmd
) 
1335   // Zero-crossings aren't meaningful unless the signal is zero-mean. 
1342   for (int i 
= 0; i 
< GraphTraceLen
; ++i
) { 
1343     if (GraphBuffer
[i
] * sign 
>= 0) { 
1344       // No change in sign, reproduce the previous sample count. 
1346       GraphBuffer
[i
] = lastZc
; 
1348       // Change in sign, reset the sample count. 
1350       GraphBuffer
[i
] = lastZc
; 
1358   RepaintGraphWindow(); 
1362 static command_t CommandTable
[] =  
1364   {"help",          CmdHelp
,            1, "This help"}, 
1365   {"amp",           CmdAmp
,             1, "Amplify peaks"}, 
1366   {"askdemod",      Cmdaskdemod
,        1, "<0 or 1> -- Attempt to demodulate simple ASK tags"}, 
1367   {"askmandemod",   Cmdaskmandemod
,     1, "[clock] [invert<0 or 1>] -- Attempt to demodulate ASK/Manchester tags and output binary (args optional[clock will try Auto-detect])"}, 
1368   {"askrawdemod",   Cmdaskrawdemod
,     1, "[clock] [invert<0 or 1>] -- Attempt to demodulate ASK tags and output binary (args optional[clock will try Auto-detect])"}, 
1369   {"autocorr",      CmdAutoCorr
,        1, "<window length> -- Autocorrelation over window"}, 
1370   {"biphaserawdecode",CmdBiphaseDecodeRaw
,1,"[offset] Biphase decode binary stream already in graph buffer (offset = bit to start decode from)"}, 
1371   {"bitsamples",    CmdBitsamples
,      0, "Get raw samples as bitstring"}, 
1372   {"bitstream",     CmdBitstream
,       1, "[clock rate] -- Convert waveform into a bitstream"}, 
1373   {"buffclear",     CmdBuffClear
,       1, "Clear sample buffer and graph window"}, 
1374   {"dec",           CmdDec
,             1, "Decimate samples"}, 
1375   {"detectaskclock",CmdDetectClockRate
, 1, "Detect ASK clock rate"}, 
1376   {"dirthreshold",  CmdDirectionalThreshold
,   1, "<thres up> <thres down> -- Max rising higher up-thres/ Min falling lower down-thres, keep rest as prev."}, 
1377   {"fskdemod",      CmdFSKdemod
,        1, "Demodulate graph window as a HID FSK"}, 
1378   {"fskhiddemod",   CmdFSKdemodHID
,     1, "Demodulate graph window as a HID FSK using raw"}, 
1379   {"fskiodemod",    CmdFSKdemodIO
,      1, "Demodulate graph window as an IO Prox FSK using raw"}, 
1380   {"fskrawdemod",   CmdFSKrawdemod
,     1, "[clock rate] [invert] Demodulate graph window from FSK to binary (clock = 64 or 50)(invert = 1 or 0)"}, 
1381   {"grid",          CmdGrid
,            1, "<x> <y> -- overlay grid on graph window, use zero value to turn off either"}, 
1382   {"hexsamples",    CmdHexsamples
,      0, "<bytes> [<offset>] -- Dump big buffer as hex bytes"},   
1383   {"hide",          CmdHide
,            1, "Hide graph window"}, 
1384   {"hpf",           CmdHpf
,             1, "Remove DC offset from trace"}, 
1385   {"load",          CmdLoad
,            1, "<filename> -- Load trace (to graph window"}, 
1386   {"ltrim",         CmdLtrim
,           1, "<samples> -- Trim samples from left of trace"}, 
1387   {"mandemod",      CmdManchesterDemod
, 1, "[i] [clock rate] -- Manchester demodulate binary stream (option 'i' to invert output)"}, 
1388   {"manrawdecode",  Cmdmandecoderaw
,    1, "Manchester decode binary stream already in graph buffer"}, 
1389   {"manmod",        CmdManchesterMod
,   1, "[clock rate] -- Manchester modulate a binary stream"}, 
1390   {"norm",          CmdNorm
,            1, "Normalize max/min to +/-500"}, 
1391   {"plot",          CmdPlot
,            1, "Show graph window (hit 'h' in window for keystroke help)"}, 
1392   {"samples",       CmdSamples
,         0, "[512 - 40000] -- Get raw samples for graph window"}, 
1393   {"save",          CmdSave
,            1, "<filename> -- Save trace (from graph window)"}, 
1394   {"scale",         CmdScale
,           1, "<int> -- Set cursor display scale"}, 
1395   {"threshold",     CmdThreshold
,       1, "<threshold> -- Maximize/minimize every value in the graph window depending on threshold"}, 
1396   {"tune",          CmdTuneSamples
,     0, "Get hw tune samples for graph window"}, 
1397   {"zerocrossings", CmdZerocrossings
,   1, "Count time between zero-crossings"}, 
1398   {NULL
, NULL
, 0, NULL
} 
1401 int CmdData(const char *Cmd
) 
1403   CmdsParse(CommandTable
, Cmd
); 
1407 int CmdHelp(const char *Cmd
) 
1409   CmdsHelp(CommandTable
);