lfem4x cleanup/add/fix

changed spacing to tabs for cmdlfem4x.c
finished the partially built lf em em4x50read function
added save/restore GraphBuffer function in graph.c
adjusted some tolerances in lfdemod.c
added a maxLen argument to the askmandemod
This commit is contained in:
marshmellow42 2015-04-02 12:48:52 -04:00
commit 23f0a7d862
8 changed files with 505 additions and 354 deletions

View file

@ -96,7 +96,7 @@ int CmdPrintDemodBuff(const char *Cmd)
{ {
char hex; char hex;
char printBuff[512]={0x00}; char printBuff[512]={0x00};
uint8_t numBits = DemodBufferLen & 0xFFF0; uint8_t numBits = DemodBufferLen & 0xFFFC;
sscanf(Cmd, "%c", &hex); sscanf(Cmd, "%c", &hex);
if (hex == 'h'){ if (hex == 'h'){
PrintAndLog("Usage: data printdemodbuffer [x]"); PrintAndLog("Usage: data printdemodbuffer [x]");
@ -414,12 +414,13 @@ int ASKmanDemod(const char *Cmd, bool verbose, bool emSearch)
int invert=0; int invert=0;
int clk=0; int clk=0;
int maxErr=100; int maxErr=100;
int maxLen=512*64;
//param_getdec(Cmd, 0, &clk); //param_getdec(Cmd, 0, &clk);
//param_getdec(Cmd, 1, &invert); //param_getdec(Cmd, 1, &invert);
//maxErr = param_get32ex(Cmd, 2, 0xFFFFFFFF, 10); //maxErr = param_get32ex(Cmd, 2, 0xFFFFFFFF, 10);
//if (maxErr == 0xFFFFFFFF) maxErr=100; //if (maxErr == 0xFFFFFFFF) maxErr=100;
uint8_t BitStream[MAX_GRAPH_TRACE_LEN]={0}; uint8_t BitStream[MAX_GRAPH_TRACE_LEN]={0};
sscanf(Cmd, "%i %i %i", &clk, &invert, &maxErr); sscanf(Cmd, "%i %i %i %i", &clk, &invert, &maxErr, &maxLen);
if (invert != 0 && invert != 1) { if (invert != 0 && invert != 1) {
PrintAndLog("Invalid argument: %s", Cmd); PrintAndLog("Invalid argument: %s", Cmd);
return 0; return 0;
@ -432,6 +433,7 @@ int ASKmanDemod(const char *Cmd, bool verbose, bool emSearch)
if (g_debugMode==1) PrintAndLog("DEBUG: Bitlen from grphbuff: %d",BitLen); if (g_debugMode==1) PrintAndLog("DEBUG: Bitlen from grphbuff: %d",BitLen);
if (BitLen==0) return 0; if (BitLen==0) return 0;
int errCnt=0; int errCnt=0;
if (maxLen<BitLen && maxLen != 0) BitLen = maxLen;
errCnt = askmandemod(BitStream, &BitLen, &clk, &invert, maxErr); errCnt = askmandemod(BitStream, &BitLen, &clk, &invert, maxErr);
if (errCnt<0||BitLen<16){ //if fatal error (or -1) if (errCnt<0||BitLen<16){ //if fatal error (or -1)
if (g_debugMode==1) PrintAndLog("no data found %d, errors:%d, bitlen:%d, clock:%d",errCnt,invert,BitLen,clk); if (g_debugMode==1) PrintAndLog("no data found %d, errors:%d, bitlen:%d, clock:%d",errCnt,invert,BitLen,clk);
@ -473,11 +475,12 @@ int ASKmanDemod(const char *Cmd, bool verbose, bool emSearch)
int Cmdaskmandemod(const char *Cmd) int Cmdaskmandemod(const char *Cmd)
{ {
char cmdp = param_getchar(Cmd, 0); char cmdp = param_getchar(Cmd, 0);
if (strlen(Cmd) > 10 || cmdp == 'h' || cmdp == 'H') { if (strlen(Cmd) > 20 || cmdp == 'h' || cmdp == 'H') {
PrintAndLog("Usage: data rawdemod am [clock] <0|1> [maxError]"); PrintAndLog("Usage: data rawdemod am [clock] <0|1> [maxError] [setSmplLen]");
PrintAndLog(" [set clock as integer] optional, if not set, autodetect."); PrintAndLog(" [set clock as integer] optional, if not set, autodetect.");
PrintAndLog(" <invert>, 1 for invert output"); PrintAndLog(" <invert>, 1 for invert output");
PrintAndLog(" [set maximum allowed errors], default = 100."); PrintAndLog(" [set maximum allowed errors], default = 100.");
PrintAndLog(" [set maximum Samples to read], default = 32768 (512 bits at rf/64).");
PrintAndLog(""); PrintAndLog("");
PrintAndLog(" sample: data rawdemod am = demod an ask/manchester tag from GraphBuffer"); PrintAndLog(" sample: data rawdemod am = demod an ask/manchester tag from GraphBuffer");
PrintAndLog(" : data rawdemod am 32 = demod an ask/manchester tag from GraphBuffer using a clock of RF/32"); PrintAndLog(" : data rawdemod am 32 = demod an ask/manchester tag from GraphBuffer using a clock of RF/32");
@ -2065,7 +2068,7 @@ int CmdRawDemod(const char *Cmd)
{ {
char cmdp = Cmd[0]; //param_getchar(Cmd, 0); char cmdp = Cmd[0]; //param_getchar(Cmd, 0);
if (strlen(Cmd) > 14 || cmdp == 'h' || cmdp == 'H' || strlen(Cmd)<2) { if (strlen(Cmd) > 20 || cmdp == 'h' || cmdp == 'H' || strlen(Cmd)<2) {
PrintAndLog("Usage: data rawdemod [modulation] <help>|<options>"); PrintAndLog("Usage: data rawdemod [modulation] <help>|<options>");
PrintAndLog(" [modulation] as 2 char, 'ab' for ask/biphase, 'am' for ask/manchester, 'ar' for ask/raw, 'fs' for fsk, ..."); PrintAndLog(" [modulation] as 2 char, 'ab' for ask/biphase, 'am' for ask/manchester, 'ar' for ask/raw, 'fs' for fsk, ...");
PrintAndLog(" 'nr' for nrz/direct, 'p1' for psk1, 'p2' for psk2"); PrintAndLog(" 'nr' for nrz/direct, 'p1' for psk1, 'p2' for psk2");

View file

@ -54,6 +54,7 @@ int CmdManchesterMod(const char *Cmd);
int CmdNorm(const char *Cmd); int CmdNorm(const char *Cmd);
int CmdNRZrawDemod(const char *Cmd); int CmdNRZrawDemod(const char *Cmd);
int CmdPlot(const char *Cmd); int CmdPlot(const char *Cmd);
int CmdPrintDemodBuff(const char *Cmd);
int CmdRawDemod(const char *Cmd); int CmdRawDemod(const char *Cmd);
int CmdSamples(const char *Cmd); int CmdSamples(const char *Cmd);
int CmdTuneSamples(const char *Cmd); int CmdTuneSamples(const char *Cmd);
@ -77,7 +78,7 @@ int getSamples(const char *Cmd, bool silent);
#define MAX_DEMOD_BUF_LEN (1024*128) #define MAX_DEMOD_BUF_LEN (1024*128)
extern uint8_t DemodBuffer[MAX_DEMOD_BUF_LEN]; extern uint8_t DemodBuffer[MAX_DEMOD_BUF_LEN];
extern int DemodBufferLen; extern int DemodBufferLen;
extern uint8_t g_debugMode;
#define BIGBUF_SIZE 40000 #define BIGBUF_SIZE 40000
#endif #endif

View file

@ -1094,6 +1094,11 @@ int CmdLFfind(const char *Cmd)
return 1; return 1;
} }
ans=EM4x50Read("", false);
if (ans>0) {
PrintAndLog("\nValid EM4x50 ID Found!");
return 1;
}
PrintAndLog("\nNo Known Tags Found!\n"); PrintAndLog("\nNo Known Tags Found!\n");
if (testRaw=='u' || testRaw=='U'){ if (testRaw=='u' || testRaw=='U'){
//test unknown tag formats (raw mode) //test unknown tag formats (raw mode)

View file

@ -19,6 +19,7 @@
#include "cmddata.h" #include "cmddata.h"
#include "cmdlf.h" #include "cmdlf.h"
#include "cmdlfem4x.h" #include "cmdlfem4x.h"
#include "lfdemod.h"
char *global_em410xId; char *global_em410xId;
static int CmdHelp(const char *Cmd); static int CmdHelp(const char *Cmd);
@ -156,6 +157,7 @@ int CmdEM410xWatch(const char *Cmd)
return 0; return 0;
} }
//currently only supports manchester modulations
int CmdEM410xWatchnSpoof(const char *Cmd) int CmdEM410xWatchnSpoof(const char *Cmd)
{ {
CmdEM410xWatch(Cmd); CmdEM410xWatch(Cmd);
@ -164,6 +166,65 @@ int CmdEM410xWatchnSpoof(const char *Cmd)
return 0; return 0;
} }
bool EM_EndParityTest(uint8_t *BitStream, size_t size, uint8_t rows, uint8_t cols, uint8_t pType)
{
if (rows*cols>size) return false;
uint8_t colP=0;
//assume last row is a parity row and do not test
for (uint8_t colNum = 0; colNum < cols-1; colNum++) {
for (uint8_t rowNum = 0; rowNum < rows; rowNum++) {
colP ^= BitStream[(rowNum*cols)+colNum];
}
if (colP != pType) return false;
}
return true;
}
bool EM_ByteParityTest(uint8_t *BitStream, size_t size, uint8_t rows, uint8_t cols, uint8_t pType)
{
if (rows*cols>size) return false;
uint8_t rowP=0;
//assume last row is a parity row and do not test
for (uint8_t rowNum = 0; rowNum < rows-1; rowNum++) {
for (uint8_t colNum = 0; colNum < cols; colNum++) {
rowP ^= BitStream[(rowNum*cols)+colNum];
}
if (rowP != pType) return false;
}
return true;
}
uint32_t OutputEM4x50_Block(uint8_t *BitStream, size_t size, bool verbose, bool pTest)
{
if (size<45) return 0;
uint32_t code = bytebits_to_byte(BitStream,8);
code = code<<8 | bytebits_to_byte(BitStream+9,8);
code = code<<8 | bytebits_to_byte(BitStream+18,8);
code = code<<8 | bytebits_to_byte(BitStream+27,8);
if (verbose || g_debugMode){
for (uint8_t i = 0; i<5; i++){
if (i == 4) PrintAndLog("");
PrintAndLog("%d%d%d%d%d%d%d%d %d -> 0x%02x",
BitStream[i*9],
BitStream[i*9+1],
BitStream[i*9+2],
BitStream[i*9+3],
BitStream[i*9+4],
BitStream[i*9+5],
BitStream[i*9+6],
BitStream[i*9+7],
BitStream[i*9+8],
bytebits_to_byte(BitStream+i*9,8)
);
}
if (pTest)
PrintAndLog("Parity Passed");
else
PrintAndLog("Parity Failed");
}
//PrintAndLog("Code: %08x",code);
return code;
}
/* Read the transmitted data of an EM4x50 tag /* Read the transmitted data of an EM4x50 tag
* Format: * Format:
* *
@ -183,17 +244,25 @@ int CmdEM410xWatchnSpoof(const char *Cmd)
* is stored in the blocks defined in the control word First and Last * is stored in the blocks defined in the control word First and Last
* Word Read values. UID is stored in block 32. * Word Read values. UID is stored in block 32.
*/ */
int CmdEM4x50Read(const char *Cmd) int EM4x50Read(const char *Cmd, bool verbose)
{ {
int i, j, startblock, skip, block, start, end, low, high; uint8_t fndClk[]={0,8,16,32,40,50,64};
int clk = 0;
int invert = 0;
sscanf(Cmd, "%i %i", &clk, &invert);
int tol = 0;
int i, j, startblock, skip, block, start, end, low, high, minClk;
bool complete= false; bool complete= false;
int tmpbuff[MAX_GRAPH_TRACE_LEN / 64]; int tmpbuff[MAX_GRAPH_TRACE_LEN / 64];
save_restoreGB(1);
uint32_t Code[6];
char tmp[6]; char tmp[6];
char tmp2[20];
high= low= 0; high= low= 0;
memset(tmpbuff, 0, MAX_GRAPH_TRACE_LEN / 64); memset(tmpbuff, 0, MAX_GRAPH_TRACE_LEN / 64);
/* first get high and low values */ // first get high and low values
for (i = 0; i < GraphTraceLen; i++) for (i = 0; i < GraphTraceLen; i++)
{ {
if (GraphBuffer[i] > high) if (GraphBuffer[i] > high)
@ -202,9 +271,10 @@ int CmdEM4x50Read(const char *Cmd)
low = GraphBuffer[i]; low = GraphBuffer[i];
} }
/* populate a buffer with pulse lengths */ // populate a buffer with pulse lengths
i= 0; i= 0;
j= 0; j= 0;
minClk= 255;
while (i < GraphTraceLen) while (i < GraphTraceLen)
{ {
// measure from low to low // measure from low to low
@ -219,93 +289,141 @@ int CmdEM4x50Read(const char *Cmd)
break; break;
} }
tmpbuff[j++]= i - start; tmpbuff[j++]= i - start;
if (i-start < minClk) minClk = i-start;
}
// set clock
if (!clk){
for (uint8_t clkCnt = 0; clkCnt<7; clkCnt++) {
tol = fndClk[clkCnt]/8;
if (fndClk[clkCnt]-tol >= minClk) {
clk=fndClk[clkCnt];
break;
}
}
} }
/* look for data start - should be 2 pairs of LW (pulses of 192,128) */ // look for data start - should be 2 pairs of LW (pulses of clk*3,clk*2)
start= -1; start= -1;
skip= 0; skip= 0;
for (i= 0; i < j - 4 ; ++i) for (i= 0; i < j - 4 ; ++i)
{ {
skip += tmpbuff[i]; skip += tmpbuff[i];
if (tmpbuff[i] >= 190 && tmpbuff[i] <= 194) if (tmpbuff[i] >= clk*3-tol && tmpbuff[i] <= clk*3+tol)
if (tmpbuff[i+1] >= 126 && tmpbuff[i+1] <= 130) if (tmpbuff[i+1] >= clk*2-tol && tmpbuff[i+1] <= clk*2+tol)
if (tmpbuff[i+2] >= 190 && tmpbuff[i+2] <= 194) if (tmpbuff[i+2] >= clk*3-tol && tmpbuff[i+2] <= clk*3+tol)
if (tmpbuff[i+3] >= 126 && tmpbuff[i+3] <= 130) if (tmpbuff[i+3] >= clk-tol)
{ {
start= i + 3; start= i + 4;
break; break;
} }
} }
startblock= i + 3; startblock= i + 4;
/* skip over the remainder of the LW */ // skip over the remainder of LW
skip += tmpbuff[i+1]+tmpbuff[i+2]; skip += tmpbuff[i+1] + tmpbuff[i+2] + clk + clk/8;
while (skip < MAX_GRAPH_TRACE_LEN && GraphBuffer[skip] > low)
++skip;
skip += 8;
/* now do it again to find the end */ int phaseoff = tmpbuff[i+3]-clk;
end= start;
// now do it again to find the end
end = skip;
for (i += 3; i < j - 4 ; ++i) for (i += 3; i < j - 4 ; ++i)
{ {
end += tmpbuff[i]; end += tmpbuff[i];
if (tmpbuff[i] >= 190 && tmpbuff[i] <= 194) if (tmpbuff[i] >= clk*3-tol && tmpbuff[i] <= clk*3 + tol)
if (tmpbuff[i+1] >= 126 && tmpbuff[i+1] <= 130) if (tmpbuff[i+1] >= clk*2-tol && tmpbuff[i+1] <= clk*2 + tol)
if (tmpbuff[i+2] >= 190 && tmpbuff[i+2] <= 194) if (tmpbuff[i+2] >= clk*3-tol && tmpbuff[i+2] <= clk*3 + tol)
if (tmpbuff[i+3] >= 126 && tmpbuff[i+3] <= 130) if (tmpbuff[i+3] >= clk-tol)
{ {
complete= true; complete= true;
break; break;
} }
} }
end = i;
if (start >= 0) // report back
PrintAndLog("Found data at sample: %i",skip); if (verbose || g_debugMode) {
else if (start >= 0) {
{ PrintAndLog("\nNote: should print 45 bits then 0177 (end of block)");
PrintAndLog(" for each block");
PrintAndLog(" Also, sometimes the demod gets out of sync and ");
PrintAndLog(" inverts the output - when this happens the 0177");
PrintAndLog(" will be 3 extra 1's at the end");
PrintAndLog(" 'data askedge' command may fix that");
} else {
PrintAndLog("No data found!"); PrintAndLog("No data found!");
PrintAndLog("Try again with more samples."); PrintAndLog("Try again with more samples.");
return 0; return 0;
} }
if (!complete) if (!complete)
{ {
PrintAndLog("*** Warning!"); PrintAndLog("*** Warning!");
PrintAndLog("Partial data - no end found!"); PrintAndLog("Partial data - no end found!");
PrintAndLog("Try again with more samples."); PrintAndLog("Try again with more samples.");
} }
} else if (start < 0) return 0;
/* get rid of leading crap */ start=skip;
sprintf(tmp,"%i",skip); snprintf(tmp2, sizeof(tmp2),"%d %d 1000 %d", clk, invert, clk*47);
// get rid of leading crap
snprintf(tmp, sizeof(tmp),"%i",skip);
CmdLtrim(tmp); CmdLtrim(tmp);
bool pTest;
/* now work through remaining buffer printing out data blocks */ bool AllPTest=true;
block= 0; // now work through remaining buffer printing out data blocks
i= startblock; block = 0;
i = startblock;
while (block < 6) while (block < 6)
{ {
PrintAndLog("Block %i:", block); if (verbose || g_debugMode) PrintAndLog("\nBlock %i:", block);
// mandemod routine needs to be split so we can call it for data skip = phaseoff;
// just print for now for debugging
CmdManchesterDemod("i 64"); // look for LW before start of next block
skip= 0;
/* look for LW before start of next block */
for ( ; i < j - 4 ; ++i) for ( ; i < j - 4 ; ++i)
{ {
skip += tmpbuff[i]; skip += tmpbuff[i];
if (tmpbuff[i] >= 190 && tmpbuff[i] <= 194) if (tmpbuff[i] >= clk*3-tol && tmpbuff[i] <= clk*3+tol)
if (tmpbuff[i+1] >= 126 && tmpbuff[i+1] <= 130) if (tmpbuff[i+1] >= clk-tol)
break; break;
} }
while (GraphBuffer[skip] > low) skip += clk;
++skip; phaseoff = tmpbuff[i+1]-clk;
skip += 8; i += 2;
sprintf(tmp,"%i",skip); if (ASKmanDemod(tmp2, false, false)<1) return 0;
//set DemodBufferLen to just one block
DemodBufferLen = skip/clk;
//test parities
pTest = EM_ByteParityTest(DemodBuffer,DemodBufferLen,5,9,0);
pTest &= EM_EndParityTest(DemodBuffer,DemodBufferLen,5,9,0);
AllPTest &= pTest;
//get output
Code[block]=OutputEM4x50_Block(DemodBuffer,DemodBufferLen,verbose, pTest);
if (g_debugMode) PrintAndLog("\nskipping %d samples, bits:%d",start, skip/clk);
//skip to start of next block
snprintf(tmp,sizeof(tmp),"%i",skip);
CmdLtrim(tmp); CmdLtrim(tmp);
start += skip;
block++; block++;
if (i>=end) break; //in case chip doesn't output 6 blocks
} }
return 0; //print full code:
if (verbose || g_debugMode || AllPTest){
PrintAndLog("Found data at sample: %i - using clock: %i",skip,clk);
//PrintAndLog("\nSummary:");
end=block;
for (block=0; block<end; block++){
PrintAndLog("Block %d: %08x",block,Code[block]);
}
if (AllPTest)
PrintAndLog("Parities Passed");
else
PrintAndLog("Parities Failed");
}
//restore GraphBuffer
save_restoreGB(0);
return (int)AllPTest;
}
int CmdEM4x50Read(const char *Cmd)
{
return EM4x50Read(Cmd, true);
} }
int CmdEM410xWrite(const char *Cmd) int CmdEM410xWrite(const char *Cmd)

View file

@ -11,7 +11,6 @@
#ifndef CMDLFEM4X_H__ #ifndef CMDLFEM4X_H__
#define CMDLFEM4X_H__ #define CMDLFEM4X_H__
int CmdLFEM4X(const char *Cmd);
int CmdEMdemodASK(const char *Cmd); int CmdEMdemodASK(const char *Cmd);
int CmdEM410xRead(const char *Cmd); int CmdEM410xRead(const char *Cmd);
int CmdEM410xSim(const char *Cmd); int CmdEM410xSim(const char *Cmd);
@ -19,9 +18,11 @@ int CmdEM410xWatch(const char *Cmd);
int CmdEM410xWatchnSpoof(const char *Cmd); int CmdEM410xWatchnSpoof(const char *Cmd);
int CmdEM410xWrite(const char *Cmd); int CmdEM410xWrite(const char *Cmd);
int CmdEM4x50Read(const char *Cmd); int CmdEM4x50Read(const char *Cmd);
int CmdLFEM4X(const char *Cmd);
int CmdReadWord(const char *Cmd); int CmdReadWord(const char *Cmd);
int CmdReadWordPWD(const char *Cmd); int CmdReadWordPWD(const char *Cmd);
int CmdWriteWord(const char *Cmd); int CmdWriteWord(const char *Cmd);
int CmdWriteWordPWD(const char *Cmd); int CmdWriteWordPWD(const char *Cmd);
int EM4x50Read(const char *Cmd, bool verbose);
#endif #endif

View file

@ -17,7 +17,6 @@
int GraphBuffer[MAX_GRAPH_TRACE_LEN]; int GraphBuffer[MAX_GRAPH_TRACE_LEN];
int GraphTraceLen; int GraphTraceLen;
/* write a manchester bit to the graph */ /* write a manchester bit to the graph */
void AppendGraph(int redraw, int clock, int bit) void AppendGraph(int redraw, int clock, int bit)
{ {
@ -46,6 +45,23 @@ int ClearGraph(int redraw)
return gtl; return gtl;
} }
// option '1' to save GraphBuffer any other to restore
void save_restoreGB(uint8_t saveOpt)
{
static int SavedGB[MAX_GRAPH_TRACE_LEN];
static int SavedGBlen;
static bool GB_Saved = false;
if (saveOpt==1) { //save
memcpy(SavedGB,GraphBuffer, sizeof(GraphBuffer));
SavedGBlen = GraphTraceLen;
GB_Saved=true;
} else if (GB_Saved){
memcpy(GraphBuffer,SavedGB, sizeof(GraphBuffer));
GraphTraceLen = SavedGBlen;
}
return;
}
// DETECT CLOCK NOW IN LFDEMOD.C // DETECT CLOCK NOW IN LFDEMOD.C

View file

@ -23,6 +23,7 @@ uint8_t GetNrzClock(const char str[], bool printAns, bool verbose);
uint8_t GetFskClock(const char str[], bool printAns, bool verbose); uint8_t GetFskClock(const char str[], bool printAns, bool verbose);
uint8_t fskClocks(uint8_t *fc1, uint8_t *fc2, uint8_t *rf1, bool verbose); uint8_t fskClocks(uint8_t *fc1, uint8_t *fc2, uint8_t *rf1, bool verbose);
void setGraphBuf(uint8_t *buff, size_t size); void setGraphBuf(uint8_t *buff, size_t size);
void save_restoreGB(uint8_t saveOpt);
bool HasGraphData(); bool HasGraphData();
void DetectHighLowInGraph(int *high, int *low, bool addFuzz); void DetectHighLowInGraph(int *high, int *low, bool addFuzz);

View file

@ -114,6 +114,57 @@ uint8_t Em410xDecode(uint8_t *BitStream, size_t *size, size_t *startIdx, uint32_
return 0; return 0;
} }
// demodulates strong heavily clipped samples
int cleanAskRawDemod(uint8_t *BinStream, size_t *size, int clk, int invert, int high, int low)
{
size_t bitCnt=0, smplCnt=0, errCnt=0;
uint8_t waveHigh = 0;
//PrintAndLog("clk: %d", clk);
for (size_t i=0; 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++;
BinStream[bitCnt++]=77;
} else if (waveHigh) {
BinStream[bitCnt++] = invert;
BinStream[bitCnt++] = invert;
} else if (!waveHigh) {
BinStream[bitCnt++] = invert ^ 1;
BinStream[bitCnt++] = invert ^ 1;
}
waveHigh ^= 1;
smplCnt = 0;
} else if (smplCnt > (clk/2) - (clk/4)-1) {
if (waveHigh) {
BinStream[bitCnt++] = invert;
} else if (!waveHigh) {
BinStream[bitCnt++] = invert ^ 1;
}
waveHigh ^= 1;
smplCnt = 0;
} else if (!bitCnt) {
//first bit
waveHigh = (BinStream[i] >= high);
smplCnt = 1;
} else {
smplCnt++;
//transition bit oops
}
} else { //haven't hit new high or new low yet
smplCnt++;
}
}
}
*size = bitCnt;
return errCnt;
}
//by marshmellow //by marshmellow
//takes 3 arguments - clock, invert, maxErr as integers //takes 3 arguments - clock, invert, maxErr as integers
//attempts to demodulate ask while decoding manchester //attempts to demodulate ask while decoding manchester
@ -131,6 +182,13 @@ int askmandemod(uint8_t *BinStream, size_t *size, int *clk, int *invert, int max
int high, low; int high, low;
if (getHiLo(BinStream, initLoopMax, &high, &low, 75, 75) < 1) return -2; //just noise if (getHiLo(BinStream, initLoopMax, &high, &low, 75, 75) < 1) return -2; //just noise
// if clean clipped waves detected run alternate demod
if (DetectCleanAskWave(BinStream, *size, high, low)) {
cleanAskRawDemod(BinStream, size, *clk, *invert, high, low);
return manrawdecode(BinStream, size);
}
// PrintAndLog("DEBUG - valid high: %d - valid low: %d",high,low); // PrintAndLog("DEBUG - valid high: %d - valid low: %d",high,low);
int lastBit = 0; //set first clock check int lastBit = 0; //set first clock check
uint16_t bitnum = 0; //output counter uint16_t bitnum = 0; //output counter
@ -138,7 +196,7 @@ int askmandemod(uint8_t *BinStream, size_t *size, int *clk, int *invert, int max
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 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 iii = 0; size_t iii = 0;
//if 0 errors allowed then only try first 2 clock cycles as we want a low tolerance //if 0 errors allowed then only try first 2 clock cycles as we want a low tolerance
if (!maxErr) initLoopMax = *clk * 2; if (!maxErr && initLoopMax > *clk*3) initLoopMax = *clk * 3;
uint16_t errCnt = 0, MaxBits = 512; uint16_t errCnt = 0, MaxBits = 512;
uint16_t bestStart = start; uint16_t bestStart = start;
uint16_t bestErrCnt = 0; uint16_t bestErrCnt = 0;
@ -147,7 +205,7 @@ int askmandemod(uint8_t *BinStream, size_t *size, int *clk, int *invert, int max
if (start <= 0 || start > initLoopMax){ if (start <= 0 || start > initLoopMax){
bestErrCnt = maxErr+1; bestErrCnt = maxErr+1;
// loop to find first wave that works // loop to find first wave that works
for (iii=0; iii < initLoopMax; ++iii){ for (iii=0; iii < initLoopMax-tol-*clk; ++iii){
// if no peak skip // if no peak skip
if (BinStream[iii] < high && BinStream[iii] > low) continue; if (BinStream[iii] < high && BinStream[iii] > low) continue;
@ -163,7 +221,7 @@ int askmandemod(uint8_t *BinStream, size_t *size, int *clk, int *invert, int max
if ((i-iii) > (MaxBits * *clk) || errCnt > maxErr) break; //got plenty of bits or too many errors if ((i-iii) > (MaxBits * *clk) || errCnt > maxErr) break; //got plenty of bits or too many errors
} }
//we got more than 64 good bits and not all errors //we got more than 64 good bits and not all errors
if ((((i-iii)/ *clk) > (64)) && (errCnt<=maxErr)) { if ((((i-iii)/ *clk) > (32)) && (errCnt<=maxErr)) {
//possible good read //possible good read
if (!errCnt || errCnt < bestErrCnt){ if (!errCnt || errCnt < bestErrCnt){
bestStart = iii; //set this as new best run bestStart = iii; //set this as new best run
@ -242,7 +300,6 @@ int manrawdecode(uint8_t * BitStream, size_t *size)
} }
errCnt=0; errCnt=0;
} }
if (bestErr<20){
for (i=bestRun; i < *size-2; i+=2){ for (i=bestRun; i < *size-2; i+=2){
if(BitStream[i] == 1 && (BitStream[i+1] == 0)){ if(BitStream[i] == 1 && (BitStream[i+1] == 0)){
BitStream[bitnum++]=0; BitStream[bitnum++]=0;
@ -254,7 +311,6 @@ int manrawdecode(uint8_t * BitStream, size_t *size)
if(bitnum>MaxBits) break; if(bitnum>MaxBits) break;
} }
*size=bitnum; *size=bitnum;
}
return bestErr; return bestErr;
} }
@ -319,57 +375,6 @@ void askAmp(uint8_t *BitStream, size_t size)
return; return;
} }
// demodulates strong heavily clipped samples
int cleanAskRawDemod(uint8_t *BinStream, size_t *size, int clk, int invert, int high, int low)
{
size_t bitCnt=0, smplCnt=0, errCnt=0;
uint8_t waveHigh = 0;
//PrintAndLog("clk: %d", clk);
for (size_t i=0; 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++;
BinStream[bitCnt++]=77;
} else if (waveHigh) {
BinStream[bitCnt++] = invert;
BinStream[bitCnt++] = invert;
} else if (!waveHigh) {
BinStream[bitCnt++] = invert ^ 1;
BinStream[bitCnt++] = invert ^ 1;
}
waveHigh ^= 1;
smplCnt = 0;
} else if (smplCnt > (clk/2) - (clk/4)-1) {
if (waveHigh) {
BinStream[bitCnt++] = invert;
} else if (!waveHigh) {
BinStream[bitCnt++] = invert ^ 1;
}
waveHigh ^= 1;
smplCnt = 0;
} else if (!bitCnt) {
//first bit
waveHigh = (BinStream[i] >= high);
smplCnt = 1;
} else {
smplCnt++;
//transition bit oops
}
} else { //haven't hit new high or new low yet
smplCnt++;
}
}
}
*size = bitCnt;
return errCnt;
}
//by marshmellow //by marshmellow
//takes 3 arguments - clock, invert and maxErr as integers //takes 3 arguments - clock, invert and maxErr as integers
//attempts to demodulate ask only //attempts to demodulate ask only
@ -401,13 +406,13 @@ int askrawdemod(uint8_t *BinStream, size_t *size, int *clk, int *invert, int max
size_t MaxBits = 1024; size_t MaxBits = 1024;
//if 0 errors allowed then only try first 2 clock cycles as we want a low tolerance //if 0 errors allowed then only try first 2 clock cycles as we want a low tolerance
if (!maxErr) initLoopMax = *clk * 2; if (!maxErr && initLoopMax > *clk*3) initLoopMax = *clk * 3;
//if best start not already found by detectclock //if best start not already found by detectclock
if (start <= 0 || start > initLoopMax){ if (start <= 0 || start > initLoopMax){
bestErrCnt = maxErr+1; bestErrCnt = maxErr+1;
//PrintAndLog("DEBUG - lastbit - %d",lastBit); //PrintAndLog("DEBUG - lastbit - %d",lastBit);
//loop to find first wave that works //loop to find first wave that works
for (iii=0; iii < initLoopMax; ++iii){ for (iii=0; iii < initLoopMax - *clk; ++iii){
if ((BinStream[iii] >= high) || (BinStream[iii] <= low)){ if ((BinStream[iii] >= high) || (BinStream[iii] <= low)){
lastBit = iii - *clk; lastBit = iii - *clk;
//loop through to see if this start location works //loop through to see if this start location works
@ -427,8 +432,8 @@ int askrawdemod(uint8_t *BinStream, size_t *size, int *clk, int *invert, int max
} }
if ((i-iii)>(MaxBits * *clk)) break; //got enough bits if ((i-iii)>(MaxBits * *clk)) break; //got enough bits
} }
//we got more than 64 good bits and not all errors //we got more than 32 good bits and not all errors
if ((((i-iii)/ *clk) > 64) && (errCnt<=maxErr)) { if ((((i-iii)/ *clk) > 32) && (errCnt<=maxErr)) {
//possible good read //possible good read
if (errCnt==0){ if (errCnt==0){
bestStart=iii; bestStart=iii;
@ -859,7 +864,8 @@ int DetectASKClock(uint8_t dest[], size_t size, int *clock, int maxErr)
size_t i=0; size_t i=0;
uint8_t clk[]={8,16,32,40,50,64,100,128,255}; uint8_t clk[]={8,16,32,40,50,64,100,128,255};
uint8_t loopCnt = 255; //don't need to loop through entire array... uint8_t loopCnt = 255; //don't need to loop through entire array...
if (size <= loopCnt) return -1; //not enough samples if (size==0) return -1;
if (size <= loopCnt) loopCnt = size-1; //not enough samples
//if we already have a valid clock quit //if we already have a valid clock quit
for (;i<8;++i) for (;i<8;++i)
@ -892,10 +898,10 @@ int DetectASKClock(uint8_t dest[], size_t size, int *clock, int maxErr)
}else{ }else{
tol=0; tol=0;
} }
if (!maxErr) loopCnt=clk[clkCnt]*2; if (!maxErr && loopCnt>clk[clkCnt]*2) loopCnt=clk[clkCnt]*2;
bestErr[clkCnt]=1000; bestErr[clkCnt]=1000;
//try lining up the peaks by moving starting point (try first 256) //try lining up the peaks by moving starting point (try first 256)
for (ii=0; ii < loopCnt; ii++){ for (ii=0; ii < loopCnt-tol-clk[clkCnt]; ii++){
if (dest[ii] < peak && dest[ii] > low) continue; if (dest[ii] < peak && dest[ii] > low) continue;
errCnt=0; errCnt=0;