+ for (; i < size-20; i++){
+ fcCounter++;
+ rfCounter++;
+
+ if (BitStream[i] <= BitStream[i-1] || BitStream[i] < BitStream[i+1])
+ continue;
+ // else new peak
+ // if we got less than the small fc + tolerance then set it to the small fc
+ // if it is inbetween set it to the last counter
+ if (fcCounter < fcHigh && fcCounter > fcLow)
+ fcCounter = lastFCcnt;
+ else if (fcCounter < fcLow+fcTol)
+ fcCounter = fcLow;
+ else //set it to the large fc
+ fcCounter = fcHigh;
+
+ //look for bit clock (rf/xx)
+ if ((fcCounter < lastFCcnt || fcCounter > lastFCcnt)){
+ //not the same size as the last wave - start of new bit sequence
+ if (firstBitFnd > 1){ //skip first wave change - probably not a complete bit
+ for (int ii=0; ii<15; ii++){
+ if (rfLens[ii] >= (rfCounter-4) && rfLens[ii] <= (rfCounter+4)){
+ rfCnts[ii]++;
+ rfCounter = 0;
+ break;
+ }
+ }
+ if (rfCounter > 0 && rfLensFnd < 15){
+ //PrintAndLog("DEBUG: rfCntr %d, fcCntr %d",rfCounter,fcCounter);
+ rfCnts[rfLensFnd]++;
+ rfLens[rfLensFnd++] = rfCounter;
+ }
+ } else {
+ *firstClockEdge = i;
+ firstBitFnd++;
+ }
+ rfCounter=0;
+ lastFCcnt=fcCounter;
+ }
+ fcCounter=0;
+ }
+ uint8_t rfHighest=15, rfHighest2=15, rfHighest3=15;
+
+ for (i=0; i<15; i++){
+ //get highest 2 RF values (might need to get more values to compare or compare all?)
+ if (rfCnts[i]>rfCnts[rfHighest]){
+ rfHighest3=rfHighest2;
+ rfHighest2=rfHighest;
+ rfHighest=i;
+ } else if(rfCnts[i]>rfCnts[rfHighest2]){
+ rfHighest3=rfHighest2;
+ rfHighest2=i;
+ } else if(rfCnts[i]>rfCnts[rfHighest3]){
+ rfHighest3=i;
+ }
+ if (g_debugMode==2) prnt("DEBUG FSK: RF %d, cnts %d",rfLens[i], rfCnts[i]);
+ }
+ // set allowed clock remainder tolerance to be 1 large field clock length+1
+ // we could have mistakenly made a 9 a 10 instead of an 8 or visa versa so rfLens could be 1 FC off
+ uint8_t tol1 = fcHigh+1;
+
+ if (g_debugMode==2) prnt("DEBUG FSK: most counted rf values: 1 %d, 2 %d, 3 %d",rfLens[rfHighest],rfLens[rfHighest2],rfLens[rfHighest3]);
+
+ // loop to find the highest clock that has a remainder less than the tolerance
+ // compare samples counted divided by
+ // test 128 down to 32 (shouldn't be possible to have fc/10 & fc/8 and rf/16 or less)
+ int ii=7;
+ for (; ii>=2; ii--){
+ if (rfLens[rfHighest] % clk[ii] < tol1 || rfLens[rfHighest] % clk[ii] > clk[ii]-tol1){
+ if (rfLens[rfHighest2] % clk[ii] < tol1 || rfLens[rfHighest2] % clk[ii] > clk[ii]-tol1){
+ if (rfLens[rfHighest3] % clk[ii] < tol1 || rfLens[rfHighest3] % clk[ii] > clk[ii]-tol1){
+ if (g_debugMode==2) prnt("DEBUG FSK: clk %d divides into the 3 most rf values within tolerance",clk[ii]);
+ break;
+ }
+ }
+ }
+ }
+
+ if (ii<2) return 0; // oops we went too far
+
+ return clk[ii];
+}
+
+//**********************************************************************************************
+//--------------------Modulation Demods &/or Decoding Section-----------------------------------
+//**********************************************************************************************
+
+// look for Sequence Terminator - should be pulses of clk*(1 or 2), clk*2, clk*(1.5 or 2), by idx we mean graph position index...
+bool findST(int *stStopLoc, int *stStartIdx, int lowToLowWaveLen[], int highToLowWaveLen[], int clk, int tol, int buffSize, size_t *i) {
+ if (buffSize < *i+4) return false;
+
+ for (; *i < buffSize - 4; *i+=1) {
+ *stStartIdx += lowToLowWaveLen[*i]; //caution part of this wave may be data and part may be ST.... to be accounted for in main function for now...
+ if (lowToLowWaveLen[*i] >= clk*1-tol && lowToLowWaveLen[*i] <= (clk*2)+tol && highToLowWaveLen[*i] < clk+tol) { //1 to 2 clocks depending on 2 bits prior
+ if (lowToLowWaveLen[*i+1] >= clk*2-tol && lowToLowWaveLen[*i+1] <= clk*2+tol && highToLowWaveLen[*i+1] > clk*3/2-tol) { //2 clocks and wave size is 1 1/2
+ if (lowToLowWaveLen[*i+2] >= (clk*3)/2-tol && lowToLowWaveLen[*i+2] <= clk*2+tol && highToLowWaveLen[*i+2] > clk-tol) { //1 1/2 to 2 clocks and at least one full clock wave
+ if (lowToLowWaveLen[*i+3] >= clk*1-tol && lowToLowWaveLen[*i+3] <= clk*2+tol) { //1 to 2 clocks for end of ST + first bit
+ *stStopLoc = *i + 3;
+ return true;
+ }
+ }
+ }
+ }
+ }
+ return false;
+}
+//by marshmellow
+//attempt to identify a Sequence Terminator in ASK modulated raw wave
+bool DetectST(uint8_t buffer[], size_t *size, int *foundclock, size_t *ststart, size_t *stend) {
+ size_t bufsize = *size;
+ //need to loop through all samples and identify our clock, look for the ST pattern
+ int clk = 0;
+ int tol = 0;
+ int j=0, high, low, skip=0, start=0, end=0, minClk=255;
+ size_t i = 0;
+ //probably should malloc... || test if memory is available ... handle device side? memory danger!!! [marshmellow]
+ int tmpbuff[bufsize / LOWEST_DEFAULT_CLOCK]; // low to low wave count //guess rf/32 clock, if click is smaller we will only have room for a fraction of the samples captured
+ int waveLen[bufsize / LOWEST_DEFAULT_CLOCK]; // high to low wave count //if clock is larger then we waste memory in array size that is not needed...
+ //size_t testsize = (bufsize < 512) ? bufsize : 512;
+ int phaseoff = 0;
+ high = low = 128;
+ memset(tmpbuff, 0, sizeof(tmpbuff));
+ memset(waveLen, 0, sizeof(waveLen));
+
+ if (!loadWaveCounters(buffer, bufsize, tmpbuff, waveLen, &j, &skip, &minClk, &high, &low)) return false;
+ // set clock - might be able to get this externally and remove this work...
+ clk = getClosestClock(minClk);
+ // clock not found - ERROR
+ if (clk == 0) {
+ if (g_debugMode==2) prnt("DEBUG STT: clock not found - quitting");
+ return false;
+ }
+ *foundclock = clk;
+
+ tol = clk/8;
+ if (!findST(&start, &skip, tmpbuff, waveLen, clk, tol, j, &i)) {
+ // first ST not found - ERROR
+ if (g_debugMode==2) prnt("DEBUG STT: first STT not found - quitting");
+ return false;
+ } else {
+ if (g_debugMode==2) prnt("DEBUG STT: first STT found at wave: %i, skip: %i, j=%i", start, skip, j);
+ }
+ if (waveLen[i+2] > clk*1+tol)
+ phaseoff = 0;
+ else
+ phaseoff = clk/2;
+
+ // skip over the remainder of ST
+ skip += clk*7/2; //3.5 clocks from tmpbuff[i] = end of st - also aligns for ending point
+
+ // now do it again to find the end
+ int dummy1 = 0;
+ end = skip;
+ i+=3;
+ if (!findST(&dummy1, &end, tmpbuff, waveLen, clk, tol, j, &i)) {
+ //didn't find second ST - ERROR
+ if (g_debugMode==2) prnt("DEBUG STT: second STT not found - quitting");
+ return false;
+ }
+ end -= phaseoff;
+ if (g_debugMode==2) prnt("DEBUG STT: start of data: %d end of data: %d, datalen: %d, clk: %d, bits: %d, phaseoff: %d", skip, end, end-skip, clk, (end-skip)/clk, phaseoff);
+ //now begin to trim out ST so we can use normal demod cmds
+ start = skip;
+ size_t datalen = end - start;
+ // check validity of datalen (should be even clock increments) - use a tolerance of up to 1/8th a clock
+ if ( clk - (datalen % clk) <= clk/8) {
+ // padd the amount off - could be problematic... but shouldn't happen often
+ datalen += clk - (datalen % clk);
+ } else if ( (datalen % clk) <= clk/8 ) {
+ // padd the amount off - could be problematic... but shouldn't happen often
+ datalen -= datalen % clk;
+ } else {
+ if (g_debugMode==2) prnt("DEBUG STT: datalen not divisible by clk: %u %% %d = %d - quitting", datalen, clk, datalen % clk);
+ return false;
+ }
+ // if datalen is less than one t55xx block - ERROR
+ if (datalen/clk < 8*4) {
+ if (g_debugMode==2) prnt("DEBUG STT: datalen is less than 1 full t55xx block - quitting");
+ return false;
+ }
+ size_t dataloc = start;
+ if (buffer[dataloc-(clk*4)-(clk/4)] <= low && buffer[dataloc] <= low && buffer[dataloc-(clk*4)] >= high) {
+ //we have low drift (and a low just before the ST and a low just after the ST) - compensate by backing up the start
+ for ( i=0; i <= (clk/4); ++i ) {
+ if ( buffer[dataloc - (clk*4) - i] <= low ) {
+ dataloc -= i;
+ break;
+ }
+ }
+ }
+
+ size_t newloc = 0;
+ i=0;
+ if (g_debugMode==2) prnt("DEBUG STT: Starting STT trim - start: %d, datalen: %d ",dataloc, datalen);
+ bool firstrun = true;
+ // warning - overwriting buffer given with raw wave data with ST removed...
+ while ( dataloc < bufsize-(clk/2) ) {
+ //compensate for long high at end of ST not being high due to signal loss... (and we cut out the start of wave high part)
+ if (buffer[dataloc]<high && buffer[dataloc]>low && buffer[dataloc+clk/4]<high && buffer[dataloc+clk/4]>low) {
+ for(i=0; i < clk/2-tol; ++i) {
+ buffer[dataloc+i] = high+5;
+ }
+ } //test for small spike outlier (high between two lows) in the case of very strong waves
+ if (buffer[dataloc] > low && buffer[dataloc+clk/4] <= low) {
+ for(i=0; i < clk/4; ++i) {
+ buffer[dataloc+i] = buffer[dataloc+clk/4];
+ }
+ }
+ if (firstrun) {
+ *stend = dataloc;
+ *ststart = dataloc-(clk*4);
+ firstrun=false;
+ }
+ for (i=0; i<datalen; ++i) {
+ if (i+newloc < bufsize) {
+ if (i+newloc < dataloc)
+ buffer[i+newloc] = buffer[dataloc];
+
+ dataloc++;
+ }
+ }
+ newloc += i;
+ //skip next ST - we just assume it will be there from now on...
+ if (g_debugMode==2) prnt("DEBUG STT: skipping STT at %d to %d", dataloc, dataloc+(clk*4));
+ dataloc += clk*4;
+ }
+ *size = newloc;
+ return true;
+}
+
+//by marshmellow
+//take 11 10 01 11 00 and make 01100 ... miller decoding
+//check for phase errors - should never have half a 1 or 0 by itself and should never exceed 1111 or 0000 in a row
+//decodes miller encoded binary
+//NOTE askrawdemod will NOT demod miller encoded ask unless the clock is manually set to 1/2 what it is detected as!
+int millerRawDecode(uint8_t *BitStream, size_t *size, int invert) {
+ if (*size < 16) return -1;
+ uint16_t MaxBits = 512, errCnt = 0;
+ size_t i, bitCnt=0;
+ uint8_t alignCnt = 0, curBit = BitStream[0], alignedIdx = 0;
+ uint8_t halfClkErr = 0;
+ //find alignment, needs 4 1s or 0s to properly align
+ for (i=1; i < *size-1; i++) {
+ alignCnt = (BitStream[i] == curBit) ? alignCnt+1 : 0;
+ curBit = BitStream[i];
+ if (alignCnt == 4) break;
+ }
+ // for now error if alignment not found. later add option to run it with multiple offsets...
+ if (alignCnt != 4) {
+ if (g_debugMode) prnt("ERROR MillerDecode: alignment not found so either your bitstream is not miller or your data does not have a 101 in it");
+ return -1;
+ }
+ alignedIdx = (i-1) % 2;
+ for (i=alignedIdx; i < *size-3; i+=2) {
+ halfClkErr = (uint8_t)((halfClkErr << 1 | BitStream[i]) & 0xFF);
+ if ( (halfClkErr & 0x7) == 5 || (halfClkErr & 0x7) == 2 || (i > 2 && (halfClkErr & 0x7) == 0) || (halfClkErr & 0x1F) == 0x1F) {
+ errCnt++;
+ BitStream[bitCnt++] = 7;
+ continue;
+ }
+ BitStream[bitCnt++] = BitStream[i] ^ BitStream[i+1] ^ invert;
+
+ if (bitCnt > MaxBits) break;
+ }
+ *size = bitCnt;
+ return errCnt;
+}
+
+//by marshmellow
+//take 01 or 10 = 1 and 11 or 00 = 0
+//check for phase errors - should never have 111 or 000 should be 01001011 or 10110100 for 1010
+//decodes biphase or if inverted it is AKA conditional dephase encoding AKA differential manchester encoding
+int BiphaseRawDecode(uint8_t *BitStream, size_t *size, int *offset, int invert) {
+ uint16_t bitnum = 0;
+ uint16_t errCnt = 0;
+ size_t i = *offset;
+ uint16_t MaxBits=512;
+ //if not enough samples - error
+ if (*size < 51) return -1;
+ //check for phase change faults - skip one sample if faulty
+ uint8_t offsetA = 1, offsetB = 1;
+ for (; i<48; i+=2){
+ if (BitStream[i+1]==BitStream[i+2]) offsetA=0;
+ if (BitStream[i+2]==BitStream[i+3]) offsetB=0;
+ }
+ if (!offsetA && offsetB) *offset+=1;
+ for (i=*offset; i<*size-3; i+=2){
+ //check for phase error
+ if (BitStream[i+1]==BitStream[i+2]) {
+ BitStream[bitnum++]=7;
+ errCnt++;
+ }
+ if((BitStream[i]==1 && BitStream[i+1]==0) || (BitStream[i]==0 && BitStream[i+1]==1)){
+ BitStream[bitnum++]=1^invert;
+ } else if((BitStream[i]==0 && BitStream[i+1]==0) || (BitStream[i]==1 && BitStream[i+1]==1)){
+ BitStream[bitnum++]=invert;
+ } else {
+ BitStream[bitnum++]=7;
+ errCnt++;
+ }
+ if(bitnum>MaxBits) break;
+ }
+ *size=bitnum;
+ return errCnt;
+}
+
+//by marshmellow
+//take 10 and 01 and manchester decode
+//run through 2 times and take least errCnt
+int manrawdecode(uint8_t * BitStream, size_t *size, uint8_t invert, uint8_t *alignPos) {
+ uint16_t bitnum=0, MaxBits = 512, errCnt = 0;
+ size_t i, ii;
+ uint16_t bestErr = 1000, bestRun = 0;
+ if (*size < 16) return -1;
+ //find correct start position [alignment]
+ for (ii=0;ii<2;++ii){
+ for (i=ii; i<*size-3; i+=2)
+ if (BitStream[i]==BitStream[i+1])
+ errCnt++;
+
+ if (bestErr>errCnt){
+ bestErr=errCnt;
+ bestRun=ii;
+ }
+ errCnt=0;
+ }
+ *alignPos=bestRun;
+ //decode
+ for (i=bestRun; i < *size-3; i+=2){
+ if(BitStream[i] == 1 && (BitStream[i+1] == 0)){
+ BitStream[bitnum++]=invert;
+ } else if((BitStream[i] == 0) && BitStream[i+1] == 1){
+ BitStream[bitnum++]=invert^1;
+ } else {
+ BitStream[bitnum++]=7;
+ }
+ if(bitnum>MaxBits) break;
+ }
+ *size=bitnum;
+ return bestErr;
+}
+
+//by marshmellow
+//demodulates strong heavily clipped samples
+int cleanAskRawDemod(uint8_t *BinStream, size_t *size, int clk, int invert, int high, int low, int *startIdx)
+{
+ *startIdx=0;
+ size_t bitCnt=0, smplCnt=1, errCnt=0;
+ bool waveHigh = (BinStream[0] >= high);
+ for (size_t i=1; i < *size; i++){
+ if (BinStream[i] >= high && waveHigh){
+ smplCnt++;
+ } else if (BinStream[i] <= low && !waveHigh){
+ smplCnt++;
+ } else { //transition
+ if ((BinStream[i] >= high && !waveHigh) || (BinStream[i] <= low && waveHigh)){
+ if (smplCnt > clk-(clk/4)-1) { //full clock
+ if (smplCnt > clk + (clk/4)+1) { //too many samples
+ errCnt++;
+ if (g_debugMode==2) prnt("DEBUG ASK: Modulation Error at: %u", i);
+ BinStream[bitCnt++] = 7;
+ } else if (waveHigh) {
+ BinStream[bitCnt++] = invert;
+ BinStream[bitCnt++] = invert;
+ } else if (!waveHigh) {
+ BinStream[bitCnt++] = invert ^ 1;
+ BinStream[bitCnt++] = invert ^ 1;
+ }
+ if (*startIdx==0) *startIdx = i-clk;
+ waveHigh = !waveHigh;
+ smplCnt = 0;
+ } else if (smplCnt > (clk/2) - (clk/4)-1) { //half clock
+ if (waveHigh) {
+ BinStream[bitCnt++] = invert;
+ } else if (!waveHigh) {
+ BinStream[bitCnt++] = invert ^ 1;
+ }
+ if (*startIdx==0) *startIdx = i-(clk/2);
+ waveHigh = !waveHigh;
+ smplCnt = 0;
+ } else {
+ smplCnt++;
+ //transition bit oops
+ }
+ } else { //haven't hit new high or new low yet
+ smplCnt++;
+ }
+ }
+ }
+ *size = bitCnt;
+ return errCnt;
+}
+
+//by marshmellow
+//attempts to demodulate ask modulations, askType == 0 for ask/raw, askType==1 for ask/manchester
+int askdemod_ext(uint8_t *BinStream, size_t *size, int *clk, int *invert, int maxErr, uint8_t amp, uint8_t askType, int *startIdx) {
+ if (*size==0) return -1;
+ int start = DetectASKClock(BinStream, *size, clk, maxErr); //clock default
+ if (*clk==0 || start < 0) return -3;
+ if (*invert != 1) *invert = 0;
+ if (amp==1) askAmp(BinStream, *size);
+ if (g_debugMode==2) prnt("DEBUG ASK: clk %d, beststart %d, amp %d", *clk, start, amp);
+
+ //start pos from detect ask clock is 1/2 clock offset
+ // NOTE: can be negative (demod assumes rest of wave was there)
+ *startIdx = start - (*clk/2);
+ uint8_t initLoopMax = 255;
+ if (initLoopMax > *size) initLoopMax = *size;
+ // Detect high and lows
+ //25% clip in case highs and lows aren't clipped [marshmellow]
+ int high, low;
+ if (getHiLo(BinStream, initLoopMax, &high, &low, 75, 75) < 1)
+ return -2; //just noise
+
+ size_t errCnt = 0;
+ // if clean clipped waves detected run alternate demod
+ if (DetectCleanAskWave(BinStream, *size, high, low)) {
+ if (g_debugMode==2) prnt("DEBUG ASK: Clean Wave Detected - using clean wave demod");
+ errCnt = cleanAskRawDemod(BinStream, size, *clk, *invert, high, low, startIdx);
+ if (askType) { //askman
+ uint8_t alignPos = 0;
+ errCnt = manrawdecode(BinStream, size, 0, &alignPos);
+ *startIdx += *clk/2 * alignPos;
+ if (g_debugMode) prnt("DEBUG ASK CLEAN: startIdx %i, alignPos %u", *startIdx, alignPos);
+ return errCnt;
+ } else { //askraw
+ return errCnt;
+ }
+ }
+ if (g_debugMode) prnt("DEBUG ASK WEAK: startIdx %i", *startIdx);
+ if (g_debugMode==2) prnt("DEBUG ASK: Weak Wave Detected - using weak wave demod");
+
+ int lastBit; //set first clock check - can go negative
+ size_t i, bitnum = 0; //output counter
+ uint8_t midBit = 0;
+ uint8_t tol = 0; //clock tolerance adjust - waves will be accepted as within the clock if they fall + or - this value + clock from last valid wave
+ if (*clk <= 32) tol = 1; //clock tolerance may not be needed anymore currently set to + or - 1 but could be increased for poor waves or removed entirely
+ size_t MaxBits = 3072; //max bits to collect
+ lastBit = start - *clk;
+
+ for (i = start; i < *size; ++i) {
+ if (i-lastBit >= *clk-tol){
+ if (BinStream[i] >= high) {
+ BinStream[bitnum++] = *invert;
+ } else if (BinStream[i] <= low) {
+ BinStream[bitnum++] = *invert ^ 1;
+ } else if (i-lastBit >= *clk+tol) {
+ if (bitnum > 0) {
+ if (g_debugMode==2) prnt("DEBUG ASK: Modulation Error at: %u", i);
+ BinStream[bitnum++]=7;
+ errCnt++;
+ }
+ } else { //in tolerance - looking for peak
+ continue;
+ }
+ midBit = 0;
+ lastBit += *clk;
+ } else if (i-lastBit >= (*clk/2-tol) && !midBit && !askType){
+ if (BinStream[i] >= high) {
+ BinStream[bitnum++] = *invert;
+ } else if (BinStream[i] <= low) {
+ BinStream[bitnum++] = *invert ^ 1;
+ } else if (i-lastBit >= *clk/2+tol) {
+ BinStream[bitnum] = BinStream[bitnum-1];
+ bitnum++;
+ } else { //in tolerance - looking for peak
+ continue;
+ }
+ midBit = 1;
+ }
+ if (bitnum >= MaxBits) break;
+ }
+ *size = bitnum;
+ return errCnt;
+}
+
+int askdemod(uint8_t *BinStream, size_t *size, int *clk, int *invert, int maxErr, uint8_t amp, uint8_t askType) {
+ int start = 0;
+ return askdemod_ext(BinStream, size, clk, invert, maxErr, amp, askType, &start);
+}
+
+// by marshmellow - demodulate NRZ wave - requires a read with strong signal
+// peaks invert bit (high=1 low=0) each clock cycle = 1 bit determined by last peak
+int nrzRawDemod(uint8_t *dest, size_t *size, int *clk, int *invert, int *startIdx) {
+ if (justNoise(dest, *size)) return -1;
+ size_t clkStartIdx = 0;
+ *clk = DetectNRZClock(dest, *size, *clk, &clkStartIdx);
+ if (*clk==0) return -2;
+ size_t i, gLen = 4096;
+ if (gLen>*size) gLen = *size-20;
+ int high, low;
+ if (getHiLo(dest, gLen, &high, &low, 75, 75) < 1) return -3; //25% fuzz on high 25% fuzz on low
+
+ uint8_t bit=0;
+ //convert wave samples to 1's and 0's
+ for(i=20; i < *size-20; i++){
+ if (dest[i] >= high) bit = 1;
+ if (dest[i] <= low) bit = 0;
+ dest[i] = bit;
+ }
+ //now demod based on clock (rf/32 = 32 1's for one 1 bit, 32 0's for one 0 bit)
+ size_t lastBit = 0;
+ size_t numBits = 0;
+ for(i=21; i < *size-20; i++) {
+ //if transition detected or large number of same bits - store the passed bits
+ if (dest[i] != dest[i-1] || (i-lastBit) == (10 * *clk)) {
+ memset(dest+numBits, dest[i-1] ^ *invert, (i - lastBit + (*clk/4)) / *clk);
+ numBits += (i - lastBit + (*clk/4)) / *clk;
+ if (lastBit == 0) {
+ *startIdx = i - (numBits * *clk);
+ if (g_debugMode==2) prnt("DEBUG NRZ: startIdx %i", *startIdx);
+ }
+ lastBit = i-1;
+ }
+ }
+ *size = numBits;
+ return 0;
+}
+
+//translate wave to 11111100000 (1 for each short wave [higher freq] 0 for each long wave [lower freq])
+size_t fsk_wave_demod(uint8_t * dest, size_t size, uint8_t fchigh, uint8_t fclow, int *startIdx) {
+ size_t last_transition = 0;
+ size_t idx = 1;
+ if (fchigh==0) fchigh=10;
+ if (fclow==0) fclow=8;
+ //set the threshold close to 0 (graph) or 128 std to avoid static
+ size_t preLastSample = 0;
+ size_t LastSample = 0;
+ size_t currSample = 0;
+ if ( size < 1024 ) return 0; // not enough samples
+
+ //find start of modulating data in trace
+ idx = findModStart(dest, size, fchigh);
+ // Need to threshold first sample
+ if(dest[idx] < FSK_PSK_THRESHOLD) dest[0] = 0;
+ else dest[0] = 1;
+
+ last_transition = idx;
+ idx++;
+ size_t numBits = 0;
+ // count cycles between consecutive lo-hi transitions, there should be either 8 (fc/8)
+ // or 10 (fc/10) cycles but in practice due to noise etc we may end up with anywhere
+ // between 7 to 11 cycles so fuzz it by treat anything <9 as 8 and anything else as 10
+ // (could also be fc/5 && fc/7 for fsk1 = 4-9)
+ for(; idx < size; idx++) {
+ // threshold current value
+ if (dest[idx] < FSK_PSK_THRESHOLD) dest[idx] = 0;
+ else dest[idx] = 1;
+
+ // Check for 0->1 transition
+ if (dest[idx-1] < dest[idx]) {
+ preLastSample = LastSample;
+ LastSample = currSample;
+ currSample = idx-last_transition;
+ if (currSample < (fclow-2)) { //0-5 = garbage noise (or 0-3)
+ //do nothing with extra garbage
+ } else if (currSample < (fchigh-1)) { //6-8 = 8 sample waves (or 3-6 = 5)
+ //correct previous 9 wave surrounded by 8 waves (or 6 surrounded by 5)
+ if (numBits > 1 && LastSample > (fchigh-2) && (preLastSample < (fchigh-1))){
+ dest[numBits-1]=1;
+ }
+ dest[numBits++]=1;
+ if (numBits > 0 && *startIdx==0) *startIdx = idx - fclow;
+ } else if (currSample > (fchigh+1) && numBits < 3) { //12 + and first two bit = unusable garbage
+ //do nothing with beginning garbage and reset.. should be rare..
+ numBits = 0;
+ } else if (currSample == (fclow+1) && LastSample == (fclow-1)) { // had a 7 then a 9 should be two 8's (or 4 then a 6 should be two 5's)
+ dest[numBits++]=1;
+ if (numBits > 0 && *startIdx==0) *startIdx = idx - fclow;
+ } else { //9+ = 10 sample waves (or 6+ = 7)
+ dest[numBits++]=0;
+ if (numBits > 0 && *startIdx==0) *startIdx = idx - fchigh;
+ }
+ last_transition = idx;
+ }
+ }
+ return numBits; //Actually, it returns the number of bytes, but each byte represents a bit: 1 or 0
+}
+
+//translate 11111100000 to 10
+//rfLen = clock, fchigh = larger field clock, fclow = smaller field clock
+size_t aggregate_bits(uint8_t *dest, size_t size, uint8_t rfLen, uint8_t invert, uint8_t fchigh, uint8_t fclow, int *startIdx) {
+ uint8_t lastval=dest[0];
+ size_t idx=0;
+ size_t numBits=0;
+ uint32_t n=1;
+ for( idx=1; idx < size; idx++) {
+ n++;
+ if (dest[idx]==lastval) continue; //skip until we hit a transition
+
+ //find out how many bits (n) we collected (use 1/2 clk tolerance)