From b03a05d67e3b782bff3ee4b615cbeb6885c8da29 Mon Sep 17 00:00:00 2001 From: marshmellow42 Date: Mon, 26 Jun 2017 22:49:46 -0400 Subject: [PATCH] add fsk cleaning / demod tool fsktonrz used old fskdemod for HID and adjusted it to build the tone tables for any fsk model detected or given. using the tone tables we are able to convert the fsk to clear strong NRZ/ASK even with very weak fsk waves. also fixed a small textual bug in `lf search u` output also added more graph clearing code to help ensure the demod overlay doesn't show when it shouldn't... and improved strong NRZ clock detection. --- client/cmddata.c | 197 ++++++++++++++++++++++++++++++++++++++++++- client/cmdlf.c | 2 +- client/cmdlfindala.c | 6 +- common/lfdemod.c | 16 +++- 4 files changed, 214 insertions(+), 7 deletions(-) diff --git a/client/cmddata.c b/client/cmddata.c index c12c2ce6..d624f615 100644 --- a/client/cmddata.c +++ b/client/cmddata.c @@ -1234,6 +1234,7 @@ int getSamples(int n, bool silent) } setClockGrid(0,0); + DemodBufferLen = 0; RepaintGraphWindow(); return 0; } @@ -1338,6 +1339,7 @@ int CmdLoad(const char *Cmd) fclose(f); PrintAndLog("loaded %d samples", GraphTraceLen); setClockGrid(0,0); + DemodBufferLen = 0; RepaintGraphWindow(); return 0; } @@ -1395,8 +1397,7 @@ int CmdNorm(const char *Cmd) if (max != min) { for (i = 0; i < GraphTraceLen; ++i) { - GraphBuffer[i] = (GraphBuffer[i] - ((max + min) / 2)) * 256 / - (max - min); + GraphBuffer[i] = ((long)(GraphBuffer[i] - ((max + min) / 2)) * 256) / (max - min); //marshmelow: adjusted *1000 to *256 to make +/- 128 so demod commands still work } } @@ -1606,6 +1607,197 @@ int Cmdhex2bin(const char *Cmd) return 0; } + /* + static const int LowTone[] = { + 1, 1, 1, 1, 1, -1, -1, -1, -1, -1, + 1, 1, 1, 1, 1, -1, -1, -1, -1, -1, + 1, 1, 1, 1, 1, -1, -1, -1, -1, -1, + 1, 1, 1, 1, 1, -1, -1, -1, -1, -1, + 1, 1, 1, 1, 1, -1, -1, -1, -1, -1 + }; + static const int HighTone[] = { + 1, 1, 1, 1, 1, -1, -1, -1, -1, + 1, 1, 1, 1, -1, -1, -1, -1, + 1, 1, 1, 1, -1, -1, -1, -1, + 1, 1, 1, 1, -1, -1, -1, -1, + 1, 1, 1, 1, -1, -1, -1, -1, + 1, 1, 1, 1, -1, -1, -1, -1, -1, + }; + */ +void GetHiLoTone(int *LowTone, int *HighTone, int clk, int LowToneFC, int HighToneFC) { + int i,j=0; + int Left_Modifier = ((clk % LowToneFC) % 2) + ((clk % LowToneFC)/2); + int Right_Modifier = (clk % LowToneFC) / 2; + //int HighToneMod = clk mod HighToneFC; + int LeftHalfFCCnt = (LowToneFC % 2) + (LowToneFC/2); //truncate + int FCs_per_clk = clk/LowToneFC; + + // need to correctly split up the clock to field clocks. + // First attempt uses modifiers on each end to make up for when FCs don't evenly divide into Clk + + // start with LowTone + // set extra 1 modifiers to make up for when FC doesn't divide evenly into Clk + for (i = 0; i < Left_Modifier; i++) { + LowTone[i] = 1; + } + + // loop # of field clocks inside the main clock + for (i = 0; i < (FCs_per_clk); i++) { + // loop # of samples per field clock + for (j = 0; j < LowToneFC; j++) { + LowTone[(i*LowToneFC)+Left_Modifier+j] = ( j < LeftHalfFCCnt ) ? 1 : -1; + } + } + + int k; + // add last -1 modifiers + for (k = 0; k < Right_Modifier; k++) { + LowTone[((i-1)*LowToneFC)+Left_Modifier+j+k] = -1; + } + + // now do hightone + Left_Modifier = ((clk % HighToneFC) % 2) + ((clk % HighToneFC)/2); + Right_Modifier = (clk % HighToneFC) / 2; + LeftHalfFCCnt = (HighToneFC % 2) + (HighToneFC/2); //truncate + FCs_per_clk = clk/HighToneFC; + + for (i = 0; i < Left_Modifier; i++) { + HighTone[i] = 1; + } + + // loop # of field clocks inside the main clock + for (i = 0; i < (FCs_per_clk); i++) { + // loop # of samples per field clock + for (j = 0; j < HighToneFC; j++) { + HighTone[(i*HighToneFC)+Left_Modifier+j] = ( j < LeftHalfFCCnt ) ? 1 : -1; + } + } + + // add last -1 modifiers + for (k = 0; k < Right_Modifier; k++) { + PrintAndLog("(i-1)*HighToneFC+lm+j+k %i",((i-1)*HighToneFC)+Left_Modifier+j+k); + HighTone[((i-1)*HighToneFC)+Left_Modifier+j+k] = -1; + } + if (g_debugMode == 2) { + for ( i = 0; i < clk; i++) { + PrintAndLog("Low: %i, High: %i",LowTone[i],HighTone[i]); + } + } +} + +//old CmdFSKdemod adapted by marshmellow +//converts FSK to clear NRZ style wave. (or demodulates) +int FSKClean(int *data, int *dataLen, int clk, int LowToneFC, int HighToneFC) { + if (clk == 0 || LowToneFC == 0 || HighToneFC == 0) { + int firstClockEdge=0; + uint8_t ans = fskClocks((uint8_t *) &LowToneFC, (uint8_t *) &HighToneFC, (uint8_t *) &clk, false, &firstClockEdge); + if (ans == 0) { + return 0; + } + } + int LowTone[clk]; + int HighTone[clk]; +// int LowToneFC = 10; // TODO allow args to set this +// int HighToneFC = 8; // TODO allow args to set this + GetHiLoTone(LowTone, HighTone, clk, LowToneFC, HighToneFC); + + int lowLen = sizeof(LowTone) / sizeof(int); + int highLen = sizeof(HighTone) / sizeof(int); + int convLen = (highLen > lowLen) ? highLen : lowLen; + + int i, j; + int minMark = 0, maxMark = 0; + + for (i = 0; i < *dataLen - convLen; ++i) { + int lowSum = 0, highSum = 0; + + for (j = 0; j < lowLen; ++j) { + lowSum += LowTone[j] * data[i+j]; + } + for (j = 0; j < highLen; ++j) { + highSum += HighTone[j] * data[i + j]; + } + lowSum = abs(100 * lowSum / lowLen); + highSum = abs(100 * highSum / highLen); + data[i] = (highSum << 16) | lowSum; + } + + for(i = 0; i < *dataLen - convLen - 16; ++i) { + int lowTot = 0, highTot = 0; + // 10 and 8 are fc_s divided by fc_l and fc_h, rounded + for (j = 0; j < 10; ++j) { + lowTot += (data[i+j] & 0xffff); + } + for (j = 0; j < 8; j++) { + highTot += (data[i + j] >> 16); + } + data[i] = lowTot - highTot; + if (data[i] > maxMark) maxMark = data[i]; + if (data[i] < minMark) minMark = data[i]; + } + + *dataLen -= (convLen + 16); + return 0; +} + +int usage_data_fsktonrz() { + PrintAndLog("Usage: data fsktonrz c l f "); + PrintAndLog("Options: "); + PrintAndLog(" h This help"); + PrintAndLog(" c enter the a clock (omit to autodetect)"); + PrintAndLog(" l enter a field clock (omit to autodetect)"); + PrintAndLog(" f enter a field clock (omit to autodetect)"); + return 0; +} + +int CmdFSKClean(const char *Cmd) { + // take clk, fc_low, fc_high + // blank = auto; + bool errors = false; + int clk = 0; + char cmdp = 0; + int fc_low = 10, fc_high = 8; + while(param_getchar(Cmd, cmdp) != 0x00) + { + switch(param_getchar(Cmd, cmdp)) + { + case 'h': + case 'H': + return usage_data_fsktonrz(); + case 'C': + case 'c': + clk = param_get32ex(Cmd, cmdp+1, 0, 10); + cmdp += 2; + break; + case 'F': + case 'f': + fc_high = param_get32ex(Cmd, cmdp+1, 0, 10); + cmdp += 2; + break; + case 'L': + case 'l': + fc_low = param_get32ex(Cmd, cmdp+1, 0, 10); + cmdp += 2; + break; + default: + PrintAndLog("Unknown parameter '%c'", param_getchar(Cmd, cmdp)); + errors = true; + break; + } + if(errors) break; + } + //Validations + if(errors) return usage_data_fsktonrz(); + + setClockGrid(0,0); + DemodBufferLen = 0; + int ans = FSKClean(GraphBuffer, &GraphTraceLen, clk, fc_low, fc_high); + CmdNorm(""); + RepaintGraphWindow(); + return ans; +} + + static command_t CommandTable[] = { {"help", CmdHelp, 1, "This help"}, @@ -1617,6 +1809,7 @@ static command_t CommandTable[] = {"buffclear", CmdBuffClear, 1, "Clear sample buffer and graph window"}, {"dec", CmdDec, 1, "Decimate samples"}, {"detectclock", CmdDetectClockRate, 1, "[modulation] Detect clock rate of wave in GraphBuffer (options: 'a','f','n','p' for ask, fsk, nrz, psk respectively)"}, + {"fsktonrz", CmdFSKClean, 1, "Convert fsk2 to nrz wave for alternate demodulating"}, {"getbitstream", CmdGetBitStream, 1, "Convert GraphBuffer's >=1 values to 1 and <1 to 0"}, {"grid", CmdGrid, 1, " -- overlay grid on graph window, use zero value to turn off either"}, {"hexsamples", CmdHexsamples, 0, " [] -- Dump big buffer as hex bytes"}, diff --git a/client/cmdlf.c b/client/cmdlf.c index 49c9ea39..79bcee0b 100644 --- a/client/cmdlf.c +++ b/client/cmdlf.c @@ -1081,7 +1081,7 @@ int CmdLFfind(const char *Cmd) if (ans>0) { PrintAndLog("Possible unknown PSK1 Modulated Tag Found above!\n\nCould also be PSK2 - try 'data rawdemod p2'"); PrintAndLog("\nCould also be PSK3 - [currently not supported]"); - PrintAndLog("\nCould also be NRZ - try 'data nrzrawdemod'"); + PrintAndLog("\nCould also be NRZ - try 'data rawdemod nr'"); return CheckChipType(cmdp); } ans = CheckChipType(cmdp); diff --git a/client/cmdlfindala.c b/client/cmdlfindala.c index de1757e9..8ec04cbb 100644 --- a/client/cmdlfindala.c +++ b/client/cmdlfindala.c @@ -96,8 +96,12 @@ int CmdIndalaDemod(const char *Cmd) { uint8_t rawbits[4096]; int rawbit = 0; int worst = 0, worstPos = 0; - // PrintAndLog("Expecting a bit less than %d raw bits", GraphTraceLen / 32); + + //clear clock grid and demod plot + setClockGrid(0, 0); + DemodBufferLen = 0; + // PrintAndLog("Expecting a bit less than %d raw bits", GraphTraceLen / 32); // loop through raw signal - since we know it is psk1 rf/32 fc/2 skip every other value (+=2) for (i = 0; i < GraphTraceLen-1; i += 2) { count += 1; diff --git a/common/lfdemod.c b/common/lfdemod.c index d2e0fca4..880e2c2b 100644 --- a/common/lfdemod.c +++ b/common/lfdemod.c @@ -505,13 +505,14 @@ int DetectASKClock(uint8_t dest[], size_t size, int *clock, int maxErr) { return bestStart[best]; } -int DetectStrongNRZClk(uint8_t *dest, size_t size, int peak, int low){ +int DetectStrongNRZClk(uint8_t *dest, size_t size, int peak, int low, bool *strong) { //find shortest transition from high to low + *strong = false; size_t i = 0; size_t transition1 = 0; int lowestTransition = 255; bool lastWasHigh = false; - + size_t transitionSampleCount = 0; //find first valid beginning of a high or low wave while ((dest[i] >= peak || dest[i] <= low) && (i < size)) ++i; @@ -527,10 +528,17 @@ int DetectStrongNRZClk(uint8_t *dest, size_t size, int peak, int low){ lastWasHigh = (dest[i] >= peak); if (i-transition1 < lowestTransition) lowestTransition = i-transition1; transition1 = i; + } else if (dest[i] < peak && dest[i] > low) { + transitionSampleCount++; } } if (lowestTransition == 255) lowestTransition = 0; if (g_debugMode==2) prnt("DEBUG NRZ: detectstrongNRZclk smallest wave: %d",lowestTransition); + // if less than 10% of the samples were not peaks (or 90% were peaks) then we have a strong wave + if (transitionSampleCount / size < 10) { + *strong = true; + lowestTransition = getClosestClock(lowestTransition); + } return lowestTransition; } @@ -550,7 +558,9 @@ int DetectNRZClock(uint8_t dest[], size_t size, int clock, size_t *clockStartIdx int peak, low; if (getHiLo(dest, loopCnt, &peak, &low, 90, 90) < 1) return 0; - int lowestTransition = DetectStrongNRZClk(dest, size-20, peak, low); + bool strong = false; + int lowestTransition = DetectStrongNRZClk(dest, size-20, peak, low, &strong); + if (strong) return lowestTransition; size_t ii; uint8_t clkCnt; uint8_t tol = 0;