-// by marshmellow - demodulate NRZ wave (both similar enough)
-// peaks invert bit (high=1 low=0) each clock cycle = 1 bit determined by last peak
-// there probably is a much simpler way to do this....
-int nrzRawDemod(uint8_t *dest, size_t *size, int *clk, int *invert, int maxErr)
-{
- if (justNoise(dest, *size)) return -1;
- *clk = DetectNRZClock(dest, *size, *clk);
- if (*clk==0) return -2;
- uint32_t i;
- int high, low, ans;
- ans = getHiLo(dest, 1260, &high, &low, 75, 75); //25% fuzz on high 25% fuzz on low
- if (ans<1) return -2; //just noise
- uint32_t gLen = 256;
- if (gLen>*size) gLen = *size;
- int lastBit = 0; //set first clock check
- uint32_t bitnum = 0; //output counter
- uint8_t tol = 1; //clock tolerance adjust - waves will be accepted as within the clock if they fall + or - this value + clock from last valid wave
- uint32_t iii = 0;
- uint16_t errCnt =0;
- uint16_t MaxBits = 1000;
- uint32_t bestErrCnt = maxErr+1;
- uint32_t bestPeakCnt = 0;
- uint32_t bestPeakStart=0;
- uint8_t curBit=0;
- uint8_t bitHigh=0;
- uint8_t errBitHigh=0;
- uint16_t peakCnt=0;
- uint8_t ignoreWindow=4;
- uint8_t ignoreCnt=ignoreWindow; //in case of noice near peak
- //loop to find first wave that works - align to clock
- for (iii=0; iii < gLen; ++iii){
- if ((dest[iii]>=high) || (dest[iii]<=low)){
- lastBit=iii-*clk;
- peakCnt=0;
- errCnt=0;
- bitnum=0;
- //loop through to see if this start location works
- for (i = iii; i < *size; ++i) {
- //if we found a high bar and we are at a clock bit
- if ((dest[i]>=high ) && (i>=lastBit+*clk-tol && i<=lastBit+*clk+tol)){
- bitHigh=1;
- lastBit+=*clk;
- bitnum++;
- peakCnt++;
- errBitHigh=0;
- ignoreCnt=ignoreWindow;
- //else if low bar found and we are at a clock point
- }else if ((dest[i]<=low ) && (i>=lastBit+*clk-tol && i<=lastBit+*clk+tol)){
- bitHigh=1;
- lastBit+=*clk;
- bitnum++;
- peakCnt++;
- errBitHigh=0;
- ignoreCnt=ignoreWindow;
- //else if no bars found
- }else if(dest[i] < high && dest[i] > low) {
- if (ignoreCnt==0){
- bitHigh=0;
- if (errBitHigh==1){
- errCnt++;
- }
- errBitHigh=0;
- } else {
- ignoreCnt--;
- }
- //if we are past a clock point
- if (i >= lastBit+*clk+tol){ //clock val
- lastBit+=*clk;
- bitnum++;
- }
- //else if bar found but we are not at a clock bit and we did not just have a clock bit
- }else if ((dest[i]>=high || dest[i]<=low) && (i<lastBit+*clk-tol || i>lastBit+*clk+tol) && (bitHigh==0)){
- //error bar found no clock...
- errBitHigh=1;
- }
- if (bitnum>=MaxBits) break;
- }
- //we got more than 64 good bits and not all errors
- if (bitnum > (64) && (errCnt <= (maxErr))) {
- //possible good read
- if (errCnt == 0){
- //bestStart = iii;
- bestErrCnt = errCnt;
- bestPeakCnt = peakCnt;
- bestPeakStart = iii;
- break; //great read - finish
- }
- if (errCnt < bestErrCnt){ //set this as new best run
- bestErrCnt = errCnt;
- //bestStart = iii;
- }
- if (peakCnt > bestPeakCnt){
- bestPeakCnt=peakCnt;
- bestPeakStart=iii;
- }
- }
- }
- }
- //PrintAndLog("DEBUG: bestErrCnt: %d, maxErr: %d, bestStart: %d, bestPeakCnt: %d, bestPeakStart: %d",bestErrCnt,maxErr,bestStart,bestPeakCnt,bestPeakStart);
- if (bestErrCnt <= maxErr){
- //best run is good enough set to best run and set overwrite BinStream
- iii=bestPeakStart;
- lastBit=bestPeakStart-*clk;
- bitnum=0;
- for (i = iii; i < *size; ++i) {
- //if we found a high bar and we are at a clock bit
- if ((dest[i] >= high ) && (i>=lastBit+*clk-tol && i<=lastBit+*clk+tol)){
- bitHigh=1;
- lastBit+=*clk;
- curBit=1-*invert;
- dest[bitnum]=curBit;
- bitnum++;
- errBitHigh=0;
- ignoreCnt=ignoreWindow;
- //else if low bar found and we are at a clock point
- }else if ((dest[i]<=low ) && (i>=lastBit+*clk-tol && i<=lastBit+*clk+tol)){
- bitHigh=1;
- lastBit+=*clk;
- curBit=*invert;
- dest[bitnum]=curBit;
- bitnum++;
- errBitHigh=0;
- ignoreCnt=ignoreWindow;
- //else if no bars found
- }else if(dest[i]<high && dest[i]>low) {
- if (ignoreCnt==0){
- bitHigh=0;
- //if peak is done was it an error peak?
- if (errBitHigh==1){
- dest[bitnum]=77;
- bitnum++;
- errCnt++;
- }
- errBitHigh=0;
- } else {
- ignoreCnt--;
- }
- //if we are past a clock point
- if (i>=lastBit+*clk+tol){ //clock val
- lastBit+=*clk;
- dest[bitnum]=curBit;
- bitnum++;
- }
- //else if bar found but we are not at a clock bit and we did not just have a clock bit
- }else if ((dest[i]>=high || dest[i]<=low) && ((i<lastBit+*clk-tol) || (i>lastBit+*clk+tol)) && (bitHigh==0)){
- //error bar found no clock...
- errBitHigh=1;
- }
- if (bitnum >= MaxBits) break;
- }
- *size=bitnum;
- } else{
- *size=bitnum;
- return -1;
- }
-
- if (bitnum>16){
- *size=bitnum;
- } else return -1;
- return errCnt;
-}
-
-//by marshmellow
-//detects the bit clock for FSK given the high and low Field Clocks
-uint8_t detectFSKClk(uint8_t *BitStream, size_t size, uint8_t fcHigh, uint8_t fcLow)
-{
- uint8_t clk[] = {8,16,32,40,50,64,100,128,0};
- uint16_t rfLens[] = {0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0};
- uint8_t rfCnts[] = {0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0};
- uint8_t rfLensFnd = 0;
- uint8_t lastFCcnt=0;
- uint32_t fcCounter = 0;
- uint16_t rfCounter = 0;
- uint8_t firstBitFnd = 0;
- size_t i;
- if (size == 0) return 0;
-
- uint8_t fcTol = (uint8_t)(0.5+(float)(fcHigh-fcLow)/2);
- rfLensFnd=0;
- fcCounter=0;
- rfCounter=0;
- firstBitFnd=0;
- //PrintAndLog("DEBUG: fcTol: %d",fcTol);
- // prime i to first up transition
- for (i = 1; i < size-1; i++)
- if (BitStream[i] > BitStream[i-1] && BitStream[i]>=BitStream[i+1])
- break;
-
- for (; i < size-1; i++){
- if (BitStream[i] > BitStream[i-1] && BitStream[i]>=BitStream[i+1]){
- // new peak
- fcCounter++;
- rfCounter++;
- // if we got less than the small fc + tolerance then set it to the small fc
- 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){
- rfCnts[ii]++;
- rfCounter=0;
- break;
- }
- }
- if (rfCounter>0 && rfLensFnd<15){
- //PrintAndLog("DEBUG: rfCntr %d, fcCntr %d",rfCounter,fcCounter);
- rfCnts[rfLensFnd]++;
- rfLens[rfLensFnd++]=rfCounter;
- }
- } else {
- firstBitFnd++;
- }
- rfCounter=0;
- lastFCcnt=fcCounter;
- }
- fcCounter=0;
- } else {
- // count sample
- fcCounter++;
- rfCounter++;
- }
- }
- uint8_t rfHighest=15, rfHighest2=15, rfHighest3=15;
-
- for (i=0; i<15; i++){
- //PrintAndLog("DEBUG: RF %d, cnts %d",rfLens[i], rfCnts[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;
- }
- }
- // 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;
-
- //PrintAndLog("DEBUG: hightest: 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
- int ii=7;
- for (; ii>=0; 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){
- break;
- }
- }
- }
- }
-
- if (ii<0) return 0; // oops we went too far
-
- return clk[ii];