// Data and Graph commands
//-----------------------------------------------------------------------------
-#include <stdio.h>
-#include <stdlib.h>
-#include <string.h>
-#include <limits.h>
-#include "proxmark3.h"
-#include "data.h"
-#include "ui.h"
-#include "graph.h"
-#include "cmdparser.h"
+#include <stdio.h> // also included in util.h
+#include <string.h> // also included in util.h
+#include <inttypes.h>
+#include <limits.h> // for CmdNorm INT_MIN && INT_MAX
+#include "data.h" // also included in util.h
+#include "cmddata.h"
#include "util.h"
#include "cmdmain.h"
-#include "cmddata.h"
-#include "lfdemod.h"
-#include "usb_cmd.h"
-#include "crc.h"
-#include "crc16.h"
-#include "loclass/cipherutils.h"
+#include "proxmark3.h"
+#include "ui.h" // for show graph controls
+#include "graph.h" // for graph data
+#include "cmdparser.h"// already included in cmdmain.h
+#include "usb_cmd.h" // already included in cmdmain.h and proxmark3.h
+#include "lfdemod.h" // for demod code
+#include "loclass/cipherutils.h" // for decimating samples in getsamples
+#include "cmdlfem4x.h"// for em410x demod
uint8_t DemodBuffer[MAX_DEMOD_BUF_LEN];
uint8_t g_debugMode=0;
size_t DemodBufferLen=0;
+int g_DemodStartIdx=0;
+int g_DemodClock=0;
+
static int CmdHelp(const char *Cmd);
//set the demod buffer with given array of binary (one bit per byte)
if (buff == NULL)
return;
- if ( size >= MAX_DEMOD_BUF_LEN)
- size = MAX_DEMOD_BUF_LEN;
+ if ( size > MAX_DEMOD_BUF_LEN - startIdx)
+ size = MAX_DEMOD_BUF_LEN - startIdx;
size_t i = 0;
for (; i < size; i++){
return;
}
+bool getDemodBuf(uint8_t *buff, size_t *size) {
+ if (buff == NULL) return false;
+ if (size == NULL) return false;
+ if (*size == 0) return false;
+
+ *size = (*size > DemodBufferLen) ? DemodBufferLen : *size;
+
+ memcpy(buff, DemodBuffer, *size);
+ return true;
+}
+
+// option '1' to save DemodBuffer any other to restore
+void save_restoreDB(uint8_t saveOpt)
+{
+ static uint8_t SavedDB[MAX_DEMOD_BUF_LEN];
+ static size_t SavedDBlen;
+ static bool DB_Saved = false;
+ static int savedDemodStartIdx = 0;
+ static int savedDemodClock = 0;
+
+ if (saveOpt == GRAPH_SAVE) { //save
+
+ memcpy(SavedDB, DemodBuffer, sizeof(DemodBuffer));
+ SavedDBlen = DemodBufferLen;
+ DB_Saved=true;
+ savedDemodStartIdx = g_DemodStartIdx;
+ savedDemodClock = g_DemodClock;
+ } else if (DB_Saved) { //restore
+ memcpy(DemodBuffer, SavedDB, sizeof(DemodBuffer));
+ DemodBufferLen = SavedDBlen;
+ g_DemodClock = savedDemodClock;
+ g_DemodStartIdx = savedDemodStartIdx;
+ }
+ return;
+}
+
int CmdSetDebugMode(const char *Cmd)
{
int demod=0;
}
int usage_data_printdemodbuf(){
- PrintAndLog("Usage: data printdemodbuffer x o <offset>");
+ PrintAndLog("Usage: data printdemodbuffer x o <offset> l <length>");
PrintAndLog("Options: ");
PrintAndLog(" h This help");
PrintAndLog(" x output in hex (omit for binary output)");
PrintAndLog(" o <offset> enter offset in # of bits");
+ PrintAndLog(" l <length> enter length to print in # of bits or hex characters respectively");
return 0;
}
char hex[512]={0x00};
bool hexMode = false;
bool errors = false;
- uint8_t offset = 0;
+ uint32_t offset = 0; //could be size_t but no param_get16...
+ uint32_t length = 512;
char cmdp = 0;
while(param_getchar(Cmd, cmdp) != 0x00)
{
break;
case 'o':
case 'O':
- offset = param_get8(Cmd, cmdp+1);
+ offset = param_get32ex(Cmd, cmdp+1, 0, 10);
if (!offset) errors = true;
cmdp += 2;
break;
+ case 'l':
+ case 'L':
+ length = param_get32ex(Cmd, cmdp+1, 512, 10);
+ if (!length) errors = true;
+ cmdp += 2;
+ break;
default:
PrintAndLog("Unknown parameter '%c'", param_getchar(Cmd, cmdp));
errors = true;
}
//Validations
if(errors) return usage_data_printdemodbuf();
-
- int numBits = (DemodBufferLen-offset) & 0x7FC; //make sure we don't exceed our string
+ length = (length > (DemodBufferLen-offset)) ? DemodBufferLen-offset : length;
+ int numBits = (length) & 0x00FFC; //make sure we don't exceed our string
if (hexMode){
char *buf = (char *) (DemodBuffer + offset);
+ numBits = (numBits > sizeof(hex)) ? sizeof(hex) : numBits;
numBits = binarraytohex(hex, buf, numBits);
if (numBits==0) return 0;
PrintAndLog("DemodBuffer: %s",hex);
} else {
- //setDemodBuf(DemodBuffer, DemodBufferLen-offset, offset);
- char *bin = sprint_bin_break(DemodBuffer+offset,numBits,16);
- PrintAndLog("DemodBuffer:\n%s",bin);
+ PrintAndLog("DemodBuffer:\n%s", sprint_bin_break(DemodBuffer+offset,numBits,16));
}
return 1;
}
return 0;
}
-//by marshmellow
-//print 64 bit EM410x ID in multiple formats
-void printEM410x(uint32_t hi, uint64_t id)
-{
- if (id || hi){
- uint64_t iii=1;
- uint64_t id2lo=0;
- uint32_t ii=0;
- uint32_t i=0;
- for (ii=5; ii>0;ii--){
- for (i=0;i<8;i++){
- id2lo=(id2lo<<1LL) | ((id & (iii << (i+((ii-1)*8)))) >> (i+((ii-1)*8)));
- }
- }
- if (hi){
- //output 88 bit em id
- PrintAndLog("\nEM TAG ID : %06X%016llX", hi, id);
- } else{
- //output 40 bit em id
- PrintAndLog("\nEM TAG ID : %010llX", id);
- PrintAndLog("Unique TAG ID : %010llX", id2lo);
- PrintAndLog("\nPossible de-scramble patterns");
- PrintAndLog("HoneyWell IdentKey {");
- PrintAndLog("DEZ 8 : %08lld",id & 0xFFFFFF);
- PrintAndLog("DEZ 10 : %010lld",id & 0xFFFFFFFF);
- PrintAndLog("DEZ 5.5 : %05lld.%05lld",(id>>16LL) & 0xFFFF,(id & 0xFFFF));
- PrintAndLog("DEZ 3.5A : %03lld.%05lld",(id>>32ll),(id & 0xFFFF));
- PrintAndLog("DEZ 3.5B : %03lld.%05lld",(id & 0xFF000000) >> 24,(id & 0xFFFF));
- PrintAndLog("DEZ 3.5C : %03lld.%05lld",(id & 0xFF0000) >> 16,(id & 0xFFFF));
- PrintAndLog("DEZ 14/IK2 : %014lld",id);
- PrintAndLog("DEZ 15/IK3 : %015lld",id2lo);
- PrintAndLog("DEZ 20/ZK : %02lld%02lld%02lld%02lld%02lld%02lld%02lld%02lld%02lld%02lld",
- (id2lo & 0xf000000000) >> 36,
- (id2lo & 0x0f00000000) >> 32,
- (id2lo & 0x00f0000000) >> 28,
- (id2lo & 0x000f000000) >> 24,
- (id2lo & 0x0000f00000) >> 20,
- (id2lo & 0x00000f0000) >> 16,
- (id2lo & 0x000000f000) >> 12,
- (id2lo & 0x0000000f00) >> 8,
- (id2lo & 0x00000000f0) >> 4,
- (id2lo & 0x000000000f)
- );
- uint64_t paxton = (((id>>32) << 24) | (id & 0xffffff)) + 0x143e00;
- PrintAndLog("}\nOther : %05lld_%03lld_%08lld",(id&0xFFFF),((id>>16LL) & 0xFF),(id & 0xFFFFFF));
- PrintAndLog("Pattern Paxton : %lld [0x%llX]", paxton, paxton);
-
- uint32_t p1id = (id & 0xFFFFFF);
- uint8_t arr[32] = {0x00};
- int i =0;
- int j = 23;
- for (; i < 24; ++i, --j ){
- arr[i] = (p1id >> i) & 1;
- }
-
- uint32_t p1 = 0;
-
- p1 |= arr[23] << 21;
- p1 |= arr[22] << 23;
- p1 |= arr[21] << 20;
- p1 |= arr[20] << 22;
-
- p1 |= arr[19] << 18;
- p1 |= arr[18] << 16;
- p1 |= arr[17] << 19;
- p1 |= arr[16] << 17;
-
- p1 |= arr[15] << 13;
- p1 |= arr[14] << 15;
- p1 |= arr[13] << 12;
- p1 |= arr[12] << 14;
-
- p1 |= arr[11] << 6;
- p1 |= arr[10] << 2;
- p1 |= arr[9] << 7;
- p1 |= arr[8] << 1;
-
- p1 |= arr[7] << 0;
- p1 |= arr[6] << 8;
- p1 |= arr[5] << 11;
- p1 |= arr[4] << 3;
-
- p1 |= arr[3] << 10;
- p1 |= arr[2] << 4;
- p1 |= arr[1] << 5;
- p1 |= arr[0] << 9;
- PrintAndLog("Pattern 1 : %d [0x%X]", p1, p1);
-
- uint16_t sebury1 = id & 0xFFFF;
- uint8_t sebury2 = (id >> 16) & 0x7F;
- uint32_t sebury3 = id & 0x7FFFFF;
- PrintAndLog("Pattern Sebury : %d %d %d [0x%X 0x%X 0x%X]", sebury1, sebury2, sebury3, sebury1, sebury2, sebury3);
- }
- }
- return;
-}
-
-int AskEm410xDecode(bool verbose, uint32_t *hi, uint64_t *lo )
-{
- size_t idx = 0;
- size_t BitLen = DemodBufferLen;
- uint8_t BitStream[MAX_GRAPH_TRACE_LEN]={0};
- memcpy(BitStream, DemodBuffer, BitLen);
- if (Em410xDecode(BitStream, &BitLen, &idx, hi, lo)){
- //set GraphBuffer for clone or sim command
- setDemodBuf(BitStream, BitLen, idx);
- if (g_debugMode){
- PrintAndLog("DEBUG: idx: %d, Len: %d, Printing Demod Buffer:", idx, BitLen);
- printDemodBuff();
- }
- if (verbose){
- PrintAndLog("EM410x pattern found: ");
- printEM410x(*hi, *lo);
- }
- return 1;
- }
- return 0;
-}
-
-int AskEm410xDemod(const char *Cmd, uint32_t *hi, uint64_t *lo, bool verbose)
-{
- if (!ASKDemod(Cmd, FALSE, FALSE, 1)) return 0;
- return AskEm410xDecode(verbose, hi, lo);
-}
-
-//by marshmellow
-//takes 3 arguments - clock, invert and maxErr as integers
-//attempts to demodulate ask while decoding manchester
-//prints binary found and saves in graphbuffer for further commands
-int CmdAskEM410xDemod(const char *Cmd)
-{
- char cmdp = param_getchar(Cmd, 0);
- if (strlen(Cmd) > 10 || cmdp == 'h' || cmdp == 'H') {
- PrintAndLog("Usage: data askem410xdemod [clock] <0|1> [maxError]");
- PrintAndLog(" [set clock as integer] optional, if not set, autodetect.");
- PrintAndLog(" <invert>, 1 for invert output");
- PrintAndLog(" [set maximum allowed errors], default = 100.");
- PrintAndLog("");
- PrintAndLog(" sample: data askem410xdemod = demod an EM410x Tag ID from GraphBuffer");
- PrintAndLog(" : data askem410xdemod 32 = demod an EM410x Tag ID from GraphBuffer using a clock of RF/32");
- PrintAndLog(" : data askem410xdemod 32 1 = demod an EM410x Tag ID from GraphBuffer using a clock of RF/32 and inverting data");
- PrintAndLog(" : data askem410xdemod 1 = demod an EM410x Tag ID from GraphBuffer while inverting data");
- PrintAndLog(" : data askem410xdemod 64 1 0 = demod an EM410x Tag ID from GraphBuffer using a clock of RF/64 and inverting data and allowing 0 demod errors");
- return 0;
- }
- uint64_t lo = 0;
- uint32_t hi = 0;
- return AskEm410xDemod(Cmd, &hi, &lo, true);
-}
-
//by marshmellow
//Cmd Args: Clock, invert, maxErr, maxLen as integers and amplify as char == 'a'
// (amp may not be needed anymore)
//verbose will print results and demoding messages
//emSearch will auto search for EM410x format in bitstream
//askType switches decode: ask/raw = 0, ask/manchester = 1
-int ASKDemod(const char *Cmd, bool verbose, bool emSearch, uint8_t askType)
-{
+int ASKDemod_ext(const char *Cmd, bool verbose, bool emSearch, uint8_t askType, bool *stCheck) {
int invert=0;
int clk=0;
int maxErr=100;
int maxLen=0;
- uint8_t askAmp = 0;
+ uint8_t askamp = 0;
char amp = param_getchar(Cmd, 0);
uint8_t BitStream[MAX_GRAPH_TRACE_LEN]={0};
sscanf(Cmd, "%i %i %i %i %c", &clk, &invert, &maxErr, &maxLen, &);
- if (!maxLen) maxLen = 512*64;
+ if (!maxLen) maxLen = BIGBUF_SIZE;
if (invert != 0 && invert != 1) {
PrintAndLog("Invalid argument: %s", Cmd);
return 0;
invert=1;
clk=0;
}
- if (amp == 'a' || amp == 'A') askAmp=1;
size_t BitLen = getFromGraphBuf(BitStream);
if (g_debugMode) PrintAndLog("DEBUG: Bitlen from grphbuff: %d",BitLen);
- if (BitLen<255) return 0;
- if (maxLen<BitLen && maxLen != 0) BitLen = maxLen;
-
- int errCnt = askdemod(BitStream, &BitLen, &clk, &invert, maxErr, askAmp, askType);
+ if (BitLen < 255) return 0;
+ if (maxLen < BitLen && maxLen != 0) BitLen = maxLen;
+ int foundclk = 0;
+ //amp before ST check
+ if (amp == 'a' || amp == 'A') {
+ askAmp(BitStream, BitLen);
+ }
+ bool st = false;
+ size_t ststart = 0, stend = 0;
+ if (*stCheck) st = DetectST(BitStream, &BitLen, &foundclk, &ststart, &stend);
+ *stCheck = st;
+ if (st) {
+ clk = (clk == 0) ? foundclk : clk;
+ CursorCPos = ststart;
+ CursorDPos = stend;
+ if (verbose || g_debugMode) PrintAndLog("\nFound Sequence Terminator - First one is shown by orange and blue graph markers");
+ //Graph ST trim (for testing)
+ //for (int i = 0; i < BitLen; i++) {
+ // GraphBuffer[i] = BitStream[i]-128;
+ //}
+ //RepaintGraphWindow();
+ }
+ int startIdx = 0;
+ int errCnt = askdemod_ext(BitStream, &BitLen, &clk, &invert, maxErr, askamp, askType, &startIdx);
if (errCnt<0 || BitLen<16){ //if fatal error (or -1)
if (g_debugMode) PrintAndLog("DEBUG: no data found %d, errors:%d, bitlen:%d, clock:%d",errCnt,invert,BitLen,clk);
return 0;
}
- if (errCnt>maxErr){
+ if (errCnt > maxErr){
if (g_debugMode) PrintAndLog("DEBUG: Too many errors found, errors:%d, bits:%d, clock:%d",errCnt, BitLen, clk);
return 0;
}
if (verbose || g_debugMode) PrintAndLog("\nUsing Clock:%d, Invert:%d, Bits Found:%d",clk,invert,BitLen);
-
//output
setDemodBuf(BitStream,BitLen,0);
+ setClockGrid(clk, startIdx);
+
if (verbose || g_debugMode){
if (errCnt>0) PrintAndLog("# Errors during Demoding (shown as 7 in bit stream): %d",errCnt);
if (askType) PrintAndLog("ASK/Manchester - Clock: %d - Decoded bitstream:",clk);
}
return 1;
}
+int ASKDemod(const char *Cmd, bool verbose, bool emSearch, uint8_t askType) {
+ bool st = false;
+ return ASKDemod_ext(Cmd, verbose, emSearch, askType, &st);
+}
//by marshmellow
//takes 5 arguments - clock, invert, maxErr, maxLen as integers and amplify as char == 'a'
int Cmdaskmandemod(const char *Cmd)
{
char cmdp = param_getchar(Cmd, 0);
- if (strlen(Cmd) > 25 || cmdp == 'h' || cmdp == 'H') {
- PrintAndLog("Usage: data rawdemod am [clock] <invert> [maxError] [maxLen] [amplify]");
+ if (strlen(Cmd) > 45 || cmdp == 'h' || cmdp == 'H') {
+ PrintAndLog("Usage: data rawdemod am <s> [clock] <invert> [maxError] [maxLen] [amplify]");
+ PrintAndLog(" ['s'] optional, check for Sequence Terminator");
PrintAndLog(" [set clock as integer] optional, if not set, autodetect");
PrintAndLog(" <invert>, 1 to invert output");
PrintAndLog(" [set maximum allowed errors], default = 100");
PrintAndLog(" : data rawdemod am 64 1 0 = demod an ask/manchester tag from GraphBuffer using a clock of RF/64, inverting data and allowing 0 demod errors");
return 0;
}
- return ASKDemod(Cmd, TRUE, TRUE, 1);
+ bool st = true;
+ if (Cmd[0]=='s')
+ return ASKDemod_ext(Cmd++, true, false, 1, &st);
+ else if (Cmd[1] == 's')
+ return ASKDemod_ext(Cmd+=2, true, false, 1, &st);
+ else
+ return ASKDemod(Cmd, true, false, 1);
}
//by marshmellow
return 0;
}
if (DemodBufferLen==0) return 0;
- uint8_t BitStream[MAX_GRAPH_TRACE_LEN]={0};
+ uint8_t BitStream[MAX_DEMOD_BUF_LEN]={0};
int high=0,low=0;
for (;i<DemodBufferLen;++i){
if (DemodBuffer[i]>high) high=DemodBuffer[i];
sscanf(Cmd, "%i %i", &invert, &maxErr);
size=i;
- errCnt=manrawdecode(BitStream, &size, invert);
+ uint8_t alignPos = 0;
+ errCnt=manrawdecode(BitStream, &size, invert, &alignPos);
if (errCnt>=maxErr){
PrintAndLog("Too many errors: %d",errCnt);
return 0;
return 0;
}
sscanf(Cmd, "%i %i %i", &offset, &invert, &maxErr);
- if (DemodBufferLen==0){
+ if (DemodBufferLen==0) {
PrintAndLog("DemodBuffer Empty - run 'data rawdemod ar' first");
return 0;
}
- uint8_t BitStream[MAX_GRAPH_TRACE_LEN]={0};
- memcpy(BitStream, DemodBuffer, DemodBufferLen);
- size = DemodBufferLen;
- errCnt=BiphaseRawDecode(BitStream, &size, offset, invert);
+ uint8_t BitStream[MAX_DEMOD_BUF_LEN]={0};
+ size = sizeof(BitStream);
+ if ( !getDemodBuf(BitStream, &size) ) return 0;
+ errCnt=BiphaseRawDecode(BitStream, &size, &offset, invert);
if (errCnt<0){
PrintAndLog("Error during decode:%d", errCnt);
return 0;
if (errCnt>0){
PrintAndLog("# Errors found during Demod (shown as 7 in bit stream): %d",errCnt);
}
+
PrintAndLog("Biphase Decoded using offset: %d - # invert:%d - data:",offset,invert);
PrintAndLog("%s", sprint_bin_break(BitStream, size, 16));
if (offset) setDemodBuf(DemodBuffer,DemodBufferLen-offset, offset); //remove first bit from raw demod
+ setClockGrid(g_DemodClock, g_DemodStartIdx + g_DemodClock*offset/2);
return 1;
}
int offset=0, clk=0, invert=0, maxErr=0;
sscanf(Cmd, "%i %i %i %i", &offset, &clk, &invert, &maxErr);
- uint8_t BitStream[MAX_DEMOD_BUF_LEN];
- size_t size = getFromGraphBuf(BitStream);
+ uint8_t BitStream[MAX_GRAPH_TRACE_LEN];
+ size_t size = getFromGraphBuf(BitStream);
+ int startIdx = 0;
//invert here inverts the ask raw demoded bits which has no effect on the demod, but we need the pointer
- int errCnt = askdemod(BitStream, &size, &clk, &invert, maxErr, 0, 0);
+ int errCnt = askdemod_ext(BitStream, &size, &clk, &invert, maxErr, 0, 0, &startIdx);
if ( errCnt < 0 || errCnt > maxErr ) {
if (g_debugMode) PrintAndLog("DEBUG: no data or error found %d, clock: %d", errCnt, clk);
return 0;
- }
+ }
//attempt to Biphase decode BitStream
- errCnt = BiphaseRawDecode(BitStream, &size, offset, invert);
+ errCnt = BiphaseRawDecode(BitStream, &size, &offset, invert);
if (errCnt < 0){
if (g_debugMode || verbose) PrintAndLog("Error BiphaseRawDecode: %d", errCnt);
return 0;
- }
+ }
if (errCnt > maxErr) {
if (g_debugMode || verbose) PrintAndLog("Error BiphaseRawDecode too many errors: %d", errCnt);
return 0;
}
//success set DemodBuffer and return
setDemodBuf(BitStream, size, 0);
+ setClockGrid(clk, startIdx + clk*offset/2);
if (g_debugMode || verbose){
PrintAndLog("Biphase Decoded using offset: %d - clock: %d - # errors:%d - data:",offset,clk,errCnt);
printDemodBuff();
PrintAndLog(" : data rawdemod ab 0 64 1 0 0 a = demod an ask/biph tag from GraphBuffer using a clock of RF/64, inverting data and allowing 0 demod errors, and amp");
return 0;
}
- return ASKbiphaseDemod(Cmd, TRUE);
-}
-
-//by marshmellow
-//attempts to demodulate and identify a G_Prox_II verex/chubb card
-//WARNING: if it fails during some points it will destroy the DemodBuffer data
-// but will leave the GraphBuffer intact.
-//if successful it will push askraw data back to demod buffer ready for emulation
-int CmdG_Prox_II_Demod(const char *Cmd)
-{
- if (!ASKbiphaseDemod(Cmd, FALSE)){
- if (g_debugMode) PrintAndLog("ASKbiphaseDemod failed 1st try");
- return 0;
- }
- size_t size = DemodBufferLen;
- //call lfdemod.c demod for gProxII
- int ans = gProxII_Demod(DemodBuffer, &size);
- if (ans < 0){
- if (g_debugMode) PrintAndLog("Error gProxII_Demod");
- return 0;
- }
- //got a good demod
- uint32_t ByteStream[65] = {0x00};
- uint8_t xorKey=0;
- uint8_t keyCnt=0;
- uint8_t bitCnt=0;
- uint8_t ByteCnt=0;
- size_t startIdx = ans + 6; //start after preamble
- for (size_t idx = 0; idx<size-6; idx++){
- if ((idx+1) % 5 == 0){
- //spacer bit - should be 0
- if (DemodBuffer[startIdx+idx] != 0) {
- if (g_debugMode) PrintAndLog("Error spacer not 0: %d, pos: %d",DemodBuffer[startIdx+idx],startIdx+idx);
- return 0;
- }
- continue;
- }
- if (keyCnt<8){ //lsb first
- xorKey = xorKey | (DemodBuffer[startIdx+idx]<<keyCnt);
- keyCnt++;
- if (keyCnt==8 && g_debugMode) PrintAndLog("xorKey Found: %02x", xorKey);
- continue;
- }
- //lsb first
- ByteStream[ByteCnt] = ByteStream[ByteCnt] | (DemodBuffer[startIdx+idx]<<bitCnt);
- bitCnt++;
- if (bitCnt % 8 == 0){
- if (g_debugMode) PrintAndLog("byte %d: %02x",ByteCnt,ByteStream[ByteCnt]);
- bitCnt=0;
- ByteCnt++;
- }
- }
- for (uint8_t i = 0; i < ByteCnt; i++){
- ByteStream[i] ^= xorKey; //xor
- if (g_debugMode) PrintAndLog("byte %d after xor: %02x", i, ByteStream[i]);
- }
- //now ByteStream contains 64 bytes of decrypted raw tag data
- //
- uint8_t fmtLen = ByteStream[0]>>2;
- uint32_t FC = 0;
- uint32_t Card = 0;
- uint32_t raw1 = bytebits_to_byte(DemodBuffer+ans,32);
- uint32_t raw2 = bytebits_to_byte(DemodBuffer+ans+32, 32);
- uint32_t raw3 = bytebits_to_byte(DemodBuffer+ans+64, 32);
-
- if (fmtLen==36){
- FC = ((ByteStream[3] & 0x7F)<<7) | (ByteStream[4]>>1);
- Card = ((ByteStream[4]&1)<<19) | (ByteStream[5]<<11) | (ByteStream[6]<<3) | (ByteStream[7]>>5);
- PrintAndLog("G-Prox-II Found: FmtLen %d, FC %d, Card %d",fmtLen,FC,Card);
- } else if(fmtLen==26){
- FC = ((ByteStream[3] & 0x7F)<<1) | (ByteStream[4]>>7);
- Card = ((ByteStream[4]&0x7F)<<9) | (ByteStream[5]<<1) | (ByteStream[6]>>7);
- PrintAndLog("G-Prox-II Found: FmtLen %d, FC %d, Card %d",fmtLen,FC,Card);
- } else {
- PrintAndLog("Unknown G-Prox-II Fmt Found: FmtLen %d",fmtLen);
- }
- PrintAndLog("Raw: %08x%08x%08x", raw1,raw2,raw3);
- setDemodBuf(DemodBuffer+ans, 96, 0);
- return 1;
-}
-
-//by marshmellow
-//see ASKDemod for what args are accepted
-int CmdVikingDemod(const char *Cmd)
-{
- if (!ASKDemod(Cmd, false, false, 1)) {
- if (g_debugMode) PrintAndLog("ASKDemod failed");
- return 0;
- }
- size_t size = DemodBufferLen;
- //call lfdemod.c demod for gProxII
- int ans = VikingDemod_AM(DemodBuffer, &size);
- if (ans < 0) {
- if (g_debugMode) PrintAndLog("Error Viking_Demod %d", ans);
- return 0;
- }
- //got a good demod
- uint32_t raw1 = bytebits_to_byte(DemodBuffer+ans, 32);
- uint32_t raw2 = bytebits_to_byte(DemodBuffer+ans+32, 32);
- uint32_t cardid = bytebits_to_byte(DemodBuffer+ans+24, 32);
- uint8_t checksum = bytebits_to_byte(DemodBuffer+ans+32+24, 8);
- PrintAndLog("Viking Tag Found: Card ID %08X, Checksum: %02X", cardid, checksum);
- PrintAndLog("Raw: %08X%08X", raw1,raw2);
- setDemodBuf(DemodBuffer+ans, 64, 0);
- return 1;
+ return ASKbiphaseDemod(Cmd, true);
}
//by marshmellow - see ASKDemod
int Cmdaskrawdemod(const char *Cmd)
{
char cmdp = param_getchar(Cmd, 0);
- if (strlen(Cmd) > 25 || cmdp == 'h' || cmdp == 'H') {
+ if (strlen(Cmd) > 35 || cmdp == 'h' || cmdp == 'H') {
PrintAndLog("Usage: data rawdemod ar [clock] <invert> [maxError] [maxLen] [amplify]");
PrintAndLog(" [set clock as integer] optional, if not set, autodetect");
PrintAndLog(" <invert>, 1 to invert output");
PrintAndLog(" : data rawdemod ar 64 1 0 0 a = demod an ask tag from GraphBuffer using a clock of RF/64, inverting data and allowing 0 demod errors, and amp");
return 0;
}
- return ASKDemod(Cmd, TRUE, FALSE, 0);
+ return ASKDemod(Cmd, true, false, 0);
}
-int AutoCorrelate(int window, bool SaveGrph, bool verbose)
+int AutoCorrelate(const int *in, int *out, size_t len, int window, bool SaveGrph, bool verbose)
{
static int CorrelBuffer[MAX_GRAPH_TRACE_LEN];
size_t Correlation = 0;
int maxSum = 0;
int lastMax = 0;
if (verbose) PrintAndLog("performing %d correlations", GraphTraceLen - window);
- for (int i = 0; i < GraphTraceLen - window; ++i) {
+ for (int i = 0; i < len - window; ++i) {
int sum = 0;
for (int j = 0; j < window; ++j) {
- sum += (GraphBuffer[j]*GraphBuffer[i + j]) / 256;
+ sum += (in[j]*in[i + j]) / 256;
}
CorrelBuffer[i] = sum;
- if (sum >= maxSum-100 && sum <= maxSum+100){
+ if (sum >= maxSum-100 && sum <= maxSum+100) {
//another max
Correlation = i-lastMax;
lastMax = i;
if (sum > maxSum) maxSum = sum;
- } else if (sum > maxSum){
+ } else if (sum > maxSum) {
maxSum=sum;
lastMax = i;
}
}
- if (Correlation==0){
+ if (Correlation==0) {
//try again with wider margin
- for (int i = 0; i < GraphTraceLen - window; i++){
- if (CorrelBuffer[i] >= maxSum-(maxSum*0.05) && CorrelBuffer[i] <= maxSum+(maxSum*0.05)){
+ for (int i = 0; i < len - window; i++) {
+ if (CorrelBuffer[i] >= maxSum-(maxSum*0.05) && CorrelBuffer[i] <= maxSum+(maxSum*0.05)) {
//another max
Correlation = i-lastMax;
lastMax = i;
- //if (CorrelBuffer[i] > maxSum) maxSum = sum;
}
}
}
if (verbose && Correlation > 0) PrintAndLog("Possible Correlation: %d samples",Correlation);
- if (SaveGrph){
- GraphTraceLen = GraphTraceLen - window;
- memcpy(GraphBuffer, CorrelBuffer, GraphTraceLen * sizeof (int));
+ if (SaveGrph) {
+ //GraphTraceLen = GraphTraceLen - window;
+ memcpy(out, CorrelBuffer, len * sizeof(int));
RepaintGraphWindow();
}
return Correlation;
return usage_data_autocorr();
int window = 4000; //set default
char grph=0;
- bool updateGrph = FALSE;
+ bool updateGrph = false;
sscanf(Cmd, "%i %c", &window, &grph);
if (window >= GraphTraceLen) {
GraphTraceLen);
return 0;
}
- if (grph == 'g') updateGrph=TRUE;
- return AutoCorrelate(window, updateGrph, TRUE);
+ if (grph == 'g') updateGrph=true;
+ return AutoCorrelate(GraphBuffer, GraphBuffer, GraphTraceLen, window, updateGrph, true);
}
int CmdBitsamples(const char *Cmd)
uint8_t factor = param_get8ex(Cmd, 0,2, 10);
//We have memory, don't we?
int swap[MAX_GRAPH_TRACE_LEN] = { 0 };
- uint32_t g_index = 0 ,s_index = 0;
- while(g_index < GraphTraceLen && s_index < MAX_GRAPH_TRACE_LEN)
+ uint32_t g_index = 0, s_index = 0;
+ while(g_index < GraphTraceLen && s_index + factor < MAX_GRAPH_TRACE_LEN)
{
int count = 0;
- for(count = 0; count < factor && s_index+count < MAX_GRAPH_TRACE_LEN; count ++)
+ for(count = 0; count < factor && s_index + count < MAX_GRAPH_TRACE_LEN; count++)
swap[s_index+count] = GraphBuffer[g_index];
- s_index+=count;
+
+ s_index += count;
+ g_index++;
}
- memcpy(GraphBuffer,swap, s_index * sizeof(int));
+ memcpy(GraphBuffer, swap, s_index * sizeof(int));
GraphTraceLen = s_index;
RepaintGraphWindow();
return 0;
return 0;
}
+int AskEdgeDetect(const int *in, int *out, int len, int threshold) {
+ int Last = 0;
+ for(int i = 1; i<len; i++) {
+ if (in[i]-in[i-1] >= threshold) //large jump up
+ Last = 127;
+ else if(in[i]-in[i-1] <= -1 * threshold) //large jump down
+ Last = -127;
+ out[i-1] = Last;
+ }
+ return 0;
+}
+
//by marshmellow
//use large jumps in read samples to identify edges of waves and then amplify that wave to max
//similar to dirtheshold, threshold commands
int CmdAskEdgeDetect(const char *Cmd)
{
int thresLen = 25;
+ int ans = 0;
sscanf(Cmd, "%i", &thresLen);
- for(int i = 1; i<GraphTraceLen; i++){
- if (GraphBuffer[i]-GraphBuffer[i-1]>=thresLen) //large jump up
- GraphBuffer[i-1] = 127;
- else if(GraphBuffer[i]-GraphBuffer[i-1]<=-1*thresLen) //large jump down
- GraphBuffer[i-1] = -127;
- }
+ ans = AskEdgeDetect(GraphBuffer, GraphBuffer, GraphTraceLen, thresLen);
RepaintGraphWindow();
- return 0;
+ return ans;
}
/* Print our clock rate */
char *GetFSKType(uint8_t fchigh, uint8_t fclow, uint8_t invert)
{
- char *fskType;
+ static char fType[8];
+ memset(fType, 0x00, 8);
+ char *fskType = fType;
if (fchigh==10 && fclow==8){
if (invert) //fsk2a
- fskType = "FSK2a";
+ memcpy(fskType, "FSK2a", 5);
else //fsk2
- fskType = "FSK2";
+ memcpy(fskType, "FSK2", 4);
} else if (fchigh == 8 && fclow == 5) {
if (invert)
- fskType = "FSK1";
+ memcpy(fskType, "FSK1", 4);
else
- fskType = "FSK1a";
+ memcpy(fskType, "FSK1a", 5);
} else {
- fskType = "FSK??";
+ memcpy(fskType, "FSK??", 5);
}
return fskType;
}
int FSKrawDemod(const char *Cmd, bool verbose)
{
//raw fsk demod no manchester decoding no start bit finding just get binary from wave
+ uint8_t rfLen, invert, fchigh, fclow;
//set defaults
- int rfLen = 0;
- int invert = 0;
- int fchigh = 0;
- int fclow = 0;
-
//set options from parameters entered with the command
- sscanf(Cmd, "%i %i %i %i", &rfLen, &invert, &fchigh, &fclow);
+ rfLen = param_get8(Cmd, 0);
+ invert = param_get8(Cmd, 1);
+ fchigh = param_get8(Cmd, 2);
+ fclow = param_get8(Cmd, 3);
if (strlen(Cmd)>0 && strlen(Cmd)<=2) {
- if (rfLen==1){
+ if (rfLen==1) {
invert = 1; //if invert option only is used
rfLen = 0;
- }
+ }
}
-
uint8_t BitStream[MAX_GRAPH_TRACE_LEN]={0};
size_t BitLen = getFromGraphBuf(BitStream);
if (BitLen==0) return 0;
//get field clock lengths
uint16_t fcs=0;
- if (fchigh==0 || fclow == 0){
+ if (!fchigh || !fclow) {
fcs = countFC(BitStream, BitLen, 1);
- if (fcs==0){
- fchigh=10;
- fclow=8;
- }else{
- fchigh = (fcs >> 8) & 0xFF;
- fclow = fcs & 0xFF;
+ if (!fcs) {
+ fchigh = 10;
+ fclow = 8;
+ } else {
+ fchigh = (fcs >> 8) & 0x00FF;
+ fclow = fcs & 0x00FF;
}
}
//get bit clock length
- if (rfLen==0){
- rfLen = detectFSKClk(BitStream, BitLen, fchigh, fclow);
- if (rfLen == 0) rfLen = 50;
- }
- int size = fskdemod(BitStream,BitLen,(uint8_t)rfLen,(uint8_t)invert,(uint8_t)fchigh,(uint8_t)fclow);
- if (size>0){
+ if (!rfLen) {
+ int firstClockEdge = 0; //todo - align grid on graph with this...
+ rfLen = detectFSKClk(BitStream, BitLen, fchigh, fclow, &firstClockEdge);
+ if (!rfLen) rfLen = 50;
+ }
+ int startIdx = 0;
+ int size = fskdemod(BitStream, BitLen, rfLen, invert, fchigh, fclow, &startIdx);
+ if (size > 0) {
setDemodBuf(BitStream,size,0);
+ setClockGrid(rfLen, startIdx);
- // Now output the bitstream to the scrollback by line of 16 bits
+ // Now output the bitstream to the scrollback by line of 16 bits
if (verbose || g_debugMode) {
- PrintAndLog("\nUsing Clock:%d, invert:%d, fchigh:%d, fclow:%d", rfLen, invert, fchigh, fclow);
+ PrintAndLog("\nUsing Clock:%u, invert:%u, fchigh:%u, fclow:%u", (unsigned int)rfLen, (unsigned int)invert, (unsigned int)fchigh, (unsigned int)fclow);
PrintAndLog("%s decoded bitstream:",GetFSKType(fchigh,fclow,invert));
printDemodBuff();
}
return 1;
- } else{
+ } else {
if (g_debugMode) PrintAndLog("no FSK data found");
}
return 0;
int CmdFSKrawdemod(const char *Cmd)
{
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 fs [clock] <invert> [fchigh] [fclow]");
PrintAndLog(" [set clock as integer] optional, omit for autodetect.");
PrintAndLog(" <invert>, 1 for invert output, can be used even if the clock is omitted");
PrintAndLog(" : data rawdemod fs 50 1 10 8 = demod an fsk2a RF/50 tag from GraphBuffer");
return 0;
}
- return FSKrawDemod(Cmd, TRUE);
-}
-
-//by marshmellow (based on existing demod + holiman's refactor)
-//HID Prox demod - FSK RF/50 with preamble of 00011101 (then manchester encoded)
-//print full HID Prox ID and some bit format details if found
-int CmdFSKdemodHID(const char *Cmd)
-{
- //raw fsk demod no manchester decoding no start bit finding just get binary from wave
- uint32_t hi2=0, hi=0, lo=0;
-
- uint8_t BitStream[MAX_GRAPH_TRACE_LEN]={0};
- size_t BitLen = getFromGraphBuf(BitStream);
- if (BitLen==0) return 0;
- //get binary from fsk wave
- int idx = HIDdemodFSK(BitStream,&BitLen,&hi2,&hi,&lo);
- if (idx<0){
- if (g_debugMode){
- if (idx==-1){
- PrintAndLog("DEBUG: Just Noise Detected");
- } else if (idx == -2) {
- PrintAndLog("DEBUG: Error demoding fsk");
- } else if (idx == -3) {
- PrintAndLog("DEBUG: Preamble not found");
- } else if (idx == -4) {
- PrintAndLog("DEBUG: Error in Manchester data, SIZE: %d", BitLen);
- } else {
- PrintAndLog("DEBUG: Error demoding fsk %d", idx);
- }
- }
- return 0;
- }
- if (hi2==0 && hi==0 && lo==0) {
- if (g_debugMode) PrintAndLog("DEBUG: Error - no values found");
- return 0;
- }
- if (hi2 != 0){ //extra large HID tags
- PrintAndLog("HID Prox TAG ID: %x%08x%08x (%d)",
- (unsigned int) hi2, (unsigned int) hi, (unsigned int) lo, (unsigned int) (lo>>1) & 0xFFFF);
- }
- else { //standard HID tags <38 bits
- uint8_t fmtLen = 0;
- uint32_t fc = 0;
- uint32_t cardnum = 0;
- if (((hi>>5)&1)==1){//if bit 38 is set then < 37 bit format is used
- uint32_t lo2=0;
- lo2=(((hi & 31) << 12) | (lo>>20)); //get bits 21-37 to check for format len bit
- uint8_t idx3 = 1;
- while(lo2>1){ //find last bit set to 1 (format len bit)
- lo2=lo2>>1;
- idx3++;
- }
- fmtLen =idx3+19;
- fc =0;
- cardnum=0;
- if(fmtLen==26){
- cardnum = (lo>>1)&0xFFFF;
- fc = (lo>>17)&0xFF;
- }
- if(fmtLen==34){
- cardnum = (lo>>1)&0xFFFF;
- fc= ((hi&1)<<15)|(lo>>17);
- }
- if(fmtLen==35){
- cardnum = (lo>>1)&0xFFFFF;
- fc = ((hi&1)<<11)|(lo>>21);
- }
- }
- else { //if bit 38 is not set then 37 bit format is used
- fmtLen = 37;
- fc = 0;
- cardnum = 0;
- if(fmtLen == 37){
- cardnum = (lo>>1)&0x7FFFF;
- fc = ((hi&0xF)<<12)|(lo>>20);
- }
- }
- PrintAndLog("HID Prox TAG ID: %x%08x (%d) - Format Len: %dbit - FC: %d - Card: %d",
- (unsigned int) hi, (unsigned int) lo, (unsigned int) (lo>>1) & 0xFFFF,
- (unsigned int) fmtLen, (unsigned int) fc, (unsigned int) cardnum);
- }
- setDemodBuf(BitStream,BitLen,idx);
- if (g_debugMode){
- PrintAndLog("DEBUG: idx: %d, Len: %d, Printing Demod Buffer:", idx, BitLen);
- printDemodBuff();
- }
- return 1;
-}
-
-//by marshmellow
-//Paradox Prox demod - FSK RF/50 with preamble of 00001111 (then manchester encoded)
-//print full Paradox Prox ID and some bit format details if found
-int CmdFSKdemodParadox(const char *Cmd)
-{
- //raw fsk demod no manchester decoding no start bit finding just get binary from wave
- uint32_t hi2=0, hi=0, lo=0;
-
- uint8_t BitStream[MAX_GRAPH_TRACE_LEN]={0};
- size_t BitLen = getFromGraphBuf(BitStream);
- if (BitLen==0) return 0;
- //get binary from fsk wave
- int idx = ParadoxdemodFSK(BitStream,&BitLen,&hi2,&hi,&lo);
- if (idx<0){
- if (g_debugMode){
- if (idx==-1){
- PrintAndLog("DEBUG: Just Noise Detected");
- } else if (idx == -2) {
- PrintAndLog("DEBUG: Error demoding fsk");
- } else if (idx == -3) {
- PrintAndLog("DEBUG: Preamble not found");
- } else if (idx == -4) {
- PrintAndLog("DEBUG: Error in Manchester data");
- } else {
- PrintAndLog("DEBUG: Error demoding fsk %d", idx);
- }
- }
- return 0;
- }
- if (hi2==0 && hi==0 && lo==0){
- if (g_debugMode) PrintAndLog("DEBUG: Error - no value found");
- return 0;
- }
- uint32_t fc = ((hi & 0x3)<<6) | (lo>>26);
- uint32_t cardnum = (lo>>10)&0xFFFF;
- uint32_t rawLo = bytebits_to_byte(BitStream+idx+64,32);
- uint32_t rawHi = bytebits_to_byte(BitStream+idx+32,32);
- uint32_t rawHi2 = bytebits_to_byte(BitStream+idx,32);
-
- PrintAndLog("Paradox TAG ID: %x%08x - FC: %d - Card: %d - Checksum: %02x - RAW: %08x%08x%08x",
- hi>>10, (hi & 0x3)<<26 | (lo>>10), fc, cardnum, (lo>>2) & 0xFF, rawHi2, rawHi, rawLo);
- setDemodBuf(BitStream,BitLen,idx);
- if (g_debugMode){
- PrintAndLog("DEBUG: idx: %d, len: %d, Printing Demod Buffer:", idx, BitLen);
- printDemodBuff();
- }
- return 1;
-}
-
-//by marshmellow
-//IO-Prox demod - FSK RF/64 with preamble of 000000001
-//print ioprox ID and some format details
-int CmdFSKdemodIO(const char *Cmd)
-{
- int idx=0;
- //something in graphbuffer?
- if (GraphTraceLen < 65) {
- if (g_debugMode)PrintAndLog("DEBUG: not enough samples in GraphBuffer");
- return 0;
- }
- uint8_t BitStream[MAX_GRAPH_TRACE_LEN]={0};
- size_t BitLen = getFromGraphBuf(BitStream);
- if (BitLen==0) return 0;
-
- //get binary from fsk wave
- idx = IOdemodFSK(BitStream,BitLen);
- if (idx<0){
- if (g_debugMode){
- if (idx==-1){
- PrintAndLog("DEBUG: Just Noise Detected");
- } else if (idx == -2) {
- PrintAndLog("DEBUG: not enough samples");
- } else if (idx == -3) {
- PrintAndLog("DEBUG: error during fskdemod");
- } else if (idx == -4) {
- PrintAndLog("DEBUG: Preamble not found");
- } else if (idx == -5) {
- PrintAndLog("DEBUG: Separator bits not found");
- } else {
- PrintAndLog("DEBUG: Error demoding fsk %d", idx);
- }
- }
- return 0;
- }
- if (idx==0){
- if (g_debugMode){
- PrintAndLog("DEBUG: IO Prox Data not found - FSK Bits: %d",BitLen);
- if (BitLen > 92) PrintAndLog("%s", sprint_bin_break(BitStream,92,16));
- }
- return 0;
- }
- //Index map
- //0 10 20 30 40 50 60
- //| | | | | | |
- //01234567 8 90123456 7 89012345 6 78901234 5 67890123 4 56789012 3 45678901 23
- //-----------------------------------------------------------------------------
- //00000000 0 11110000 1 facility 1 version* 1 code*one 1 code*two 1 ???????? 11
- //
- //XSF(version)facility:codeone+codetwo (raw)
- //Handle the data
- if (idx+64>BitLen) {
- if (g_debugMode) PrintAndLog("not enough bits found - bitlen: %d",BitLen);
- return 0;
- }
- PrintAndLog("%d%d%d%d%d%d%d%d %d",BitStream[idx], BitStream[idx+1], BitStream[idx+2], BitStream[idx+3], BitStream[idx+4], BitStream[idx+5], BitStream[idx+6], BitStream[idx+7], BitStream[idx+8]);
- PrintAndLog("%d%d%d%d%d%d%d%d %d",BitStream[idx+9], BitStream[idx+10], BitStream[idx+11],BitStream[idx+12],BitStream[idx+13],BitStream[idx+14],BitStream[idx+15],BitStream[idx+16],BitStream[idx+17]);
- PrintAndLog("%d%d%d%d%d%d%d%d %d facility",BitStream[idx+18], BitStream[idx+19], BitStream[idx+20],BitStream[idx+21],BitStream[idx+22],BitStream[idx+23],BitStream[idx+24],BitStream[idx+25],BitStream[idx+26]);
- PrintAndLog("%d%d%d%d%d%d%d%d %d version",BitStream[idx+27], BitStream[idx+28], BitStream[idx+29],BitStream[idx+30],BitStream[idx+31],BitStream[idx+32],BitStream[idx+33],BitStream[idx+34],BitStream[idx+35]);
- PrintAndLog("%d%d%d%d%d%d%d%d %d code1",BitStream[idx+36], BitStream[idx+37], BitStream[idx+38],BitStream[idx+39],BitStream[idx+40],BitStream[idx+41],BitStream[idx+42],BitStream[idx+43],BitStream[idx+44]);
- PrintAndLog("%d%d%d%d%d%d%d%d %d code2",BitStream[idx+45], BitStream[idx+46], BitStream[idx+47],BitStream[idx+48],BitStream[idx+49],BitStream[idx+50],BitStream[idx+51],BitStream[idx+52],BitStream[idx+53]);
- PrintAndLog("%d%d%d%d%d%d%d%d %d%d checksum",BitStream[idx+54],BitStream[idx+55],BitStream[idx+56],BitStream[idx+57],BitStream[idx+58],BitStream[idx+59],BitStream[idx+60],BitStream[idx+61],BitStream[idx+62],BitStream[idx+63]);
-
- uint32_t code = bytebits_to_byte(BitStream+idx,32);
- uint32_t code2 = bytebits_to_byte(BitStream+idx+32,32);
- uint8_t version = bytebits_to_byte(BitStream+idx+27,8); //14,4
- uint8_t facilitycode = bytebits_to_byte(BitStream+idx+18,8) ;
- uint16_t number = (bytebits_to_byte(BitStream+idx+36,8)<<8)|(bytebits_to_byte(BitStream+idx+45,8)); //36,9
- uint8_t crc = bytebits_to_byte(BitStream+idx+54,8);
- uint16_t calccrc = 0;
-
- for (uint8_t i=1; i<6; ++i){
- calccrc += bytebits_to_byte(BitStream+idx+9*i,8);
- }
- calccrc &= 0xff;
- calccrc = 0xff - calccrc;
-
- char *crcStr = (crc == calccrc) ? "crc ok": "!crc";
-
- PrintAndLog("IO Prox XSF(%02d)%02x:%05d (%08x%08x) [%02x %s]",version,facilitycode,number,code,code2, crc, crcStr);
- setDemodBuf(BitStream,64,idx);
- if (g_debugMode){
- PrintAndLog("DEBUG: idx: %d, Len: %d, Printing demod buffer:",idx,64);
- printDemodBuff();
- }
- return 1;
-}
-
-//by marshmellow
-//AWID Prox demod - FSK RF/50 with preamble of 00000001 (always a 96 bit data stream)
-//print full AWID Prox ID and some bit format details if found
-int CmdFSKdemodAWID(const char *Cmd)
-{
- uint8_t BitStream[MAX_GRAPH_TRACE_LEN]={0};
- size_t size = getFromGraphBuf(BitStream);
- if (size==0) return 0;
-
- //get binary from fsk wave
- int idx = AWIDdemodFSK(BitStream, &size);
- if (idx<=0){
- if (g_debugMode==1){
- if (idx == -1)
- PrintAndLog("DEBUG: Error - not enough samples");
- else if (idx == -2)
- PrintAndLog("DEBUG: Error - only noise found");
- else if (idx == -3)
- PrintAndLog("DEBUG: Error - problem during FSK demod");
- else if (idx == -4)
- PrintAndLog("DEBUG: Error - AWID preamble not found");
- else if (idx == -5)
- PrintAndLog("DEBUG: Error - Size not correct: %d", size);
- else
- PrintAndLog("DEBUG: Error %d",idx);
- }
- return 0;
- }
-
- // Index map
- // 0 10 20 30 40 50 60
- // | | | | | | |
- // 01234567 890 1 234 5 678 9 012 3 456 7 890 1 234 5 678 9 012 3 456 7 890 1 234 5 678 9 012 3 - to 96
- // -----------------------------------------------------------------------------
- // 00000001 000 1 110 1 101 1 011 1 101 1 010 0 000 1 000 1 010 0 001 0 110 1 100 0 000 1 000 1
- // premable bbb o bbb o bbw o fff o fff o ffc o ccc o ccc o ccc o ccc o ccc o wxx o xxx o xxx o - to 96
- // |---26 bit---| |-----117----||-------------142-------------|
- // b = format bit len, o = odd parity of last 3 bits
- // f = facility code, c = card number
- // w = wiegand parity
- // (26 bit format shown)
-
- //get raw ID before removing parities
- uint32_t rawLo = bytebits_to_byte(BitStream+idx+64,32);
- uint32_t rawHi = bytebits_to_byte(BitStream+idx+32,32);
- uint32_t rawHi2 = bytebits_to_byte(BitStream+idx,32);
- setDemodBuf(BitStream,96,idx);
-
- size = removeParity(BitStream, idx+8, 4, 1, 88);
- if (size != 66){
- if (g_debugMode==1) PrintAndLog("DEBUG: Error - at parity check-tag size does not match AWID format");
- return 0;
- }
- // ok valid card found!
-
- // Index map
- // 0 10 20 30 40 50 60
- // | | | | | | |
- // 01234567 8 90123456 7890123456789012 3 456789012345678901234567890123456
- // -----------------------------------------------------------------------------
- // 00011010 1 01110101 0000000010001110 1 000000000000000000000000000000000
- // bbbbbbbb w ffffffff cccccccccccccccc w xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
- // |26 bit| |-117--| |-----142------|
- // b = format bit len, o = odd parity of last 3 bits
- // f = facility code, c = card number
- // w = wiegand parity
- // (26 bit format shown)
-
- uint32_t fc = 0;
- uint32_t cardnum = 0;
- uint32_t code1 = 0;
- uint32_t code2 = 0;
- uint8_t fmtLen = bytebits_to_byte(BitStream,8);
- if (fmtLen==26){
- fc = bytebits_to_byte(BitStream+9, 8);
- cardnum = bytebits_to_byte(BitStream+17, 16);
- code1 = bytebits_to_byte(BitStream+8,fmtLen);
- PrintAndLog("AWID Found - BitLength: %d, FC: %d, Card: %d - Wiegand: %x, Raw: %08x%08x%08x", fmtLen, fc, cardnum, code1, rawHi2, rawHi, rawLo);
- } else {
- cardnum = bytebits_to_byte(BitStream+8+(fmtLen-17), 16);
- if (fmtLen>32){
- code1 = bytebits_to_byte(BitStream+8,fmtLen-32);
- code2 = bytebits_to_byte(BitStream+8+(fmtLen-32),32);
- PrintAndLog("AWID Found - BitLength: %d -unknown BitLength- (%d) - Wiegand: %x%08x, Raw: %08x%08x%08x", fmtLen, cardnum, code1, code2, rawHi2, rawHi, rawLo);
- } else{
- code1 = bytebits_to_byte(BitStream+8,fmtLen);
- PrintAndLog("AWID Found - BitLength: %d -unknown BitLength- (%d) - Wiegand: %x, Raw: %08x%08x%08x", fmtLen, cardnum, code1, rawHi2, rawHi, rawLo);
- }
- }
- if (g_debugMode){
- PrintAndLog("DEBUG: idx: %d, Len: %d Printing Demod Buffer:", idx, 96);
- printDemodBuff();
- }
- //todo - convert hi2, hi, lo to demodbuffer for future sim/clone commands
- return 1;
-}
-
-//by marshmellow
-//Pyramid Prox demod - FSK RF/50 with preamble of 0000000000000001 (always a 128 bit data stream)
-//print full Farpointe Data/Pyramid Prox ID and some bit format details if found
-int CmdFSKdemodPyramid(const char *Cmd)
-{
- //raw fsk demod no manchester decoding no start bit finding just get binary from wave
- uint8_t BitStream[MAX_GRAPH_TRACE_LEN]={0};
- size_t size = getFromGraphBuf(BitStream);
- if (size==0) return 0;
-
- //get binary from fsk wave
- int idx = PyramiddemodFSK(BitStream, &size);
- if (idx < 0){
- if (g_debugMode==1){
- if (idx == -5)
- PrintAndLog("DEBUG: Error - not enough samples");
- else if (idx == -1)
- PrintAndLog("DEBUG: Error - only noise found");
- else if (idx == -2)
- PrintAndLog("DEBUG: Error - problem during FSK demod");
- else if (idx == -3)
- PrintAndLog("DEBUG: Error - Size not correct: %d", size);
- else if (idx == -4)
- PrintAndLog("DEBUG: Error - Pyramid preamble not found");
- else
- PrintAndLog("DEBUG: Error - idx: %d",idx);
- }
- return 0;
- }
- // Index map
- // 0 10 20 30 40 50 60
- // | | | | | | |
- // 0123456 7 8901234 5 6789012 3 4567890 1 2345678 9 0123456 7 8901234 5 6789012 3
- // -----------------------------------------------------------------------------
- // 0000000 0 0000000 1 0000000 1 0000000 1 0000000 1 0000000 1 0000000 1 0000000 1
- // premable xxxxxxx o xxxxxxx o xxxxxxx o xxxxxxx o xxxxxxx o xxxxxxx o xxxxxxx o
-
- // 64 70 80 90 100 110 120
- // | | | | | | |
- // 4567890 1 2345678 9 0123456 7 8901234 5 6789012 3 4567890 1 2345678 9 0123456 7
- // -----------------------------------------------------------------------------
- // 0000000 1 0000000 1 0000000 1 0110111 0 0011000 1 0000001 0 0001100 1 1001010 0
- // xxxxxxx o xxxxxxx o xxxxxxx o xswffff o ffffccc o ccccccc o ccccccw o ppppppp o
- // |---115---||---------71---------|
- // s = format start bit, o = odd parity of last 7 bits
- // f = facility code, c = card number
- // w = wiegand parity, x = extra space for other formats
- // p = unknown checksum
- // (26 bit format shown)
-
- //get bytes for checksum calc
- uint8_t checksum = bytebits_to_byte(BitStream + idx + 120, 8);
- uint8_t csBuff[14] = {0x00};
- for (uint8_t i = 0; i < 13; i++){
- csBuff[i] = bytebits_to_byte(BitStream + idx + 16 + (i*8), 8);
- }
- //check checksum calc
- //checksum calc thanks to ICEMAN!!
- uint32_t checkCS = CRC8Maxim(csBuff,13);
-
- //get raw ID before removing parities
- uint32_t rawLo = bytebits_to_byte(BitStream+idx+96,32);
- uint32_t rawHi = bytebits_to_byte(BitStream+idx+64,32);
- uint32_t rawHi2 = bytebits_to_byte(BitStream+idx+32,32);
- uint32_t rawHi3 = bytebits_to_byte(BitStream+idx,32);
- setDemodBuf(BitStream,128,idx);
-
- size = removeParity(BitStream, idx+8, 8, 1, 120);
- if (size != 105){
- if (g_debugMode==1)
- PrintAndLog("DEBUG: Error at parity check - tag size does not match Pyramid format, SIZE: %d, IDX: %d, hi3: %x",size, idx, rawHi3);
- return 0;
- }
-
- // ok valid card found!
-
- // Index map
- // 0 10 20 30 40 50 60 70
- // | | | | | | | |
- // 01234567890123456789012345678901234567890123456789012345678901234567890
- // -----------------------------------------------------------------------
- // 00000000000000000000000000000000000000000000000000000000000000000000000
- // xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
-
- // 71 80 90 100
- // | | | |
- // 1 2 34567890 1234567890123456 7 8901234
- // ---------------------------------------
- // 1 1 01110011 0000000001000110 0 1001010
- // s w ffffffff cccccccccccccccc w ppppppp
- // |--115-| |------71------|
- // s = format start bit, o = odd parity of last 7 bits
- // f = facility code, c = card number
- // w = wiegand parity, x = extra space for other formats
- // p = unknown checksum
- // (26 bit format shown)
-
- //find start bit to get fmtLen
- int j;
- for (j=0; j<size; j++){
- if(BitStream[j]) break;
- }
- uint8_t fmtLen = size-j-8;
- uint32_t fc = 0;
- uint32_t cardnum = 0;
- uint32_t code1 = 0;
- if (fmtLen==26){
- fc = bytebits_to_byte(BitStream+73, 8);
- cardnum = bytebits_to_byte(BitStream+81, 16);
- code1 = bytebits_to_byte(BitStream+72,fmtLen);
- PrintAndLog("Pyramid ID Found - BitLength: %d, FC: %d, Card: %d - Wiegand: %x, Raw: %08x%08x%08x%08x", fmtLen, fc, cardnum, code1, rawHi3, rawHi2, rawHi, rawLo);
- } else if (fmtLen==45){
- fmtLen=42; //end = 10 bits not 7 like 26 bit fmt
- fc = bytebits_to_byte(BitStream+53, 10);
- cardnum = bytebits_to_byte(BitStream+63, 32);
- PrintAndLog("Pyramid ID Found - BitLength: %d, FC: %d, Card: %d - Raw: %08x%08x%08x%08x", fmtLen, fc, cardnum, rawHi3, rawHi2, rawHi, rawLo);
- } else {
- cardnum = bytebits_to_byte(BitStream+81, 16);
- if (fmtLen>32){
- //code1 = bytebits_to_byte(BitStream+(size-fmtLen),fmtLen-32);
- //code2 = bytebits_to_byte(BitStream+(size-32),32);
- PrintAndLog("Pyramid ID Found - BitLength: %d -unknown BitLength- (%d), Raw: %08x%08x%08x%08x", fmtLen, cardnum, rawHi3, rawHi2, rawHi, rawLo);
- } else{
- //code1 = bytebits_to_byte(BitStream+(size-fmtLen),fmtLen);
- PrintAndLog("Pyramid ID Found - BitLength: %d -unknown BitLength- (%d), Raw: %08x%08x%08x%08x", fmtLen, cardnum, rawHi3, rawHi2, rawHi, rawLo);
- }
- }
- if (checksum == checkCS)
- PrintAndLog("Checksum %02x passed", checksum);
- else
- PrintAndLog("Checksum %02x failed - should have been %02x", checksum, checkCS);
-
- if (g_debugMode){
- PrintAndLog("DEBUG: idx: %d, Len: %d, Printing Demod Buffer:", idx, 128);
- printDemodBuff();
- }
- return 1;
-}
-
-// FDX-B ISO11784/85 demod (aka animal tag) BIPHASE, inverted, rf/32, with preamble of 00000000001 (128bits)
-// 8 databits + 1 parity (1)
-// CIITT 16 chksum
-// NATIONAL CODE, ICAR database
-// COUNTRY CODE (ISO3166) or http://cms.abvma.ca/uploads/ManufacturersISOsandCountryCodes.pdf
-// FLAG (animal/non-animal)
-int CmdFDXBdemodBI(const char *Cmd){
-
- int invert = 1;
- int clk = 32;
- int errCnt = 0;
- int maxErr = 0;
- uint8_t BitStream[MAX_DEMOD_BUF_LEN];
- size_t size = getFromGraphBuf(BitStream);
-
- errCnt = askdemod(BitStream, &size, &clk, &invert, maxErr, 0, 0);
- if ( errCnt < 0 || errCnt > maxErr ) {
- if (g_debugMode) PrintAndLog("DEBUG: no data or error found %d, clock: %d", errCnt, clk);
- return 0;
- }
-
- errCnt = BiphaseRawDecode(BitStream, &size, maxErr, 1);
- if (errCnt < 0 || errCnt > maxErr ) {
- if (g_debugMode) PrintAndLog("Error BiphaseRawDecode: %d", errCnt);
- return 0;
- }
-
- int preambleIndex = FDXBdemodBI(BitStream, &size);
- if (preambleIndex < 0){
- if (g_debugMode) PrintAndLog("Error FDXBDemod , no startmarker found :: %d",preambleIndex);
- return 0;
- }
-
- setDemodBuf(BitStream, 128, preambleIndex);
-
- // remove marker bits (1's every 9th digit after preamble) (pType = 2)
- size = removeParity(BitStream, preambleIndex + 11, 9, 2, 117);
- if ( size != 104 ) {
- if (g_debugMode) PrintAndLog("Error removeParity:: %d", size);
- return 0;
- }
- if (g_debugMode) {
- char *bin = sprint_bin_break(BitStream,size,16);
- PrintAndLog("DEBUG BinStream:\n%s",bin);
- }
- PrintAndLog("\nFDX-B / ISO 11784/5 Animal Tag ID Found:");
- if (g_debugMode) PrintAndLog("Start marker %d; Size %d", preambleIndex, size);
-
- //got a good demod
- uint64_t NationalCode = ((uint64_t)(bytebits_to_byteLSBF(BitStream+32,6)) << 32) | bytebits_to_byteLSBF(BitStream,32);
- uint32_t countryCode = bytebits_to_byteLSBF(BitStream+38,10);
- uint8_t dataBlockBit = BitStream[48];
- uint32_t reservedCode = bytebits_to_byteLSBF(BitStream+49,14);
- uint8_t animalBit = BitStream[63];
- uint32_t crc16 = bytebits_to_byteLSBF(BitStream+64,16);
- uint32_t extended = bytebits_to_byteLSBF(BitStream+80,24);
-
- uint64_t rawid = ((uint64_t)bytebits_to_byte(BitStream,32)<<32) | bytebits_to_byte(BitStream+32,32);
- uint8_t raw[8];
- num_to_bytes(rawid, 8, raw);
-
- if (g_debugMode) PrintAndLog("Raw ID Hex: %s", sprint_hex(raw,8));
-
- uint16_t calcCrc = crc16_ccitt_kermit(raw, 8);
- PrintAndLog("Animal ID: %04u-%012llu", countryCode, NationalCode);
- PrintAndLog("National Code: %012llu", NationalCode);
- PrintAndLog("CountryCode: %04u", countryCode);
- PrintAndLog("Extended Data: %s", dataBlockBit ? "True" : "False");
- PrintAndLog("reserved Code: %u", reservedCode);
- PrintAndLog("Animal Tag: %s", animalBit ? "True" : "False");
- PrintAndLog("CRC: 0x%04X - [%04X] - %s", crc16, calcCrc, (calcCrc == crc16) ? "Passed" : "Failed");
- PrintAndLog("Extended: 0x%X\n", extended);
-
- return 1;
+ return FSKrawDemod(Cmd, true);
}
-
//by marshmellow
//attempt to psk1 demod graph buffer
int PSKDemod(const char *Cmd, bool verbose)
uint8_t BitStream[MAX_GRAPH_TRACE_LEN]={0};
size_t BitLen = getFromGraphBuf(BitStream);
if (BitLen==0) return 0;
- uint8_t carrier=countFC(BitStream, BitLen, 0);
- if (carrier!=2 && carrier!=4 && carrier!=8){
- //invalid carrier
- return 0;
- }
int errCnt=0;
- errCnt = pskRawDemod(BitStream, &BitLen, &clk, &invert);
+ int startIdx = 0;
+ errCnt = pskRawDemod_ext(BitStream, &BitLen, &clk, &invert, &startIdx);
if (errCnt > maxErr){
if (g_debugMode || verbose) PrintAndLog("Too many errors found, clk: %d, invert: %d, numbits: %d, errCnt: %d",clk,invert,BitLen,errCnt);
return 0;
}
//prime demod buffer for output
setDemodBuf(BitStream,BitLen,0);
- return 1;
-}
-
-// Indala 26 bit decode
-// by marshmellow
-// optional arguments - same as CmdpskNRZrawDemod (clock & invert)
-int CmdIndalaDecode(const char *Cmd)
-{
- int ans;
- if (strlen(Cmd)>0){
- ans = PSKDemod(Cmd, 0);
- } else{ //default to RF/32
- ans = PSKDemod("32", 0);
- }
-
- if (!ans){
- if (g_debugMode==1)
- PrintAndLog("Error1: %d",ans);
- return 0;
- }
- uint8_t invert=0;
- size_t size = DemodBufferLen;
- size_t startIdx = indala26decode(DemodBuffer, &size, &invert);
- if (startIdx < 1) {
- if (g_debugMode==1)
- PrintAndLog("Error2: %d",ans);
- return -1;
- }
- setDemodBuf(DemodBuffer, size, startIdx);
- if (invert)
- if (g_debugMode==1)
- PrintAndLog("Had to invert bits");
-
- PrintAndLog("BitLen: %d",DemodBufferLen);
- //convert UID to HEX
- uint32_t uid1, uid2, uid3, uid4, uid5, uid6, uid7;
- uid1=bytebits_to_byte(DemodBuffer,32);
- uid2=bytebits_to_byte(DemodBuffer+32,32);
- if (DemodBufferLen==64) {
- PrintAndLog("Indala UID=%s (%x%08x)", sprint_bin(DemodBuffer,DemodBufferLen), uid1, uid2);
- } else {
- uid3=bytebits_to_byte(DemodBuffer+64,32);
- uid4=bytebits_to_byte(DemodBuffer+96,32);
- uid5=bytebits_to_byte(DemodBuffer+128,32);
- uid6=bytebits_to_byte(DemodBuffer+160,32);
- uid7=bytebits_to_byte(DemodBuffer+192,32);
- PrintAndLog("Indala UID=%s (%x%08x%08x%08x%08x%08x%08x)",
- sprint_bin(DemodBuffer,DemodBufferLen), uid1, uid2, uid3, uid4, uid5, uid6, uid7);
- }
- if (g_debugMode){
- PrintAndLog("DEBUG: printing demodbuffer:");
- printDemodBuff();
- }
- return 1;
-}
-
-int CmdPSKNexWatch(const char *Cmd)
-{
- if (!PSKDemod("", false)) return 0;
- uint8_t preamble[28] = {0,0,0,0,0,1,0,1,0,1,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0};
- size_t startIdx = 0, size = DemodBufferLen;
- bool invert = false;
- if (!preambleSearch(DemodBuffer, preamble, sizeof(preamble), &size, &startIdx)){
- // if didn't find preamble try again inverting
- if (!PSKDemod("1", false)) return 0;
- size = DemodBufferLen;
- if (!preambleSearch(DemodBuffer, preamble, sizeof(preamble), &size, &startIdx)) return 0;
- invert = true;
- }
- if (size != 128) return 0;
- setDemodBuf(DemodBuffer, size, startIdx+4);
- startIdx = 8+32; //4 = extra i added, 8 = preamble, 32 = reserved bits (always 0)
- //get ID
- uint32_t ID = 0;
- for (uint8_t wordIdx=0; wordIdx<4; wordIdx++){
- for (uint8_t idx=0; idx<8; idx++){
- ID = (ID << 1) | DemodBuffer[startIdx+wordIdx+(idx*4)];
- }
- }
- //parity check (TBD)
-
- //checksum check (TBD)
-
- //output
- PrintAndLog("NexWatch ID: %d", ID);
- if (invert){
- PrintAndLog("Had to Invert - probably NexKey");
- for (uint8_t idx=0; idx<size; idx++)
- DemodBuffer[idx] ^= 1;
- }
+ setClockGrid(clk, startIdx);
- CmdPrintDemodBuff("x");
return 1;
}
size_t BitLen = getFromGraphBuf(BitStream);
if (BitLen==0) return 0;
int errCnt=0;
- errCnt = nrzRawDemod(BitStream, &BitLen, &clk, &invert, maxErr);
+ int clkStartIdx = 0;
+ errCnt = nrzRawDemod(BitStream, &BitLen, &clk, &invert, &clkStartIdx);
if (errCnt > maxErr){
if (g_debugMode) PrintAndLog("Too many errors found, clk: %d, invert: %d, numbits: %d, errCnt: %d",clk,invert,BitLen,errCnt);
return 0;
if (verbose || g_debugMode) PrintAndLog("Tried NRZ Demod using Clock: %d - invert: %d - Bits Found: %d",clk,invert,BitLen);
//prime demod buffer for output
setDemodBuf(BitStream,BitLen,0);
+ setClockGrid(clk, clkStartIdx);
+
if (errCnt>0 && (verbose || g_debugMode)) PrintAndLog("# Errors during Demoding (shown as 7 in bit stream): %d",errCnt);
if (verbose || g_debugMode) {
int CmdNRZrawDemod(const char *Cmd)
{
char cmdp = param_getchar(Cmd, 0);
- if (strlen(Cmd) > 10 || cmdp == 'h' || cmdp == 'H') {
+ if (strlen(Cmd) > 16 || cmdp == 'h' || cmdp == 'H') {
PrintAndLog("Usage: data rawdemod nr [clock] <0|1> [maxError]");
PrintAndLog(" [set clock as integer] optional, if not set, autodetect.");
PrintAndLog(" <invert>, 1 for invert output");
PrintAndLog(" : data rawdemod nr 64 1 0 = demod a nrz/direct tag from GraphBuffer using a clock of RF/64, inverting data and allowing 0 demod errors");
return 0;
}
- return NRZrawDemod(Cmd, TRUE);
+ return NRZrawDemod(Cmd, true);
}
// by marshmellow
{
int ans;
char cmdp = param_getchar(Cmd, 0);
- if (strlen(Cmd) > 10 || cmdp == 'h' || cmdp == 'H') {
+ if (strlen(Cmd) > 16 || cmdp == 'h' || cmdp == 'H') {
PrintAndLog("Usage: data rawdemod p1 [clock] <0|1> [maxError]");
PrintAndLog(" [set clock as integer] optional, if not set, autodetect.");
PrintAndLog(" <invert>, 1 for invert output");
PrintAndLog(" : data rawdemod p1 64 1 0 = demod a psk1 tag from GraphBuffer using a clock of RF/64, inverting data and allowing 0 demod errors");
return 0;
}
- ans = PSKDemod(Cmd, TRUE);
+ ans = PSKDemod(Cmd, true);
//output
if (!ans){
if (g_debugMode) PrintAndLog("Error demoding: %d",ans);
{
int ans=0;
char cmdp = param_getchar(Cmd, 0);
- if (strlen(Cmd) > 10 || cmdp == 'h' || cmdp == 'H') {
+ if (strlen(Cmd) > 16 || cmdp == 'h' || cmdp == 'H') {
PrintAndLog("Usage: data rawdemod p2 [clock] <0|1> [maxError]");
PrintAndLog(" [set clock as integer] optional, if not set, autodetect.");
PrintAndLog(" <invert>, 1 for invert output");
PrintAndLog(" : data rawdemod p2 64 1 0 = demod a psk2 tag from GraphBuffer using a clock of RF/64, inverting output and allowing 0 demod errors");
return 0;
}
- ans=PSKDemod(Cmd, TRUE);
+ ans=PSKDemod(Cmd, true);
if (!ans){
if (g_debugMode) PrintAndLog("Error demoding: %d",ans);
return 0;
{
char cmdp = Cmd[0]; //param_getchar(Cmd, 0);
- if (strlen(Cmd) > 20 || cmdp == 'h' || cmdp == 'H' || strlen(Cmd)<2) {
+ if (strlen(Cmd) > 35 || cmdp == 'h' || cmdp == 'H' || strlen(Cmd)<2) {
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(" 'nr' for nrz/direct, 'p1' for psk1, 'p2' for psk2");
return ans;
}
+void setClockGrid(int clk, int offset) {
+ g_DemodStartIdx = offset;
+ g_DemodClock = clk;
+ if (g_debugMode) PrintAndLog("demodoffset %d, clk %d",offset,clk);
+
+ if (offset > clk) offset %= clk;
+ if (offset < 0) offset += clk;
+
+ if (offset > GraphTraceLen || offset < 0) return;
+ if (clk < 8 || clk > GraphTraceLen) {
+ GridLocked = false;
+ GridOffset = 0;
+ PlotGridX = 0;
+ PlotGridXdefault = 0;
+ RepaintGraphWindow();
+ } else {
+ GridLocked = true;
+ GridOffset = offset;
+ PlotGridX = clk;
+ PlotGridXdefault = clk;
+ RepaintGraphWindow();
+ }
+}
+
int CmdGrid(const char *Cmd)
{
sscanf(Cmd, "%i %i", &PlotGridX, &PlotGridY);
return 0;
}
+int CmdSetGraphMarkers(const char *Cmd) {
+ sscanf(Cmd, "%i %i", &CursorCPos, &CursorDPos);
+ RepaintGraphWindow();
+ return 0;
+}
+
int CmdHexsamples(const char *Cmd)
{
int i, j;
return val;
}
-int getSamples(const char *Cmd, bool silent)
+int getSamples(int n, bool silent)
{
//If we get all but the last byte in bigbuf,
// we don't have to worry about remaining trash
uint8_t got[BIGBUF_SIZE-1] = { 0 };
- int n = strtol(Cmd, NULL, 0);
-
- if (n == 0)
+ if (n == 0 || n > sizeof(got))
n = sizeof(got);
- if (n > sizeof(got))
- n = sizeof(got);
-
- PrintAndLog("Reading %d bytes from device memory\n", n);
+ if (!silent) PrintAndLog("Reading %d bytes from device memory\n", n);
GetFromBigBuf(got,n,0);
- PrintAndLog("Data fetched");
+ if (!silent) PrintAndLog("Data fetched");
UsbCommand response;
WaitForResponse(CMD_ACK, &response);
uint8_t bits_per_sample = 8;
if(response.arg[0] > 0)
{
sample_config *sc = (sample_config *) response.d.asBytes;
- PrintAndLog("Samples @ %d bits/smpl, decimation 1:%d ", sc->bits_per_sample
+ if (!silent) PrintAndLog("Samples @ %d bits/smpl, decimation 1:%d ", sc->bits_per_sample
, sc->decimation);
bits_per_sample = sc->bits_per_sample;
}
if(bits_per_sample < 8)
{
- PrintAndLog("Unpacking...");
+ if (!silent) PrintAndLog("Unpacking...");
BitstreamIn bout = { got, bits_per_sample * n, 0};
int j =0;
for (j = 0; j * bits_per_sample < n * 8 && j < n; j++) {
GraphTraceLen = n;
}
+ setClockGrid(0,0);
+ DemodBufferLen = 0;
RepaintGraphWindow();
return 0;
}
int CmdSamples(const char *Cmd)
{
- return getSamples(Cmd, false);
+ int n = strtol(Cmd, NULL, 0);
+ return getSamples(n, false);
}
int CmdTuneSamples(const char *Cmd)
{
- int timeout = 0;
+ int timeout = 0, arg = FLAG_TUNE_ALL;
+
+ if(*Cmd == 'l') {
+ arg = FLAG_TUNE_LF;
+ } else if (*Cmd == 'h') {
+ arg = FLAG_TUNE_HF;
+ } else if (*Cmd != '\0') {
+ PrintAndLog("use 'tune' or 'tune l' or 'tune h'");
+ return 0;
+ }
+
printf("\nMeasuring antenna characteristics, please wait...");
- UsbCommand c = {CMD_MEASURE_ANTENNA_TUNING};
+ UsbCommand c = {CMD_MEASURE_ANTENNA_TUNING, {arg, 0, 0}};
SendCommand(&c);
UsbCommand resp;
peakf = resp.arg[2] & 0xffff;
peakv = resp.arg[2] >> 16;
PrintAndLog("");
- PrintAndLog("# LF antenna: %5.2f V @ 125.00 kHz", vLf125/1000.0);
- PrintAndLog("# LF antenna: %5.2f V @ 134.00 kHz", vLf134/1000.0);
- PrintAndLog("# LF optimal: %5.2f V @%9.2f kHz", peakv/1000.0, 12000.0/(peakf+1));
+ PrintAndLog("# LF antenna: %5.2f V @ 125.00 kHz", vLf125/500.0);
+ PrintAndLog("# LF antenna: %5.2f V @ 134.00 kHz", vLf134/500.0);
+ PrintAndLog("# LF optimal: %5.2f V @%9.2f kHz", peakv/500.0, 12000.0/(peakf+1));
PrintAndLog("# HF antenna: %5.2f V @ 13.56 MHz", vHf/1000.0);
- #define LF_UNUSABLE_V 2948 // was 2000. Changed due to bugfix in voltage measurements. LF results are now 47% higher.
- #define LF_MARGINAL_V 14739 // was 10000. Changed due to bugfix bug in voltage measurements. LF results are now 47% higher.
- #define HF_UNUSABLE_V 3167 // was 2000. Changed due to bugfix in voltage measurements. HF results are now 58% higher.
- #define HF_MARGINAL_V 7917 // was 5000. Changed due to bugfix in voltage measurements. HF results are now 58% higher.
+ #define LF_UNUSABLE_V 3000
+ #define LF_MARGINAL_V 15000
+ #define HF_UNUSABLE_V 3200
+ #define HF_MARGINAL_V 8000
- if (peakv < LF_UNUSABLE_V)
+ if (peakv<<1 < LF_UNUSABLE_V)
PrintAndLog("# Your LF antenna is unusable.");
- else if (peakv < LF_MARGINAL_V)
+ else if (peakv<<1 < LF_MARGINAL_V)
PrintAndLog("# Your LF antenna is marginal.");
if (vHf < HF_UNUSABLE_V)
PrintAndLog("# Your HF antenna is unusable.");
else if (vHf < HF_MARGINAL_V)
PrintAndLog("# Your HF antenna is marginal.");
- if (peakv >= LF_UNUSABLE_V) {
+ if (peakv<<1 >= LF_UNUSABLE_V) {
for (int i = 0; i < 256; i++) {
GraphBuffer[i] = resp.d.asBytes[i] - 128;
}
}
fclose(f);
PrintAndLog("loaded %d samples", GraphTraceLen);
+ setClockGrid(0,0);
+ DemodBufferLen = 0;
RepaintGraphWindow();
return 0;
}
return 0;
}
+// trim graph (middle) piece
+int CmdMtrim(const char *Cmd) {
+ int start = 0, stop = 0;
+ sscanf(Cmd, "%i %i", &start, &stop);
+
+ if (start > GraphTraceLen || stop > GraphTraceLen || start > stop) return 0;
+ start++; //leave start position sample
+
+ GraphTraceLen = stop - start;
+ for (int i = 0; i < GraphTraceLen; i++) {
+ GraphBuffer[i] = GraphBuffer[start+i];
+ }
+ return 0;
+}
+
+
int CmdNorm(const char *Cmd)
{
int i;
if (max != min) {
for (i = 0; i < GraphTraceLen; ++i) {
- GraphBuffer[i] = (GraphBuffer[i] - ((max + min) / 2)) * 256 /
- (max - min);
+ GraphBuffer[i] = ((long)(GraphBuffer[i] - ((max + min) / 2)) * 256) / (max - min);
//marshmelow: adjusted *1000 to *256 to make +/- 128 so demod commands still work
}
}
return 0;
}
-int CmdDirectionalThreshold(const char *Cmd)
+int directionalThreshold(const int* in, int *out, size_t len, int8_t up, int8_t down)
{
- int8_t upThres = param_get8(Cmd, 0);
- int8_t downThres = param_get8(Cmd, 1);
-
- printf("Applying Up Threshold: %d, Down Threshold: %d\n", upThres, downThres);
-
- int lastValue = GraphBuffer[0];
- GraphBuffer[0] = 0; // Will be changed at the end, but init 0 as we adjust to last samples value if no threshold kicks in.
+ int lastValue = in[0];
+ out[0] = 0; // Will be changed at the end, but init 0 as we adjust to last samples value if no threshold kicks in.
- for (int i = 1; i < GraphTraceLen; ++i) {
+ for (int i = 1; i < len; ++i) {
// Apply first threshold to samples heading up
- if (GraphBuffer[i] >= upThres && GraphBuffer[i] > lastValue)
+ if (in[i] >= up && in[i] > lastValue)
{
- lastValue = GraphBuffer[i]; // Buffer last value as we overwrite it.
- GraphBuffer[i] = 1;
+ lastValue = out[i]; // Buffer last value as we overwrite it.
+ out[i] = 1;
}
// Apply second threshold to samples heading down
- else if (GraphBuffer[i] <= downThres && GraphBuffer[i] < lastValue)
+ else if (in[i] <= down && in[i] < lastValue)
{
- lastValue = GraphBuffer[i]; // Buffer last value as we overwrite it.
- GraphBuffer[i] = -1;
+ lastValue = out[i]; // Buffer last value as we overwrite it.
+ out[i] = -1;
}
else
{
- lastValue = GraphBuffer[i]; // Buffer last value as we overwrite it.
- GraphBuffer[i] = GraphBuffer[i-1];
-
+ lastValue = out[i]; // Buffer last value as we overwrite it.
+ out[i] = out[i-1];
}
}
- GraphBuffer[0] = GraphBuffer[1]; // Aline with first edited sample.
+ out[0] = out[1]; // Align with first edited sample.
+ return 0;
+}
+
+int CmdDirectionalThreshold(const char *Cmd)
+{
+ int8_t upThres = param_get8(Cmd, 0);
+ int8_t downThres = param_get8(Cmd, 1);
+
+ printf("Applying Up Threshold: %d, Down Threshold: %d\n", upThres, downThres);
+
+ directionalThreshold(GraphBuffer, GraphBuffer,GraphTraceLen, upThres, downThres);
RepaintGraphWindow();
return 0;
}
return 0;
}
-int usage_data_hex2bin(){
-
- PrintAndLog("Usage: data bin2hex <binary_digits>");
+int usage_data_hex2bin() {
+ PrintAndLog("Usage: data hex2bin <hex_digits>");
PrintAndLog(" This function will ignore all non-hexadecimal characters (but stop reading on whitespace)");
return 0;
return 0;
}
+ /* // example of FSK2 RF/50 Tones
+ static const int LowTone[] = {
+ 1, 1, 1, 1, 1, -1, -1, -1, -1, -1,
+ 1, 1, 1, 1, 1, -1, -1, -1, -1, -1,
+ 1, 1, 1, 1, 1, -1, -1, -1, -1, -1,
+ 1, 1, 1, 1, 1, -1, -1, -1, -1, -1,
+ 1, 1, 1, 1, 1, -1, -1, -1, -1, -1
+ };
+ static const int HighTone[] = {
+ 1, 1, 1, 1, 1, -1, -1, -1, -1, // note one extra 1 to padd due to 50/8 remainder (1/2 the remainder)
+ 1, 1, 1, 1, -1, -1, -1, -1,
+ 1, 1, 1, 1, -1, -1, -1, -1,
+ 1, 1, 1, 1, -1, -1, -1, -1,
+ 1, 1, 1, 1, -1, -1, -1, -1,
+ 1, 1, 1, 1, -1, -1, -1, -1, -1, // note one extra -1 to padd due to 50/8 remainder
+ };
+ */
+void GetHiLoTone(int *LowTone, int *HighTone, int clk, int LowToneFC, int HighToneFC) {
+ int i,j=0;
+ int Left_Modifier = ((clk % LowToneFC) % 2) + ((clk % LowToneFC)/2);
+ int Right_Modifier = (clk % LowToneFC) / 2;
+ //int HighToneMod = clk mod HighToneFC;
+ int LeftHalfFCCnt = (LowToneFC % 2) + (LowToneFC/2); //truncate
+ int FCs_per_clk = clk/LowToneFC;
+
+ // need to correctly split up the clock to field clocks.
+ // First attempt uses modifiers on each end to make up for when FCs don't evenly divide into Clk
+
+ // start with LowTone
+ // set extra 1 modifiers to make up for when FC doesn't divide evenly into Clk
+ for (i = 0; i < Left_Modifier; i++) {
+ LowTone[i] = 1;
+ }
+
+ // loop # of field clocks inside the main clock
+ for (i = 0; i < (FCs_per_clk); i++) {
+ // loop # of samples per field clock
+ for (j = 0; j < LowToneFC; j++) {
+ LowTone[(i*LowToneFC)+Left_Modifier+j] = ( j < LeftHalfFCCnt ) ? 1 : -1;
+ }
+ }
+
+ int k;
+ // add last -1 modifiers
+ for (k = 0; k < Right_Modifier; k++) {
+ LowTone[((i-1)*LowToneFC)+Left_Modifier+j+k] = -1;
+ }
+
+ // now do hightone
+ Left_Modifier = ((clk % HighToneFC) % 2) + ((clk % HighToneFC)/2);
+ Right_Modifier = (clk % HighToneFC) / 2;
+ LeftHalfFCCnt = (HighToneFC % 2) + (HighToneFC/2); //truncate
+ FCs_per_clk = clk/HighToneFC;
+
+ for (i = 0; i < Left_Modifier; i++) {
+ HighTone[i] = 1;
+ }
+
+ // loop # of field clocks inside the main clock
+ for (i = 0; i < (FCs_per_clk); i++) {
+ // loop # of samples per field clock
+ for (j = 0; j < HighToneFC; j++) {
+ HighTone[(i*HighToneFC)+Left_Modifier+j] = ( j < LeftHalfFCCnt ) ? 1 : -1;
+ }
+ }
+
+ // add last -1 modifiers
+ for (k = 0; k < Right_Modifier; k++) {
+ PrintAndLog("(i-1)*HighToneFC+lm+j+k %i",((i-1)*HighToneFC)+Left_Modifier+j+k);
+ HighTone[((i-1)*HighToneFC)+Left_Modifier+j+k] = -1;
+ }
+ if (g_debugMode == 2) {
+ for ( i = 0; i < clk; i++) {
+ PrintAndLog("Low: %i, High: %i",LowTone[i],HighTone[i]);
+ }
+ }
+}
+
+//old CmdFSKdemod adapted by marshmellow
+//converts FSK to clear NRZ style wave. (or demodulates)
+int FSKToNRZ(int *data, int *dataLen, int clk, int LowToneFC, int HighToneFC) {
+ uint8_t ans=0;
+ if (clk == 0 || LowToneFC == 0 || HighToneFC == 0) {
+ int firstClockEdge=0;
+ ans = fskClocks((uint8_t *) &LowToneFC, (uint8_t *) &HighToneFC, (uint8_t *) &clk, false, &firstClockEdge);
+ if (g_debugMode > 1) {
+ PrintAndLog ("DEBUG FSKtoNRZ: detected clocks: fc_low %i, fc_high %i, clk %i, firstClockEdge %i, ans %u", LowToneFC, HighToneFC, clk, firstClockEdge, ans);
+ }
+ }
+ // currently only know fsk modulations with field clocks < 10 samples and > 4 samples. filter out to remove false positives (and possibly destroying ask/psk modulated waves...)
+ if (ans == 0 || clk == 0 || LowToneFC == 0 || HighToneFC == 0 || LowToneFC > 10 || HighToneFC < 4) {
+ if (g_debugMode > 1) {
+ PrintAndLog ("DEBUG FSKtoNRZ: no fsk clocks found");
+ }
+ return 0;
+ }
+ int LowTone[clk];
+ int HighTone[clk];
+ GetHiLoTone(LowTone, HighTone, clk, LowToneFC, HighToneFC);
+
+ int i, j;
+
+ // loop through ([all samples] - clk)
+ for (i = 0; i < *dataLen - clk; ++i) {
+ int lowSum = 0, highSum = 0;
+
+ // sum all samples together starting from this sample for [clk] samples for each tone (multiply tone value with sample data)
+ for (j = 0; j < clk; ++j) {
+ lowSum += LowTone[j] * data[i+j];
+ highSum += HighTone[j] * data[i + j];
+ }
+ // get abs( [average sample value per clk] * 100 ) (or a rolling average of sorts)
+ lowSum = abs(100 * lowSum / clk);
+ highSum = abs(100 * highSum / clk);
+ // save these back to buffer for later use
+ data[i] = (highSum << 16) | lowSum;
+ }
+
+ // now we have the abs( [average sample value per clk] * 100 ) for each tone
+ // loop through again [all samples] - clk - 16
+ // note why 16??? is 16 the largest FC? changed to LowToneFC as that should be the > fc
+ for(i = 0; i < *dataLen - clk - LowToneFC; ++i) {
+ int lowTot = 0, highTot = 0;
+
+ // sum a field clock width of abs( [average sample values per clk] * 100) for each tone
+ for (j = 0; j < LowToneFC; ++j) { //10 for fsk2
+ lowTot += (data[i + j] & 0xffff);
+ }
+ for (j = 0; j < HighToneFC; j++) { //8 for fsk2
+ highTot += (data[i + j] >> 16);
+ }
+
+ // subtract the sum of lowTone averages by the sum of highTone averages as it
+ // and write back the new graph value
+ data[i] = lowTot - highTot;
+ }
+ // update dataLen to what we put back to the data sample buffer
+ *dataLen -= (clk + LowToneFC);
+ return 0;
+}
+
+int usage_data_fsktonrz() {
+ PrintAndLog("Usage: data fsktonrz c <clock> l <fc_low> f <fc_high>");
+ PrintAndLog("Options: ");
+ PrintAndLog(" h This help");
+ PrintAndLog(" c <clock> enter the a clock (omit to autodetect)");
+ PrintAndLog(" l <fc_low> enter a field clock (omit to autodetect)");
+ PrintAndLog(" f <fc_high> enter a field clock (omit to autodetect)");
+ return 0;
+}
+
+int CmdFSKToNRZ(const char *Cmd) {
+ // take clk, fc_low, fc_high
+ // blank = auto;
+ bool errors = false;
+ int clk = 0;
+ char cmdp = 0;
+ int fc_low = 10, fc_high = 8;
+ while(param_getchar(Cmd, cmdp) != 0x00)
+ {
+ switch(param_getchar(Cmd, cmdp))
+ {
+ case 'h':
+ case 'H':
+ return usage_data_fsktonrz();
+ case 'C':
+ case 'c':
+ clk = param_get32ex(Cmd, cmdp+1, 0, 10);
+ cmdp += 2;
+ break;
+ case 'F':
+ case 'f':
+ fc_high = param_get32ex(Cmd, cmdp+1, 0, 10);
+ cmdp += 2;
+ break;
+ case 'L':
+ case 'l':
+ fc_low = param_get32ex(Cmd, cmdp+1, 0, 10);
+ cmdp += 2;
+ break;
+ default:
+ PrintAndLog("Unknown parameter '%c'", param_getchar(Cmd, cmdp));
+ errors = true;
+ break;
+ }
+ if(errors) break;
+ }
+ //Validations
+ if(errors) return usage_data_fsktonrz();
+
+ setClockGrid(0,0);
+ DemodBufferLen = 0;
+ int ans = FSKToNRZ(GraphBuffer, &GraphTraceLen, clk, fc_low, fc_high);
+ CmdNorm("");
+ RepaintGraphWindow();
+ return ans;
+}
+
+
static command_t CommandTable[] =
{
{"help", CmdHelp, 1, "This help"},
{"askedgedetect", CmdAskEdgeDetect, 1, "[threshold] Adjust Graph for manual ask demod using the length of sample differences to detect the edge of a wave (use 20-45, def:25)"},
- {"askem410xdemod", CmdAskEM410xDemod, 1, "[clock] [invert<0|1>] [maxErr] -- Demodulate an EM410x tag from GraphBuffer (args optional)"},
- {"askgproxiidemod", CmdG_Prox_II_Demod, 1, "Demodulate a G Prox II tag from GraphBuffer"},
- {"askvikingdemod", CmdVikingDemod, 1, "Demodulate a Viking tag from GraphBuffer"},
{"autocorr", CmdAutoCorr, 1, "[window length] [g] -- Autocorrelation over window - g to save back to GraphBuffer (overwrite)"},
{"biphaserawdecode",CmdBiphaseDecodeRaw,1, "[offset] [invert<0|1>] [maxErr] -- Biphase decode bin stream in DemodBuffer (offset = 0|1 bits to shift the decode start)"},
{"bin2hex", Cmdbin2hex, 1, "bin2hex <digits> -- Converts binary to hexadecimal"},
{"buffclear", CmdBuffClear, 1, "Clear sample buffer and graph window"},
{"dec", CmdDec, 1, "Decimate samples"},
{"detectclock", CmdDetectClockRate, 1, "[modulation] Detect clock rate of wave in GraphBuffer (options: 'a','f','n','p' for ask, fsk, nrz, psk respectively)"},
- {"fdxbdemod", CmdFDXBdemodBI , 1, "Demodulate a FDX-B ISO11784/85 Biphase tag from GraphBuffer"},
- {"fskawiddemod", CmdFSKdemodAWID, 1, "Demodulate an AWID FSK tag from GraphBuffer"},
- //{"fskfcdetect", CmdFSKfcDetect, 1, "Try to detect the Field Clock of an FSK wave"},
- {"fskhiddemod", CmdFSKdemodHID, 1, "Demodulate a HID FSK tag from GraphBuffer"},
- {"fskiodemod", CmdFSKdemodIO, 1, "Demodulate an IO Prox FSK tag from GraphBuffer"},
- {"fskpyramiddemod", CmdFSKdemodPyramid, 1, "Demodulate a Pyramid FSK tag from GraphBuffer"},
- {"fskparadoxdemod", CmdFSKdemodParadox, 1, "Demodulate a Paradox FSK tag from GraphBuffer"},
+ {"fsktonrz", CmdFSKToNRZ, 1, "Convert fsk2 to nrz wave for alternate fsk demodulating (for weak fsk)"},
{"getbitstream", CmdGetBitStream, 1, "Convert GraphBuffer's >=1 values to 1 and <1 to 0"},
{"grid", CmdGrid, 1, "<x> <y> -- overlay grid on graph window, use zero value to turn off either"},
{"hexsamples", CmdHexsamples, 0, "<bytes> [<offset>] -- Dump big buffer as hex bytes"},
{"load", CmdLoad, 1, "<filename> -- Load trace (to graph window"},
{"ltrim", CmdLtrim, 1, "<samples> -- Trim samples from left of trace"},
{"rtrim", CmdRtrim, 1, "<location to end trace> -- Trim samples from right of trace"},
+ {"mtrim", CmdMtrim, 1, "<start> <stop> -- Trim out samples from the specified start to the specified stop"},
{"manrawdecode", Cmdmandecoderaw, 1, "[invert] [maxErr] -- Manchester decode binary stream in DemodBuffer"},
{"norm", CmdNorm, 1, "Normalize max/min to +/-128"},
{"plot", CmdPlot, 1, "Show graph window (hit 'h' in window for keystroke help)"},
- {"printdemodbuffer",CmdPrintDemodBuff, 1, "[x] [o] <offset> -- print the data in the DemodBuffer - 'x' for hex output"},
- {"pskindalademod", CmdIndalaDecode, 1, "[clock] [invert<0|1>] -- Demodulate an indala tag (PSK1) from GraphBuffer (args optional)"},
- {"psknexwatchdemod",CmdPSKNexWatch, 1, "Demodulate a NexWatch tag (nexkey, quadrakey) (PSK1) from GraphBuffer"},
+ {"printdemodbuffer",CmdPrintDemodBuff, 1, "[x] [o] <offset> [l] <length> -- print the data in the DemodBuffer - 'x' for hex output"},
{"rawdemod", CmdRawDemod, 1, "[modulation] ... <options> -see help (h option) -- Demodulate the data in the GraphBuffer and output binary"},
{"samples", CmdSamples, 0, "[512 - 40000] -- Get raw samples for graph window (GraphBuffer)"},
{"save", CmdSave, 1, "<filename> -- Save trace (from graph window)"},
+ {"setgraphmarkers", CmdSetGraphMarkers, 1, "[orange_marker] [blue_marker] (in graph window)"},
{"scale", CmdScale, 1, "<int> -- Set cursor display scale"},
- {"setdebugmode", CmdSetDebugMode, 1, "<0|1> -- Turn on or off Debugging Mode for demods"},
+ {"setdebugmode", CmdSetDebugMode, 1, "<0|1|2> -- Turn on or off Debugging Level for lf demods"},
{"shiftgraphzero", CmdGraphShiftZero, 1, "<shift> -- Shift 0 for Graphed wave + or - shift value"},
{"dirthreshold", CmdDirectionalThreshold, 1, "<thres up> <thres down> -- Max rising higher up-thres/ Min falling lower down-thres, keep rest as prev."},
{"tune", CmdTuneSamples, 0, "Get hw tune samples for graph window"},