-//countFC is to detect the field clock lengths.
-//counts and returns the 2 most common wave lengths
-uint16_t countFC(uint8_t *BitStream, size_t size)
-{
- uint8_t fcLens[] = {0,0,0,0,0,0,0,0,0,0};
- uint16_t fcCnts[] = {0,0,0,0,0,0,0,0,0,0};
- uint8_t fcLensFnd = 0;
- uint8_t lastFCcnt=0;
- uint32_t fcCounter = 0;
- size_t i;
-
- // 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 up transition
- fcCounter++;
-
- //if we had 5 and now have 9 then go back to 8 (for when we get a fc 9 instead of an 8)
- if (lastFCcnt==5 && fcCounter==9) fcCounter--;
- //if odd and not rc/5 add one (for when we get a fc 9 instead of 10)
- if ((fcCounter==9 && fcCounter & 1) || fcCounter==4) fcCounter++;
-
- // save last field clock count (fc/xx)
- // find which fcLens to save it to:
- for (int ii=0; ii<10; ii++){
- if (fcLens[ii]==fcCounter){
- fcCnts[ii]++;
- fcCounter=0;
- break;
- }
- }
- if (fcCounter>0 && fcLensFnd<10){
- //add new fc length
- fcCnts[fcLensFnd]++;
- fcLens[fcLensFnd++]=fcCounter;
- }
- fcCounter=0;
- } else {
- // count sample
- fcCounter++;
- }
- }
-
- uint8_t best1=9, best2=9, best3=9;
- uint16_t maxCnt1=0;
- // go through fclens and find which ones are bigest 2
- for (i=0; i<10; i++){
- // PrintAndLog("DEBUG: FC %d, Cnt %d, Errs %d",fcLens[i],fcCnts[i],errCnt);
- // get the 3 best FC values
- if (fcCnts[i]>maxCnt1) {
- best3=best2;
- best2=best1;
- maxCnt1=fcCnts[i];
- best1=i;
- } else if(fcCnts[i]>fcCnts[best2]){
- best3=best2;
- best2=i;
- } else if(fcCnts[i]>fcCnts[best3]){
- best3=i;
- }
- }
- uint8_t fcH=0, fcL=0;
- if (fcLens[best1]>fcLens[best2]){
- fcH=fcLens[best1];
- fcL=fcLens[best2];
- } else{
- fcH=fcLens[best2];
- fcL=fcLens[best1];
- }
-
- // TODO: take top 3 answers and compare to known Field clocks to get top 2
-
- uint16_t fcs = (((uint16_t)fcH)<<8) | fcL;
- // PrintAndLog("DEBUG: Best %d best2 %d best3 %d",fcLens[best1],fcLens[best2],fcLens[best3]);
-
- return fcs;
+//attempt to identify a Sequence Terminator in ASK modulated raw wave
+bool DetectST(uint8_t buffer[], size_t *size, int *foundclock) {
+ size_t bufsize = *size;
+ //need to loop through all samples and identify our clock, look for the ST pattern
+ uint8_t fndClk[] = {8,16,32,40,50,64,128};
+ int clk = 0;
+ int tol = 0;
+ int i, j, skip, start, end, low, high, minClk, waveStart;
+ bool complete = false;
+ int tmpbuff[bufsize / 64];
+ int waveLen[bufsize / 64];
+ size_t testsize = (bufsize < 512) ? bufsize : 512;
+ int phaseoff = 0;
+ high = low = 128;
+ memset(tmpbuff, 0, sizeof(tmpbuff));
+
+ if ( getHiLo(buffer, testsize, &high, &low, 80, 80) == -1 ) {
+ if (g_debugMode==2) prnt("DEBUG STT: just noise detected - quitting");
+ return false; //just noise
+ }
+ i = 0;
+ j = 0;
+ minClk = 255;
+ // get to first full low to prime loop and skip incomplete first pulse
+ while ((buffer[i] < high) && (i < bufsize))
+ ++i;
+ while ((buffer[i] > low) && (i < bufsize))
+ ++i;
+ skip = i;
+
+ // populate tmpbuff buffer with pulse lengths
+ while (i < bufsize) {
+ // measure from low to low
+ while ((buffer[i] > low) && (i < bufsize))
+ ++i;
+ start= i;
+ while ((buffer[i] < high) && (i < bufsize))
+ ++i;
+ //first high point for this wave
+ waveStart = i;
+ while ((buffer[i] > low) && (i < bufsize))
+ ++i;
+ if (j >= (bufsize/64)) {
+ break;
+ }
+ waveLen[j] = i - waveStart; //first high to first low
+ tmpbuff[j++] = i - start;
+ if (i-start < minClk && i < bufsize) {
+ minClk = i - start;
+ }
+ }
+ // set clock - might be able to get this externally and remove this work...
+ if (!clk) {
+ for (uint8_t clkCnt = 0; clkCnt<7; clkCnt++) {
+ tol = fndClk[clkCnt]/8;
+ if (minClk >= fndClk[clkCnt]-tol && minClk <= fndClk[clkCnt]+1) {
+ clk=fndClk[clkCnt];
+ break;
+ }
+ }
+ // clock not found - ERROR
+ if (!clk) {
+ if (g_debugMode==2) prnt("DEBUG STT: clock not found - quitting");
+ return false;
+ }
+ } else tol = clk/8;
+
+ *foundclock = clk;
+
+ // look for Sequence Terminator - should be pulses of clk*(1 or 1.5), clk*2, clk*(1.5 or 2)
+ start = -1;
+ for (i = 0; i < j - 4; ++i) {
+ skip += tmpbuff[i];
+ if (tmpbuff[i] >= clk*1-tol && tmpbuff[i] <= (clk*2)+tol && waveLen[i] < clk+tol) { //1 to 2 clocks depending on 2 bits prior
+ if (tmpbuff[i+1] >= clk*2-tol && tmpbuff[i+1] <= clk*2+tol && waveLen[i+1] > clk*3/2-tol) { //2 clocks and wave size is 1 1/2
+ if (tmpbuff[i+2] >= (clk*3)/2-tol && tmpbuff[i+2] <= clk*2+tol && waveLen[i+2] > clk-tol) { //1 1/2 to 2 clocks and at least one full clock wave
+ if (tmpbuff[i+3] >= clk*1-tol && tmpbuff[i+3] <= clk*2+tol) { //1 to 2 clocks for end of ST + first bit
+ start = i + 3;
+ break;
+ }
+ }
+ }
+ }
+ }
+ // first ST not found - ERROR
+ if (start < 0) {
+ if (g_debugMode==2) prnt("DEBUG STT: first STT not found - quitting");
+ return false;
+ }
+ 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
+ end = skip;
+ for (i += 3; i < j - 4; ++i) {
+ end += tmpbuff[i];
+ if (tmpbuff[i] >= clk*1-tol && tmpbuff[i] <= (clk*2)+tol) { //1 to 2 clocks depending on 2 bits prior
+ if (tmpbuff[i+1] >= clk*2-tol && tmpbuff[i+1] <= clk*2+tol && waveLen[i+1] > clk*3/2-tol) { //2 clocks and wave size is 1 1/2
+ if (tmpbuff[i+2] >= (clk*3)/2-tol && tmpbuff[i+2] <= clk*2+tol && waveLen[i+2] > clk-tol) { //1 1/2 to 2 clocks and at least one full clock wave
+ if (tmpbuff[i+3] >= clk*1-tol && tmpbuff[i+3] <= clk*2+tol) { //1 to 2 clocks for end of ST + first bit
+ complete = true;
+ break;
+ }
+ }
+ }
+ }
+ }
+ end -= phaseoff;
+ //didn't find second ST - ERROR
+ if (!complete) {
+ if (g_debugMode==2) prnt("DEBUG STT: second STT not found - quitting");
+ return false;
+ }
+ 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 (datalen % clk > clk/8) {
+ if (g_debugMode==2) prnt("DEBUG STT: datalen not divisible by clk: %u %% %d = %d - quitting", datalen, clk, datalen % clk);
+ return false;
+ } else {
+ // padd the amount off - could be problematic... but shouldn't happen often
+ datalen += datalen % clk;
+ }
+ // 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;
+ size_t newloc = 0;
+ i=0;
+ // 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... (we cut out the high part)
+ if (buffer[dataloc]<high && buffer[dataloc]>low && buffer[dataloc+3]<high && buffer[dataloc+3]>low) {
+ for(i=0; i < clk/2-tol; ++i) {
+ buffer[dataloc+i] = high+5;
+ }
+ }
+ 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
+ dataloc += clk*4;
+ }
+ *size = newloc;
+ return true;