+ return;
+}
+
+int CmdPrintDemodBuff(const char *Cmd)
+{
+ char hex[512]={0x00};
+ bool hexMode = false;
+ bool errors = false;
+ uint32_t offset = 0; //could be size_t but no param_get16...
+ uint32_t length = 512;
+ char cmdp = 0;
+ while(param_getchar(Cmd, cmdp) != 0x00)
+ {
+ switch(param_getchar(Cmd, cmdp))
+ {
+ case 'h':
+ case 'H':
+ return usage_data_printdemodbuf();
+ case 'x':
+ case 'X':
+ hexMode = true;
+ cmdp++;
+ break;
+ case 'o':
+ case 'O':
+ offset = param_get32ex(Cmd, cmdp+1, 0, 10);
+ if (!offset) errors = true;
+ cmdp += 2;
+ break;
+ case 'l':
+ case 'L':
+ length = param_get32ex(Cmd, cmdp+1, 512, 10);
+ if (!length) errors = true;
+ cmdp += 2;
+ break;
+ default:
+ PrintAndLog("Unknown parameter '%c'", param_getchar(Cmd, cmdp));
+ errors = true;
+ break;
+ }
+ if(errors) break;
+ }
+ //Validations
+ if(errors) return usage_data_printdemodbuf();
+ length = (length > (DemodBufferLen-offset)) ? DemodBufferLen-offset : length;
+ int numBits = (length) & 0x00FFC; //make sure we don't exceed our string
+
+ if (hexMode){
+ char *buf = (char *) (DemodBuffer + offset);
+ numBits = (numBits > sizeof(hex)) ? sizeof(hex) : numBits;
+ numBits = binarraytohex(hex, buf, numBits);
+ if (numBits==0) return 0;
+ PrintAndLog("DemodBuffer: %s",hex);
+ } else {
+ PrintAndLog("DemodBuffer:\n%s", sprint_bin_break(DemodBuffer+offset,numBits,16));
+ }
+ return 1;
+}
+
+//by marshmellow
+//this function strictly converts >1 to 1 and <1 to 0 for each sample in the graphbuffer
+int CmdGetBitStream(const char *Cmd)
+{
+ int i;
+ CmdHpf(Cmd);
+ for (i = 0; i < GraphTraceLen; i++) {
+ if (GraphBuffer[i] >= 1) {
+ GraphBuffer[i] = 1;
+ } else {
+ GraphBuffer[i] = 0;
+ }
+ }
+ RepaintGraphWindow();
+ return 0;
+}
+
+//by marshmellow
+//Cmd Args: Clock, invert, maxErr, maxLen as integers and amplify as char == 'a'
+// (amp may not be needed anymore)
+//verbose will print results and demoding messages
+//emSearch will auto search for EM410x format in bitstream
+//askType switches decode: ask/raw = 0, ask/manchester = 1
+int ASKDemod_ext(const char *Cmd, bool verbose, bool emSearch, uint8_t askType, bool *stCheck) {
+ int invert=0;
+ int clk=0;
+ int maxErr=100;
+ int maxLen=0;
+ uint8_t askamp = 0;
+ char amp = param_getchar(Cmd, 0);
+ uint8_t BitStream[MAX_GRAPH_TRACE_LEN]={0};
+ sscanf(Cmd, "%i %i %i %i %c", &clk, &invert, &maxErr, &maxLen, &);
+ if (!maxLen) maxLen = BIGBUF_SIZE;
+ 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) PrintAndLog("DEBUG: Bitlen from grphbuff: %d",BitLen);
+ if (BitLen < 255) return 0;
+ if (maxLen < BitLen && maxLen != 0) BitLen = maxLen;
+ int foundclk = 0;
+ //amp before ST check
+ if (amp == 'a' || amp == 'A') {
+ askAmp(BitStream, BitLen);
+ }
+ bool st = false;
+ size_t ststart = 0, stend = 0;
+ if (*stCheck) st = DetectST(BitStream, &BitLen, &foundclk, &ststart, &stend);
+ *stCheck = st;
+ if (st) {
+ clk = (clk == 0) ? foundclk : clk;
+ CursorCPos = ststart;
+ CursorDPos = stend;
+ if (verbose || g_debugMode) PrintAndLog("\nFound Sequence Terminator - First one is shown by orange and blue graph markers");
+ //Graph ST trim (for testing)
+ //for (int i = 0; i < BitLen; i++) {
+ // GraphBuffer[i] = BitStream[i]-128;
+ //}
+ //RepaintGraphWindow();
+ }
+ int startIdx = 0;
+ int errCnt = askdemod_ext(BitStream, &BitLen, &clk, &invert, maxErr, askamp, askType, &startIdx);
+ if (errCnt<0 || BitLen<16){ //if fatal error (or -1)
+ if (g_debugMode) PrintAndLog("DEBUG: no data found %d, errors:%d, bitlen:%d, clock:%d",errCnt,invert,BitLen,clk);
+ return 0;
+ }
+ if (errCnt > maxErr){
+ if (g_debugMode) PrintAndLog("DEBUG: Too many errors found, errors:%d, bits:%d, clock:%d",errCnt, BitLen, clk);
+ return 0;
+ }
+ if (verbose || g_debugMode) PrintAndLog("\nUsing Clock:%d, Invert:%d, Bits Found:%d",clk,invert,BitLen);
+ //output
+ setDemodBuf(BitStream,BitLen,0);
+ setClockGrid(clk, startIdx);
+
+ if (verbose || g_debugMode){
+ if (errCnt>0) PrintAndLog("# Errors during Demoding (shown as 7 in bit stream): %d",errCnt);
+ if (askType) PrintAndLog("ASK/Manchester - Clock: %d - Decoded bitstream:",clk);
+ else PrintAndLog("ASK/Raw - Clock: %d - Decoded bitstream:",clk);
+ // Now output the bitstream to the scrollback by line of 16 bits
+ printDemodBuff();
+
+ }
+ uint64_t lo = 0;
+ uint32_t hi = 0;
+ if (emSearch){
+ AskEm410xDecode(true, &hi, &lo);
+ }
+ return 1;
+}
+int ASKDemod(const char *Cmd, bool verbose, bool emSearch, uint8_t askType) {
+ bool st = false;
+ return ASKDemod_ext(Cmd, verbose, emSearch, askType, &st);
+}
+
+//by marshmellow
+//takes 5 arguments - clock, invert, maxErr, maxLen as integers and amplify as char == 'a'
+//attempts to demodulate ask while decoding manchester
+//prints binary found and saves in graphbuffer for further commands
+int Cmdaskmandemod(const char *Cmd)
+{
+ char cmdp = param_getchar(Cmd, 0);
+ if (strlen(Cmd) > 45 || cmdp == 'h' || cmdp == 'H') {
+ PrintAndLog("Usage: data rawdemod am <s> [clock] <invert> [maxError] [maxLen] [amplify]");
+ PrintAndLog(" ['s'] optional, check for Sequence Terminator");
+ PrintAndLog(" [set clock as integer] optional, if not set, autodetect");
+ PrintAndLog(" <invert>, 1 to invert output");
+ PrintAndLog(" [set maximum allowed errors], default = 100");
+ PrintAndLog(" [set maximum Samples to read], default = 32768 (512 bits at rf/64)");
+ PrintAndLog(" <amplify>, 'a' to attempt demod with ask amplification, default = no amp");
+ PrintAndLog("");
+ PrintAndLog(" sample: data rawdemod am = demod an ask/manchester tag from GraphBuffer");
+ PrintAndLog(" : data rawdemod am 32 = demod an ask/manchester tag from GraphBuffer using a clock of RF/32");
+ PrintAndLog(" : data rawdemod am 32 1 = demod an ask/manchester tag from GraphBuffer using a clock of RF/32 and inverting data");
+ PrintAndLog(" : data rawdemod am 1 = demod an ask/manchester tag from GraphBuffer while inverting data");
+ PrintAndLog(" : data rawdemod am 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;
+ }
+ bool st = true;
+ if (Cmd[0]=='s')
+ return ASKDemod_ext(Cmd++, true, false, 1, &st);
+ else if (Cmd[1] == 's')
+ return ASKDemod_ext(Cmd+=2, true, false, 1, &st);
+ else
+ return ASKDemod(Cmd, true, false, 1);
+}
+
+//by marshmellow
+//manchester decode
+//stricktly take 10 and 01 and convert to 0 and 1
+int Cmdmandecoderaw(const char *Cmd)
+{
+ int i =0;
+ int errCnt=0;
+ size_t size=0;
+ int invert=0;
+ int maxErr = 20;
+ char cmdp = param_getchar(Cmd, 0);
+ if (strlen(Cmd) > 5 || cmdp == 'h' || cmdp == 'H') {
+ PrintAndLog("Usage: data manrawdecode [invert] [maxErr]");
+ PrintAndLog(" Takes 10 and 01 and converts to 0 and 1 respectively");
+ PrintAndLog(" --must have binary sequence in demodbuffer (run data askrawdemod first)");
+ PrintAndLog(" [invert] invert output");
+ PrintAndLog(" [maxErr] set number of errors allowed (default = 20)");
+ PrintAndLog("");
+ PrintAndLog(" sample: data manrawdecode = decode manchester bitstream from the demodbuffer");
+ return 0;
+ }
+ if (DemodBufferLen==0) return 0;
+ uint8_t BitStream[MAX_DEMOD_BUF_LEN]={0};
+ int high=0,low=0;
+ for (;i<DemodBufferLen;++i){
+ if (DemodBuffer[i]>high) high=DemodBuffer[i];
+ else if(DemodBuffer[i]<low) low=DemodBuffer[i];
+ BitStream[i]=DemodBuffer[i];
+ }
+ if (high>7 || low <0 ){
+ PrintAndLog("Error: please raw demod the wave first then manchester raw decode");
+ return 0;
+ }
+
+ sscanf(Cmd, "%i %i", &invert, &maxErr);
+ size=i;
+ uint8_t alignPos = 0;
+ errCnt=manrawdecode(BitStream, &size, invert, &alignPos);
+ if (errCnt>=maxErr){
+ PrintAndLog("Too many errors: %d",errCnt);
+ return 0;
+ }
+ PrintAndLog("Manchester Decoded - # errors:%d - data:",errCnt);
+ PrintAndLog("%s", sprint_bin_break(BitStream, size, 16));
+ if (errCnt==0){
+ uint64_t id = 0;
+ uint32_t hi = 0;
+ size_t idx=0;
+ if (Em410xDecode(BitStream, &size, &idx, &hi, &id)){
+ //need to adjust to set bitstream back to manchester encoded data
+ //setDemodBuf(BitStream, size, idx);
+
+ printEM410x(hi, id);
+ }
+ }
+ return 1;
+}
+
+//by marshmellow
+//biphase decode
+//take 01 or 10 = 0 and 11 or 00 = 1
+//takes 2 arguments "offset" default = 0 if 1 it will shift the decode by one bit
+// and "invert" default = 0 if 1 it will invert output
+// the argument offset allows us to manually shift if the output is incorrect - [EDIT: now auto detects]
+int CmdBiphaseDecodeRaw(const char *Cmd)
+{
+ size_t size=0;
+ int offset=0, invert=0, maxErr=20, errCnt=0;
+ char cmdp = param_getchar(Cmd, 0);
+ if (strlen(Cmd) > 3 || cmdp == 'h' || cmdp == 'H') {
+ PrintAndLog("Usage: data biphaserawdecode [offset] [invert] [maxErr]");
+ PrintAndLog(" Converts 10 or 01 to 1 and 11 or 00 to 0");
+ PrintAndLog(" --must have binary sequence in demodbuffer (run data askrawdemod first)");
+ PrintAndLog(" --invert for Conditional Dephase Encoding (CDP) AKA Differential Manchester");
+ 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(" [maxErr int], set max errors tolerated - default=20");
+ 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 %i", &offset, &invert, &maxErr);
+ if (DemodBufferLen==0) {
+ PrintAndLog("DemodBuffer Empty - run 'data rawdemod ar' first");
+ return 0;
+ }
+ uint8_t BitStream[MAX_DEMOD_BUF_LEN]={0};
+ size = sizeof(BitStream);
+ if ( !getDemodBuf(BitStream, &size) ) return 0;
+ errCnt=BiphaseRawDecode(BitStream, &size, &offset, invert);
+ if (errCnt<0){
+ PrintAndLog("Error during decode:%d", errCnt);
+ return 0;
+ }
+ if (errCnt>maxErr){
+ PrintAndLog("Too many errors attempting to decode: %d",errCnt);
+ return 0;
+ }
+
+ if (errCnt>0){
+ PrintAndLog("# Errors found during Demod (shown as 7 in bit stream): %d",errCnt);
+ }
+
+ PrintAndLog("Biphase Decoded using offset: %d - # invert:%d - data:",offset,invert);
+ PrintAndLog("%s", sprint_bin_break(BitStream, size, 16));
+
+ if (offset) setDemodBuf(DemodBuffer,DemodBufferLen-offset, offset); //remove first bit from raw demod
+ setClockGrid(g_DemodClock, g_DemodStartIdx + g_DemodClock*offset/2);
+ return 1;
+}
+
+//by marshmellow
+// - ASK Demod then Biphase decode GraphBuffer samples
+int ASKbiphaseDemod(const char *Cmd, bool verbose)
+{
+ //ask raw demod GraphBuffer first
+ int offset=0, clk=0, invert=0, maxErr=0;
+ sscanf(Cmd, "%i %i %i %i", &offset, &clk, &invert, &maxErr);
+
+ uint8_t BitStream[MAX_GRAPH_TRACE_LEN];
+ size_t size = getFromGraphBuf(BitStream);
+ int startIdx = 0;
+ //invert here inverts the ask raw demoded bits which has no effect on the demod, but we need the pointer
+ int errCnt = askdemod_ext(BitStream, &size, &clk, &invert, maxErr, 0, 0, &startIdx);
+ if ( errCnt < 0 || errCnt > maxErr ) {
+ if (g_debugMode) PrintAndLog("DEBUG: no data or error found %d, clock: %d", errCnt, clk);
+ return 0;
+ }
+
+ //attempt to Biphase decode BitStream
+ errCnt = BiphaseRawDecode(BitStream, &size, &offset, invert);
+ if (errCnt < 0){
+ if (g_debugMode || verbose) PrintAndLog("Error BiphaseRawDecode: %d", errCnt);
+ return 0;
+ }
+ if (errCnt > maxErr) {
+ if (g_debugMode || verbose) PrintAndLog("Error BiphaseRawDecode too many errors: %d", errCnt);
+ return 0;
+ }
+ //success set DemodBuffer and return
+ setDemodBuf(BitStream, size, 0);
+ setClockGrid(clk, startIdx + clk*offset/2);
+ if (g_debugMode || verbose){
+ PrintAndLog("Biphase Decoded using offset: %d - clock: %d - # errors:%d - data:",offset,clk,errCnt);
+ printDemodBuff();
+ }
+ return 1;
+}
+//by marshmellow - see ASKbiphaseDemod
+int Cmdaskbiphdemod(const char *Cmd)
+{
+ char cmdp = param_getchar(Cmd, 0);
+ if (strlen(Cmd) > 25 || cmdp == 'h' || cmdp == 'H') {
+ PrintAndLog("Usage: data rawdemod ab [offset] [clock] <invert> [maxError] [maxLen] <amplify>");
+ PrintAndLog(" [offset], offset to begin biphase, default=0");
+ PrintAndLog(" [set clock as integer] optional, if not set, autodetect");
+ PrintAndLog(" <invert>, 1 to invert output");
+ PrintAndLog(" [set maximum allowed errors], default = 100");
+ PrintAndLog(" [set maximum Samples to read], default = 32768 (512 bits at rf/64)");
+ PrintAndLog(" <amplify>, 'a' to attempt demod with ask amplification, default = no amp");
+ PrintAndLog(" NOTE: <invert> can be entered as second or third argument");
+ PrintAndLog(" NOTE: <amplify> can be entered as first, second or last argument");
+ PrintAndLog(" NOTE: any other arg must have previous args set to work");
+ PrintAndLog("");
+ PrintAndLog(" NOTE: --invert for Conditional Dephase Encoding (CDP) AKA Differential Manchester");
+ PrintAndLog("");
+ PrintAndLog(" sample: data rawdemod ab = demod an ask/biph tag from GraphBuffer");
+ PrintAndLog(" : data rawdemod ab 0 a = demod an ask/biph tag from GraphBuffer, amplified");
+ PrintAndLog(" : data rawdemod ab 1 32 = demod an ask/biph tag from GraphBuffer using an offset of 1 and a clock of RF/32");
+ PrintAndLog(" : data rawdemod ab 0 32 1 = demod an ask/biph tag from GraphBuffer using a clock of RF/32 and inverting data");
+ PrintAndLog(" : data rawdemod ab 0 1 = demod an ask/biph tag from GraphBuffer while inverting data");
+ PrintAndLog(" : data rawdemod ab 0 64 1 0 = demod an ask/biph tag from GraphBuffer using a clock of RF/64, inverting data and allowing 0 demod errors");
+ PrintAndLog(" : data rawdemod ab 0 64 1 0 0 a = demod an ask/biph tag from GraphBuffer using a clock of RF/64, inverting data and allowing 0 demod errors, and amp");
+ return 0;
+ }
+ return ASKbiphaseDemod(Cmd, true);
+}
+
+//by marshmellow - see ASKDemod
+int Cmdaskrawdemod(const char *Cmd)
+{
+ char cmdp = param_getchar(Cmd, 0);
+ if (strlen(Cmd) > 35 || cmdp == 'h' || cmdp == 'H') {
+ PrintAndLog("Usage: data rawdemod ar [clock] <invert> [maxError] [maxLen] [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(" [set maximum Samples to read], default = 32768 (1024 bits at rf/64)");
+ PrintAndLog(" <amplify>, 'a' to attempt demod with ask amplification, default = no amp");
+ PrintAndLog("");
+ PrintAndLog(" sample: data rawdemod ar = demod an ask tag from GraphBuffer");
+ PrintAndLog(" : data rawdemod ar a = demod an ask tag from GraphBuffer, amplified");
+ PrintAndLog(" : data rawdemod ar 32 = demod an ask tag from GraphBuffer using a clock of RF/32");
+ PrintAndLog(" : data rawdemod ar 32 1 = demod an ask tag from GraphBuffer using a clock of RF/32 and inverting data");
+ PrintAndLog(" : data rawdemod ar 1 = demod an ask tag from GraphBuffer while inverting data");
+ PrintAndLog(" : data rawdemod ar 64 1 0 = demod an ask tag from GraphBuffer using a clock of RF/64, inverting data and allowing 0 demod errors");
+ PrintAndLog(" : data rawdemod ar 64 1 0 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;
+ }
+ return ASKDemod(Cmd, true, false, 0);
+}
+
+int AutoCorrelate(const int *in, int *out, size_t len, int window, bool SaveGrph, bool verbose)
+{
+ static int CorrelBuffer[MAX_GRAPH_TRACE_LEN];
+ size_t Correlation = 0;
+ int maxSum = 0;
+ int lastMax = 0;
+ if (verbose) PrintAndLog("performing %d correlations", GraphTraceLen - window);
+ for (int i = 0; i < len - window; ++i) {
+ int sum = 0;
+ for (int j = 0; j < window; ++j) {
+ sum += (in[j]*in[i + j]) / 256;
+ }
+ CorrelBuffer[i] = sum;
+ if (sum >= maxSum-100 && sum <= maxSum+100) {
+ //another max
+ Correlation = i-lastMax;
+ lastMax = i;
+ if (sum > maxSum) maxSum = sum;
+ } else if (sum > maxSum) {
+ maxSum=sum;
+ lastMax = i;
+ }
+ }
+ if (Correlation==0) {
+ //try again with wider margin
+ for (int i = 0; i < len - window; i++) {
+ if (CorrelBuffer[i] >= maxSum-(maxSum*0.05) && CorrelBuffer[i] <= maxSum+(maxSum*0.05)) {
+ //another max
+ Correlation = i-lastMax;
+ lastMax = i;
+ }
+ }
+ }
+ if (verbose && Correlation > 0) PrintAndLog("Possible Correlation: %d samples",Correlation);
+
+ if (SaveGrph) {
+ //GraphTraceLen = GraphTraceLen - window;
+ memcpy(out, CorrelBuffer, len * sizeof(int));
+ RepaintGraphWindow();
+ }
+ return Correlation;
+}
+
+int usage_data_autocorr(void)
+{
+ //print help
+ PrintAndLog("Usage: data autocorr [window] [g]");
+ PrintAndLog("Options: ");
+ PrintAndLog(" h This help");
+ PrintAndLog(" [window] window length for correlation - default = 4000");
+ PrintAndLog(" g save back to GraphBuffer (overwrite)");
+ return 0;
+}
+
+int CmdAutoCorr(const char *Cmd)
+{
+ char cmdp = param_getchar(Cmd, 0);
+ if (cmdp == 'h' || cmdp == 'H')
+ return usage_data_autocorr();
+ int window = 4000; //set default
+ char grph=0;
+ bool updateGrph = false;
+ sscanf(Cmd, "%i %c", &window, &grph);
+
+ if (window >= GraphTraceLen) {
+ PrintAndLog("window must be smaller than trace (%d samples)",
+ GraphTraceLen);
+ return 0;
+ }
+ if (grph == 'g') updateGrph=true;
+ return AutoCorrelate(GraphBuffer, GraphBuffer, GraphTraceLen, window, updateGrph, true);