From: marshmellow42 <marshmellowrf@gmail.com>
Date: Mon, 6 Jun 2016 02:20:36 +0000 (-0400)
Subject: Merge remote-tracking branch 'upstream/master'
X-Git-Tag: v3.0.0~87^2~12
X-Git-Url: https://git.zerfleddert.de/cgi-bin/gitweb.cgi/proxmark3-svn/commitdiff_plain/c0d32c3186e5b11cf13394b10770cc1b6abab83f?hp=6fcb5dda51b7bedb8a8bb1bb216a2f4a60a6095c

Merge remote-tracking branch 'upstream/master'
---

diff --git a/armsrc/appmain.c b/armsrc/appmain.c
index 475b1c1b..ffe6b7f2 100644
--- a/armsrc/appmain.c
+++ b/armsrc/appmain.c
@@ -37,8 +37,6 @@
  #include "iso14443a.h"
 #endif
 
-#define abs(x) ( ((x)<0) ? -(x) : (x) )
-
 //=============================================================================
 // A buffer where we can queue things up to be sent through the FPGA, for
 // any purpose (fake tag, as reader, whatever). We go MSB first, since that
@@ -842,7 +840,7 @@ void ListenReaderField(int limit)
 
 		if (limit != HF_ONLY) {
 			if(mode == 1) {
-				if (abs(lf_av - lf_baseline) > REPORT_CHANGE) 
+				if (ABS(lf_av - lf_baseline) > REPORT_CHANGE) 
 					LED_D_ON();
 				else
 					LED_D_OFF();
@@ -850,7 +848,7 @@ void ListenReaderField(int limit)
 
 			lf_av_new = AvgAdc(ADC_CHAN_LF);
 			// see if there's a significant change
-			if(abs(lf_av - lf_av_new) > REPORT_CHANGE) {
+			if(ABS(lf_av - lf_av_new) > REPORT_CHANGE) {
 				Dbprintf("LF 125/134kHz Field Change: %5dmV", (MAX_ADC_LF_VOLTAGE * lf_av_new) >> 10);
 				lf_av = lf_av_new;
 				if (lf_av > lf_max)
@@ -860,7 +858,7 @@ void ListenReaderField(int limit)
 
 		if (limit != LF_ONLY) {
 			if (mode == 1){
-				if (abs(hf_av - hf_baseline) > REPORT_CHANGE) 	
+				if (ABS(hf_av - hf_baseline) > REPORT_CHANGE) 	
 					LED_B_ON();
 				else
 					LED_B_OFF();
@@ -868,7 +866,7 @@ void ListenReaderField(int limit)
 
 			hf_av_new = AvgAdc(ADC_CHAN_HF);
 			// see if there's a significant change
-			if(abs(hf_av - hf_av_new) > REPORT_CHANGE) {
+			if(ABS(hf_av - hf_av_new) > REPORT_CHANGE) {
 				Dbprintf("HF 13.56MHz Field Change: %5dmV", (MAX_ADC_HF_VOLTAGE * hf_av_new) >> 10);
 				hf_av = hf_av_new;
 				if (hf_av > hf_max)
diff --git a/armsrc/iso14443b.c b/armsrc/iso14443b.c
index 82e5dd6a..22227e74 100644
--- a/armsrc/iso14443b.c
+++ b/armsrc/iso14443b.c
@@ -547,15 +547,20 @@ static RAMFUNC int Handle14443bSamplesDemod(int ci, int cq)
 	}
  */
 // Subcarrier amplitude v = sqrt(ci^2 + cq^2), approximated here by max(abs(ci),abs(cq)) + 1/2*min(abs(ci),abs(cq)))
+
+	//note: couldn't we just use MAX(ABS(ci),ABS(cq)) + (MIN(ABS(ci),ABS(cq))/2) from common.h - marshmellow
 #define CHECK_FOR_SUBCARRIER() { \
+		v = MAX(ABS(ci),ABS(cq)) + (MIN(ABS(ci),ABS(cq))/2); \
+ 	}
+		/*
 		if(ci < 0) { \
-			if(cq < 0) { /* ci < 0, cq < 0 */ \
+			if(cq < 0) { \ // ci < 0, cq < 0
 				if (cq < ci) { \
 					v = -cq - (ci >> 1); \
 				} else { \
 					v = -ci - (cq >> 1); \
 				} \
-			} else {	/* ci < 0, cq >= 0 */ \
+			} else {	\ // ci < 0, cq >= 0
 				if (cq < -ci) { \
 					v = -ci + (cq >> 1); \
 				} else { \
@@ -563,13 +568,13 @@ static RAMFUNC int Handle14443bSamplesDemod(int ci, int cq)
 				} \
 			} \
 		} else { \
-			if(cq < 0) { /* ci >= 0, cq < 0 */ \
+			if(cq < 0) { \ // ci >= 0, cq < 0
 				if (-cq < ci) { \
 					v = ci - (cq >> 1); \
 				} else { \
 					v = -cq + (ci >> 1); \
 				} \
-			} else {	/* ci >= 0, cq >= 0 */ \
+			} else {	\ // ci >= 0, cq >= 0
 				if (cq < ci) { \
 					v = ci + (cq >> 1); \
 				} else { \
@@ -578,6 +583,7 @@ static RAMFUNC int Handle14443bSamplesDemod(int ci, int cq)
 			} \
 		} \
 	}
+		*/
 
 	switch(Demod.state) {
 		case DEMOD_UNSYNCD:
diff --git a/armsrc/iso15693.c b/armsrc/iso15693.c
index e7145c5c..9a6ef9f0 100644
--- a/armsrc/iso15693.c
+++ b/armsrc/iso15693.c
@@ -319,18 +319,7 @@ static int GetIso15693AnswerFromTag(uint8_t *receivedResponse, int maxLen, int *
 			// every other is Q. We just want power, so abs(I) + abs(Q) is
 			// close to what we want.
 			if(getNext) {
-				int8_t r;
-
-				if(b < 0) {
-					r = -b;
-				} else {
-					r = b;
-				}
-				if(prev < 0) {
-					r -= prev;
-				} else {
-					r += prev;
-				}
+				int8_t r = ABS(b) + ABS(prev);
 
 				dest[c++] = (uint8_t)r;
 
@@ -468,18 +457,7 @@ static int GetIso15693AnswerFromSniff(uint8_t *receivedResponse, int maxLen, int
 			// every other is Q. We just want power, so abs(I) + abs(Q) is
 			// close to what we want.
 			if(getNext) {
-				int8_t r;
-
-				if(b < 0) {
-					r = -b;
-				} else {
-					r = b;
-				}
-				if(prev < 0) {
-					r -= prev;
-				} else {
-					r += prev;
-				}
+				int8_t r = ABS(b) + ABS(prev);
 
 				dest[c++] = (uint8_t)r;
 
@@ -648,18 +626,7 @@ void AcquireRawAdcSamplesIso15693(void)
 			// every other is Q. We just want power, so abs(I) + abs(Q) is
 			// close to what we want.
 			if(getNext) {
-				int8_t r;
-
-				if(b < 0) {
-					r = -b;
-				} else {
-					r = b;
-				}
-				if(prev < 0) {
-					r -= prev;
-				} else {
-					r += prev;
-				}
+				int8_t r = ABS(b) + ABS(prev);
 
 				dest[c++] = (uint8_t)r;
 
@@ -713,18 +680,7 @@ void RecordRawAdcSamplesIso15693(void)
 			// every other is Q. We just want power, so abs(I) + abs(Q) is
 			// close to what we want.
 			if(getNext) {
-				int8_t r;
-
-				if(b < 0) {
-					r = -b;
-				} else {
-					r = b;
-				}
-				if(prev < 0) {
-					r -= prev;
-				} else {
-					r += prev;
-				}
+				int8_t r = ABS(b) + ABS(prev);
 
 				dest[c++] = (uint8_t)r;
 
diff --git a/armsrc/lfops.c b/armsrc/lfops.c
index 14b62673..2079f263 100644
--- a/armsrc/lfops.c
+++ b/armsrc/lfops.c
@@ -379,7 +379,7 @@ void WriteTItag(uint32_t idhi, uint32_t idlo, uint16_t crc)
 	AcquireTiType();
 
 	FpgaWriteConfWord(FPGA_MAJOR_MODE_OFF);
-	DbpString("Now use tiread to check");
+	DbpString("Now use `lf ti read` to check");
 }
 
 void SimulateTagLowFrequency(int period, int gap, int ledcontrol)
@@ -642,6 +642,19 @@ static void biphaseSimBit(uint8_t c, int *n, uint8_t clock, uint8_t *phase)
 		memset(dest+(*n), c ^ *phase, clock);
 		*phase ^= 1;
 	}
+	*n += clock;
+}
+
+static void stAskSimBit(int *n, uint8_t clock) {
+	uint8_t *dest = BigBuf_get_addr();
+	uint8_t halfClk = clock/2;
+	//ST = .5 high .5 low 1.5 high .5 low 1 high	
+	memset(dest+(*n), 1, halfClk);
+	memset(dest+(*n) + halfClk, 0, halfClk);
+	memset(dest+(*n) + clock, 1, clock + halfClk);
+	memset(dest+(*n) + clock*2 + halfClk, 0, halfClk);
+	memset(dest+(*n) + clock*3, 1, clock);
+	*n += clock*4;
 }
 
 // args clock, ask/man or askraw, invert, transmission separator
@@ -659,7 +672,7 @@ void CmdASKsimTag(uint16_t arg1, uint16_t arg2, size_t size, uint8_t *BitStream)
 		for (i=0; i<size; i++){
 			biphaseSimBit(BitStream[i]^invert, &n, clk, &phase);
 		}
-		if (BitStream[0]==BitStream[size-1]){ //run a second set inverted to keep phase in check
+		if (phase==1) { //run a second set inverted to keep phase in check
 			for (i=0; i<size; i++){
 				biphaseSimBit(BitStream[i]^invert, &n, clk, &phase);
 			}
@@ -674,8 +687,10 @@ void CmdASKsimTag(uint16_t arg1, uint16_t arg2, size_t size, uint8_t *BitStream)
 			}
 		}
 	}
-	
-	if (separator==1) Dbprintf("sorry but separator option not yet available"); 
+	if (separator==1 && encoding == 1)
+		stAskSimBit(&n, clk);
+	else if (separator==1)
+		Dbprintf("sorry but separator option not yet available");
 
 	Dbprintf("Simulating with clk: %d, invert: %d, encoding: %d, separator: %d, n: %d",clk, invert, encoding, separator, n);
 	//DEBUG
@@ -685,7 +700,7 @@ void CmdASKsimTag(uint16_t arg1, uint16_t arg2, size_t size, uint8_t *BitStream)
 	//Dbprintf("%d%d%d%d%d%d%d%d%d%d%d%d%d%d%d%d", dest[i],dest[i+1],dest[i+2],dest[i+3],dest[i+4],dest[i+5],dest[i+6],dest[i+7],dest[i+8],dest[i+9],dest[i+10],dest[i+11],dest[i+12],dest[i+13],dest[i+14],dest[i+15]);
 	//i+=16;
 	//Dbprintf("%d%d%d%d%d%d%d%d%d%d%d%d%d%d%d%d", dest[i],dest[i+1],dest[i+2],dest[i+3],dest[i+4],dest[i+5],dest[i+6],dest[i+7],dest[i+8],dest[i+9],dest[i+10],dest[i+11],dest[i+12],dest[i+13],dest[i+14],dest[i+15]);
-
+	
 	if (ledcontrol) LED_A_ON();
 	SimulateTagLowFrequency(n, 0, ledcontrol);
 	if (ledcontrol) LED_A_OFF();
@@ -1415,7 +1430,7 @@ void WriteEM410x(uint32_t card, uint32_t id_hi, uint32_t id_lo) {
 	LED_D_ON();
 
 	// Write EM410x ID
-	uint32_t data[] = {0, id>>32, id & 0xFFFFFFFF};
+	uint32_t data[] = {0, (uint32_t)(id>>32), (uint32_t)(id & 0xFFFFFFFF)};
 
 	clock = (card & 0xFF00) >> 8;
 	clock = (clock == 0) ? 64 : clock;
diff --git a/armsrc/pcf7931.c b/armsrc/pcf7931.c
index 165319ca..f9f33c53 100644
--- a/armsrc/pcf7931.c
+++ b/armsrc/pcf7931.c
@@ -7,9 +7,6 @@
 #define T0_PCF 8 //period for the pcf7931 in us
 #define ALLOC 16
 
-#define abs(x) ( ((x)<0) ? -(x) : (x) )
-#define max(x,y) ( x<y ? y:x)
-
 int DemodPCF7931(uint8_t **outBlocks) {
 
     uint8_t bits[256] = {0x00};
@@ -72,7 +69,7 @@ int DemodPCF7931(uint8_t **outBlocks) {
 
 			// Switch depending on lc length:
 			// Tolerance is 1/8 of clock rate (arbitrary)
-			if (abs(lc-clock/4) < tolerance) {
+			if (ABS(lc-clock/4) < tolerance) {
 				// 16T0
 				if((i - pmc) == lc) { /* 16T0 was previous one */
 					/* It's a PMC ! */
@@ -84,7 +81,7 @@ int DemodPCF7931(uint8_t **outBlocks) {
 				else {
 					pmc = i;
 				}
-			} else if (abs(lc-clock/2) < tolerance) {
+			} else if (ABS(lc-clock/2) < tolerance) {
 				// 32TO
 				if((i - pmc) == lc) { /* 16T0 was previous one */
 					/* It's a PMC ! */
@@ -99,7 +96,7 @@ int DemodPCF7931(uint8_t **outBlocks) {
 				}
 				else
 					half_switch++;
-			} else if (abs(lc-clock) < tolerance) {
+			} else if (ABS(lc-clock) < tolerance) {
 				// 64TO
                 bits[bitidx++] = 1;
 			} else {
@@ -204,7 +201,7 @@ void ReadPCF7931() {
 						Blocks[0][ALLOC] = 1;
 						memcpy(Blocks[1], tmpBlocks[i+1], 16);
 						Blocks[1][ALLOC] = 1;
-						max_blocks = max((Blocks[1][14] & 0x7f), Blocks[1][15]) + 1;
+						max_blocks = MAX((Blocks[1][14] & 0x7f), Blocks[1][15]) + 1;
 						// Debug print
 						Dbprintf("(dbg) Max blocks: %d", max_blocks);
 						num_blocks = 2;
diff --git a/client/Makefile b/client/Makefile
index 0972f441..7f9c4c84 100644
--- a/client/Makefile
+++ b/client/Makefile
@@ -99,6 +99,8 @@ CMDSRCS = 	nonce2key/crapto1.c\
 			cmdlft55xx.c \
 			cmdlfpcf7931.c\
 			cmdlfviking.c\
+			cmdlfpresco.c\
+			cmdlfpyramid.c\
 			pm3_binlib.c\
 			scripting.c\
 			cmdscript.c\
diff --git a/client/cmddata.c b/client/cmddata.c
index c7fdc91e..9854ccfa 100644
--- a/client/cmddata.c
+++ b/client/cmddata.c
@@ -8,23 +8,22 @@
 // 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 <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 "crc.h"      // for pyramid checksum maxim
+#include "crc16.h"    // for FDXB demod checksum
+#include "loclass/cipherutils.h" // for decimating samples in getsamples
 
 uint8_t DemodBuffer[MAX_DEMOD_BUF_LEN];
 uint8_t g_debugMode=0;
@@ -592,7 +591,7 @@ int Cmdaskbiphdemod(const char *Cmd)
 int CmdG_Prox_II_Demod(const char *Cmd)
 {
 	if (!ASKbiphaseDemod(Cmd, FALSE)){
-		if (g_debugMode) PrintAndLog("ASKbiphaseDemod failed 1st try");
+		if (g_debugMode) PrintAndLog("Error gProxII: ASKbiphaseDemod failed 1st try");
 		return 0;
 	}
 	size_t size = DemodBufferLen;
@@ -602,46 +601,32 @@ int CmdG_Prox_II_Demod(const char *Cmd)
 		if (g_debugMode) PrintAndLog("Error gProxII_Demod");
 		return 0;
 	}
-	//got a good demod
-	uint32_t ByteStream[65] = {0x00};
+	//got a good demod of 96 bits
+	uint8_t ByteStream[8] = {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: %u, pos: %u", (unsigned int)DemodBuffer[startIdx+idx],(unsigned int)(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", (unsigned int)xorKey);
-			continue;
-		}
-		//lsb first
-		ByteStream[ByteCnt] = ByteStream[ByteCnt] | (DemodBuffer[startIdx+idx]<<bitCnt);
-		bitCnt++;
-		if (bitCnt % 8 == 0){
-			if (g_debugMode) PrintAndLog("byte %u: %02x", (unsigned int)ByteCnt, ByteStream[ByteCnt]);
-			bitCnt=0;
-			ByteCnt++;
-		}
+	size_t startIdx = ans + 6; //start after 6 bit preamble
+
+	uint8_t bits_no_spacer[90];
+	//so as to not mess with raw DemodBuffer copy to a new sample array
+	memcpy(bits_no_spacer, DemodBuffer + startIdx, 90);
+	// remove the 18 (90/5=18) parity bits (down to 72 bits (96-6-18=72))
+	size_t bitLen = removeParity(bits_no_spacer, 0, 5, 3, 90); //source, startloc, paritylen, ptype, length_to_run
+	if (bitLen != 72) {
+		if (g_debugMode) PrintAndLog("Error gProxII: spacer removal did not produce 72 bits: %u, start: %u", bitLen, startIdx);
+		return 0;
 	}
-	for (uint8_t i = 0; i < ByteCnt; i++){
-		ByteStream[i] ^= xorKey; //xor
-		if (g_debugMode) PrintAndLog("byte %u after xor: %02x", (unsigned int)i, ByteStream[i]);
+	// get key and then get all 8 bytes of payload decoded
+	xorKey = (uint8_t)bytebits_to_byteLSBF(bits_no_spacer, 8);
+	for (size_t idx = 0; idx < 8; idx++) {
+		ByteStream[idx] = ((uint8_t)bytebits_to_byteLSBF(bits_no_spacer+8 + (idx*8),8)) ^ xorKey;
+		if (g_debugMode) PrintAndLog("byte %u after xor: %02x", (unsigned int)idx, ByteStream[idx]);
 	}
-	//now ByteStream contains 64 bytes of decrypted raw tag data
+	//now ByteStream contains 8 Bytes (64 bits) of decrypted raw tag data
 	// 
 	uint8_t fmtLen = ByteStream[0]>>2;
 	uint32_t FC = 0;
 	uint32_t Card = 0;
+	//get raw 96 bits to print
 	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);
@@ -649,13 +634,14 @@ int CmdG_Prox_II_Demod(const char *Cmd)
 	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);
+		PrintAndLog("G-Prox-II Found: FmtLen %d, FC %u, Card %u", (int)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",(unsigned int)fmtLen,FC,Card);
+		PrintAndLog("G-Prox-II Found: FmtLen %d, FC %u, Card %u", (int)fmtLen, FC, Card);
 	} else {
 		PrintAndLog("Unknown G-Prox-II Fmt Found: FmtLen %d",(int)fmtLen);
+		PrintAndLog("Decoded Raw: %s", sprint_hex(ByteStream, 8)); 
 	}
 	PrintAndLog("Raw: %08x%08x%08x", raw1,raw2,raw3);
 	setDemodBuf(DemodBuffer+ans, 96, 0);
@@ -848,16 +834,18 @@ int CmdUndec(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;
@@ -1276,7 +1264,7 @@ int CmdFSKdemodAWID(const char *Cmd)
 	//get binary from fsk wave
 	int idx = AWIDdemodFSK(BitStream, &size);
 	if (idx<=0){
-		if (g_debugMode==1){
+		if (g_debugMode){
 			if (idx == -1)
 				PrintAndLog("DEBUG: Error - not enough samples");
 			else if (idx == -2)
@@ -1314,7 +1302,7 @@ int CmdFSKdemodAWID(const char *Cmd)
 
 	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");
+		if (g_debugMode) PrintAndLog("DEBUG: Error - at parity check-tag size does not match AWID format");
 		return 0;
 	}
 	// ok valid card found!
@@ -1374,7 +1362,7 @@ int CmdFSKdemodPyramid(const char *Cmd)
 	//get binary from fsk wave
 	int idx = PyramiddemodFSK(BitStream, &size);
 	if (idx < 0){
-		if (g_debugMode==1){
+		if (g_debugMode){
 			if (idx == -5)
 				PrintAndLog("DEBUG: Error - not enough samples");
 			else if (idx == -1)
@@ -1430,7 +1418,7 @@ int CmdFSKdemodPyramid(const char *Cmd)
 
 	size = removeParity(BitStream, idx+8, 8, 1, 120);
 	if (size != 105){
-		if (g_debugMode==1) 
+		if (g_debugMode) 
 			PrintAndLog("DEBUG: Error at parity check - tag size does not match Pyramid format, SIZE: %d, IDX: %d, hi3: %x",size, idx, rawHi3);
 		return 0;
 	}
@@ -1653,21 +1641,21 @@ int CmdIndalaDecode(const char *Cmd)
 	}
 
 	if (!ans){
-		if (g_debugMode==1) 
+		if (g_debugMode) 
 			PrintAndLog("Error1: %d",ans);
 		return 0;
 	}
 	uint8_t invert=0;
 	size_t size = DemodBufferLen;
-	size_t startIdx = indala26decode(DemodBuffer, &size, &invert);
-	if (startIdx < 1 || size > 224) {
-		if (g_debugMode==1)
+	int startIdx = indala26decode(DemodBuffer, &size, &invert);
+	if (startIdx < 0 || size > 224) {
+		if (g_debugMode)
 			PrintAndLog("Error2: %d",ans);
 		return -1;
 	}
-	setDemodBuf(DemodBuffer, size, startIdx);
+	setDemodBuf(DemodBuffer, size, (size_t)startIdx);
 	if (invert)
-		if (g_debugMode==1)
+		if (g_debugMode)
 			PrintAndLog("Had to invert bits");
 
 	PrintAndLog("BitLen: %d",DemodBufferLen);
@@ -2334,9 +2322,8 @@ int Cmdbin2hex(const char *Cmd)
 	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;
 
diff --git a/client/cmddata.h b/client/cmddata.h
index 20bdbd2b..9b9f2da9 100644
--- a/client/cmddata.h
+++ b/client/cmddata.h
@@ -11,6 +11,12 @@
 #ifndef CMDDATA_H__
 #define CMDDATA_H__
 
+#include <stdlib.h>  //size_t
+#include <stdint.h>  //uint_32+
+#include <stdbool.h> //bool
+
+#include "cmdparser.h" // for command_t
+
 command_t * CmdDataCommands();
 
 int CmdData(const char *Cmd);
diff --git a/client/cmdlf.c b/client/cmdlf.c
index 34e0c1c7..016f0fe2 100644
--- a/client/cmdlf.c
+++ b/client/cmdlf.c
@@ -13,24 +13,26 @@
 #include <string.h>
 #include <limits.h>
 #include "proxmark3.h"
-#include "data.h"
-#include "graph.h"
-#include "ui.h"
-#include "cmdparser.h"
-#include "cmdmain.h"
-#include "cmddata.h"
-#include "util.h"
 #include "cmdlf.h"
-#include "cmdlfhid.h"
-#include "cmdlfawid.h"
-#include "cmdlfti.h"
-#include "cmdlfem4x.h"
-#include "cmdlfhitag.h"
-#include "cmdlft55xx.h"
-#include "cmdlfpcf7931.h"
-#include "cmdlfio.h"
-#include "cmdlfviking.h"
-#include "lfdemod.h"
+#include "lfdemod.h"     // for psk2TOpsk1
+#include "util.h"        // for parsing cli command utils
+#include "ui.h"          // for show graph controls
+#include "graph.h"       // for graph data
+#include "cmdparser.h"   // for getting cli commands included in cmdmain.h
+#include "cmdmain.h"     // for sending cmds to device
+#include "data.h"        // for GetFromBigBuf
+#include "cmddata.h"     // for `lf search`
+#include "cmdlfawid.h"   // for awid menu
+#include "cmdlfem4x.h"   // for em4x menu
+#include "cmdlfhid.h"    // for hid menu
+#include "cmdlfhitag.h"  // for hitag menu
+#include "cmdlfio.h"     // for ioprox menu
+#include "cmdlft55xx.h"  // for t55xx menu
+#include "cmdlfti.h"     // for ti menu
+#include "cmdlfpresco.h" // for presco menu
+#include "cmdlfpcf7931.h"// for pcf7931 menu
+#include "cmdlfpyramid.h"// for pyramid menu
+#include "cmdlfviking.h" // for viking menu
 
 static int CmdHelp(const char *Cmd);
 
@@ -538,7 +540,7 @@ int CmdLFSetConfig(const char *Cmd)
 		return usage_lf_config();
 	}
 	//Bps is limited to 8, so fits in lower half of arg1
-	if(bps >> 8) bps = 8;
+	if(bps >> 4) bps = 8;
 
 	sample_config config = {
 		decimation,bps,averaging,divisor,trigger_threshold
@@ -662,7 +664,7 @@ int usage_lf_simask(void)
 	PrintAndLog("       b              sim ask/biphase");
 	PrintAndLog("       m              sim ask/manchester - Default");
 	PrintAndLog("       r              sim ask/raw");
-	PrintAndLog("       s              TBD- -to enable a gap between playback repetitions - default: no gap");
+	PrintAndLog("       s              add t55xx Sequence Terminator gap - default: no gaps (only manchester)");
 	PrintAndLog("       d <hexdata>    Data to sim as hex - omit to sim from DemodBuffer");
 	return 0;
 }
@@ -1219,7 +1221,9 @@ static command_t CommandTable[] =
 	{"hid",         CmdLFHID,           1, "{ HID RFIDs...     }"},
 	{"hitag",       CmdLFHitag,         1, "{ Hitag tags and transponders... }"},
 	{"io",          CmdLFIO,            1, "{ ioProx tags...   }"},
+	{"presco",      CmdLFPresco,        1, "{ Presco RFIDs... }"},
 	{"pcf7931",     CmdLFPCF7931,       1, "{ PCF7931 RFIDs... }"},
+	{"pyramid",     CmdLFPyramid,       1, "{ Farpointe/Pyramid RFIDs... }"},
 	{"t55xx",       CmdLFT55XX,         1, "{ T55xx RFIDs...   }"},
 	{"ti",          CmdLFTI,            1, "{ TI RFIDs...      }"},
 	{"viking",      CmdLFViking,        1, "{ Viking tags...   }"},
diff --git a/client/cmdlfpresco.c b/client/cmdlfpresco.c
new file mode 100644
index 00000000..abae165d
--- /dev/null
+++ b/client/cmdlfpresco.c
@@ -0,0 +1,263 @@
+//-----------------------------------------------------------------------------
+//
+// This code is licensed to you under the terms of the GNU GPL, version 2 or,
+// at your option, any later version. See the LICENSE.txt file for the text of
+// the license.
+//-----------------------------------------------------------------------------
+// Low frequency Presco tag commands
+//-----------------------------------------------------------------------------
+#include <string.h>
+#include <inttypes.h>
+#include "cmdlfpresco.h"
+#include "proxmark3.h"
+#include "ui.h"
+#include "util.h"
+#include "graph.h"
+#include "cmdparser.h"
+#include "cmddata.h"
+#include "cmdmain.h"
+#include "cmdlf.h"
+#include "protocols.h"  // for T55xx config register definitions
+#include "lfdemod.h"    // parityTest
+
+static int CmdHelp(const char *Cmd);
+
+int usage_lf_presco_clone(void){
+	PrintAndLog("clone a Presco tag to a T55x7 tag.");
+	PrintAndLog("Usage: lf presco clone d <Card-ID> H <hex-ID> <Q5>");
+	PrintAndLog("Options :");
+	PrintAndLog("  d <Card-ID>   : 9 digit presco card ID");
+	PrintAndLog("  H <hex-ID>    : 8 digit hex card number");
+	PrintAndLog("  <Q5>          : specify write to Q5 (t5555 instead of t55x7)");
+	PrintAndLog("");
+	PrintAndLog("Sample  : lf presco clone d 123456789");
+	return 0;
+}
+
+int usage_lf_presco_sim(void) {
+	PrintAndLog("Enables simulation of presco card with specified card number.");
+	PrintAndLog("Simulation runs until the button is pressed or another USB command is issued.");
+	PrintAndLog("Per presco format, the card number is 9 digit number and can contain *# chars. Larger values are truncated.");
+	PrintAndLog("");
+	PrintAndLog("Usage:  lf presco sim d <Card-ID> or H <hex-ID>");
+	PrintAndLog("Options :");
+	PrintAndLog("  d <Card-ID>   : 9 digit presco card number");
+	PrintAndLog("  H <hex-ID>    : 8 digit hex card number");
+	PrintAndLog("");
+	PrintAndLog("Sample  : lf presco sim d 123456789");
+	return 0;
+}
+
+// convert base 12 ID to sitecode & usercode & 8 bit other unknown code
+int GetWiegandFromPresco(const char *Cmd, uint32_t *sitecode, uint32_t *usercode, uint32_t *fullcode, bool *Q5) {
+
+	uint8_t val = 0;
+	bool hex = false, errors = false;
+	uint8_t cmdp = 0;
+	char id[11];
+	int stringlen = 0;
+	while(param_getchar(Cmd, cmdp) != 0x00) {
+		switch(param_getchar(Cmd, cmdp)) {
+			case 'h':
+				return -1;
+			case 'H':
+				hex = true;
+				//get hex
+				*fullcode = param_get32ex(Cmd, cmdp+1, 0, 10);
+				cmdp+=2;
+				break;
+			case 'P':
+			case 'p':
+				//param get string int param_getstr(const char *line, int paramnum, char * str)
+				stringlen = param_getstr(Cmd, cmdp+1, id);
+				if (stringlen < 2) return -1;
+				cmdp+=2;
+				break;
+			case 'Q':
+			case 'q':
+				*Q5 = true;
+				cmdp++;
+				break;
+			default:
+				PrintAndLog("Unknown parameter '%c'", param_getchar(Cmd, cmdp));
+				errors = 1;
+				break;
+		}
+		if(errors) break;
+	}
+	// No args
+	if(cmdp == 0) errors = 1;
+
+	//Validations
+	if(errors) return -1;
+
+	if (!hex) {
+		for (int index =0; index < strlen(id); ++index) {
+			// Get value from number string.
+			if ( id[index] == '*' ) val = 10;
+			if ( id[index] == '#')	val = 11;		
+			if ( id[index] >= 0x30 && id[index] <= 0x39 )
+				val = id[index] - 0x30;
+			
+			*fullcode += val;
+			
+			// last digit is only added, not multipled.
+			if ( index < strlen(id)-1 ) 
+				*fullcode *= 12;
+		}
+	}
+
+	*usercode = *fullcode & 0x0000FFFF; //% 65566
+	*sitecode = (*fullcode >> 24) & 0x000000FF;  // /= 16777216;
+	return 0;
+}
+
+// calc not certain - intended to get bitstream for programming / sim
+int GetPrescoBits(uint32_t fullcode, uint8_t *prescoBits) {
+	num_to_bytebits(0x10D00000, 32, prescoBits);
+	num_to_bytebits(0x00000000, 32, prescoBits+32);
+	num_to_bytebits(0x00000000, 32, prescoBits+64);
+	num_to_bytebits(fullcode  , 32, prescoBits+96);
+	return 1;
+}
+
+//see ASKDemod for what args are accepted
+int CmdPrescoDemod(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 Viking
+	int ans = PrescoDemod(DemodBuffer, &size);
+	if (ans < 0) {
+		if (g_debugMode) PrintAndLog("Error Presco_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 raw3 = bytebits_to_byte(DemodBuffer+ans+64, 32);
+	uint32_t raw4 = bytebits_to_byte(DemodBuffer+ans+96, 32);
+	uint32_t cardid = raw4;
+	PrintAndLog("Presco Tag Found: Card ID %08X", cardid);
+	PrintAndLog("Raw: %08X%08X%08X%08X", raw1,raw2,raw3,raw4);
+	setDemodBuf(DemodBuffer+ans, 128, 0);
+	
+	uint32_t sitecode = 0, usercode = 0, fullcode = 0;
+	bool Q5=false;
+	char cmd[12] = {0};
+	sprintf(cmd, "H %08X", cardid);
+	GetWiegandFromPresco(cmd, &sitecode, &usercode, &fullcode, &Q5);
+	PrintAndLog("SiteCode %u, UserCode %u, FullCode, %08X", sitecode, usercode, fullcode);
+
+	return 1;
+}
+
+//see ASKDemod for what args are accepted
+int CmdPrescoRead(const char *Cmd) {
+	// Presco Number: 123456789 --> Sitecode 30 | usercode 8665
+
+	// read lf silently
+	CmdLFRead("s");
+	// get samples silently
+	getSamples("30000",false);
+	// demod and output Presco ID	
+	return CmdPrescoDemod(Cmd);
+}
+
+// takes base 12 ID converts to hex
+// Or takes 8 digit hex ID
+int CmdPrescoClone(const char *Cmd) {
+
+	bool Q5 = false;
+	uint32_t sitecode=0, usercode=0, fullcode=0;
+	uint32_t blocks[5] = {T55x7_MODULATION_MANCHESTER | T55x7_BITRATE_RF_32 | 4<<T55x7_MAXBLOCK_SHIFT | T55x7_ST_TERMINATOR, 0, 0, 0, 5};
+	
+	// get wiegand from printed number.
+	if (GetWiegandFromPresco(Cmd, &sitecode, &usercode, &fullcode, &Q5) == -1) return usage_lf_presco_clone();
+
+	if (Q5)
+		blocks[0] = T5555_MODULATION_MANCHESTER | 32<<T5555_BITRATE_SHIFT | 4<<T5555_MAXBLOCK_SHIFT | T5555_ST_TERMINATOR;
+
+	if ((sitecode & 0xFF) != sitecode) {
+		sitecode &= 0xFF;
+		PrintAndLog("Facility-Code Truncated to 8-bits (Presco): %u", sitecode);
+	}
+
+	if ((usercode & 0xFFFF) != usercode) {
+		usercode &= 0xFFFF;
+		PrintAndLog("Card Number Truncated to 16-bits (Presco): %u", usercode);
+	}
+	
+	blocks[1] = 0x10D00000; //preamble
+	blocks[2] = 0x00000000;
+	blocks[3] = 0x00000000;
+	blocks[4] = fullcode;
+
+	PrintAndLog("Preparing to clone Presco to T55x7 with SiteCode: %u, UserCode: %u, FullCode: %08x", sitecode, usercode, fullcode);
+	PrintAndLog("Blk | Data ");
+	PrintAndLog("----+------------");
+	PrintAndLog(" 00 | 0x%08x", blocks[0]);
+	PrintAndLog(" 01 | 0x%08x", blocks[1]);
+	PrintAndLog(" 02 | 0x%08x", blocks[2]);
+	PrintAndLog(" 03 | 0x%08x", blocks[3]);	
+	PrintAndLog(" 04 | 0x%08x", blocks[4]);	
+
+	UsbCommand resp;
+	UsbCommand c = {CMD_T55XX_WRITE_BLOCK, {0,0,0}};
+
+	for (int i=4; i>=0; i--) {
+		c.arg[0] = blocks[i];
+		c.arg[1] = i;
+		clearCommandBuffer();
+		SendCommand(&c);
+		if (!WaitForResponseTimeout(CMD_ACK, &resp, 1000)){
+			PrintAndLog("Error occurred, device did not respond during write operation.");
+			return -1;
+		}
+	}
+	return 0;
+}
+
+// takes base 12 ID converts to hex
+// Or takes 8 digit hex ID
+int CmdPrescoSim(const char *Cmd) {
+	uint32_t sitecode=0, usercode=0, fullcode=0;
+	bool Q5=false;
+	// get wiegand from printed number.
+	if (GetWiegandFromPresco(Cmd, &sitecode, &usercode, &fullcode, &Q5) == -1) return usage_lf_presco_sim();
+
+	uint8_t clk = 32, encoding = 1, separator = 1, invert = 0;
+	uint16_t arg1, arg2;
+	size_t size = 128;
+	arg1 = clk << 8 | encoding;
+	arg2 = invert << 8 | separator;
+
+	PrintAndLog("Simulating Presco - SiteCode: %u, UserCode: %u, FullCode: %08X",sitecode, usercode, fullcode);
+
+	UsbCommand c = {CMD_ASK_SIM_TAG, {arg1, arg2, size}};
+	GetPrescoBits(fullcode, c.d.asBytes);
+	clearCommandBuffer();
+	SendCommand(&c);
+	return 0;
+}
+
+static command_t CommandTable[] = {
+	{"help",  CmdHelp,        1, "This help"},
+	{"read",  CmdPrescoRead,  0, "Attempt to read and Extract tag data"},
+	{"clone", CmdPrescoClone, 0, "d <9 digit ID> or h <hex> [Q5] clone presco tag"},
+	{"sim",   CmdPrescoSim,   0, "d <9 digit ID> or h <hex> simulate presco tag"},
+	{NULL, NULL, 0, NULL}
+};
+
+int CmdLFPresco(const char *Cmd) {
+	clearCommandBuffer();
+    CmdsParse(CommandTable, Cmd);
+    return 0;
+}
+
+int CmdHelp(const char *Cmd) {
+    CmdsHelp(CommandTable);
+    return 0;
+}
diff --git a/client/cmdlfpresco.h b/client/cmdlfpresco.h
new file mode 100644
index 00000000..801df8a9
--- /dev/null
+++ b/client/cmdlfpresco.h
@@ -0,0 +1,24 @@
+//-----------------------------------------------------------------------------
+//
+// This code is licensed to you under the terms of the GNU GPL, version 2 or,
+// at your option, any later version. See the LICENSE.txt file for the text of
+// the license.
+//-----------------------------------------------------------------------------
+// Low frequency T55xx commands
+//-----------------------------------------------------------------------------
+#ifndef CMDLFPRESCO_H__
+#define CMDLFPRESCO_H__
+
+#include <stdint.h>  //uint_32+
+#include <stdbool.h> //bool
+
+int CmdLFPresco(const char *Cmd);
+int CmdPrescoClone(const char *Cmd);
+int CmdPrescoSim(const char *Cmd);
+
+int GetWiegandFromPresco(const char *id, uint32_t *sitecode, uint32_t *usercode, uint32_t *fullcode, bool *Q5);
+
+int usage_lf_presco_clone(void);
+int usage_lf_presco_sim(void);
+#endif
+
diff --git a/client/cmdlfpyramid.c b/client/cmdlfpyramid.c
new file mode 100644
index 00000000..7c19fbdb
--- /dev/null
+++ b/client/cmdlfpyramid.c
@@ -0,0 +1,199 @@
+//-----------------------------------------------------------------------------
+//
+// This code is licensed to you under the terms of the GNU GPL, version 2 or,
+// at your option, any later version. See the LICENSE.txt file for the text of
+// the license.
+//-----------------------------------------------------------------------------
+// Low frequency Farpoint / Pyramid tag commands
+//-----------------------------------------------------------------------------
+#include <string.h>
+#include <inttypes.h>
+#include "cmdlfpyramid.h"
+#include "proxmark3.h"
+#include "ui.h"
+#include "util.h"
+#include "graph.h"
+#include "cmdparser.h"
+#include "cmddata.h"
+#include "cmdmain.h"
+#include "cmdlf.h"
+#include "protocols.h"  // for T55xx config register definitions
+#include "lfdemod.h"    // parityTest
+#include "crc.h"
+
+static int CmdHelp(const char *Cmd);
+
+int usage_lf_pyramid_clone(void){
+	PrintAndLog("clone a Farpointe/Pyramid tag to a T55x7 tag.");
+	PrintAndLog("The facility-code is 8-bit and the card number is 16-bit.  Larger values are truncated. ");
+	PrintAndLog("Currently work only on 26bit");
+	PrintAndLog("");
+	PrintAndLog("Usage: lf pyramid clone <Facility-Code> <Card-Number>");
+	PrintAndLog("Options :");
+	PrintAndLog("  <Facility-Code> :  8-bit value facility code");
+	PrintAndLog("  <Card Number>   : 16-bit value card number");
+	PrintAndLog("  Q5              : optional - clone to Q5 (T5555) instead of T55x7 chip");
+	PrintAndLog("");
+	PrintAndLog("Sample  : lf pyramid clone 123 11223");
+	return 0;
+}
+
+int usage_lf_pyramid_sim(void) {
+	PrintAndLog("Enables simulation of Farpointe/Pyramid card with specified card number.");
+	PrintAndLog("Simulation runs until the button is pressed or another USB command is issued.");
+	PrintAndLog("The facility-code is 8-bit and the card number is 16-bit.  Larger values are truncated.");
+	PrintAndLog("Currently work only on 26bit");
+	PrintAndLog("");
+	PrintAndLog("Usage:  lf pyramid sim <Card-Number>");
+	PrintAndLog("Options :");
+	PrintAndLog("  <Facility-Code> :  8-bit value facility code");
+	PrintAndLog("  <Card Number>   : 16-bit value card number");
+	PrintAndLog("");
+	PrintAndLog("Sample  : lf pyramid sim 123 11223");
+	return 0;
+}
+
+// Works for 26bits.
+int GetPyramidBits(uint32_t fc, uint32_t cn, uint8_t *pyramidBits) {
+
+	uint8_t pre[128];
+	memset(pre, 0x00, sizeof(pre));
+
+	// format start bit
+	pre[79] = 1;
+	
+	// Get 26 wiegand from FacilityCode, CardNumber	
+	uint8_t wiegand[24];
+	memset(wiegand, 0x00, sizeof(wiegand));
+	num_to_bytebits(fc, 8, wiegand);
+	num_to_bytebits(cn, 16, wiegand+8);
+
+	// add wiegand parity bits (dest, source, len)
+	wiegand_add_parity(pre+80, wiegand, 24);
+	
+	// add paritybits	(bitsource, dest, sourcelen, paritylen, parityType (odd, even,)
+	addParity(pre+8, pyramidBits+8, 102, 8, 1);
+
+	// add checksum		
+	uint8_t csBuff[13];
+	for (uint8_t i = 0; i < 13; i++)
+		csBuff[i] = bytebits_to_byte(pyramidBits + 16 + (i*8), 8);
+
+	uint32_t crc = CRC8Maxim(csBuff, 13);
+	num_to_bytebits(crc, 8, pyramidBits+120);
+	return 1;
+}
+
+int CmdPyramidRead(const char *Cmd) {
+	CmdLFRead("s");
+	getSamples("30000",false);
+	return CmdFSKdemodPyramid("");
+}
+
+int CmdPyramidClone(const char *Cmd) {
+
+	char cmdp = param_getchar(Cmd, 0);
+	if (strlen(Cmd) == 0 || cmdp == 'h' || cmdp == 'H') return usage_lf_pyramid_clone();
+
+	uint32_t facilitycode=0, cardnumber=0, fc = 0, cn = 0;
+	uint32_t blocks[5];
+	uint8_t i;
+	uint8_t bs[128];
+	memset(bs, 0x00, sizeof(bs));
+
+	if (sscanf(Cmd, "%u %u", &fc, &cn ) != 2) return usage_lf_pyramid_clone();
+
+	facilitycode = (fc & 0x000000FF);
+	cardnumber = (cn & 0x0000FFFF);
+	
+	if ( !GetPyramidBits(facilitycode, cardnumber, bs)) {
+		PrintAndLog("Error with tag bitstream generation.");
+		return 1;
+	}
+
+	//Pyramid - compat mode, FSK2a, data rate 50, 4 data blocks
+	blocks[0] = T55x7_MODULATION_FSK2a | T55x7_BITRATE_RF_50 | 4<<T55x7_MAXBLOCK_SHIFT;
+
+	if (param_getchar(Cmd, 3) == 'Q' || param_getchar(Cmd, 3) == 'q')
+		blocks[0] = T5555_MODULATION_FSK2 | T5555_INVERT_OUTPUT | 50<<T5555_BITRATE_SHIFT | 4<<T5555_MAXBLOCK_SHIFT;
+
+	blocks[1] = bytebits_to_byte(bs,32);
+	blocks[2] = bytebits_to_byte(bs+32,32);
+	blocks[3] = bytebits_to_byte(bs+64,32);
+	blocks[4] = bytebits_to_byte(bs+96,32);
+
+	PrintAndLog("Preparing to clone Farpointe/Pyramid to T55x7 with Facility Code: %u, Card Number: %u", facilitycode, cardnumber);
+	PrintAndLog("Blk | Data ");
+	PrintAndLog("----+------------");
+	for ( i = 0; i<5; ++i )
+		PrintAndLog(" %02d | %08" PRIx32, i, blocks[i]);
+
+	UsbCommand resp;
+	UsbCommand c = {CMD_T55XX_WRITE_BLOCK, {0,0,0}};
+
+	for ( i = 0; i<5; ++i ) {
+		c.arg[0] = blocks[i];
+		c.arg[1] = i;
+		clearCommandBuffer();
+		SendCommand(&c);
+		if (!WaitForResponseTimeout(CMD_ACK, &resp, 1000)){
+			PrintAndLog("Error occurred, device did not respond during write operation.");
+			return -1;
+		}
+	}
+	return 0;
+}
+
+int CmdPyramidSim(const char *Cmd) {
+
+	char cmdp = param_getchar(Cmd, 0);
+	if (strlen(Cmd) == 0 || cmdp == 'h' || cmdp == 'H') return usage_lf_pyramid_sim();
+
+	uint32_t facilitycode = 0, cardnumber = 0, fc = 0, cn = 0;
+
+	uint8_t bs[128];
+	size_t size = sizeof(bs);
+	memset(bs, 0x00, size);
+
+	// Pyramid uses:  fcHigh: 10, fcLow: 8, clk: 50, invert: 0
+	uint64_t arg1, arg2;
+	arg1 = (10 << 8) + 8;
+	arg2 = 50 | 0;
+
+	if (sscanf(Cmd, "%u %u", &fc, &cn ) != 2) return usage_lf_pyramid_sim();
+
+	facilitycode = (fc & 0x000000FF);
+	cardnumber = (cn & 0x0000FFFF);
+
+	if ( !GetPyramidBits(facilitycode, cardnumber, bs)) {
+		PrintAndLog("Error with tag bitstream generation.");
+		return 1;
+	}
+
+	PrintAndLog("Simulating Farpointe/Pyramid - Facility Code: %u, CardNumber: %u", facilitycode, cardnumber );
+
+	UsbCommand c = {CMD_FSK_SIM_TAG, {arg1, arg2, size}};
+	memcpy(c.d.asBytes, bs, size);
+	clearCommandBuffer();
+	SendCommand(&c);
+	return 0;
+}
+
+static command_t CommandTable[] = {
+	{"help",  CmdHelp,         1, "This help"},
+	{"read",  CmdPyramidRead,  0, "Attempt to read and extract tag data"},
+	{"clone", CmdPyramidClone, 0, "<Facility-Code> <Card Number>  clone pyramid tag"},
+	{"sim",   CmdPyramidSim,   0, "<Facility-Code> <Card Number>  simulate pyramid tag"},
+	{NULL, NULL, 0, NULL}
+};
+
+int CmdLFPyramid(const char *Cmd) {
+	clearCommandBuffer();
+	CmdsParse(CommandTable, Cmd);
+	return 0;
+}
+
+int CmdHelp(const char *Cmd) {
+	CmdsHelp(CommandTable);
+	return 0;
+}
diff --git a/client/cmdlfpyramid.h b/client/cmdlfpyramid.h
new file mode 100644
index 00000000..73e8338a
--- /dev/null
+++ b/client/cmdlfpyramid.h
@@ -0,0 +1,19 @@
+//-----------------------------------------------------------------------------
+//
+// This code is licensed to you under the terms of the GNU GPL, version 2 or,
+// at your option, any later version. See the LICENSE.txt file for the text of
+// the license.
+//-----------------------------------------------------------------------------
+// Low frequency T55xx commands
+//-----------------------------------------------------------------------------
+#ifndef CMDLFPYRAMID_H__
+#define CMDLFPYRAMID_H__
+
+int CmdLFPyramid(const char *Cmd);
+int CmdPyramidClone(const char *Cmd);
+int CmdPyramidSim(const char *Cmd);
+
+int usage_lf_pyramid_clone(void);
+int usage_lf_pyramid_sim(void);
+#endif
+
diff --git a/client/cmdlft55xx.c b/client/cmdlft55xx.c
index 7d954353..9e4883c7 100644
--- a/client/cmdlft55xx.c
+++ b/client/cmdlft55xx.c
@@ -76,7 +76,7 @@ int usage_t55xx_read(){
 	return 0;
 }
 int usage_t55xx_write(){
-	PrintAndLog("Usage:  lf t55xx wr [b <block>] [d <data>] [p <password>] [1]");
+	PrintAndLog("Usage:  lf t55xx write [b <block>] [d <data>] [p <password>] [1]");
 	PrintAndLog("Options:");
 	PrintAndLog("     b <block>    - block number to write. Between 0-7");
 	PrintAndLog("     d <data>     - 4 bytes of data to write (8 hex characters)");
@@ -84,8 +84,8 @@ int usage_t55xx_write(){
 	PrintAndLog("     1            - OPTIONAL write Page 1 instead of Page 0");
 	PrintAndLog("");
 	PrintAndLog("Examples:");
-	PrintAndLog("      lf t55xx wr b 3 d 11223344            - write 11223344 to block 3");
-	PrintAndLog("      lf t55xx wr b 3 d 11223344 p feedbeef - write 11223344 to block 3 password feedbeef");
+	PrintAndLog("      lf t55xx write b 3 d 11223344            - write 11223344 to block 3");
+	PrintAndLog("      lf t55xx write b 3 d 11223344 p feedbeef - write 11223344 to block 3 password feedbeef");
 	PrintAndLog("");
 	return 0;
 }
diff --git a/client/proxgui.h b/client/proxgui.h
index 6fcf4d0a..94b47acd 100644
--- a/client/proxgui.h
+++ b/client/proxgui.h
@@ -19,7 +19,7 @@ void MainGraphics(void);
 void InitGraphics(int argc, char **argv);
 void ExitGraphics(void);
 
-#define MAX_GRAPH_TRACE_LEN (1024*128)
+#define MAX_GRAPH_TRACE_LEN (40000*8)
 extern int GraphBuffer[MAX_GRAPH_TRACE_LEN];
 extern int GraphTraceLen;
 extern double CursorScaleFactor;
diff --git a/client/util.h b/client/util.h
index 5674adcf..34e821bf 100644
--- a/client/util.h
+++ b/client/util.h
@@ -9,13 +9,12 @@
 //-----------------------------------------------------------------------------
 
 #include <stdio.h>
-#include <stdint.h>
-#include <stdio.h>
+#include <stdint.h>  //included in data.h
 #include <stdlib.h>
 #include <string.h>
 #include <ctype.h>
 #include <time.h>
-#include "data.h"
+#include "data.h"    //for FILE_PATH_SIZE
 
 #ifndef ROTR
 # define ROTR(x,n) (((uintmax_t)(x) >> (n)) | ((uintmax_t)(x) << ((sizeof(x) * 8) - (n))))
diff --git a/common/lfdemod.c b/common/lfdemod.c
index 7398f1b2..cf11b25b 100644
--- a/common/lfdemod.c
+++ b/common/lfdemod.c
@@ -68,7 +68,7 @@ uint8_t parityTest(uint32_t bits, uint8_t bitLen, uint8_t pType)
 
 // by marshmellow
 // takes a array of binary values, start position, length of bits per parity (includes parity bit),
-//   Parity Type (1 for odd; 0 for even; 2 Always 1's), and binary Length (length to run) 
+//   Parity Type (1 for odd; 0 for even; 2 for Always 1's; 3 for Always 0's), and binary Length (length to run) 
 size_t removeParity(uint8_t *BitStream, size_t startIdx, uint8_t pLen, uint8_t pType, size_t bLen)
 {
 	uint32_t parityWd = 0;
@@ -80,10 +80,11 @@ size_t removeParity(uint8_t *BitStream, size_t startIdx, uint8_t pLen, uint8_t p
 		}
 		j--; // overwrite parity with next data
 		// if parity fails then return 0
-		if (pType == 2) { // then marker bit which should be a 1
-			if (!BitStream[j]) return 0;
-		} else {
-			if (parityTest(parityWd, pLen, pType) == 0) return 0;			
+		switch (pType) {
+			case 3: if (BitStream[j]==1) return 0; break; //should be 0 spacer bit
+			case 2: if (BitStream[j]==0) return 0; break; //should be 1 spacer bit
+			default: //test parity
+				if (parityTest(parityWd, pLen, pType) == 0) return 0; break;
 		}
 		bitCnt+=(pLen-1);
 		parityWd = 0;
@@ -95,7 +96,8 @@ size_t removeParity(uint8_t *BitStream, size_t startIdx, uint8_t pLen, uint8_t p
 
 // by marshmellow
 // takes a array of binary values, length of bits per parity (includes parity bit),
-//   Parity Type (1 for odd; 0 for even; 2 Always 1's), and binary Length (length to run)
+//   Parity Type (1 for odd; 0 for even; 2 Always 1's; 3 Always 0's), and binary Length (length to run)
+//   Make sure *dest is long enough to store original sourceLen + #_of_parities_to_be_added
 size_t addParity(uint8_t *BitSource, uint8_t *dest, uint8_t sourceLen, uint8_t pLen, uint8_t pType)
 {
 	uint32_t parityWd = 0;
@@ -106,10 +108,12 @@ size_t addParity(uint8_t *BitSource, uint8_t *dest, uint8_t sourceLen, uint8_t p
 			dest[j++] = (BitSource[word+bit]);
 		}
 		// if parity fails then return 0
-		if (pType == 2) { // then marker bit which should be a 1
-			dest[j++]=1;
-		} else {
-			dest[j++] = parityTest(parityWd, pLen-1, pType) ^ 1;
+		switch (pType) {
+			case 3: dest[j++]=0; break; // marker bit which should be a 0
+			case 2: dest[j++]=1; break; // marker bit which should be a 1
+			default: 
+				dest[j++] = parityTest(parityWd, pLen-1, pType) ^ 1;
+				break;
 		}
 		bitCnt += pLen;
 		parityWd = 0;
@@ -258,9 +262,9 @@ void askAmp(uint8_t *BitStream, size_t size)
 {
 	for(size_t i = 1; i<size; i++){
 		if (BitStream[i]-BitStream[i-1]>=30) //large jump up
-			BitStream[i]=127;
+			BitStream[i]=255;
 		else if(BitStream[i]-BitStream[i-1]<=-20) //large jump down
-			BitStream[i]=-127;
+			BitStream[i]=0;
 	}
 	return;
 }
@@ -460,10 +464,10 @@ int gProxII_Demod(uint8_t BitStream[], size_t *size)
 		//return start position
 		return (int) startIdx;
 	}
-	return -5;
+	return -5; //spacer bits not found - not a valid gproxII
 }
 
-//translate wave to 11111100000 (1 for each short wave 0 for each long wave)
+//translate wave to 11111100000 (1 for each short wave [higher freq] 0 for each long wave [lower freq])
 size_t fsk_wave_demod(uint8_t * dest, size_t size, uint8_t fchigh, uint8_t fclow)
 {
 	size_t last_transition = 0;
@@ -487,6 +491,7 @@ size_t fsk_wave_demod(uint8_t * dest, size_t size, uint8_t fchigh, uint8_t fclow
 	// count cycles between consecutive lo-hi transitions, there should be either 8 (fc/8)
 	// or 10 (fc/10) cycles but in practice due to noise etc we may end up with anywhere
 	// between 7 to 11 cycles so fuzz it by treat anything <9 as 8 and anything else as 10
+	//  (could also be fc/5 && fc/7 for fsk1 = 4-9)
 	for(idx = 161; idx < size-20; idx++) {
 		// threshold current value
 
@@ -494,23 +499,24 @@ size_t fsk_wave_demod(uint8_t * dest, size_t size, uint8_t fchigh, uint8_t fclow
 		else dest[idx] = 1;
 
 		// Check for 0->1 transition
-		if (dest[idx-1] < dest[idx]) { // 0 -> 1 transition
+		if (dest[idx-1] < dest[idx]) {
 			preLastSample = LastSample;
 			LastSample = currSample;
 			currSample = idx-last_transition;
-			if (currSample < (fclow-2)){            //0-5 = garbage noise (or 0-3)
+			if (currSample < (fclow-2)) {                   //0-5 = garbage noise (or 0-3)
 				//do nothing with extra garbage
-			} else if (currSample < (fchigh-1)) { //6-8 = 8 sample waves  or 3-6 = 5
+			} else if (currSample < (fchigh-1)) {           //6-8 = 8 sample waves  (or 3-6 = 5)
+				//correct previous 9 wave surrounded by 8 waves (or 6 surrounded by 5)
 				if (LastSample > (fchigh-2) && (preLastSample < (fchigh-1) || preLastSample	== 0 )){
-					dest[numBits-1]=1;  //correct previous 9 wave surrounded by 8 waves
+					dest[numBits-1]=1;
 				}
 				dest[numBits++]=1;
 
-			} else if (currSample > (fchigh) && !numBits) { //12 + and first bit = garbage 
+			} else if (currSample > (fchigh) && !numBits) { //12 + and first bit = unusable garbage 
 				//do nothing with beginning garbage
-			} else if (currSample == (fclow+1) && LastSample == (fclow-1)) { // had a 7 then a 9 should be two 8's
+			} else if (currSample == (fclow+1) && LastSample == (fclow-1)) { // had a 7 then a 9 should be two 8's (or 4 then a 6 should be two 5's)
 				dest[numBits++]=1;
-			} else {                                         //9+ = 10 sample waves
+			} else {                                        //9+ = 10 sample waves (or 6+ = 7)
 				dest[numBits++]=0;
 			}
 			last_transition = idx;
@@ -520,6 +526,7 @@ size_t fsk_wave_demod(uint8_t * dest, size_t size, uint8_t fchigh, uint8_t fclow
 }
 
 //translate 11111100000 to 10
+//rfLen = clock, fchigh = larger field clock, fclow = smaller field clock
 size_t aggregate_bits(uint8_t *dest, size_t size, uint8_t rfLen,
 		uint8_t invert, uint8_t fchigh, uint8_t fclow)
 {
@@ -529,8 +536,9 @@ size_t aggregate_bits(uint8_t *dest, size_t size, uint8_t rfLen,
 	uint32_t n=1;
 	for( idx=1; idx < size; idx++) {
 		n++;
-		if (dest[idx]==lastval) continue; 
+		if (dest[idx]==lastval) continue; //skip until we hit a transition
 		
+		//find out how many bits (n) we collected
 		//if lastval was 1, we have a 1->0 crossing
 		if (dest[idx-1]==1) {
 			n = (n * fclow + rfLen/2) / rfLen;
@@ -539,6 +547,7 @@ size_t aggregate_bits(uint8_t *dest, size_t size, uint8_t rfLen,
 		}
 		if (n == 0) n = 1;
 
+		//add to our destination the bits we collected		
 		memset(dest+numBits, dest[idx-1]^invert , n);
 		numBits += n;
 		n=0;
@@ -680,6 +689,19 @@ int VikingDemod_AM(uint8_t *dest, size_t *size) {
 	return (int) startIdx;
 }
 
+// find presco preamble 0x10D in already demoded data
+int PrescoDemod(uint8_t *dest, size_t *size) {
+	//make sure buffer has data
+	if (*size < 64*2) return -2;
+
+	size_t startIdx = 0;
+	uint8_t preamble[] = {1,0,0,0,0,1,1,0,1,0,0,0,0,0,0,0,0,0,0,0};
+	uint8_t errChk = preambleSearch(dest, preamble, sizeof(preamble), size, &startIdx);
+	if (errChk == 0) return -4; //preamble not found
+	//return start position
+	return (int) startIdx;
+}
+
 // Ask/Biphase Demod then try to locate an ISO 11784/85 ID
 // BitStream must contain previously askrawdemod and biphasedemoded data
 int FDXBdemodBI(uint8_t *dest, size_t *size)
@@ -1478,8 +1500,8 @@ int pskRawDemod(uint8_t dest[], size_t *size, int *clock, int *invert)
 	numBits += (firstFullWave / *clock);
 	//set start of wave as clock align
 	lastClkBit = firstFullWave;
-	//PrintAndLog("DEBUG: firstFullWave: %d, waveLen: %d",firstFullWave,fullWaveLen);  
-	//PrintAndLog("DEBUG: clk: %d, lastClkBit: %d", *clock, lastClkBit);
+	if (g_debugMode==2) prnt("DEBUG PSK: firstFullWave: %u, waveLen: %u",firstFullWave,fullWaveLen);  
+	if (g_debugMode==2) prnt("DEBUG: clk: %d, lastClkBit: %u, fc: %u", *clock, lastClkBit,(unsigned int) fc);
 	waveStart = 0;
 	dest[numBits++] = curPhase; //set first read bit
 	for (i = firstFullWave + fullWaveLen - 1; i < *size-3; i++){
@@ -1662,7 +1684,7 @@ bool DetectST(uint8_t buffer[], size_t *size, int *foundclock) {
 	i=0;
 	// warning - overwriting buffer given with raw wave data with ST removed...
 	while ( dataloc < bufsize-(clk/2) ) {
-		//compensate for long high at end of ST not being high... (we cut out the high part)
+		//compensate for long high at end of ST not being high due to signal loss... (and we cut out the start of wave high part)
 		if (buffer[dataloc]<high && buffer[dataloc]>low && buffer[dataloc+3]<high && buffer[dataloc+3]>low) {
 			for(i=0; i < clk/2-tol; ++i) {
 				buffer[dataloc+i] = high+5;
@@ -1677,7 +1699,7 @@ bool DetectST(uint8_t buffer[], size_t *size, int *foundclock) {
 			}
 		}
 		newloc += i;
-		//skip next ST
+		//skip next ST  -  we just assume it will be there from now on...
 		dataloc += clk*4;
 	}
 	*size = newloc;
diff --git a/common/lfdemod.h b/common/lfdemod.h
index d4a1fda0..56c758ae 100644
--- a/common/lfdemod.h
+++ b/common/lfdemod.h
@@ -13,8 +13,8 @@
 
 #ifndef LFDEMOD_H__
 #define LFDEMOD_H__
-#include <stdint.h>
-#include "common.h"  //for bool
+#include <stdint.h>  // for uint_32+
+#include <stdbool.h> // for bool
 
 //generic
 size_t   addParity(uint8_t *BitSource, uint8_t *dest, uint8_t sourceLen, uint8_t pLen, uint8_t pType);
@@ -54,5 +54,5 @@ int indala26decode(uint8_t *bitStream, size_t *size, uint8_t *invert);
 int ParadoxdemodFSK(uint8_t *dest, size_t *size, uint32_t *hi2, uint32_t *hi, uint32_t *lo);
 int PyramiddemodFSK(uint8_t *dest, size_t *size);
 int VikingDemod_AM(uint8_t *dest, size_t *size);
-
+int PrescoDemod(uint8_t *dest, size_t *size);
 #endif
diff --git a/include/common.h b/include/common.h
index feed109c..998db64d 100644
--- a/include/common.h
+++ b/include/common.h
@@ -24,6 +24,10 @@ typedef unsigned char byte_t;
 #ifndef MAX
 # define MAX(a, b) (((a) > (b)) ? (a) : (b))
 #endif
+#ifndef ABS
+# define ABS(a) ( ((a)<0) ? -(a) : (a) )
+#endif
+
 
 #define RAMFUNC __attribute((long_call, section(".ramfunc")))