]> git.zerfleddert.de Git - proxmark3-svn/commitdiff
Merge remote-tracking branch 'upstream/master'
authormarshmellow42 <marshmellowrf@gmail.com>
Fri, 6 Feb 2015 19:45:46 +0000 (14:45 -0500)
committermarshmellow42 <marshmellowrf@gmail.com>
Fri, 6 Feb 2015 19:45:46 +0000 (14:45 -0500)
1  2 
armsrc/lfops.c
client/cmddata.c
client/cmdlf.c
client/graph.h

diff --combined armsrc/lfops.c
index 67652986afd87560d45e86fe0a2bfdbdbef7fa4e,479da77204ebc3fc357b5c569afbc3b0aab2f2bc..e34eab35f5bc813f8201b699967db819ed9da556
  #include "crc16.h"
  #include "string.h"
  #include "lfdemod.h"
+ #include "lfsampling.h"
  
  
  /**
- * Does the sample acquisition. If threshold is specified, the actual sampling
- * is not commenced until the threshold has been reached.
- * @param trigger_threshold - the threshold
- * @param silent - is true, now outputs are made. If false, dbprints the status
- */
- void DoAcquisition125k_internal(int trigger_threshold,bool silent)
- {
-     uint8_t *dest = BigBuf_get_addr();
-     int n = BigBuf_max_traceLen();
-     int i;
-     memset(dest, 0, n);
-     i = 0;
-     for(;;) {
-         if (AT91C_BASE_SSC->SSC_SR & AT91C_SSC_TXRDY) {
-             AT91C_BASE_SSC->SSC_THR = 0x43;
-             LED_D_ON();
-         }
-         if (AT91C_BASE_SSC->SSC_SR & AT91C_SSC_RXRDY) {
-             dest[i] = (uint8_t)AT91C_BASE_SSC->SSC_RHR;
-             LED_D_OFF();
-             if (trigger_threshold != -1 && dest[i] < trigger_threshold)
-                 continue;
-             else
-                 trigger_threshold = -1;
-             if (++i >= n) break;
-         }
-     }
-     if(!silent)
-     {
-         Dbprintf("buffer samples: %02x %02x %02x %02x %02x %02x %02x %02x ...",
-                  dest[0], dest[1], dest[2], dest[3], dest[4], dest[5], dest[6], dest[7]);
-     }
- }
- /**
- * Perform sample aquisition.
- */
- void DoAcquisition125k(int trigger_threshold)
- {
-     DoAcquisition125k_internal(trigger_threshold, false);
- }
- /**
- * Setup the FPGA to listen for samples. This method downloads the FPGA bitstream
- * if not already loaded, sets divisor and starts up the antenna.
- * @param divisor : 1, 88> 255 or negative ==> 134.8 KHz
- *                                0 or 95 ==> 125 KHz
- *
- **/
- void LFSetupFPGAForADC(int divisor, bool lf_field)
- {
-     FpgaDownloadAndGo(FPGA_BITSTREAM_LF);
-     if ( (divisor == 1) || (divisor < 0) || (divisor > 255) )
-         FpgaSendCommand(FPGA_CMD_SET_DIVISOR, 88); //134.8Khz
-     else if (divisor == 0)
-         FpgaSendCommand(FPGA_CMD_SET_DIVISOR, 95); //125Khz
-     else
-         FpgaSendCommand(FPGA_CMD_SET_DIVISOR, divisor);
-     FpgaWriteConfWord(FPGA_MAJOR_MODE_LF_ADC | (lf_field ? FPGA_LF_ADC_READER_FIELD : 0));
-     // Connect the A/D to the peak-detected low-frequency path.
-     SetAdcMuxFor(GPIO_MUXSEL_LOPKD);
-     // Give it a bit of time for the resonant antenna to settle.
-     SpinDelay(50);
-     // Now set up the SSC to get the ADC samples that are now streaming at us.
-     FpgaSetupSsc();
- }
- /**
- * Initializes the FPGA, and acquires the samples.
- **/
- void AcquireRawAdcSamples125k(int divisor)
- {
-     LFSetupFPGAForADC(divisor, true);
-     // Now call the acquisition routine
-     DoAcquisition125k_internal(-1,false);
- }
- /**
- * Initializes the FPGA for snoop-mode, and acquires the samples.
- **/
- void SnoopLFRawAdcSamples(int divisor, int trigger_threshold)
- {
-     LFSetupFPGAForADC(divisor, false);
-     DoAcquisition125k(trigger_threshold);
- }
+  * Function to do a modulation and then get samples.
+  * @param delay_off
+  * @param period_0
+  * @param period_1
+  * @param command
+  */
  void ModThenAcquireRawAdcSamples125k(int delay_off, int period_0, int period_1, uint8_t *command)
  {
  
-     /* Make sure the tag is reset */
-     FpgaDownloadAndGo(FPGA_BITSTREAM_LF);
-     FpgaWriteConfWord(FPGA_MAJOR_MODE_OFF);
-     SpinDelay(2500);
      int divisor_used = 95; // 125 KHz
      // see if 'h' was specified
  
      if (command[strlen((char *) command) - 1] == 'h')
          divisor_used = 88; // 134.8 KHz
  
+       sample_config sc = { 0,0,1, divisor_used, 0};
+       setSamplingConfig(&sc);
  
-     FpgaSendCommand(FPGA_CMD_SET_DIVISOR, divisor_used);
-     FpgaWriteConfWord(FPGA_MAJOR_MODE_LF_ADC | FPGA_LF_ADC_READER_FIELD);
-     // Give it a bit of time for the resonant antenna to settle.
-     SpinDelay(50);
+       /* Make sure the tag is reset */
+       FpgaDownloadAndGo(FPGA_BITSTREAM_LF);
+       FpgaWriteConfWord(FPGA_MAJOR_MODE_OFF);
+       SpinDelay(2500);
  
-     // And a little more time for the tag to fully power up
-     SpinDelay(2000);
+       LFSetupFPGAForADC(sc.divisor, 1);
  
-     // Now set up the SSC to get the ADC samples that are now streaming at us.
-     FpgaSetupSsc();
+       // And a little more time for the tag to fully power up
+       SpinDelay(2000);
  
      // now modulate the reader field
      while(*command != '\0' && *command != ' ') {
          FpgaWriteConfWord(FPGA_MAJOR_MODE_OFF);
          LED_D_OFF();
          SpinDelayUs(delay_off);
-         FpgaSendCommand(FPGA_CMD_SET_DIVISOR, divisor_used);
+               FpgaSendCommand(FPGA_CMD_SET_DIVISOR, sc.divisor);
  
          FpgaWriteConfWord(FPGA_MAJOR_MODE_LF_ADC | FPGA_LF_ADC_READER_FIELD);
          LED_D_ON();
      FpgaWriteConfWord(FPGA_MAJOR_MODE_OFF);
      LED_D_OFF();
      SpinDelayUs(delay_off);
-     FpgaSendCommand(FPGA_CMD_SET_DIVISOR, divisor_used);
+       FpgaSendCommand(FPGA_CMD_SET_DIVISOR, sc.divisor);
  
      FpgaWriteConfWord(FPGA_MAJOR_MODE_LF_ADC | FPGA_LF_ADC_READER_FIELD);
  
      // now do the read
-     DoAcquisition125k(-1);
+       DoAcquisition_config(false);
  }
  
  /* blank r/w tag data stream
  ...0000000000000000 01111111
  1010101010101010101010101010101010101010101010101010101010101010
@@@ -645,8 -561,8 +561,8 @@@ void CmdHIDdemodFSK(int findone, int *h
          WDT_HIT();
          if (ledcontrol) LED_A_ON();
  
-         DoAcquisition125k_internal(-1,true);
-         // FSK demodulator
+               DoAcquisition_default(-1,true);
+               // FSK demodulator
          size = sizeOfBigBuff;  //variable size will change after demod so re initialize it before use
                idx = HIDdemodFSK(dest, &size, &hi2, &hi, &lo);
          
@@@ -724,7 -640,7 +640,7 @@@ void CmdEM410xdemod(int findone, int *h
      uint8_t *dest = BigBuf_get_addr();
  
        size_t size=0, idx=0;
 -    int clk=0, invert=0, errCnt=0;
 +    int clk=0, invert=0, errCnt=0, maxErr=20;
      uint64_t lo=0;
      // Configure to go in 125Khz listen mode
      LFSetupFPGAForADC(95, true);
          WDT_HIT();
          if (ledcontrol) LED_A_ON();
  
-         DoAcquisition125k_internal(-1,true);
-         size  = BigBuf_max_traceLen();
+               DoAcquisition_default(-1,true);
+               size  = BigBuf_max_traceLen();
          //Dbprintf("DEBUG: Buffer got");
                //askdemod and manchester decode
 -              errCnt = askmandemod(dest, &size, &clk, &invert);
 +              errCnt = askmandemod(dest, &size, &clk, &invert, maxErr);
          //Dbprintf("DEBUG: ASK Got");
          WDT_HIT();
  
@@@ -787,8 -703,8 +703,8 @@@ void CmdIOdemodFSK(int findone, int *hi
      while(!BUTTON_PRESS()) {
          WDT_HIT();
          if (ledcontrol) LED_A_ON();
-         DoAcquisition125k_internal(-1,true);
-         //fskdemod and get start index
+               DoAcquisition_default(-1,true);
+               //fskdemod and get start index
          WDT_HIT();
          idx = IOdemodFSK(dest, BigBuf_max_traceLen());
          if (idx>0){
@@@ -1394,7 -1310,9 +1310,9 @@@ int DemodPCF7931(uint8_t **outBlocks) 
      int lmin=128, lmax=128;
      uint8_t dir;
  
-     AcquireRawAdcSamples125k(0);
+       LFSetupFPGAForADC(95, true);
+       DoAcquisition_default(0, 0);
  
      lmin = 64;
      lmax = 192;
diff --combined client/cmddata.c
index 66ba7455531954d98f2491472a322b2317b149b1,430afb174b9cee1b1f64da2f37ba3fb8e8ee4374..a1159ec80675c6742942a4896f0c9783bed7f30e
@@@ -21,6 -21,8 +21,8 @@@
  #include "cmdmain.h"
  #include "cmddata.h"
  #include "lfdemod.h"
+ #include "usb_cmd.h"
  uint8_t DemodBuffer[MAX_DEMOD_BUF_LEN];
  uint8_t g_debugMode;
  int DemodBufferLen;
@@@ -247,113 -249,44 +249,113 @@@ void printEM410x(uint64_t id
  }
  
  //by marshmellow
 -//take binary from demod buffer and see if we can find an EM410x ID
 -int CmdEm410xDecode(const char *Cmd)
 +//takes 3 arguments - clock, invert and maxErr as integers
 +//attempts to demodulate ask while decoding manchester
 +//prints binary found and saves in graphbuffer for further commands
 +int CmdAskEM410xDemod(const char *Cmd)
  {
 -  uint64_t id=0;
 -  size_t size = DemodBufferLen, idx=0;
 -      id = Em410xDecode(DemodBuffer, &size, &idx);
 -  if (id>0){
 -    setDemodBuf(DemodBuffer, size, idx);
 +  int invert=0;
 +  int clk=0;
 +  int maxErr=100;
 +  char cmdp = param_getchar(Cmd, 0);
 +  if (strlen(Cmd) > 10 || cmdp == 'h' || cmdp == 'H') {
 +    PrintAndLog("Usage:  data askem410xdemod [clock] <0|1> [maxError]");
 +    PrintAndLog("     [set clock as integer] optional, if not set, autodetect.");
 +    PrintAndLog("     <invert>, 1 for invert output");
 +    PrintAndLog("     [set maximum allowed errors], default = 100.");
 +    PrintAndLog("");
 +    PrintAndLog("    sample: data askem410xdemod        = demod an EM410x Tag ID from GraphBuffer");
 +    PrintAndLog("          : data askem410xdemod 32     = demod an EM410x Tag ID from GraphBuffer using a clock of RF/32");
 +    PrintAndLog("          : data askem410xdemod 32 1   = demod an EM410x Tag ID from GraphBuffer using a clock of RF/32 and inverting data");
 +    PrintAndLog("          : data askem410xdemod 1      = demod an EM410x Tag ID from GraphBuffer while inverting data");
 +    PrintAndLog("          : data askem410xdemod 64 1 0 = demod an EM410x Tag ID from GraphBuffer using a clock of RF/64 and inverting data and allowing 0 demod errors");
 +
 +    return 0;
 +  }
 +
 +
 +  uint8_t BitStream[MAX_GRAPH_TRACE_LEN]={0};
 +  sscanf(Cmd, "%i %i %i", &clk, &invert, &maxErr);
 +  if (invert != 0 && invert != 1) {
 +    PrintAndLog("Invalid argument: %s", Cmd);
 +    return 0;
 +  }
 +  size_t BitLen = getFromGraphBuf(BitStream);
 +
 +  if (g_debugMode==1) PrintAndLog("DEBUG: Bitlen from grphbuff: %d",BitLen);
 +  if (BitLen==0) return 0;
 +  int errCnt=0;
 +  errCnt = askmandemod(BitStream, &BitLen, &clk, &invert, maxErr);
 +  if (errCnt<0||BitLen<16){  //if fatal error (or -1)
 +    if (g_debugMode==1) PrintAndLog("no data found %d, errors:%d, bitlen:%d, clock:%d",errCnt,invert,BitLen,clk);
 +    return 0;
 +  }
 +  PrintAndLog("\nUsing Clock: %d - Invert: %d - Bits Found: %d",clk,invert,BitLen);
 +
 +  //output
 +  if (errCnt>0){
 +    PrintAndLog("# Errors during Demoding (shown as 77 in bit stream): %d",errCnt);
 +  }
 +  //PrintAndLog("ASK/Manchester decoded bitstream:");
 +  // Now output the bitstream to the scrollback by line of 16 bits
 +  setDemodBuf(BitStream,BitLen,0);
 +  //printDemodBuff();
 +  uint64_t lo =0;
 +  size_t idx=0;
 +  lo = Em410xDecode(BitStream, &BitLen, &idx);
 +  if (lo>0){
 +    //set GraphBuffer for clone or sim command
 +    setDemodBuf(BitStream, BitLen, idx);
      if (g_debugMode){
 -      PrintAndLog("DEBUG: Printing demod buffer:");
 +      PrintAndLog("DEBUG: idx: %d, Len: %d, Printing Demod Buffer:", idx, BitLen);
        printDemodBuff();
      }
 -    printEM410x(id);
 -    return 1; 
 +    PrintAndLog("EM410x pattern found: ");
 +    printEM410x(lo);
 +    return 1;
    }
    return 0;
  }
  
 -
  //by marshmellow
 -//takes 2 arguments - clock and invert both as integers
 +//takes 3 arguments - clock, invert, maxErr as integers
  //attempts to demodulate ask while decoding manchester
  //prints binary found and saves in graphbuffer for further commands
  int Cmdaskmandemod(const char *Cmd)
  {
    int invert=0;
        int clk=0;
 +  int maxErr=100;
 +  char cmdp = param_getchar(Cmd, 0);
 +  if (strlen(Cmd) > 10 || cmdp == 'h' || cmdp == 'H') {
 +    PrintAndLog("Usage:  data askmandemod [clock] <0|1> [maxError]");
 +    PrintAndLog("     [set clock as integer] optional, if not set, autodetect.");
 +    PrintAndLog("     <invert>, 1 for invert output");
 +    PrintAndLog("     [set maximum allowed errors], default = 100.");
 +    PrintAndLog("");
 +    PrintAndLog("    sample: data askmandemod        = demod an ask/manchester tag from GraphBuffer");
 +    PrintAndLog("          : data askmandemod 32     = demod an ask/manchester tag from GraphBuffer using a clock of RF/32");
 +    PrintAndLog("          : data askmandemod 32 1   = demod an ask/manchester tag from GraphBuffer using a clock of RF/32 and inverting data");
 +    PrintAndLog("          : data askmandemod 1      = demod an ask/manchester tag from GraphBuffer while inverting data");
 +    PrintAndLog("          : data askmandemod 64 1 0 = demod an ask/manchester tag from GraphBuffer using a clock of RF/64, inverting data and allowing 0 demod errors");
 +
 +    return 0;
 +  }
    uint8_t BitStream[MAX_GRAPH_TRACE_LEN]={0};
 -      sscanf(Cmd, "%i %i", &clk, &invert);
 +      sscanf(Cmd, "%i %i %i", &clk, &invert, &maxErr);
    if (invert != 0 && invert != 1) {
      PrintAndLog("Invalid argument: %s", Cmd);
      return 0;
    }
 -
 +  if (clk==1){
 +    invert=1;
 +    clk=0;
 +  }
        size_t BitLen = getFromGraphBuf(BitStream);
    if (g_debugMode==1) PrintAndLog("DEBUG: Bitlen from grphbuff: %d",BitLen);
 +  if (BitLen==0) return 0;
    int errCnt=0;
 -   errCnt = askmandemod(BitStream, &BitLen,&clk,&invert);
 +  errCnt = askmandemod(BitStream, &BitLen, &clk, &invert, maxErr);
        if (errCnt<0||BitLen<16){  //if fatal error (or -1)
                if (g_debugMode==1) PrintAndLog("no data found %d, errors:%d, bitlen:%d, clock:%d",errCnt,invert,BitLen,clk);
      return 0;
      printEM410x(lo);
      return 1;
    }
 -  return 0;
 +  return 1;
  }
  
  //by marshmellow
@@@ -393,17 -326,6 +395,17 @@@ int Cmdmandecoderaw(const char *Cmd
    int i =0;
    int errCnt=0;
        size_t size=0;
 +  size_t maxErr = 20;
 +  char cmdp = param_getchar(Cmd, 0);
 +  if (strlen(Cmd) > 1 || cmdp == 'h' || cmdp == 'H') {
 +    PrintAndLog("Usage:  data manrawdecode");
 +    PrintAndLog("     Takes 10 and 01 and converts to 0 and 1 respectively");
 +    PrintAndLog("     --must have binary sequence in demodbuffer (run data askrawdemod first)");
 +    PrintAndLog("");
 +    PrintAndLog("    sample: data manrawdecode   = decode manchester bitstream from the demodbuffer");
 +    return 0;
 +  }
 +  if (DemodBufferLen==0) return 0;
    uint8_t BitStream[MAX_GRAPH_TRACE_LEN]={0};
    int high=0,low=0;
        for (;i<DemodBufferLen;++i){
    }
        size=i;
        errCnt=manrawdecode(BitStream, &size);
 -  if (errCnt>=20){
 +  if (errCnt>=maxErr){
      PrintAndLog("Too many errors: %d",errCnt);
      return 0;
    }
@@@ -455,21 -377,7 +457,21 @@@ int CmdBiphaseDecodeRaw(const char *Cmd
    int offset=0;
    int invert=0;
    int high=0, low=0;
 +  char cmdp = param_getchar(Cmd, 0);
 +  if (strlen(Cmd) > 3 || cmdp == 'h' || cmdp == 'H') {
 +    PrintAndLog("Usage:  data biphaserawdecode [offset] <invert>");
 +    PrintAndLog("     Converts 10 or 01 to 0 and 11 or 00 to 1");
 +    PrintAndLog("     --must have binary sequence in demodbuffer (run data askrawdemod first)");   
 +    PrintAndLog("");
 +    PrintAndLog("     [offset <0|1>], set to 0 not to adjust start position or to 1 to adjust decode start position");
 +    PrintAndLog("     [invert <0|1>], set to 1 to invert output");
 +    PrintAndLog("");
 +    PrintAndLog("    sample: data biphaserawdecode     = decode biphase bitstream from the demodbuffer");
 +    PrintAndLog("    sample: data biphaserawdecode 1 1 = decode biphase bitstream from the demodbuffer, set offset, and invert output");
 +    return 0;
 +  }
        sscanf(Cmd, "%i %i", &offset, &invert);
 +  if (DemodBufferLen==0) return 0;
    uint8_t BitStream[MAX_GRAPH_TRACE_LEN]={0};
    //get graphbuffer & high and low
        for (;i<DemodBufferLen;++i){
  }
  
  //by marshmellow
 -//takes 2 arguments - clock and invert both as integers
 +//takes 4 arguments - clock, invert, maxErr as integers and amplify as char
  //attempts to demodulate ask only
  //prints binary found and saves in graphbuffer for further commands
  int Cmdaskrawdemod(const char *Cmd)
  {
        int invert=0;
        int clk=0;
 +  int maxErr=100;
 +  uint8_t askAmp = 0;
 +  char amp = param_getchar(Cmd, 0);
 +  char cmdp = param_getchar(Cmd, 0);
 +  if (strlen(Cmd) > 12 || cmdp == 'h' || cmdp == 'H') {
 +    PrintAndLog("Usage:  data askrawdemod [clock] <invert> [maxError] [amplify]");
 +    PrintAndLog("     [set clock as integer] optional, if not set, autodetect");
 +    PrintAndLog("     <invert>, 1 to invert output");
 +    PrintAndLog("     [set maximum allowed errors], default = 100");
 +    PrintAndLog("     <amplify>, 'a' to attempt demod with ask amplification, default = no amp");
 +    PrintAndLog("");
 +    PrintAndLog("    sample: data askrawdemod          = demod an ask tag from GraphBuffer");
 +    PrintAndLog("          : data askrawdemod a        = demod an ask tag from GraphBuffer, amplified");
 +    PrintAndLog("          : data askrawdemod 32       = demod an ask tag from GraphBuffer using a clock of RF/32");
 +    PrintAndLog("          : data askrawdemod 32 1     = demod an ask tag from GraphBuffer using a clock of RF/32 and inverting data");
 +    PrintAndLog("          : data askrawdemod 1        = demod an ask tag from GraphBuffer while inverting data");
 +    PrintAndLog("          : data askrawdemod 64 1 0   = demod an ask tag from GraphBuffer using a clock of RF/64, inverting data and allowing 0 demod errors");
 +    PrintAndLog("          : data askrawdemod 64 1 0 a = demod an ask tag from GraphBuffer using a clock of RF/64, inverting data and allowing 0 demod errors, and amp");
 +    return 0;
 +  }
    uint8_t BitStream[MAX_GRAPH_TRACE_LEN]={0};
 -      sscanf(Cmd, "%i %i", &clk, &invert);
 +      sscanf(Cmd, "%i %i %i %c", &clk, &invert, &maxErr, &amp);
    if (invert != 0 && invert != 1) {
      PrintAndLog("Invalid argument: %s", Cmd);
      return 0;
    }
 +  if (clk==1){
 +    invert=1;
 +    clk=0;
 +  }
 +  if (amp == 'a' || amp == 'A') askAmp=1; 
        size_t BitLen = getFromGraphBuf(BitStream);
 +  if (BitLen==0) return 0;
    int errCnt=0;
 -      errCnt = askrawdemod(BitStream, &BitLen,&clk,&invert);
 +      errCnt = askrawdemod(BitStream, &BitLen, &clk, &invert, maxErr, askAmp);
        if (errCnt==-1||BitLen<16){  //throw away static - allow 1 and -1 (in case of threshold command first)
                PrintAndLog("no data found");
      if (g_debugMode==1) PrintAndLog("errCnt: %d, BitLen: %d, clk: %d, invert: %d", errCnt, BitLen, clk, invert);
      return 0;
        }
 -  PrintAndLog("Using Clock: %d - invert: %d - Bits Found: %d",clk,invert,BitLen);
 +  PrintAndLog("Using Clock: %d - invert: %d - Bits Found: %d", clk, invert, BitLen);
    
    //move BitStream back to DemodBuffer
        setDemodBuf(BitStream,BitLen,0);
  
        //output
    if (errCnt>0){
 -    PrintAndLog("# Errors during Demoding (shown as 77 in bit stream): %d",errCnt);
 +    PrintAndLog("# Errors during Demoding (shown as 77 in bit stream): %d", errCnt);
    }
    PrintAndLog("ASK demoded bitstream:");
    // Now output the bitstream to the scrollback by line of 16 bits
@@@ -689,6 -571,43 +691,43 @@@ int CmdDec(const char *Cmd
    RepaintGraphWindow();
    return 0;
  }
+ /**
+  * Undecimate - I'd call it 'interpolate', but we'll save that
+  * name until someone does an actual interpolation command, not just
+  * blindly repeating samples
+  * @param Cmd
+  * @return
+  */
+ int CmdUndec(const char *Cmd)
+ {
+       if(param_getchar(Cmd, 0) == 'h')
+       {
+               PrintAndLog("Usage: data undec [factor]");
+               PrintAndLog("This function performs un-decimation, by repeating each sample N times");
+               PrintAndLog("Options:        ");
+               PrintAndLog("       h            This help");
+               PrintAndLog("       factor       The number of times to repeat each sample.[default:2]");
+               PrintAndLog("Example: 'data undec 3'");
+               return 0;
+       }
+       uint8_t factor = param_get8ex(Cmd, 0,2, 10);
+       //We have memory, don't we?
+       int swap[MAX_GRAPH_TRACE_LEN] = { 0 };
+       uint32_t g_index = 0 ,s_index = 0;
+       while(g_index < GraphTraceLen && s_index < MAX_GRAPH_TRACE_LEN)
+       {
+               int count = 0;
+               for(count = 0; count < factor && s_index+count < MAX_GRAPH_TRACE_LEN; count ++)
+                       swap[s_index+count] = GraphBuffer[g_index];
+               s_index+=count;
+       }
+       memcpy(GraphBuffer,swap, s_index * sizeof(int));
+       GraphTraceLen = s_index;
+       RepaintGraphWindow();
+       return 0;
+ }
  
  //by marshmellow
  //shift graph zero up or down based on input + or -
@@@ -711,47 -630,20 +750,47 @@@ int CmdGraphShiftZero(const char *Cmd
    return 0;
  }
  
 +//by marshmellow
 +//use large jumps in read samples to identify edges of waves and then amplify that wave to max
 +//similar to dirtheshold, threshold, and askdemod commands 
 +//takes a threshold length which is the measured length between two samples then determines an edge
 +int CmdAskEdgeDetect(const char *Cmd)
 +{
 +  int thresLen = 25;
 +  sscanf(Cmd, "%i", &thresLen); 
 +  int shift = 127;
 +  int shiftedVal=0;
 +  for(int i = 1; i<GraphTraceLen; i++){
 +    if (GraphBuffer[i]-GraphBuffer[i-1]>=thresLen) //large jump up
 +      shift=127;
 +    else if(GraphBuffer[i]-GraphBuffer[i-1]<=-1*thresLen) //large jump down
 +      shift=-127;
 +
 +    shiftedVal=GraphBuffer[i]+shift;
 +
 +    if (shiftedVal>127) 
 +      shiftedVal=127;
 +    else if (shiftedVal<-127) 
 +      shiftedVal=-127;
 +    GraphBuffer[i-1] = shiftedVal;
 +  }
 +  RepaintGraphWindow();
 +  //CmdNorm("");
 +  return 0;
 +}
 +
  /* Print our clock rate */
  // uses data from graphbuffer
  int CmdDetectClockRate(const char *Cmd)
  {
 -  GetClock("",0,0);
 -      //int clock = DetectASKClock(0);
 -      //PrintAndLog("Auto-detected clock rate: %d", clock);
 -  return 0;
 +  int ans = GetClock("",0,0);
 +  return ans;
  }
  
  //by marshmellow
  //fsk raw demod and print binary
 -//takes 4 arguments - Clock, invert, rchigh, rclow
 -//defaults: clock = 50, invert=0, rchigh=10, rclow=8 (RF/10 RF/8 (fsk2a))
 +//takes 4 arguments - Clock, invert, fchigh, fclow
 +//defaults: clock = 50, invert=1, fchigh=10, fclow=8 (RF/10 RF/8 (fsk2a))
  int CmdFSKrawdemod(const char *Cmd)
  {
    //raw fsk demod  no manchester decoding no start bit finding just get binary from wave
    int invert=0;
    int fchigh=0;
    int fclow=0;
 +  char cmdp = param_getchar(Cmd, 0);
 +  if (strlen(Cmd) > 10 || cmdp == 'h' || cmdp == 'H') {
 +    PrintAndLog("Usage:  data fskrawdemod [clock] <invert> [fchigh] [fclow]");
 +    PrintAndLog("     [set clock as integer] optional, omit for autodetect.");
 +    PrintAndLog("     <invert>, 1 for invert output, can be used even if the clock is omitted");
 +    PrintAndLog("     [fchigh], larger field clock length, omit for autodetect");
 +    PrintAndLog("     [fclow], small field clock length, omit for autodetect");
 +    PrintAndLog("");
 +    PrintAndLog("    sample: data fskrawdemod           = demod an fsk tag from GraphBuffer using autodetect");
 +    PrintAndLog("          : data fskrawdemod 32        = demod an fsk tag from GraphBuffer using a clock of RF/32, autodetect fc");
 +    PrintAndLog("          : data fskrawdemod 1         = demod an fsk tag from GraphBuffer using autodetect, invert output");   
 +    PrintAndLog("          : data fskrawdemod 32 1      = demod an fsk tag from GraphBuffer using a clock of RF/32, invert output, autodetect fc");
 +    PrintAndLog("          : data fskrawdemod 64 0 8 5  = demod an fsk1 RF/64 tag from GraphBuffer");
 +    PrintAndLog("          : data fskrawdemod 50 0 10 8 = demod an fsk2 RF/50 tag from GraphBuffer");
 +    PrintAndLog("          : data fskrawdemod 50 1 10 8 = demod an fsk2a RF/50 tag from GraphBuffer");
 +    return 0;
 +  }
    //set options from parameters entered with the command
        sscanf(Cmd, "%i %i %i %i", &rfLen, &invert, &fchigh, &fclow);
  
  
    uint8_t BitStream[MAX_GRAPH_TRACE_LEN]={0};
        size_t BitLen = getFromGraphBuf(BitStream);
 +  if (BitLen==0) return 0;
    //get field clock lengths
    uint16_t fcs=0;
 +  uint8_t dummy=0;
    if (fchigh==0 || fclow == 0){
 -    fcs=countFC(BitStream, BitLen);
 +    fcs=countFC(BitStream, BitLen, &dummy);
      if (fcs==0){
        fchigh=10;
        fclow=8;
      // Now output the bitstream to the scrollback by line of 16 bits
      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
      printBitStream(BitStream,size);
 +    return 1;
    } else{
      PrintAndLog("no FSK data found");
    }
@@@ -834,9 -706,8 +873,9 @@@ int CmdFSKdemodHID(const char *Cmd
  
    uint8_t BitStream[MAX_GRAPH_TRACE_LEN]={0};
        size_t BitLen = getFromGraphBuf(BitStream);
 +      if (BitLen==0) return 0;
    //get binary from fsk wave
 -      int idx  = HIDdemodFSK(BitStream,&BitLen,&hi2,&hi,&lo);
 +  int idx  = HIDdemodFSK(BitStream,&BitLen,&hi2,&hi,&lo);
    if (idx<0){
      if (g_debugMode){
        if (idx==-1){
@@@ -920,7 -791,6 +959,7 @@@ int CmdFSKdemodParadox(const char *Cmd
  
    uint8_t BitStream[MAX_GRAPH_TRACE_LEN]={0};
    size_t BitLen = getFromGraphBuf(BitStream);
 +  if (BitLen==0) return 0;
    //get binary from fsk wave
    int idx = ParadoxdemodFSK(BitStream,&BitLen,&hi2,&hi,&lo);
    if (idx<0){
@@@ -972,7 -842,6 +1011,7 @@@ int CmdFSKdemodIO(const char *Cmd
    }
    uint8_t BitStream[MAX_GRAPH_TRACE_LEN]={0};
        size_t BitLen = getFromGraphBuf(BitStream);
 +  if (BitLen==0) return 0;
  
    //get binary from fsk wave
        idx = IOdemodFSK(BitStream,BitLen);
@@@ -1049,7 -918,6 +1088,7 @@@ int CmdFSKdemodAWID(const char *Cmd
    //raw fsk demod no manchester decoding no start bit finding just get binary from wave
    uint8_t BitStream[MAX_GRAPH_TRACE_LEN]={0};
    size_t size = getFromGraphBuf(BitStream);
 +  if (size==0) return 0;
  
    //get binary from fsk wave
    int idx = AWIDdemodFSK(BitStream, &size);
@@@ -1149,7 -1017,6 +1188,7 @@@ int CmdFSKdemodPyramid(const char *Cmd
    //raw fsk demod no manchester decoding no start bit finding just get binary from wave
    uint8_t BitStream[MAX_GRAPH_TRACE_LEN]={0};
    size_t size = getFromGraphBuf(BitStream);
 +  if (size==0) return 0;
  
    //get binary from fsk wave
    int idx = PyramiddemodFSK(BitStream, &size);
@@@ -1389,9 -1256,8 +1428,9 @@@ int CmdFSKfcDetect(const char *Cmd
  {
    uint8_t BitStream[MAX_GRAPH_TRACE_LEN]={0};
    size_t size = getFromGraphBuf(BitStream);
 -
 -  uint16_t ans = countFC(BitStream, size); 
 +  if (size==0) return 0;
 +  uint8_t dummy = 0;
 +  uint16_t ans = countFC(BitStream, size, &dummy); 
    if (ans==0) {
      if (g_debugMode) PrintAndLog("DEBUG: No data found");
      return 0;
      if (g_debugMode) PrintAndLog("DEBUG: Clock detect error");
      return 0;
    }
 -  PrintAndLog("Detected Field Clocks: FC/%d, FC/%d - Bit Clock: RF/%d", fc1, fc2, rf1);
 -  return 1;
 +  if ((fc1==10 && fc2==8) || (fc1==8 && fc2==5)){
 +    PrintAndLog("Detected Field Clocks: FC/%d, FC/%d - Bit Clock: RF/%d", fc1, fc2, rf1);
 +    return 1;
 +  }
 +  if (g_debugMode){
 +    PrintAndLog("DEBUG: unknown fsk field clock detected");
 +    PrintAndLog("Detected Field Clocks: FC/%d, FC/%d - Bit Clock: RF/%d", fc1, fc2, rf1);
 +  }
 +  return 0;
  }
  
  //by marshmellow
 -//attempt to detect the bit clock for PSK or NRZ modulations
 -int CmdDetectNRZpskClockRate(const char *Cmd)
 +//attempt to detect the bit clock for PSK modulations
 +int CmdDetectPSKClockRate(const char *Cmd)
  {
 -      GetNRZpskClock("",0,0);
 +      GetPskClock("",0,0);
        return 0;
  }
  
  //by marshmellow
 -//attempt to psk1 or nrz demod graph buffer
 -//NOTE CURRENTLY RELIES ON PEAKS :(
 -int PSKnrzDemod(const char *Cmd, uint8_t verbose)
 +//attempt to detect the bit clock for NRZ modulations
 +int CmdDetectNRZClockRate(const char *Cmd)
  {
 -      int invert=0;
 -      int clk=0;
 -      sscanf(Cmd, "%i %i", &clk, &invert);
 -      if (invert != 0 && invert != 1) {
 -              PrintAndLog("Invalid argument: %s", Cmd);
 -              return -1;
 -      }
 -      uint8_t BitStream[MAX_GRAPH_TRACE_LEN]={0};
 -      size_t BitLen = getFromGraphBuf(BitStream);
 -      int errCnt=0;
 -      errCnt = pskNRZrawDemod(BitStream, &BitLen,&clk,&invert);
 -      if (errCnt<0|| BitLen<16){  //throw away static - allow 1 and -1 (in case of threshold command first)
 -              if (g_debugMode==1) PrintAndLog("no data found, clk: %d, invert: %d, numbits: %d, errCnt: %d",clk,invert,BitLen,errCnt);
 -              return -1;
 -      }
 -  if (verbose) PrintAndLog("Tried PSK/NRZ Demod using Clock: %d - invert: %d - Bits Found: %d",clk,invert,BitLen);
 +  GetNrzClock("",0,0);
 +  return 0;
 +}
  
 -      //prime demod buffer for output
 -      setDemodBuf(BitStream,BitLen,0);
 -      return errCnt;
 +//by marshmellow
 +//attempt to psk1 demod graph buffer
 +int PSKDemod(const char *Cmd, uint8_t verbose)
 +{
 +  int invert=0;
 +  int clk=0;
 +  int maxErr=100;
 +  sscanf(Cmd, "%i %i %i", &clk, &invert, &maxErr);
 +  if (clk==1){
 +    invert=1;
 +    clk=0;
 +  }
 +  if (invert != 0 && invert != 1) {
 +    PrintAndLog("Invalid argument: %s", Cmd);
 +    return -1;
 +  }
 +  uint8_t BitStream[MAX_GRAPH_TRACE_LEN]={0};
 +  size_t BitLen = getFromGraphBuf(BitStream);
 +  if (BitLen==0) return 0;
 +  int errCnt=0;
 +  errCnt = pskRawDemod(BitStream, &BitLen,&clk,&invert);
 +  if (errCnt > maxErr){
 +    if (g_debugMode==1) PrintAndLog("Too many errors found, clk: %d, invert: %d, numbits: %d, errCnt: %d",clk,invert,BitLen,errCnt);
 +    return -1;
 +  } 
 +  if (errCnt<0|| BitLen<16){  //throw away static - allow 1 and -1 (in case of threshold command first)
 +    if (g_debugMode==1) PrintAndLog("no data found, clk: %d, invert: %d, numbits: %d, errCnt: %d",clk,invert,BitLen,errCnt);
 +    return -1;
 +  }
 +  if (verbose) PrintAndLog("Tried PSK Demod using Clock: %d - invert: %d - Bits Found: %d",clk,invert,BitLen);
 +  //prime demod buffer for output
 +  setDemodBuf(BitStream,BitLen,0);
 +  return errCnt;
  }
 +
 +
  // Indala 26 bit decode
  // by marshmellow
  // optional arguments - same as CmdpskNRZrawDemod (clock & invert)
@@@ -1475,9 -1316,9 +1514,9 @@@ int CmdIndalaDecode(const char *Cmd
  {
    int ans;
    if (strlen(Cmd)>0){
 -    ans = PSKnrzDemod(Cmd, 0);
 +    ans = PSKDemod(Cmd, 0);
    } else{ //default to RF/32
 -    ans = PSKnrzDemod("32", 0);
 +    ans = PSKDemod("32", 0);
    }
  
        if (ans < 0){
        return 1;
  }
  
 +/*
  //by marshmellow
  //attempt to clean psk wave noise after a peak 
  //NOTE RELIES ON PEAKS :(
@@@ -1561,104 -1401,35 +1600,104 @@@ int CmdPskClean(const char *Cmd
        setGraphBuf(bitStream, bitLen);
        return 0;
  }
 +*/
  
  // by marshmellow
 -// takes 2 arguments - clock and invert both as integers
 +// takes 3 arguments - clock, invert, maxErr as integers
 +// attempts to demodulate nrz only
 +// prints binary found and saves in demodbuffer for further commands
 +int CmdNRZrawDemod(const char *Cmd)
 +{
 +  int invert=0;
 +  int clk=0;
 +  int maxErr=100;
 +  char cmdp = param_getchar(Cmd, 0);
 +  if (strlen(Cmd) > 10 || cmdp == 'h' || cmdp == 'H') {
 +    PrintAndLog("Usage:  data nrzrawdemod [clock] <0|1> [maxError]");
 +    PrintAndLog("     [set clock as integer] optional, if not set, autodetect.");
 +    PrintAndLog("     <invert>, 1 for invert output");
 +    PrintAndLog("     [set maximum allowed errors], default = 100.");
 +    PrintAndLog("");
 +    PrintAndLog("    sample: data nrzrawdemod        = demod a nrz/direct tag from GraphBuffer");
 +    PrintAndLog("          : data nrzrawdemod 32     = demod a nrz/direct tag from GraphBuffer using a clock of RF/32");
 +    PrintAndLog("          : data nrzrawdemod 32 1   = demod a nrz/direct tag from GraphBuffer using a clock of RF/32 and inverting data");
 +    PrintAndLog("          : data nrzrawdemod 1      = demod a nrz/direct tag from GraphBuffer while inverting data");
 +    PrintAndLog("          : data nrzrawdemod 64 1 0 = demod a nrz/direct tag from GraphBuffer using a clock of RF/64, inverting data and allowing 0 demod errors");
 +
 +    return 0;
 +  }
 + 
 +  sscanf(Cmd, "%i %i %i", &clk, &invert, &maxErr);
 +  if (clk==1){
 +    invert=1;
 +    clk=0;
 +  }
 +  if (invert != 0 && invert != 1) {
 +    PrintAndLog("Invalid argument: %s", Cmd);
 +    return 0;
 +  }
 +  uint8_t BitStream[MAX_GRAPH_TRACE_LEN]={0};
 +  size_t BitLen = getFromGraphBuf(BitStream);
 +  if (BitLen==0) return 0;
 +  int errCnt=0;
 +  errCnt = nrzRawDemod(BitStream, &BitLen, &clk, &invert, maxErr);
 +  if (errCnt > maxErr){
 +    if (g_debugMode==1) PrintAndLog("Too many errors found, clk: %d, invert: %d, numbits: %d, errCnt: %d",clk,invert,BitLen,errCnt);
 +    return 0;
 +  } 
 +  if (errCnt<0|| BitLen<16){  //throw away static - allow 1 and -1 (in case of threshold command first)
 +    if (g_debugMode==1) PrintAndLog("no data found, clk: %d, invert: %d, numbits: %d, errCnt: %d",clk,invert,BitLen,errCnt);
 +    return 0;
 +  }
 +  PrintAndLog("Tried NRZ Demod using Clock: %d - invert: %d - Bits Found: %d",clk,invert,BitLen);
 +  //prime demod buffer for output
 +  setDemodBuf(BitStream,BitLen,0);
 +
 +  if (errCnt>0){
 +    PrintAndLog("# Errors during Demoding (shown as 77 in bit stream): %d",errCnt);
 +  }else{
 +  }
 +  PrintAndLog("NRZ demoded bitstream:");
 +  // Now output the bitstream to the scrollback by line of 16 bits
 +  printDemodBuff();
 +  return 1;
 +}
 +
 +// by marshmellow
 +// takes 3 arguments - clock, invert, maxErr as integers
  // attempts to demodulate psk only
  // prints binary found and saves in demodbuffer for further commands
 -int CmdpskNRZrawDemod(const char *Cmd)
 +int CmdPSK1rawDemod(const char *Cmd)
  {
    int errCnt;
 - 
 -  errCnt = PSKnrzDemod(Cmd, 1);
 +  char cmdp = param_getchar(Cmd, 0);
 +  if (strlen(Cmd) > 10 || cmdp == 'h' || cmdp == 'H') {
 +    PrintAndLog("Usage:  data psk1rawdemod [clock] <0|1> [maxError]");
 +    PrintAndLog("     [set clock as integer] optional, if not set, autodetect.");
 +    PrintAndLog("     <invert>, 1 for invert output");
 +    PrintAndLog("     [set maximum allowed errors], default = 100.");
 +    PrintAndLog("");
 +    PrintAndLog("    sample: data psk1rawdemod        = demod a psk1 tag from GraphBuffer");
 +    PrintAndLog("          : data psk1rawdemod 32     = demod a psk1 tag from GraphBuffer using a clock of RF/32");
 +    PrintAndLog("          : data psk1rawdemod 32 1   = demod a psk1 tag from GraphBuffer using a clock of RF/32 and inverting data");
 +    PrintAndLog("          : data psk1rawdemod 1      = demod a psk1 tag from GraphBuffer while inverting data");
 +    PrintAndLog("          : data psk1rawdemod 64 1 0 = demod a psk1 tag from GraphBuffer using a clock of RF/64, inverting data and allowing 0 demod errors");
 +    return 0;
 +  }
 +  errCnt = PSKDemod(Cmd, 1);
        //output
        if (errCnt<0){
 -    if (g_debugMode) PrintAndLog("Error demoding: %d",errCnt);  
 +    if (g_debugMode) PrintAndLog("Error demoding: %d",errCnt); 
      return 0;
 -  } 
 +  }
        if (errCnt>0){
 -              if (g_debugMode){
 -      PrintAndLog("# Errors during Demoding (shown as 77 in bit stream): %d",errCnt);
 -      PrintAndLog("PSK or NRZ demoded bitstream:");
 -      // Now output the bitstream to the scrollback by line of 16 bits
 -      printDemodBuff();
 -    }
 +    PrintAndLog("# Errors during Demoding (shown as 77 in bit stream): %d",errCnt);
        }else{
 -    PrintAndLog("PSK or NRZ demoded bitstream:");
 -    // Now output the bitstream to the scrollback by line of 16 bits
 -    printDemodBuff();  
 -    return 1;
    }
 -  return 0;
 +  PrintAndLog("PSK demoded bitstream:");
 +  // Now output the bitstream to the scrollback by line of 16 bits
 +  printDemodBuff();
 +  return 1;
  }
  
  // by marshmellow
  int CmdPSK2rawDemod(const char *Cmd)
  {
    int errCnt=0;
 -  errCnt=PSKnrzDemod(Cmd, 1);
 +  char cmdp = param_getchar(Cmd, 0);
 +  if (strlen(Cmd) > 10 || cmdp == 'h' || cmdp == 'H') {
 +    PrintAndLog("Usage:  data psk2rawdemod [clock] <0|1> [maxError]");
 +    PrintAndLog("     [set clock as integer] optional, if not set, autodetect.");
 +    PrintAndLog("     <invert>, 1 for invert output");
 +    PrintAndLog("     [set maximum allowed errors], default = 100.");
 +    PrintAndLog("");
 +    PrintAndLog("    sample: data psk2rawdemod        = demod a psk2 tag from GraphBuffer, autodetect clock");
 +    PrintAndLog("          : data psk2rawdemod 32     = demod a psk2 tag from GraphBuffer using a clock of RF/32");
 +    PrintAndLog("          : data psk2rawdemod 32 1   = demod a psk2 tag from GraphBuffer using a clock of RF/32 and inverting output");
 +    PrintAndLog("          : data psk2rawdemod 1      = demod a psk2 tag from GraphBuffer, autodetect clock and invert output");
 +    PrintAndLog("          : data psk2rawdemod 64 1 0 = demod a psk2 tag from GraphBuffer using a clock of RF/64, inverting output and allowing 0 demod errors");
 +    return 0;
 +  }
 +  errCnt=PSKDemod(Cmd, 1);
    if (errCnt<0){
      if (g_debugMode) PrintAndLog("Error demoding: %d",errCnt);  
      return 0;
@@@ -1773,25 -1530,79 +1812,79 @@@ int CmdHpf(const char *Cmd
    RepaintGraphWindow();
    return 0;
  }
+ typedef struct {
+       uint8_t * buffer;
+       uint32_t numbits;
+       uint32_t position;
+ }BitstreamOut;
+ bool _headBit( BitstreamOut *stream)
+ {
+       int bytepos = stream->position >> 3; // divide by 8
+       int bitpos = (stream->position++) & 7; // mask out 00000111
+       return (*(stream->buffer + bytepos) >> (7-bitpos)) & 1;
+ }
+ uint8_t getByte(uint8_t bits_per_sample, BitstreamOut* b)
+ {
+       int i;
+       uint8_t val = 0;
+       for(i =0 ; i < bits_per_sample; i++)
+       {
+               val |= (_headBit(b) << (7-i));
+       }
+       return val;
+ }
  
  int CmdSamples(const char *Cmd)
  {
-       uint8_t got[BIGBUF_SIZE] = {0x00};
+       //If we get all but the last byte in bigbuf,
+       // we don't have to worry about remaining trash
+       // in the last byte in case the bits-per-sample
+       // does not line up on byte boundaries
+       uint8_t got[BIGBUF_SIZE-1] = { 0 };
  
        int n = strtol(Cmd, NULL, 0);
        if (n == 0)
-               n = 20000;
+               n = sizeof(got);
  
        if (n > sizeof(got))
                n = sizeof(got);
  
-       PrintAndLog("Reading %d samples from device memory\n", n);
+       PrintAndLog("Reading %d bytes from device memory\n", n);
        GetFromBigBuf(got,n,0);
-       WaitForResponse(CMD_ACK,NULL);
-       for (int j = 0; j < n; j++) {
-               GraphBuffer[j] = ((int)got[j]) - 128;
+       PrintAndLog("Data fetched");
+       UsbCommand response;
+       WaitForResponse(CMD_ACK, &response);
+       uint8_t bits_per_sample = 8;
+       //Old devices without this feature would send 0 at arg[0]
+       if(response.arg[0] > 0)
+       {
+               sample_config *sc = (sample_config *) response.d.asBytes;
+               PrintAndLog("Samples @ %d bits/smpl, decimation 1:%d ", sc->bits_per_sample
+                                       , sc->decimation);
+               bits_per_sample = sc->bits_per_sample;
        }
-       GraphTraceLen = n;
+       if(bits_per_sample < 8)
+       {
+               PrintAndLog("Unpacking...");
+               BitstreamOut bout = { got, bits_per_sample * n,  0};
+               int j =0;
+               for (j = 0; j * bits_per_sample < n * 8 && j < sizeof(GraphBuffer); j++) {
+                       uint8_t sample = getByte(bits_per_sample, &bout);
+                       GraphBuffer[j] = ((int) sample )- 128;
+               }
+               GraphTraceLen = j;
+               PrintAndLog("Unpacked %d samples" , j );
+       }else
+       {
+               for (int j = 0; j < n; j++) {
+                       GraphBuffer[j] = ((int)got[j]) - 128;
+               }
+               GraphTraceLen = n;
+       }
        RepaintGraphWindow();
        return 0;
  }
@@@ -2284,9 -2095,7 +2377,9 @@@ static command_t CommandTable[] 
    {"help",          CmdHelp,            1, "This help"},
    {"amp",           CmdAmp,             1, "Amplify peaks"},
    {"askdemod",      Cmdaskdemod,        1, "<0 or 1> -- Attempt to demodulate simple ASK tags"},
 -      {"askmandemod",   Cmdaskmandemod,     1, "[clock] [invert<0|1>] -- Attempt to demodulate ASK/Manchester tags and output binary (args optional)"},
 +  {"askedgedetect", CmdAskEdgeDetect,   1, "[threshold] Adjust Graph for manual ask demod using length of sample differences to detect the edge of a wave - default = 25"},
 +  {"askem410xdemod",CmdAskEM410xDemod,  1, "[clock] [invert<0|1>] [maxErr] -- Attempt to demodulate ASK/Manchester tags and output binary (args optional)"},
 +      {"askmandemod",   Cmdaskmandemod,     1, "[clock] [invert<0|1>] [maxErr] -- Attempt to demodulate ASK/Manchester tags and output binary (args optional)"},
        {"askrawdemod",   Cmdaskrawdemod,     1, "[clock] [invert<0|1>] -- Attempt to demodulate ASK tags and output bin (args optional)"},
    {"autocorr",      CmdAutoCorr,        1, "<window length> -- Autocorrelation over window"},
    {"biphaserawdecode",CmdBiphaseDecodeRaw,1,"[offset] [invert<0|1>] Biphase decode bin stream in demod buffer (offset = 0|1 bits to shift the decode start)"},
    {"manrawdecode",  Cmdmandecoderaw,    1, "Manchester decode binary stream already in graph buffer"},
    {"manmod",        CmdManchesterMod,   1, "[clock rate] -- Manchester modulate a binary stream"},
        {"norm",          CmdNorm,            1, "Normalize max/min to +/-128"},
 +  {"nrzdetectclock",CmdDetectNRZClockRate, 1, "Detect ASK, PSK, or NRZ clock rate"},
 +  {"nrzrawdemod",   CmdNRZrawDemod,     1, "[clock] [invert<0|1>] [maxErr] -- Attempt to demodulate nrz tags and output binary (args optional)"},
    {"plot",          CmdPlot,            1, "Show graph window (hit 'h' in window for keystroke help)"},
 -      {"pskclean",      CmdPskClean,        1, "Attempt to clean psk wave"},
 -      {"pskdetectclock",CmdDetectNRZpskClockRate, 1, "Detect ASK, PSK, or NRZ clock rate"},
 +      {"pskdetectclock",CmdDetectPSKClockRate, 1, "Detect ASK, PSK, or NRZ clock rate"},
        {"pskindalademod",CmdIndalaDecode,    1, "[clock] [invert<0|1>] -- Attempt to demodulate psk1 indala tags and output ID binary & hex (args optional)"},
 -      {"psk1nrzrawdemod",CmdpskNRZrawDemod, 1, "[clock] [invert<0|1>] -- Attempt to demodulate psk1 or nrz tags and output binary (args optional)"},
 -  {"psk2rawdemod",  CmdPSK2rawDemod,    1, "[clock] [invert<0|1>] -- Attempt to demodulate psk2 tags and output binary (args optional)"},
 +      {"psk1rawdemod",  CmdPSK1rawDemod,    1, "[clock] [invert<0|1>] [maxErr] -- Attempt to demodulate psk1 tags and output binary (args optional)"},
 +  {"psk2rawdemod",  CmdPSK2rawDemod,    1, "[clock] [invert<0|1>] [maxErr] -- Attempt to demodulate psk2 tags and output binary (args optional)"},
    {"samples",       CmdSamples,         0, "[512 - 40000] -- Get raw samples for graph window"},
    {"save",          CmdSave,            1, "<filename> -- Save trace (from graph window)"},
    {"scale",         CmdScale,           1, "<int> -- Set cursor display scale"},
    {"threshold",     CmdThreshold,       1, "<threshold> -- Maximize/minimize every value in the graph window depending on threshold"},
        {"dirthreshold",  CmdDirectionalThreshold,   1, "<thres up> <thres down> -- Max rising higher up-thres/ Min falling lower down-thres, keep rest as prev."},
        {"tune",          CmdTuneSamples,     0, "Get hw tune samples for graph window"},
-   {"zerocrossings", CmdZerocrossings,   1, "Count time between zero-crossings"},
+       {"undec",         CmdUndec,         1, "Un-decimate samples by 2"},
+       {"zerocrossings", CmdZerocrossings,   1, "Count time between zero-crossings"},
    {NULL, NULL, 0, NULL}
  };
  
diff --combined client/cmdlf.c
index a34275f36763f664e9f0847542e8fd98a5f1cacf,f56aa1b7576fe758e5d84cb728f4de9eed02610a..ea1ff131430ecbcd4d5a6519ac18797ebc5ac0f2
@@@ -356,24 -356,155 +356,155 @@@ int CmdIndalaClone(const char *Cmd
    return 0;
  }
  
+ int usage_lf_read()
+ {
+       PrintAndLog("Usage: lf read");
+       PrintAndLog("Options:        ");
+       PrintAndLog("       h            This help");
+       PrintAndLog("This function takes no arguments. ");
+       PrintAndLog("Use 'lf config' to set parameters.");
+       return 0;
+ }
+ int usage_lf_snoop()
+ {
+       PrintAndLog("Usage: lf snoop");
+       PrintAndLog("Options:        ");
+       PrintAndLog("       h            This help");
+       PrintAndLog("This function takes no arguments. ");
+       PrintAndLog("Use 'lf config' to set parameters.");
+       return 0;
+ }
+ int usage_lf_config()
+ {
+       PrintAndLog("Usage: lf config [H|<divisor>] [b <bps>] [d <decim>] [a 0|1]");
+       PrintAndLog("Options:        ");
+       PrintAndLog("       h             This help");
+       PrintAndLog("       L             Low frequency (125 KHz)");
+       PrintAndLog("       H             High frequency (134 KHz)");
+       PrintAndLog("       q <divisor>   Manually set divisor. 88-> 134KHz, 95-> 125 Hz");
+       PrintAndLog("       b <bps>       Sets resolution of bits per sample. Default (max): 8");
+       PrintAndLog("       d <decim>     Sets decimation. A value of N saves only 1 in N samples. Default: 1");
+       PrintAndLog("       a [0|1]       Averaging - if set, will average the stored sample value when decimating. Default: 1");
+       PrintAndLog("       t <threshold> Sets trigger threshold. 0 means no threshold");
+       PrintAndLog("Examples:");
+       PrintAndLog("      lf config b 8 L");
+       PrintAndLog("                    Samples at 125KHz, 8bps.");
+       PrintAndLog("      lf config H b 4 d 3");
+       PrintAndLog("                    Samples at 134KHz, averages three samples into one, stored with ");
+       PrintAndLog("                    a resolution of 4 bits per sample.");
+       PrintAndLog("      lf read");
+       PrintAndLog("                    Performs a read (active field)");
+       PrintAndLog("      lf snoop");
+       PrintAndLog("                    Performs a snoop (no active field)");
+       return 0;
+ }
+ int CmdLFSetConfig(const char *Cmd)
+ {
+       uint8_t divisor =  0;//Frequency divisor
+       uint8_t bps = 0; // Bits per sample
+       uint8_t decimation = 0; //How many to keep
+       bool averaging = 1; // Defaults to true
+       bool errors = FALSE;
+       int trigger_threshold =-1;//Means no change
+       uint8_t unsigned_trigg = 0;
+       uint8_t cmdp =0;
+       while(param_getchar(Cmd, cmdp) != 0x00)
+       {
+               PrintAndLog("working %c", param_getchar(Cmd, cmdp));
+               switch(param_getchar(Cmd, cmdp))
+               {
+               case 'h':
+                       return usage_lf_config();
+               case 'H':
+                       divisor = 88;
+                       cmdp++;
+                       break;
+               case 'L':
+                       divisor = 95;
+                       cmdp++;
+                       break;
+               case 'q':
+                       errors |= param_getdec(Cmd,cmdp+1,&divisor);
+                       cmdp+=2;
+                       break;
+               case 't':
+                       errors |= param_getdec(Cmd,cmdp+1,&unsigned_trigg);
+                       cmdp+=2;
+                       if(!errors) trigger_threshold = unsigned_trigg;
+                       break;
+               case 'b':
+                       errors |= param_getdec(Cmd,cmdp+1,&bps);
+                       cmdp+=2;
+                       break;
+               case 'd':
+                       errors |= param_getdec(Cmd,cmdp+1,&decimation);
+                       cmdp+=2;
+                       break;
+               case 'a':
+                       averaging = param_getchar(Cmd,cmdp+1) == '1';
+                       cmdp+=2;
+                       break;
+               default:
+                       PrintAndLog("Unknown parameter '%c'", param_getchar(Cmd, cmdp));
+                       errors = 1;
+                       break;
+               }
+               if(errors) break;
+       }
+       if(cmdp == 0)
+       {
+               errors = 1;// No args
+       }
+       //Validations
+       if(errors)
+       {
+               return usage_lf_config();
+       }
+       //Bps is limited to 8, so fits in lower half of arg1
+       if(bps >> 8) bps = 8;
+       sample_config config = {
+               decimation,bps,averaging,divisor,trigger_threshold
+       };
+       //Averaging is a flag on high-bit of arg[1]
+       UsbCommand c = {CMD_SET_LF_SAMPLING_CONFIG};
+       memcpy(c.d.asBytes,&config,sizeof(sample_config));
+       SendCommand(&c);
+       return 0;
+ }
  int CmdLFRead(const char *Cmd)
  {
-   UsbCommand c = {CMD_ACQUIRE_RAW_ADC_SAMPLES_125K};
-   // 'h' means higher-low-frequency, 134 kHz
-   if(*Cmd == 'h') {
-     c.arg[0] = 1;
-   } else if (*Cmd == '\0') {
-     c.arg[0] = 0;
-   } else if (sscanf(Cmd, "%"lli, &c.arg[0]) != 1) {
-               PrintAndLog("Samples 1: 'lf read'");
-               PrintAndLog("        2: 'lf read h'");
-               PrintAndLog("        3: 'lf read <divisor>'");
-     return 0;
-   }
-   SendCommand(&c);
-   WaitForResponse(CMD_ACK,NULL);
-   return 0;
+       uint8_t cmdp =0;
+       if(param_getchar(Cmd, cmdp) == 'h')
+       {
+               return usage_lf_read();
+       }
+       //And ship it to device
+       UsbCommand c = {CMD_ACQUIRE_RAW_ADC_SAMPLES_125K};
+       SendCommand(&c);
+       WaitForResponse(CMD_ACK,NULL);
+       return 0;
+ }
+ int CmdLFSnoop(const char *Cmd)
+ {
+       uint8_t cmdp =0;
+       if(param_getchar(Cmd, cmdp) == 'h')
+       {
+               return usage_lf_snoop();
+       }
+       UsbCommand c = {CMD_LF_SNOOP_RAW_ADC_SAMPLES};
+       SendCommand(&c);
+       WaitForResponse(CMD_ACK,NULL);
+       return 0;
  }
  
  static void ChkBitstream(const char *str)
@@@ -450,33 -581,6 +581,6 @@@ int CmdLFSimManchester(const char *Cmd
    return 0;
  }
  
- int CmdLFSnoop(const char *Cmd)
- {
-   UsbCommand c = {CMD_LF_SNOOP_RAW_ADC_SAMPLES};
-   // 'h' means higher-low-frequency, 134 kHz
-   c.arg[0] = 0;
-   c.arg[1] = -1;
-       if (*Cmd == 'l') {
-     sscanf(Cmd, "l %"lli, &c.arg[1]);
-   } else if(*Cmd == 'h') {
-     c.arg[0] = 1;
-     sscanf(Cmd, "h %"lli, &c.arg[1]);
-   } else if (sscanf(Cmd, "%"lli" %"lli, &c.arg[0], &c.arg[1]) < 1) {
-               PrintAndLog("usage 1:  snoop");
-               PrintAndLog("      2:  snoop <l|h> [trigger threshold]");
-               PrintAndLog("      3:  snoop <divisor> [trigger threshold]");
-               PrintAndLog("");
-               PrintAndLog("Sample: lf snoop l 200");
-               PrintAndLog("      : lf snoop 95 200");
-     return 0;
-   }
-   SendCommand(&c);
-   WaitForResponse(CMD_ACK,NULL);
-   return 0;
- }
  
  int CmdVchDemod(const char *Cmd)
  {
@@@ -559,17 -663,13 +663,17 @@@ int CmdLFfind(const char *Cmd
  {
    int ans=0;
        char cmdp = param_getchar(Cmd, 0);
 -      
 -      if (strlen(Cmd) > 1 || cmdp == 'h' || cmdp == 'H') {
 -              PrintAndLog("Usage:  lf search <0|1>");
 -              PrintAndLog("     <use data from Graphbuffer>, if not set, try reading data from tag.");
 +      char testRaw = param_getchar(Cmd, 1);
 +      if (strlen(Cmd) > 2 || cmdp == 'h' || cmdp == 'H') {
 +              PrintAndLog("Usage:  lf search <0|1> [u]");
 +              PrintAndLog("     <use data from Graphbuffer> , if not set, try reading data from tag.");
 +    PrintAndLog("     [Search for Unknown tags] , if not set, reads only known tags.");
                PrintAndLog("");
 -              PrintAndLog("    sample: lf search");
 -              PrintAndLog("          : lf search 1");
 +              PrintAndLog("    sample: lf search     = try reading data from tag & search for known tags");
 +              PrintAndLog("          : lf search 1   = use data from GraphBuffer & search for known tags");
 +    PrintAndLog("          : lf search u   = try reading data from tag & search for known and unknown tags");
 +    PrintAndLog("          : lf search 1 u = use data from GraphBuffer & search for known and unknown tags");
 +
                return 0;
        }
  
                PrintAndLog("Data in Graphbuffer was too small.");
                return 0;
    }
 -
 +  if (cmdp == 'u' || cmdp == 'U') testRaw = 'u';
    PrintAndLog("NOTE: some demods output possible binary\n  if it finds something that looks like a tag");
 +  PrintAndLog("False Positives ARE possible\n");  
    PrintAndLog("\nChecking for known tags:\n");
    ans=CmdFSKdemodIO("");
    if (ans>0) {
      PrintAndLog("\nValid Indala ID Found!");
      return 1;
    }
 -  ans=Cmdaskmandemod("");
 +  ans=CmdAskEM410xDemod("");
    if (ans>0) {
      PrintAndLog("\nValid EM410x ID Found!");
      return 1;
    }
 -  PrintAndLog("No Known Tags Found!\n");
 +  PrintAndLog("\nNo Known Tags Found!\n");
 +  if (testRaw=='u' || testRaw=='U'){
 +    //test unknown tag formats (raw mode)
 +    PrintAndLog("\nChecking for Unknown tags:\n");
 +    ans=CmdFSKfcDetect("");
 +    if (ans == 1){ //fsk
 +      ans=CmdFSKrawdemod("");
 +      if (ans>0) {
 +        PrintAndLog("\nUnknown FSK Modulated Tag Found!");
 +        return 1;
 +      }      
 +    }
 +    ans=Cmdaskmandemod("");
 +    if (ans>0) {
 +      PrintAndLog("\nUnknown ASK Modulated and Manchester encoded Tag Found!");
 +      return 1;
 +    }  
 +    ans=CmdPSK1rawDemod("");
 +    if (ans>0) {
 +      PrintAndLog("Possible unknown PSK1 Modulated Tag Found above!\n\nCould also be PSK2 - try 'data psk2rawdemod'");
 +      PrintAndLog("\nCould also be PSK3 - [currently not supported]");
 +      PrintAndLog("\nCould also be NRZ - try 'data nrzrawdemod");
 +      return 1;
 +    }          
 +    PrintAndLog("\nNo Data Found!\n");
 +  }
    return 0;
  }
  
@@@ -654,12 -728,13 +758,13 @@@ static command_t CommandTable[] 
    {"help",        CmdHelp,            1, "This help"},
    {"cmdread",     CmdLFCommandRead,   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)"},
    {"em4x",        CmdLFEM4X,          1, "{ EM4X RFIDs... }"},
+   {"config",      CmdLFSetConfig,     0, "Set config for LF sampling, bit/sample, decimation, frequency"},
    {"flexdemod",   CmdFlexdemod,       1, "Demodulate samples for FlexPass"},
    {"hid",         CmdLFHID,           1, "{ HID RFIDs... }"},
    {"io",                CmdLFIO,                1, "{ ioProx tags... }"},
    {"indalademod", CmdIndalaDemod,     1, "['224'] -- Demodulate samples for Indala 64 bit UID (option '224' for 224 bit)"},
    {"indalaclone", CmdIndalaClone,     0, "<UID> ['l']-- Clone Indala to T55x7 (tag must be in antenna)(UID in HEX)(option 'l' for 224 UID"},
-   {"read",        CmdLFRead,          0, "['h' or <divisor>] -- Read 125/134 kHz LF ID-only tag (option 'h' for 134, alternatively: f=12MHz/(divisor+1))"},
+   {"read",        CmdLFRead,          0, "Read 125/134 kHz LF ID-only tag. Do 'lf read h' for help"},
    {"search",      CmdLFfind,          1, "Read and Search for valid known tag (in offline mode it you can load first then search)"},
    {"sim",         CmdLFSim,           0, "[GAP] -- Simulate LF tag from buffer with optional GAP (in microseconds)"},
    {"simbidir",    CmdLFSimBidir,      0, "Simulate LF tag (with bidirectional data transmission between reader and tag)"},
diff --combined client/graph.h
index 56d6178c4995d648cee294378bce7ce1306d4e17,9817d7762d7575714b994927a2bd7e0e2a452400..279b5f7b0b57b4ea83424e55dfc4e89293168fc1
@@@ -17,14 -17,15 +17,16 @@@ int ClearGraph(int redraw)
  //int DetectClock(int peak);
  size_t getFromGraphBuf(uint8_t *buff);
  int GetClock(const char *str, int peak, int verbose);
 -int GetNRZpskClock(const char *str, int peak, int verbose);
 +int GetPskClock(const char *str, int peak, int verbose);
 +int GetNrzClock(const char *str, int peak, int verbose);
  void setGraphBuf(uint8_t *buff, size_t size);
  
  bool HasGraphData();
  void DetectHighLowInGraph(int *high, int *low, bool addFuzz); 
  
- #define MAX_GRAPH_TRACE_LEN (1024*128)
+ // Max graph trace len: 40000 (bigbuf) * 8 (at 1 bit per sample)
+ #define MAX_GRAPH_TRACE_LEN (40000 * 8 )
  extern int GraphBuffer[MAX_GRAPH_TRACE_LEN];
  extern int GraphTraceLen;
  #endif
Impressum, Datenschutz