mirror of
https://github.com/Proxmark/proxmark3.git
synced 2025-02-25 16:13:58 +08:00
lf FSK demod tools/fixes
added full ability to detect FSK clocks applied autodetect of fsk clock to data fskrawdemod this finished data fskfcdetect (now detects field clocks and bit clock)
This commit is contained in:
parent
ec75f5c10a
commit
03e6bb4aed
3 changed files with 180 additions and 130 deletions
|
@ -604,22 +604,40 @@ int CmdFSKrawdemod(const char *Cmd)
|
|||
{
|
||||
//raw fsk demod no manchester decoding no start bit finding just get binary from wave
|
||||
//set defaults
|
||||
int rfLen = 50;
|
||||
int rfLen = 0;
|
||||
int invert=0;
|
||||
int fchigh=10;
|
||||
int fclow=8;
|
||||
int fchigh=0;
|
||||
int fclow=0;
|
||||
//set options from parameters entered with the command
|
||||
sscanf(Cmd, "%i %i %i %i", &rfLen, &invert, &fchigh, &fclow);
|
||||
|
||||
if (strlen(Cmd)>0 && strlen(Cmd)<=2) {
|
||||
if (rfLen==1){
|
||||
invert=1; //if invert option only is used
|
||||
rfLen = 50;
|
||||
} else if(rfLen==0) rfLen=50;
|
||||
rfLen = 0;
|
||||
}
|
||||
PrintAndLog("Args invert: %d - Clock:%d - fchigh:%d - fclow: %d",invert,rfLen,fchigh, fclow);
|
||||
}
|
||||
|
||||
uint8_t BitStream[MAX_GRAPH_TRACE_LEN]={0};
|
||||
size_t BitLen = getFromGraphBuf(BitStream);
|
||||
//get field clock lengths
|
||||
uint16_t fcs=0;
|
||||
if (fchigh==0 || fclow == 0){
|
||||
fcs=countFC(BitStream, BitLen);
|
||||
if (fcs==0){
|
||||
fchigh=10;
|
||||
fclow=8;
|
||||
}else{
|
||||
fchigh = (fcs >> 8) & 0xFF;
|
||||
fclow = fcs & 0xFF;
|
||||
}
|
||||
}
|
||||
//get bit clock length
|
||||
if (rfLen==0){
|
||||
rfLen = detectFSKClk(BitStream, BitLen, fchigh, fclow);
|
||||
if (rfLen == 0) rfLen = 50;
|
||||
}
|
||||
PrintAndLog("Args invert: %d - Clock:%d - fchigh:%d - fclow: %d",invert,rfLen,fchigh, fclow);
|
||||
int size = fskdemod(BitStream,BitLen,(uint8_t)rfLen,(uint8_t)invert,(uint8_t)fchigh,(uint8_t)fclow);
|
||||
if (size>0){
|
||||
PrintAndLog("FSK decoded bitstream:");
|
||||
|
@ -1159,12 +1177,20 @@ int CmdFSKfcDetect(const char *Cmd)
|
|||
uint8_t BitStream[MAX_GRAPH_TRACE_LEN]={0};
|
||||
size_t size = getFromGraphBuf(BitStream);
|
||||
|
||||
|
||||
uint32_t ans = countFC(BitStream, size);
|
||||
int fc1, fc2, rf1;
|
||||
uint16_t ans = countFC(BitStream, size);
|
||||
if (ans==0) {
|
||||
if (g_debugMode) PrintAndLog("DEBUG: No data found");
|
||||
return 0;
|
||||
}
|
||||
uint8_t fc1, fc2;
|
||||
fc1 = (ans >> 8) & 0xFF;
|
||||
fc2 = ans & 0xFF;
|
||||
rf1 = (ans >>16) & 0xFF;
|
||||
|
||||
uint8_t rf1 = detectFSKClk(BitStream, size, fc1, fc2);
|
||||
if (rf1==0) {
|
||||
if (g_debugMode) PrintAndLog("DEBUG: Clock detect error");
|
||||
return 0;
|
||||
}
|
||||
PrintAndLog("Detected Field Clocks: FC/%d, FC/%d - Bit Clock: RF/%d", fc1, fc2, rf1);
|
||||
return 1;
|
||||
}
|
||||
|
|
213
common/lfdemod.c
213
common/lfdemod.c
|
@ -1200,96 +1200,64 @@ int pskNRZrawDemod(uint8_t *dest, size_t *size, int *clk, int *invert)
|
|||
|
||||
|
||||
//by marshmellow
|
||||
//countFC is to detect the field clock and bit clock rates.
|
||||
//for fsk or ask not psk or nrz
|
||||
uint32_t countFC(uint8_t *BitStream, size_t size)
|
||||
//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)
|
||||
{
|
||||
// get high/low thresholds
|
||||
int high, low;
|
||||
getHiLo(BitStream,10, &high, &low, 100, 100);
|
||||
// get zero crossing
|
||||
uint8_t zeroC = (high-low)/2+low;
|
||||
uint8_t clk[]={8,16,32,40,50,64,100,128};
|
||||
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 rfLens[] = {0,0,0,0,0,0,0,0,0,0,0};
|
||||
// uint8_t rfCnts[] = {0,0,0,0,0,0,0,0,0,0};
|
||||
uint8_t fcLensFnd = 0;
|
||||
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 lastBit=0;
|
||||
uint8_t curBit=0;
|
||||
uint8_t lastFCcnt=0;
|
||||
uint32_t errCnt=0;
|
||||
uint32_t fcCounter = 0;
|
||||
uint32_t rfCounter = 0;
|
||||
uint16_t rfCounter = 0;
|
||||
uint8_t firstBitFnd = 0;
|
||||
int i;
|
||||
size_t i;
|
||||
|
||||
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; i++)
|
||||
if (BitStream[i]>=zeroC && BitStream[i-1]<zeroC)
|
||||
for (i = 1; i < size-1; i++)
|
||||
if (BitStream[i] > BitStream[i-1] && BitStream[i]>=BitStream[i+1])
|
||||
break;
|
||||
|
||||
for (; i < size; i++){
|
||||
curBit = BitStream[i];
|
||||
lastBit = BitStream[i-1];
|
||||
if (lastBit<zeroC && curBit >= zeroC){
|
||||
// new up transition
|
||||
for (; i < size-1; i++){
|
||||
if (BitStream[i] > BitStream[i-1] && BitStream[i]>=BitStream[i+1]){
|
||||
// new peak
|
||||
fcCounter++;
|
||||
rfCounter++;
|
||||
if (fcCounter > 3 && fcCounter < 256){
|
||||
//we've counted enough that it could be a valid field clock
|
||||
|
||||
//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++;
|
||||
// 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<10; ii++){
|
||||
for (int ii=0; ii<15; ii++){
|
||||
if (rfLens[ii]==rfCounter){
|
||||
//rfCnts[ii]++;
|
||||
rfCnts[ii]++;
|
||||
rfCounter=0;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (rfCounter>0 && rfLensFnd<10){
|
||||
if (rfCounter>0 && rfLensFnd<15){
|
||||
//PrintAndLog("DEBUG: rfCntr %d, fcCntr %d",rfCounter,fcCounter);
|
||||
//rfCnts[rfLensFnd]++;
|
||||
rfCnts[rfLensFnd]++;
|
||||
rfLens[rfLensFnd++]=rfCounter;
|
||||
}
|
||||
} else {
|
||||
//PrintAndLog("DEBUG i: %d",i);
|
||||
firstBitFnd++;
|
||||
}
|
||||
rfCounter=0;
|
||||
lastFCcnt=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
|
||||
//PrintAndLog("FCCntr %d",fcCounter);
|
||||
fcCnts[fcLensFnd]++;
|
||||
fcLens[fcLensFnd++]=fcCounter;
|
||||
}
|
||||
} else{
|
||||
// hmmm this should not happen often - count them
|
||||
errCnt++;
|
||||
}
|
||||
// reset counter
|
||||
fcCounter=0;
|
||||
} else {
|
||||
// count sample
|
||||
|
@ -1297,43 +1265,27 @@ uint32_t countFC(uint8_t *BitStream, size_t size)
|
|||
rfCounter++;
|
||||
}
|
||||
}
|
||||
// if too many errors return errors as negative number (IS THIS NEEDED?)
|
||||
if (errCnt>100) return -1*errCnt;
|
||||
uint8_t rfHighest=15, rfHighest2=15, rfHighest3=15;
|
||||
|
||||
uint8_t maxCnt1=0, best1=9, best2=9, best3=9, rfHighest=10, rfHighest2=10, rfHighest3=10;
|
||||
|
||||
// go through fclens and find which ones are bigest 2
|
||||
for (i=0; i<10; i++){
|
||||
// PrintAndLog("DEBUG: FC %d, Cnt %d, Errs %d, RF %d",fcLens[i],fcCnts[i],errCnt,rfLens[i]);
|
||||
|
||||
// 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;
|
||||
}
|
||||
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 (rfLens[i]>rfLens[rfHighest]){
|
||||
if (rfCnts[i]>rfCnts[rfHighest]){
|
||||
rfHighest3=rfHighest2;
|
||||
rfHighest2=rfHighest;
|
||||
rfHighest=i;
|
||||
} else if(rfLens[i]>rfLens[rfHighest2]){
|
||||
} else if(rfCnts[i]>rfCnts[rfHighest2]){
|
||||
rfHighest3=rfHighest2;
|
||||
rfHighest2=i;
|
||||
} else if(rfLens[i]>rfLens[rfHighest3]){
|
||||
} else if(rfCnts[i]>rfCnts[rfHighest3]){
|
||||
rfHighest3=i;
|
||||
}
|
||||
}
|
||||
|
||||
// set allowed clock remainder tolerance to be 1 large field clock length
|
||||
// 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
|
||||
int tol1 = (fcLens[best1]>fcLens[best2]) ? fcLens[best1] : fcLens[best2];
|
||||
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
|
||||
|
@ -1348,19 +1300,90 @@ uint32_t countFC(uint8_t *BitStream, size_t size)
|
|||
}
|
||||
}
|
||||
|
||||
if (ii<0) ii=7; // oops we went too far
|
||||
if (ii<0) return 0; // oops we went too far
|
||||
|
||||
return clk[ii];
|
||||
}
|
||||
|
||||
//by marshmellow
|
||||
//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
|
||||
|
||||
uint32_t fcs=0;
|
||||
// PrintAndLog("DEBUG: Best %d best2 %d best3 %d, clk %d, clk2 %d",fcLens[best1],fcLens[best2],fcLens[best3],clk[i],clk[ii]);
|
||||
//
|
||||
|
||||
if (fcLens[best1]>fcLens[best2]){
|
||||
fcs = (((uint32_t)clk[ii])<<16) | (((uint32_t)fcLens[best1])<<8) | ((fcLens[best2]));
|
||||
} else {
|
||||
fcs = (((uint32_t)clk[ii])<<16) | (((uint32_t)fcLens[best2])<<8) | ((fcLens[best1]));
|
||||
}
|
||||
uint16_t fcs = (((uint16_t)fcH)<<8) | fcL;
|
||||
// PrintAndLog("DEBUG: Best %d best2 %d best3 %d",fcLens[best1],fcLens[best2],fcLens[best3]);
|
||||
|
||||
return fcs;
|
||||
}
|
||||
|
|
|
@ -33,7 +33,8 @@ void pskCleanWave(uint8_t *bitStream, size_t size);
|
|||
int PyramiddemodFSK(uint8_t *dest, size_t size);
|
||||
int AWIDdemodFSK(uint8_t *dest, size_t size);
|
||||
size_t removeParity(uint8_t *BitStream, size_t startIdx, uint8_t pLen, uint8_t pType, size_t bLen);
|
||||
uint32_t countFC(uint8_t *BitStream, size_t size);
|
||||
uint16_t countFC(uint8_t *BitStream, size_t size);
|
||||
uint8_t detectFSKClk(uint8_t *BitStream, size_t size, uint8_t fcHigh, uint8_t fcLow);
|
||||
int getHiLo(uint8_t *BitStream, size_t size, int *high, int *low, uint8_t fuzzHi, uint8_t fuzzLo);
|
||||
size_t ParadoxdemodFSK(uint8_t *dest, size_t *size, uint32_t *hi2, uint32_t *hi, uint32_t *lo);
|
||||
|
||||
|
|
Loading…
Reference in a new issue