From: marshmellow42 <marshmellowrf@gmail.com>
Date: Sun, 22 Nov 2015 05:00:32 +0000 (-0500)
Subject: lf viking build / lf awid refactor / lfdemod.c debugMode==2
X-Git-Tag: v2.3.0~13^2~10
X-Git-Url: https://git.zerfleddert.de/cgi-bin/gitweb.cgi/proxmark3-svn/commitdiff_plain/709665b5d1abddd92403082c23f13e8cddfcd508?ds=sidebyside

lf viking build / lf awid refactor / lfdemod.c debugMode==2

lf viking from other users - just put my spin on it
lf awid refactored code - possible to make it not 26bit specific now
with minor chanages
lfdemod.c now supports extra debug printing if `data setdebug` = 2 when
not on device (on client not arm)
---

diff --git a/armsrc/appmain.c b/armsrc/appmain.c
index e7324723..97817709 100644
--- a/armsrc/appmain.c
+++ b/armsrc/appmain.c
@@ -1001,6 +1001,9 @@ void UsbPacketReceived(uint8_t *packet, int len)
 		case CMD_AWID_DEMOD_FSK: // Set realtime AWID demodulation
 			CmdAWIDdemodFSK(c->arg[0], 0, 0, 1);
 			break;
+		case CMD_VIKING_CLONE_TAG:
+			CopyVikingtoT55xx(c->arg[0], c->arg[1], c->arg[2]);
+			break;
 #endif
 
 #ifdef WITH_HITAG
diff --git a/armsrc/apps.h b/armsrc/apps.h
index 4f3b50c6..c8397c38 100644
--- a/armsrc/apps.h
+++ b/armsrc/apps.h
@@ -65,6 +65,7 @@ void WriteTItag(uint32_t idhi, uint32_t idlo, uint16_t crc);
 void AcquireTiType(void);
 void AcquireRawBitsTI(void);
 void SimulateTagLowFrequency(int period, int gap, int ledcontrol);
+void SimulateTagLowFrequencyBidir(int divisor, int max_bitlen);
 void CmdHIDsimTAG(int hi, int lo, int ledcontrol);
 void CmdFSKsimTAG(uint16_t arg1, uint16_t arg2, size_t size, uint8_t *BitStream);
 void CmdASKsimTag(uint16_t arg1, uint16_t arg2, size_t size, uint8_t *BitStream);
@@ -74,8 +75,8 @@ void CmdAWIDdemodFSK(int findone, int *high, int *low, int ledcontrol); // Realt
 void CmdEM410xdemod(int findone, int *high, int *low, int ledcontrol);
 void CmdIOdemodFSK(int findone, int *high, int *low, int ledcontrol);
 void CopyIOtoT55x7(uint32_t hi, uint32_t lo); // Clone an ioProx card to T5557/T5567
-void SimulateTagLowFrequencyBidir(int divisor, int max_bitlen);
 void CopyHIDtoT55x7(uint32_t hi2, uint32_t hi, uint32_t lo, uint8_t longFMT); // Clone an HID card to T5557/T5567
+void CopyVikingtoT55xx(uint32_t block1, uint32_t block2, uint8_t Q5);
 void WriteEM410x(uint32_t card, uint32_t id_hi, uint32_t id_lo);
 void CopyIndala64toT55x7(uint32_t hi, uint32_t lo); // Clone Indala 64-bit tag by UID to T55x7
 void CopyIndala224toT55x7(uint32_t uid1, uint32_t uid2, uint32_t uid3, uint32_t uid4, uint32_t uid5, uint32_t uid6, uint32_t uid7); // Clone Indala 224-bit tag by UID to T55x7
diff --git a/armsrc/lfops.c b/armsrc/lfops.c
index 0691098b..5cdfe834 100644
--- a/armsrc/lfops.c
+++ b/armsrc/lfops.c
@@ -73,8 +73,6 @@ void ModThenAcquireRawAdcSamples125k(uint32_t delay_off, uint32_t period_0, uint
 	DoAcquisition_config(false);
 }
 
-
-
 /* blank r/w tag data stream
 ...0000000000000000 01111111
 1010101010101010101010101010101010101010101010101010101010101010
@@ -214,8 +212,6 @@ void ReadTItag(void)
 	}
 }
 
-
-
 void WriteTIbyte(uint8_t b)
 {
 	int i = 0;
@@ -250,7 +246,7 @@ void AcquireTiType(void)
 
 	// clear buffer
 	uint32_t *BigBuf = (uint32_t *)BigBuf_get_addr();
-	memset(BigBuf,0,BigBuf_max_traceLen()/sizeof(uint32_t));
+	BigBuf_Clear_ext(false);
 
 	// Set up the synchronous serial port
 	AT91C_BASE_PIOA->PIO_PDR = GPIO_SSC_DIN;
@@ -312,16 +308,11 @@ void AcquireTiType(void)
 	}
 }
 
-
-
-
 // arguments: 64bit data split into 32bit idhi:idlo and optional 16bit crc
 // if crc provided, it will be written with the data verbatim (even if bogus)
 // if not provided a valid crc will be computed from the data and written.
 void WriteTItag(uint32_t idhi, uint32_t idlo, uint16_t crc)
 {
-
-
 	FpgaDownloadAndGo(FPGA_BITSTREAM_LF);
 	if(crc == 0) {
 		crc = update_crc16(crc, (idlo)&0xff);
@@ -402,8 +393,8 @@ void SimulateTagLowFrequency(int period, int gap, int ledcontrol)
 	AT91C_BASE_PIOA->PIO_OER = GPIO_SSC_DOUT;
 	AT91C_BASE_PIOA->PIO_ODR = GPIO_SSC_CLK;
 
- #define SHORT_COIL()	LOW(GPIO_SSC_DOUT)
- #define OPEN_COIL()		HIGH(GPIO_SSC_DOUT)
+ #define SHORT_COIL()   LOW(GPIO_SSC_DOUT)
+ #define OPEN_COIL()    HIGH(GPIO_SSC_DOUT)
 
 	i = 0;
 	for(;;) {
@@ -693,13 +684,9 @@ void CmdASKsimTag(uint16_t arg1, uint16_t arg2, size_t size, uint8_t *BitStream)
 	//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();
-	
+	if (ledcontrol) LED_A_ON();
 	SimulateTagLowFrequency(n, 0, ledcontrol);
-
-	if (ledcontrol)
-		LED_A_OFF();
+	if (ledcontrol) LED_A_OFF();
 }
 
 //carrier can be 2,4 or 8
@@ -749,12 +736,9 @@ void CmdPSKsimTag(uint16_t arg1, uint16_t arg2, size_t size, uint8_t *BitStream)
 	//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();
+	if (ledcontrol) LED_A_ON();
 	SimulateTagLowFrequency(n, 0, ledcontrol);
-
-	if (ledcontrol)
-		LED_A_OFF();
+	if (ledcontrol) LED_A_OFF();
 }
 
 // loop to get raw HID waveform then FSK demodulate the TAG ID from it
@@ -851,7 +835,6 @@ void CmdHIDdemodFSK(int findone, int *high, int *low, int ledcontrol)
 void CmdAWIDdemodFSK(int findone, int *high, int *low, int ledcontrol)
 {
 	uint8_t *dest = BigBuf_get_addr();
-	//const size_t sizeOfBigBuff = BigBuf_max_traceLen();
 	size_t size; 
 	int idx=0;
 	// Configure to go in 125Khz listen mode
@@ -864,72 +847,71 @@ void CmdAWIDdemodFSK(int findone, int *high, int *low, int ledcontrol)
 
 		DoAcquisition_default(-1,true);
 		// FSK demodulator
-		//size = sizeOfBigBuff;  //variable size will change after demod so re initialize it before use
 		size = 50*128*2; //big enough to catch 2 sequences of largest format
 		idx = AWIDdemodFSK(dest, &size);
 		
-		if (idx>0 && size==96){
-	        // 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(dest+idx+64,32);
-	        uint32_t rawHi = bytebits_to_byte(dest+idx+32,32);
-	        uint32_t rawHi2 = bytebits_to_byte(dest+idx,32);
-
-	        size = removeParity(dest, idx+8, 4, 1, 88);
-	        // 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(dest,8);
-	        if (fmtLen==26){
-	                fc = bytebits_to_byte(dest+9, 8);
-	                cardnum = bytebits_to_byte(dest+17, 16);
-	                code1 = bytebits_to_byte(dest+8,fmtLen);
-	                Dbprintf("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(dest+8+(fmtLen-17), 16);
-	                if (fmtLen>32){
-                        code1 = bytebits_to_byte(dest+8,fmtLen-32);
-                        code2 = bytebits_to_byte(dest+8+(fmtLen-32),32);
-                        Dbprintf("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(dest+8,fmtLen);
-                        Dbprintf("AWID Found - BitLength: %d -unknown BitLength- (%d) - Wiegand: %x, Raw: %08x%08x%08x", fmtLen, cardnum, code1, rawHi2, rawHi, rawLo);
-                }
-			}
-			if (findone){
-				if (ledcontrol)	LED_A_OFF();
-				return;
+		if (idx<=0 || size!=96) continue;
+		// 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(dest+idx+64,32);
+		uint32_t rawHi = bytebits_to_byte(dest+idx+32,32);
+		uint32_t rawHi2 = bytebits_to_byte(dest+idx,32);
+
+		size = removeParity(dest, idx+8, 4, 1, 88);
+		if (size != 66) continue;
+		// 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(dest,8);
+		if (fmtLen==26){
+			fc = bytebits_to_byte(dest+9, 8);
+			cardnum = bytebits_to_byte(dest+17, 16);
+			code1 = bytebits_to_byte(dest+8,fmtLen);
+			Dbprintf("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(dest+8+(fmtLen-17), 16);
+			if (fmtLen>32){
+				code1 = bytebits_to_byte(dest+8,fmtLen-32);
+				code2 = bytebits_to_byte(dest+8+(fmtLen-32),32);
+				Dbprintf("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(dest+8,fmtLen);
+				Dbprintf("AWID Found - BitLength: %d -unknown BitLength- (%d) - Wiegand: %x, Raw: %08x%08x%08x", fmtLen, cardnum, code1, rawHi2, rawHi, rawLo);
 			}
-			// reset
 		}
+		if (findone){
+			if (ledcontrol)	LED_A_OFF();
+			return;
+		}
+		// reset
 		idx = 0;
 		WDT_HIT();
 	}
@@ -1064,11 +1046,8 @@ void CmdIOdemodFSK(int findone, int *high, int *low, int ledcontrol)
 /*------------------------------
  * T5555/T5557/T5567/T5577 routines
  *------------------------------
- */
-
-/* NOTE: T55x7/T5555 configuration register definitions moved to protocols.h */
-
-/*
+ * NOTE: T55x7/T5555 configuration register definitions moved to protocols.h
+ *
  * Relevant communication times in microsecond
  * To compensate antenna falling times shorten the write times
  * and enlarge the gap ones.
@@ -1255,7 +1234,6 @@ void T55xxWakeUp(uint32_t Pwd){
 void WriteT55xx(uint32_t *blockdata, uint8_t startblock, uint8_t numblocks) {
 	// write last block first and config block last (if included)
 	for (uint8_t i = numblocks+startblock; i > startblock; i--) {
-		//Dbprintf("write- Blk: %d, d:%08X",i-1,blockdata[i-1]);
 		T55xxWriteBlockExt(blockdata[i-1],i-1,0,0);
 	}
 }
@@ -1263,7 +1241,6 @@ void WriteT55xx(uint32_t *blockdata, uint8_t startblock, uint8_t numblocks) {
 // Copy HID id to card and setup block 0 config
 void CopyHIDtoT55x7(uint32_t hi2, uint32_t hi, uint32_t lo, uint8_t longFMT) {
 	uint32_t data[] = {0,0,0,0,0,0,0};
-	//int data1=0, data2=0, data3=0, data4=0, data5=0, data6=0; //up to six blocks for long format
 	uint8_t last_block = 0;
 
 	if (longFMT) {
@@ -1353,6 +1330,15 @@ void CopyIndala224toT55x7(uint32_t uid1, uint32_t uid2, uint32_t uid3, uint32_t
 	//	T5567WriteBlock(0x603E10E2,0);
 	DbpString("DONE!");
 }
+// clone viking tag to T55xx
+void CopyVikingtoT55xx(uint32_t block1, uint32_t block2, uint8_t Q5) {
+	uint32_t data[] = {T55x7_BITRATE_RF_32 | T55x7_MODULATION_MANCHESTER | (2 << T55x7_MAXBLOCK_SHIFT), block1, block2};
+	if (Q5) data[0] = (32 << T5555_BITRATE_SHIFT) | T5555_MODULATION_MANCHESTER | 2 << T5555_MAXBLOCK_SHIFT;
+	// Program the data blocks for supplied ID and the block 0 config
+	WriteT55xx(data, 0, 3);
+	LED_D_OFF();
+	cmd_send(CMD_ACK,0,0,0,0,0);
+}
 
 // Define 9bit header for EM410x tags
 #define EM410X_HEADER		  0x1FF
@@ -1450,7 +1436,6 @@ void WriteEM410x(uint32_t card, uint32_t id_hi, uint32_t id_lo) {
 #define FWD_CMD_READ 0x9
 #define FWD_CMD_DISABLE 0x5
 
-
 uint8_t forwardLink_data[64]; //array of forwarded bits
 uint8_t * forward_ptr; //ptr for forward message preparation
 uint8_t fwd_bit_sz; //forwardlink bit counter
@@ -1470,7 +1455,6 @@ uint8_t * fwd_write_ptr; //forwardlink bit pointer
 //  WRITE_0 = 23*8 , 9*8  SpinDelayUs(23*8); 
 
 uint8_t Prepare_Cmd( uint8_t cmd ) {
-	//--------------------------------------------------------------------
 
 	*forward_ptr++ = 0; //start bit
 	*forward_ptr++ = 0; //second pause for 4050 code
@@ -1490,10 +1474,7 @@ uint8_t Prepare_Cmd( uint8_t cmd ) {
 // prepares address bits
 // see EM4469 spec
 //====================================================================
-
-//--------------------------------------------------------------------
 uint8_t Prepare_Addr( uint8_t addr ) {
-	//--------------------------------------------------------------------
 
 	register uint8_t line_parity;
 
@@ -1514,10 +1495,7 @@ uint8_t Prepare_Addr( uint8_t addr ) {
 // prepares data bits intreleaved with parity bits
 // see EM4469 spec
 //====================================================================
-
-//--------------------------------------------------------------------
 uint8_t Prepare_Data( uint16_t data_low, uint16_t data_hi) {
-	//--------------------------------------------------------------------
 
 	register uint8_t line_parity;
 	register uint8_t column_parity;
@@ -1569,7 +1547,6 @@ void SendForward(uint8_t fwd_bit_count) {
 	fwd_write_ptr++;
 	FpgaWriteConfWord(FPGA_MAJOR_MODE_OFF); // field off
 	SpinDelayUs(55*8); //55 cycles off (8us each)for 4305
-	FpgaSendCommand(FPGA_CMD_SET_DIVISOR, 95); //125Khz
 	FpgaWriteConfWord(FPGA_MAJOR_MODE_LF_ADC | FPGA_LF_ADC_READER_FIELD);//field on
 	SpinDelayUs(16*8); //16 cycles on (8us each)
 
@@ -1581,7 +1558,6 @@ void SendForward(uint8_t fwd_bit_count) {
 			//These timings work for 4469/4269/4305 (with the 55*8 above)
 			FpgaWriteConfWord(FPGA_MAJOR_MODE_OFF); // field off
 			SpinDelayUs(23*8); //16-4 cycles off (8us each)
-			FpgaSendCommand(FPGA_CMD_SET_DIVISOR, 95); //125Khz
 			FpgaWriteConfWord(FPGA_MAJOR_MODE_LF_ADC | FPGA_LF_ADC_READER_FIELD);//field on
 			SpinDelayUs(9*8); //16 cycles on (8us each)
 		}
@@ -1600,7 +1576,6 @@ void EM4xLogin(uint32_t Password) {
 
 	//Wait for command to complete
 	SpinDelay(20);
-
 }
 
 void EM4xReadWord(uint8_t Address, uint32_t Pwd, uint8_t PwdMode) {
@@ -1611,7 +1586,7 @@ void EM4xReadWord(uint8_t Address, uint32_t Pwd, uint8_t PwdMode) {
 	uint32_t i = 0;
 
 	// Clear destination buffer before sending the command
-	memset(dest, 0x80, bufferlength);
+	BigBuf_Clear_ext(false);
 
 	//If password mode do login
 	if (PwdMode == 1) EM4xLogin(Pwd);
diff --git a/client/cmddata.c b/client/cmddata.c
index d4dcf661..ca4fcafc 100644
--- a/client/cmddata.c
+++ b/client/cmddata.c
@@ -125,9 +125,7 @@ int CmdPrintDemodBuff(const char *Cmd)
 		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;
 }
@@ -656,7 +654,7 @@ int CmdVikingDemod(const char *Cmd)
 	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);
+	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);
@@ -1481,6 +1479,17 @@ int CmdFSKdemodPyramid(const char *Cmd)
 // NATIONAL CODE, ICAR database
 // COUNTRY CODE (ISO3166) or http://cms.abvma.ca/uploads/ManufacturersISOsandCountryCodes.pdf
 // FLAG (animal/non-animal)
+/*
+38 IDbits   
+10 country code 
+1 extra app bit
+14 reserved bits
+1 animal bit
+16 ccitt CRC chksum over 64bit ID CODE.
+24 appli bits.
+
+-- sample: 985121004515220  [ 37FF65B88EF94 ]
+*/
 int CmdFDXBdemodBI(const char *Cmd){
 
 	int invert = 1;
@@ -1640,7 +1649,7 @@ int CmdIndalaDecode(const char *Cmd)
 	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);
+		PrintAndLog("Indala UID=%s (%x%08x)", sprint_bin_break(DemodBuffer,DemodBufferLen,16), uid1, uid2);
 	} else {
 		uid3=bytebits_to_byte(DemodBuffer+64,32);
 		uid4=bytebits_to_byte(DemodBuffer+96,32);
@@ -1648,7 +1657,7 @@ int CmdIndalaDecode(const char *Cmd)
 		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);
+		    sprint_bin_break(DemodBuffer,DemodBufferLen,16), uid1, uid2, uid3, uid4, uid5, uid6, uid7);
 	}
 	if (g_debugMode){
 		PrintAndLog("DEBUG: printing demodbuffer:");
@@ -1964,10 +1973,7 @@ int getSamples(const char *Cmd, bool silent)
 
 	int n = strtol(Cmd, NULL, 0);
 
-	if (n == 0)
-		n = sizeof(got);
-
-	if (n > sizeof(got))
+	if (n == 0 || n > sizeof(got))
 		n = sizeof(got);
 
 	PrintAndLog("Reading %d bytes from device memory\n", n);
@@ -2384,7 +2390,7 @@ static command_t CommandTable[] =
 	{"samples",         CmdSamples,         0, "[512 - 40000] -- Get raw samples for graph window (GraphBuffer)"},
 	{"save",            CmdSave,            1, "<filename> -- Save trace (from 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"},
diff --git a/client/cmdlf.c b/client/cmdlf.c
index a310a075..467816aa 100644
--- a/client/cmdlf.c
+++ b/client/cmdlf.c
@@ -423,6 +423,7 @@ int CmdIndalaClone(const char *Cmd)
 		c.arg[1] = uid2;
 	}
 
+	clearCommandBuffer();
 	SendCommand(&c);
 	return 0;
 }
@@ -545,6 +546,7 @@ int CmdLFSetConfig(const char *Cmd)
 	//Averaging is a flag on high-bit of arg[1]
 	UsbCommand c = {CMD_SET_LF_SAMPLING_CONFIG};
 	memcpy(c.d.asBytes,&config,sizeof(sample_config));
+	clearCommandBuffer();
 	SendCommand(&c);
 	return 0;
 }
@@ -561,6 +563,7 @@ int CmdLFRead(const char *Cmd)
 	if (param_getchar(Cmd, cmdp) == 's') arg1 = true; //suppress print
 	//And ship it to device
 	UsbCommand c = {CMD_ACQUIRE_RAW_ADC_SAMPLES_125K, {arg1,0,0}};
+	clearCommandBuffer();
 	SendCommand(&c);
 	//WaitForResponse(CMD_ACK,NULL);	
 	if ( !WaitForResponseTimeout(CMD_ACK,NULL,2500) ) {
@@ -580,6 +583,7 @@ int CmdLFSnoop(const char *Cmd)
 	}
 
 	UsbCommand c = {CMD_LF_SNOOP_RAW_ADC_SAMPLES};
+	clearCommandBuffer();
 	SendCommand(&c);
 	WaitForResponse(CMD_ACK,NULL);
 	return 0;
@@ -626,6 +630,7 @@ int CmdLFSim(const char *Cmd)
 	printf("\n");
 	PrintAndLog("Starting to simulate");
 	UsbCommand c = {CMD_SIMULATE_TAG_125K, {GraphTraceLen, gap, 0}};
+	clearCommandBuffer();
 	SendCommand(&c);
 	return 0;
 }
@@ -775,6 +780,7 @@ int CmdLFfskSim(const char *Cmd)
 	UsbCommand c = {CMD_FSK_SIM_TAG, {arg1, arg2, size}};
 
 	memcpy(c.d.asBytes, DemodBuffer, size);
+	clearCommandBuffer();
 	SendCommand(&c);
 	return 0;
 }
@@ -868,6 +874,7 @@ int CmdLFaskSim(const char *Cmd)
 	UsbCommand c = {CMD_ASK_SIM_TAG, {arg1, arg2, size}};
 	PrintAndLog("preparing to sim ask data: %d bits", size);
 	memcpy(c.d.asBytes, DemodBuffer, size);
+	clearCommandBuffer();
 	SendCommand(&c);
 	return 0;
 }
@@ -975,6 +982,7 @@ int CmdLFpskSim(const char *Cmd)
 	UsbCommand c = {CMD_PSK_SIM_TAG, {arg1, arg2, size}};
 	PrintAndLog("DEBUG: Sending DemodBuffer Length: %d", size);
 	memcpy(c.d.asBytes, DemodBuffer, size);
+	clearCommandBuffer();
 	SendCommand(&c);
 	
 	return 0;
diff --git a/client/cmdlfawid.c b/client/cmdlfawid.c
index 06397e70..309f4118 100644
--- a/client/cmdlfawid.c
+++ b/client/cmdlfawid.c
@@ -16,9 +16,11 @@
 #include "cmdparser.h"  // CmdsParse, CmdsHelp
 #include "cmdlfawid.h"  // AWID function declarations
 #include "lfdemod.h"    // parityTest
+#include "util.h"       // weigandparity
+#include "protocols.h"  // for T55xx config register definitions
 #include "cmdmain.h"
-static int CmdHelp(const char *Cmd);
 
+static int CmdHelp(const char *Cmd);
 
 int usage_lf_awid_fskdemod(void) {
 	PrintAndLog("Enables AWID26 compatible reader mode printing details of scanned AWID26 tags.");
@@ -26,11 +28,11 @@ int usage_lf_awid_fskdemod(void) {
 	PrintAndLog("If the ['1'] option is provided, reader mode is exited after reading a single AWID26 card.");
 	PrintAndLog("");
 	PrintAndLog("Usage:  lf awid fskdemod ['1']");
-	PrintAndLog("  Options : ");
+	PrintAndLog("Options : ");
 	PrintAndLog("  1 : (optional) stop after reading a single card");
 	PrintAndLog("");
-	PrintAndLog("   sample : lf awid fskdemod");
-	PrintAndLog("          : lf awid fskdemod 1");
+	PrintAndLog("Samples : lf awid fskdemod");
+	PrintAndLog("        : lf awid fskdemod 1");
 	return 0;
 }
 
@@ -40,11 +42,11 @@ int usage_lf_awid_sim(void) {
 	PrintAndLog("Per AWID26 format, the facility-code is 8-bit and the card number is 16-bit.  Larger values are truncated.");
 	PrintAndLog("");
 	PrintAndLog("Usage:  lf awid sim <Facility-Code> <Card-Number>");
-	PrintAndLog("  Options : ");
+	PrintAndLog("Options : ");
 	PrintAndLog("  <Facility-Code> : 8-bit value representing the AWID facility code");
 	PrintAndLog("  <Card Number>   : 16-bit value representing the AWID card number");
 	PrintAndLog("");
-	PrintAndLog("   sample : lf awid sim 224 1337");
+	PrintAndLog("Sample : lf awid sim 224 1337");
 	return 0;
 }
 
@@ -54,133 +56,91 @@ int usage_lf_awid_clone(void) {
 	PrintAndLog("Per AWID26 format, the facility-code is 8-bit and the card number is 16-bit.  Larger values are truncated.");
 	PrintAndLog("");
 	PrintAndLog("Usage:  lf awid clone <Facility-Code> <Card-Number>");
-	PrintAndLog("  Options : ");
+	PrintAndLog("Options : ");
 	PrintAndLog("  <Facility-Code> : 8-bit value representing the AWID facility code");
 	PrintAndLog("  <Card Number>   : 16-bit value representing the AWID card number");
+	PrintAndLog("  Q5              : optional - clone to Q5 (T5555) instead of T55x7 chip");
 	PrintAndLog("");
-	PrintAndLog("   sample : lf awid clone 224 1337");
+	PrintAndLog("Sample  : lf awid clone 224 1337");
 	return 0;
 }
 
-int CmdAWIDDemodFSK(const char *Cmd)
-{
+int CmdAWIDDemodFSK(const char *Cmd) {
 	int findone=0;
-	if(Cmd[0]=='1') findone=1;
-	if (Cmd[0]=='h' || Cmd[0] == 'H') return usage_lf_awid_fskdemod();
-	UsbCommand c={CMD_AWID_DEMOD_FSK};
-	c.arg[0]=findone;
+	if (Cmd[0] == 'h' || Cmd[0] == 'H') return usage_lf_awid_fskdemod();
+	if (Cmd[0] == '1') findone = 1;
+
+	UsbCommand c = {CMD_AWID_DEMOD_FSK, {findone, 0, 0}};
+	clearCommandBuffer();
 	SendCommand(&c);
 	return 0;   
 }
 
-int getAWIDBits(unsigned int fc, unsigned int cn, uint8_t *AWIDBits)
-{
-	int i;
-	uint32_t fcode=(fc & 0x000000FF), cnum=(cn & 0x0000FFFF), uBits=0;
-	if (fcode != fc)
-		PrintAndLog("NOTE: Facility code truncated for AWID26 format (8-bit facility code)");
-	if (cnum!=cn)
-		PrintAndLog("NOTE: Card number was truncated for AWID26 format (16-bit card number)");
-
-	AWIDBits[0] = 0x01; // 6-bit Preamble with 2 parity bits
-	AWIDBits[1] = 0x1D; // First byte from card format (26-bit) plus parity bits
-	AWIDBits[2] = 0x80; // Set the next two bits as 0b10 to finish card format
-	uBits = (fcode<<4) + (cnum>>12);
-	if (!parityTest(uBits,12,0))
-		AWIDBits[2] |= (1<<5); // If not already even parity, set bit to make even
-	uBits = AWIDBits[2]>>5;
-	if (!parityTest(uBits, 3, 1))
-		AWIDBits[2] |= (1<<4);
-	uBits = fcode>>5; // first 3 bits of facility-code
-	AWIDBits[2] += (uBits<<1);
-	if (!parityTest(uBits, 3, 1))
-		AWIDBits[2]++; // Set parity bit to make odd parity
-	uBits = (fcode & 0x1C)>>2;
-	AWIDBits[3] = 0;
-	if (!parityTest(uBits,3,1))
-		AWIDBits[3] |= (1<<4);
-	AWIDBits[3] += (uBits<<5);
-	uBits = ((fcode & 0x3)<<1) + ((cnum & 0x8000)>>15); // Grab/shift 2 LSBs from facility code and add shifted MSB from cardnum
-	if (!parityTest(uBits,3,1))
-		AWIDBits[3]++; // Set LSB for parity
-	AWIDBits[3]+= (uBits<<1);
-	uBits = (cnum & 0x7000)>>12;
-	AWIDBits[4] = uBits<<5;
-	if (!parityTest(uBits,3,1))
-		AWIDBits[4] |= (1<<4);
-	uBits = (cnum & 0x0E00)>>9;
-	AWIDBits[4] += (uBits<<1);
-	if (!parityTest(uBits,3,1))
-		AWIDBits[4]++; // Set LSB for parity
-	uBits = (cnum & 0x1C0)>>6; // Next bits from card number
-	AWIDBits[5]=(uBits<<5);
-	if (!parityTest(uBits,3,1))
-		AWIDBits[5] |= (1<<4); // Set odd parity bit as needed
-	uBits = (cnum & 0x38)>>3;
-	AWIDBits[5]+= (uBits<<1);
-	if (!parityTest(uBits,3,1))
-		AWIDBits[5]++; // Set odd parity bit as needed
-	uBits = (cnum & 0x7); // Last three bits from card number!
-	AWIDBits[6] = (uBits<<5);
-	if (!parityTest(uBits,3,1))
-		AWIDBits[6] |= (1<<4);
-	uBits = (cnum & 0x0FFF);
-	if (!parityTest(uBits,12,1))
-		AWIDBits[6] |= (1<<3);
-	else
-		AWIDBits[6]++;
-	for (i = 7; i<12; i++)
-		AWIDBits[i]=0x11;
+//refactored by marshmellow
+int getAWIDBits(uint32_t fc, uint32_t cn, uint8_t	*AWIDBits) {
+	uint8_t pre[66];
+	memset(pre, 0, sizeof(pre));
+	AWIDBits[7]=1;
+	num_to_bytebits(26, 8, pre);
+
+	uint8_t wiegand[24];
+	num_to_bytebits(fc, 8, wiegand);
+	num_to_bytebits(cn, 16, wiegand+8);
+
+	wiegand_add_parity(pre+8, wiegand, 24);
+
+	size_t bitLen = addParity(pre, AWIDBits+8, 66, 4, 1);
+	if (bitLen != 88) return 0;
+	//for (uint8_t i = 0; i<3; i++){
+	//	PrintAndLog("DEBUG: %08X", bytebits_to_byte(AWIDBits+(32*i),32));
+	//}
 	return 1;
 }
 
-int CmdAWIDSim(const char *Cmd)
-{
-	uint32_t fcode = 0, cnum = 0, fc=0, cn=0, i=0;
-	uint8_t *BS, BitStream[12];
+int CmdAWIDSim(const char *Cmd) {
+	uint32_t fcode = 0, cnum = 0, fc=0, cn=0;
+	uint8_t BitStream[96];
+	uint8_t *bs = BitStream;
+	size_t size = sizeof(BitStream);
+	memset(bs, 0, size);
+
 	uint64_t arg1 = (10<<8) + 8; // fcHigh = 10, fcLow = 8
 	uint64_t arg2 = 50; // clk RF/50 invert=0
-	BS = BitStream;
-	if (sscanf(Cmd, "%u %u", &fc, &cn ) != 2) {
-		return usage_lf_awid_sim();
-	}
+	
+	if (sscanf(Cmd, "%u %u", &fc, &cn ) != 2) return usage_lf_awid_sim();
+
+	fcode = (fc & 0x000000FF);
+	cnum = (cn & 0x0000FFFF);
+
+	if (fc != fcode) PrintAndLog("Facility-Code (%u) truncated to 8-bits: %u",fc,fcode);
+	if (cn != cnum) PrintAndLog("Card number (%u) truncated to 16-bits: %u",cn,cnum);
 
-	fcode=(fc & 0x000000FF);
-	cnum=(cn & 0x0000FFFF);
-	if (fc!=fcode)
-		PrintAndLog("Facility-Code (%u) truncated to 8-bits: %u",fc,fcode);
-	if (cn!=cnum)
-		PrintAndLog("Card number (%u) truncated to 16-bits: %u",cn,cnum);
 	PrintAndLog("Emulating AWID26 -- FC: %u; CN: %u\n",fcode,cnum);
 	PrintAndLog("Press pm3-button to abort simulation or run another command");
+
+	if (!getAWIDBits(fc, cn, bs)) {
+		PrintAndLog("Error with tag bitstream generation.");
+		return 1;
+	}
 	// AWID uses: fcHigh: 10, fcLow: 8, clk: 50, invert: 0
-	if (getAWIDBits(fc, cn, BS)) {
-			PrintAndLog("Running 'lf simfsk c 50 H 10 L 8 d %02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x'", 
-																				BS[0],BS[1],BS[2],BS[3],BS[4],BS[5],BS[6],
-																				BS[7],BS[8],BS[9],BS[10],BS[11]);
-		} else
-			PrintAndLog("Error with tag bitstream generation.");
-	UsbCommand c;
-	c.cmd = CMD_FSK_SIM_TAG;
-	c.arg[0] = arg1; // fcHigh<<8 + fcLow
-	c.arg[1] = arg2; // Inversion and clk setting
-	c.arg[2] = 96; // Bitstream length: 96-bits == 12 bytes
-	for (i=0; i < 96; i++)
-		c.d.asBytes[i] = (BS[i/8] & (1<<(7-(i%8))))?1:0;
+	UsbCommand c = {CMD_FSK_SIM_TAG, {arg1, arg2, size}};
+	memcpy(c.d.asBytes, bs, size);
+	clearCommandBuffer();
 	SendCommand(&c);
 	return 0;
 }
 
-int CmdAWIDClone(const char *Cmd)
-{
-	uint32_t fc=0,cn=0,blocks[4] = {0x00107060, 0, 0, 0x11111111}, i=0;
-	uint8_t BitStream[12];
-	uint8_t *BS=BitStream;
-	UsbCommand c, resp;
+int CmdAWIDClone(const char *Cmd) {
+	uint32_t blocks[4] = {T55x7_MODULATION_FSK2a | T55x7_BITRATE_RF_50 | 3<<T55x7_MAXBLOCK_SHIFT, 0, 0, 0};
+	uint32_t fc=0,cn=0;
+	uint8_t BitStream[96];
+	uint8_t *bs=BitStream;
+	memset(bs,0,sizeof(BitStream));
 
-	if (sscanf(Cmd, "%u %u", &fc, &cn ) != 2) {
-		return usage_lf_awid_clone();
-	}
+	if (sscanf(Cmd, "%u %u", &fc, &cn ) != 2) return usage_lf_awid_clone();
+
+	if (param_getchar(Cmd, 3) == 'Q' || param_getchar(Cmd, 3) == 'q')
+		blocks[0] = T5555_MODULATION_FSK2 | T5555_INVERT_OUTPUT | 50<<T5555_BITRATE_SHIFT | 3<<T5555_MAXBLOCK_SHIFT;
 
 	if ((fc & 0xFF) != fc) {
 		fc &= 0xFF;
@@ -190,48 +150,58 @@ int CmdAWIDClone(const char *Cmd)
 		cn &= 0xFFFF;
 		PrintAndLog("Card Number Truncated to 16-bits (AWID26): %u", cn);
 	}
-	if (getAWIDBits(fc,cn,BS)) {
-		PrintAndLog("Preparing to clone AWID26 to T55x7 with FC: %u, CN: %u (Raw: %02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x)", 
-									fc,cn, BS[0],BS[1],BS[2],BS[3],BS[4],BS[5],BS[6],BS[7],BS[8],BS[9],BS[10],BS[11]);
-		blocks[1] = (BS[0]<<24) + (BS[1]<<16) + (BS[2]<<8) + (BS[3]);
-		blocks[2] = (BS[4]<<24) + (BS[5]<<16) + (BS[6]<<8) + (BS[7]);
-		PrintAndLog("Block 0: 0x%08x", blocks[0]);
-		PrintAndLog("Block 1: 0x%08x", blocks[1]);
-		PrintAndLog("Block 2: 0x%08x", blocks[2]);
-		PrintAndLog("Block 3: 0x%08x", blocks[3]);
-		for (i=0; i<4; i++) {
-			c.cmd = CMD_T55XX_WRITE_BLOCK;
-			c.arg[0] = blocks[i];
-			c.arg[1] = i;
-			c.arg[2] = 0;
-			SendCommand(&c);
-			if (!WaitForResponseTimeout(CMD_ACK, &resp, 1000)){
-				PrintAndLog("Error occurred, device did not respond during write operation.");
-				return -1;
-			}
 
+	if ( !getAWIDBits(fc, cn, bs)) {
+		PrintAndLog("Error with tag bitstream generation.");
+		return 1;
+	}
+
+	blocks[1] = bytebits_to_byte(bs,32);
+	blocks[2] = bytebits_to_byte(bs+32,32);
+	blocks[3] = bytebits_to_byte(bs+64,32);
+
+	PrintAndLog("Preparing to clone AWID26 to T55x7 with FC: %u, CN: %u", 
+	    fc, cn);
+	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]);
+
+	UsbCommand resp;
+	UsbCommand c = {CMD_T55XX_WRITE_BLOCK, {0,0,0}};
+
+	for (uint8_t i=0; i<4; i++) {
+		c.cmd = CMD_T55XX_WRITE_BLOCK;
+		c.arg[0] = blocks[i];
+		c.arg[1] = i;
+		c.arg[2] = 0;
+		clearCommandBuffer();
+		SendCommand(&c);
+		if (!WaitForResponseTimeout(CMD_ACK, &resp, 1000)){
+			PrintAndLog("Error occurred, device did not respond during write operation.");
+			return -1;
 		}
+
 	}
 	return 0;
 }
 
-static command_t CommandTable[] = 
-{
-	{"help",      CmdHelp,        1, "This help"},
+static command_t CommandTable[] = {
+	{"help",      CmdHelp,         1, "This help"},
 	{"fskdemod",  CmdAWIDDemodFSK, 0, "['1'] Realtime AWID FSK demodulator (option '1' for one tag only)"},
 	{"sim",       CmdAWIDSim,      0, "<Facility-Code> <Card Number> -- AWID tag simulator"},
-	{"clone",     CmdAWIDClone,    0, "<Facility-Code> <Card Number> -- Clone AWID to T55x7 (tag must be in range of antenna)"},
+	{"clone",     CmdAWIDClone,    0, "<Facility-Code> <Card Number> <Q5> -- Clone AWID to T55x7 (tag must be in range of antenna)"},
 	{NULL, NULL, 0, NULL}
 };
 
-int CmdLFAWID(const char *Cmd)
-{
+int CmdLFAWID(const char *Cmd) {
 	CmdsParse(CommandTable, Cmd);
 	return 0;
 }
 
-int CmdHelp(const char *Cmd)
-{
+int CmdHelp(const char *Cmd) {
 	CmdsHelp(CommandTable);
 	return 0;
 }
diff --git a/client/cmdlfio.c b/client/cmdlfio.c
index aa21c44b..e3769511 100644
--- a/client/cmdlfio.c
+++ b/client/cmdlfio.c
@@ -67,9 +67,9 @@ int CmdIOClone(const char *Cmd)
 static command_t CommandTable[] = 
 {
   {"help",        CmdHelp,            1, "This help"},
-  //{"demod",	  CmdIOProxDemod,     1, "Demodulate Stream"},
+  //{"demod",       CmdIOProxDemod,     1, "Demodulate Stream"},
   {"fskdemod",    CmdIODemodFSK,      0, "['1'] Realtime IO FSK demodulator (option '1' for one tag only)"},
-  {"clone",	  CmdIOClone,         0, "Clone ioProx Tag"},
+  {"clone",       CmdIOClone,         0, "Clone ioProx Tag"},
   {NULL, NULL, 0, NULL}
 };
 
diff --git a/client/cmdlft55xx.c b/client/cmdlft55xx.c
index d3d78c22..0e8043a9 100644
--- a/client/cmdlft55xx.c
+++ b/client/cmdlft55xx.c
@@ -26,8 +26,9 @@
 #include "../common/iso14443crc.h"
 #include "cmdhf14a.h"
 
-#define CONFIGURATION_BLOCK 0x00
-#define TRACE_BLOCK 0x01
+#define T55x7_CONFIGURATION_BLOCK 0x00
+#define T55x7_PAGE0 0x00
+#define T55x7_PAGE1 0x01
 #define REGULAR_READ_MODE_BLOCK 0xFF
 
 // Default configuration
@@ -148,6 +149,12 @@ int usage_t55xx_wakup(){
 
 static int CmdHelp(const char *Cmd);
 
+void printT5xxHeader(uint8_t page){
+	PrintAndLog("Reading Page %d:", page);	
+	PrintAndLog("blk | hex data | binary");
+	PrintAndLog("----+----------+---------------------------------");	
+}
+
 int CmdT55xxSetConfig(const char *Cmd) {
 
 	uint8_t offset = 0;
@@ -256,7 +263,7 @@ int T55xxReadBlock(uint8_t block, bool page1, bool usepwd, bool override, uint32
 	if ( usepwd ) {
 		// try reading the config block and verify that PWD bit is set before doing this!
 		if ( !override ) {
-			if ( !AquireData(0, CONFIGURATION_BLOCK, false, 0 ) ) return 0;
+			if ( !AquireData(T55x7_PAGE0, T55x7_CONFIGURATION_BLOCK, false, 0 ) ) return 0;
 			if ( !tryDetectModulation() ) {
 				PrintAndLog("Safety Check: Could not detect if PWD bit is set in config block. Exits.");
 				return 0;
@@ -324,8 +331,8 @@ int CmdT55xxReadBlock(const char *Cmd) {
 		PrintAndLog("Block must be between 0 and 7");
 		return 0;
 	}
-	PrintAndLog("Reading Page %d:", page1);	
-	PrintAndLog("blk | hex data | binary");
+
+	printT5xxHeader(page1);
 	return T55xxReadBlock(block, page1, usepwd, override, password);
 }
 
@@ -387,14 +394,27 @@ bool DecodeT55xxBlock(){
 
 int CmdT55xxDetect(const char *Cmd){
 
+	uint32_t password = 0; //default to blank Block 7
+
 	char cmdp = param_getchar(Cmd, 0);
-	if (strlen(Cmd) > 1 || cmdp == 'h' || cmdp == 'H')
-		return usage_t55xx_detect();
+	if (strlen(Cmd) > 1 || cmdp == 'h' || cmdp == 'H') return usage_t55xx_detect();
+
+	bool usepwd = ( strlen(Cmd) > 0);	
+	if ( usepwd ){
+		password = param_get32ex(Cmd, 0, 0, 16);
+		// if (param_getchar(Cmd, 1) =='o' )
+			// override = true;
+	}
+
 	
-	if (strlen(Cmd)==0)
-		if ( !AquireData(0, CONFIGURATION_BLOCK, false, 0) )
-			return 0;
+	if (strlen(Cmd)==1) {
+		password = param_get32ex(Cmd, 0, 0, 16);
+		//if (param_getchar(Cmd, 1) =='o' ) override = true;
+	}
 
+	if ( !AquireData(T55x7_PAGE0, T55x7_CONFIGURATION_BLOCK, usepwd, password) )
+		return 0;
+		
 	if ( !tryDetectModulation() )
 		PrintAndLog("Could not detect modulation automatically. Try setting it manually with \'lf t55xx config\'");
 
@@ -408,6 +428,7 @@ bool tryDetectModulation(){
 	int bitRate=0;
 	uint8_t fc1 = 0, fc2 = 0, clk=0;
 	save_restoreGB(1);
+
 	if (GetFskClock("", FALSE, FALSE)){ 
 		fskClocks(&fc1, &fc2, &clk, FALSE);
 		if ( FSKrawDemod("0 0", FALSE) && test(DEMOD_FSK, &tests[hits].offset, &bitRate, clk, &tests[hits].Q5)){
@@ -787,8 +808,8 @@ int CmdT55xxWakeUp(const char *Cmd) {
 
 int CmdT55xxWriteBlock(const char *Cmd) {
 	uint8_t block = 0xFF; //default to invalid block
-	uint32_t data = 0xFFFFFFFF; //default to blank Block 
-	uint32_t password = 0xFFFFFFFF; //default to blank Block 7
+	uint32_t data = 0; //default to blank Block 
+	uint32_t password = 0; //default to blank Block 7
 	bool usepwd = false;
 	bool page1 = false;	
 	bool gotdata = false;
@@ -837,13 +858,15 @@ int CmdT55xxWriteBlock(const char *Cmd) {
 	UsbCommand resp;
  	c.d.asBytes[0] = (page1) ? 0x2 : 0; 
 
-	PrintAndLog("Writing to page: %d  block: %d  data : 0x%08X", page1, block, data);
+	char pwdStr[16] = {0};
+	snprintf(pwdStr, sizeof(pwdStr), "pwd: 0x%08X", password);
+
+	PrintAndLog("Writing page %d  block: %02d  data: 0x%08X %s", page1, block, data,  (usepwd) ? pwdStr : "" );
 
 	//Password mode
 	if (usepwd) {
 		c.arg[2] = password;
 		c.d.asBytes[0] |= 0x1; 
-		PrintAndLog("pwd   : 0x%08X", password);
 	}
 	clearCommandBuffer();
 	SendCommand(&c);
@@ -862,7 +885,7 @@ int CmdT55xxReadTrace(const char *Cmd) {
 		return usage_t55xx_trace();
 
 	if (strlen(Cmd)==0)
-		if ( !AquireData( TRACE_BLOCK, REGULAR_READ_MODE_BLOCK, pwdmode, password ) )
+		if ( !AquireData( T55x7_PAGE1, REGULAR_READ_MODE_BLOCK, pwdmode, password ) )
 			return 0;
 	
 	if (!DecodeT55xxBlock()) return 0;
@@ -951,7 +974,7 @@ int CmdT55xxInfo(const char *Cmd){
 		return usage_t55xx_info();
 	
 	if (strlen(Cmd)==0)
-		if ( !AquireData( 0, CONFIGURATION_BLOCK, pwdmode, password ) )
+		if ( !AquireData( T55x7_PAGE0, T55x7_CONFIGURATION_BLOCK, pwdmode, password ) )
 			return 1;
 
 	if (!DecodeT55xxBlock()) return 1;
@@ -1015,32 +1038,21 @@ int CmdT55xxDump(const char *Cmd){
 			override = true;
 	}
 	
-	PrintAndLog("Reading Page 0:");	
-	PrintAndLog("blk | hex data | binary");
-	for ( uint8_t i = 0; i <8; ++i){
+	printT5xxHeader(0);
+	for ( uint8_t i = 0; i <8; ++i)
 		T55xxReadBlock(i, 0, usepwd, override, password);
-		/*memset(s,0,sizeof(s));
-		if ( hasPwd ) {
-			if ( override ) {
-				sprintf(s,"b %d p %02x%02x%02x%02x o", i, pwd[0],pwd[1],pwd[2],pwd[3]);				
-			} else {
-				sprintf(s,"b %d p %02x%02x%02x%02x", i, pwd[0],pwd[1],pwd[2],pwd[3]);				
-			}
-		} else {
-			sprintf(s,"b %d", i);
-		}
-		CmdT55xxReadBlock(s);*/
-	}
-	PrintAndLog("Reading Page 1:");	
-	PrintAndLog("blk | hex data | binary");
-	for ( uint8_t	i = 0; i<4; i++){
+
+	printT5xxHeader(1);
+	for ( uint8_t	i = 0; i<4; i++)
 		T55xxReadBlock(i, 1, usepwd, override, password);		
-	}
+
 	return 1;
 }
 
 int AquireData( uint8_t page, uint8_t block, bool pwdmode, uint32_t password ){
-
+	// arg0 bitmodes:
+	// bit0 = pwdmode
+	// bit1 = page to read from
 	uint8_t arg0 = (page<<1) | pwdmode;
 	UsbCommand c = {CMD_T55XX_READ_BLOCK, {arg0, block, password}};
 
@@ -1251,33 +1263,34 @@ int CmdResetRead(const char *Cmd) {
 int CmdT55xxWipe(const char *Cmd) {
 	char writeData[20] = {0};
 	char *ptrData = writeData;
-	uint8_t blk = 0;
+
 	PrintAndLog("\nBeginning Wipe of a T55xx tag (assuming the tag is not password protected)\n");
+
 	//try with the default password to reset block 0  (with a pwd should work even if pwd bit not set)
-	snprintf(ptrData,sizeof(writeData),"b %d d 00088040 p 0", blk);
-	if (!CmdT55xxWriteBlock(ptrData)){
-		PrintAndLog("Error writing blk %d", blk);
-	}
-	blk = 1;
-	for (; blk<8; blk++) {
+	snprintf(ptrData,sizeof(writeData),"b 0 d 00088040 p 0");
+
+	if (!CmdT55xxWriteBlock(ptrData))
+		PrintAndLog("Error writing blk 0");
+
+	for (uint8_t blk = 1; blk<8; blk++) {
 		snprintf(ptrData,sizeof(writeData),"b %d d 0", blk);
-		if (!CmdT55xxWriteBlock(ptrData)){
+		if (!CmdT55xxWriteBlock(ptrData))
 			PrintAndLog("Error writing blk %d", blk);
-		}
+
+		memset(writeData, sizeof(writeData), 0x00);
 	}
 	return 0;
 }
 
-static command_t CommandTable[] =
-{
+static command_t CommandTable[] = {
   {"help",     CmdHelp,           1, "This help"},
   {"config",   CmdT55xxSetConfig, 1, "Set/Get T55XX configuration (modulation, inverted, offset, rate)"},
-  {"detect",   CmdT55xxDetect,    0, "[1] Try detecting the tag modulation from reading the configuration block."},
+  {"detect",   CmdT55xxDetect,    1, "[1] Try detecting the tag modulation from reading the configuration block."},
   {"read",     CmdT55xxReadBlock, 0, "b <block> p [password] [o] [1] -- Read T55xx block data. Optional [p password], [override], [page1]"},
   {"resetread",CmdResetRead,      0, "Send Reset Cmd then lf read the stream to attempt to identify the start of it (needs a demod and/or plot after)"},
   {"write",    CmdT55xxWriteBlock,0, "b <block> d <data> p [password] [1] -- Write T55xx block data. Optional [p password], [page1]"},
-  {"trace",    CmdT55xxReadTrace, 0, "[1] Show T55x7 traceability data (page 1/ blk 0-1)"},
-  {"info",     CmdT55xxInfo,      0, "[1] Show T55x7 configuration data (page 0/ blk 0)"},
+  {"trace",    CmdT55xxReadTrace, 1, "[1] Show T55x7 traceability data (page 1/ blk 0-1)"},
+  {"info",     CmdT55xxInfo,      1, "[1] Show T55x7 configuration data (page 0/ blk 0)"},
   {"dump",     CmdT55xxDump,      0, "[password] [o] Dump T55xx card block 0-7. Optional [password], [override]"},
   {"special",  special,           0, "Show block changes with 64 different offsets"},
   {"wakeup",   CmdT55xxWakeUp,    0, "Send AOR wakeup command"},
@@ -1285,14 +1298,12 @@ static command_t CommandTable[] =
   {NULL, NULL, 0, NULL}
 };
 
-int CmdLFT55XX(const char *Cmd)
-{
+int CmdLFT55XX(const char *Cmd) {
   CmdsParse(CommandTable, Cmd);
   return 0;
 }
 
-int CmdHelp(const char *Cmd)
-{
+int CmdHelp(const char *Cmd) {
   CmdsHelp(CommandTable);
   return 0;
 }
diff --git a/client/cmdlfviking.c b/client/cmdlfviking.c
new file mode 100644
index 00000000..b3ea51ca
--- /dev/null
+++ b/client/cmdlfviking.c
@@ -0,0 +1,125 @@
+//-----------------------------------------------------------------------------
+//
+// 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 Viking tag commands
+//-----------------------------------------------------------------------------
+#include <stdio.h>
+#include <string.h>
+#include <inttypes.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 "cmdlfviking.h"
+#include "lfdemod.h"
+static int CmdHelp(const char *Cmd);
+
+int usage_lf_viking_clone(void) {
+	PrintAndLog("clone a Viking AM tag to a T55x7 tag.");
+	PrintAndLog("Usage: lf viking clone <Card ID - 8 hex digits> <Q5>");
+  PrintAndLog("Options :");
+  PrintAndLog("  <Card Number>  : 8 digit hex viking card number");
+  PrintAndLog("  <Q5>           : specify write to Q5 (t5555 instead of t55x7)");
+  PrintAndLog("");
+  PrintAndLog("Sample  : lf viking clone 1A337 Q5");
+	return 0;
+}
+
+int usage_lf_viking_sim(void) {
+  PrintAndLog("Enables simulation of viking card with specified card number.");
+  PrintAndLog("Simulation runs until the button is pressed or another USB command is issued.");
+  PrintAndLog("Per viking format, the card number is 8 digit hex number.  Larger values are truncated.");
+  PrintAndLog("");
+  PrintAndLog("Usage:  lf viking sim <Card-Number>");
+  PrintAndLog("Options :");
+  PrintAndLog("  <Card Number>   : 8 digit hex viking card number");
+  PrintAndLog("");
+  PrintAndLog("Sample  : lf viking sim 1A337");
+  return 0;
+}
+
+uint64_t getVikingBits(uint32_t id) {
+	//calc checksum
+	uint8_t checksum = (id>>24) ^ ((id>>16) & 0xFF) ^ ((id>>8) & 0xFF) ^ (id & 0xFF) ^ 0xF2 ^ 0xA8;
+	return (0xF2 << 56) | (id << 8) | checksum;
+}
+//by marshmellow
+//see ASKDemod for what args are accepted
+int CmdVikingRead(const char *Cmd) {
+	// read lf silently
+	CmdLFRead("s");
+	// get samples silently
+	getSamples("30000",false);
+	// demod and output viking ID	
+	return CmdVikingDemod(Cmd);
+}
+
+int CmdVikingClone(const char *Cmd) {
+	uint32_t id = 0;
+	uint64_t rawID = 0;
+	bool Q5 = false;
+	char cmdp = param_getchar(Cmd, 0);
+	if (strlen(Cmd) < 0 || cmdp == 'h' || cmdp == 'H') return usage_lf_viking_clone();
+
+	id = param_get32ex(Cmd, 0, 0, 16)
+	if (id == 0) return usage_lf_viking_clone();
+	if (param_getchar(Cmd, 1)=='Q' || param_getchar(Cmd, 1)=='q')
+		Q5 = true;
+
+	rawID = getVikingBits(id);
+
+	UsbCommand c = {CMD_VIKING_CLONE_TAG,{rawID >> 32, rawID & 0xFFFF, Q5}};
+	clearCommandBuffer();
+	SendCommand(&c);
+	//check for ACK
+	WaitForResponse(CMD_ACK,NULL);
+	return 0;
+}
+
+int CmdVikingSim(static char *Cmd) {
+	uint32_t id = 0;
+	uint64_t rawID = 0;
+	uint8_t clk = 32, encoding = 1, separator = 0, invert = 0;
+
+	if (strlen(Cmd) < 0 || cmdp == 'h' || cmdp == 'H') return usage_lf_viking_sim();
+	id = param_get32ex(Cmd, 0, 0, 16)
+	if (id == 0) return usage_lf_viking_sim();
+
+	rawID = getVikingBits(id);
+
+  uint16_t arg1, arg2;
+  size_t size = 64;
+  arg1 = clk << 8 | encoding;
+  arg2 = invert << 8 | separator;
+
+  UsbCommand c = {CMD_ASK_SIM_TAG, {arg1, arg2, size}};
+  PrintAndLog("preparing to sim ask data: %d bits", size);
+  num_to_bytebits(rawID, 64, c.d.asBytes);
+	clearCommandBuffer();
+  SendCommand(&c);
+}
+
+static command_t CommandTable[] = {
+	{"help",  CmdHelp,        1, "This help"},
+	{"read",  CmdVikingRead,  0, "Attempt to read and Extract tag data"},
+	{"clone", CmdVikingClone, 0, "<8 digit ID number> clone viking tag"},
+	{"sim",   CmdVikingSim,   0, "<8 digit ID number> simulate viking tag"},
+	{NULL, NULL, 0, NULL}
+};
+
+int CmdLFViking(const char *Cmd) {
+	CmdsParse(CommandTable, Cmd);
+	return 0;
+}
+
+int CmdHelp(const char *Cmd) {
+	CmdsHelp(CommandTable);
+	return 0;
+}
diff --git a/client/cmdlfviking.h b/client/cmdlfviking.h
new file mode 100644
index 00000000..fe4f522c
--- /dev/null
+++ b/client/cmdlfviking.h
@@ -0,0 +1,16 @@
+//-----------------------------------------------------------------------------
+//
+// 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 CMDLFVIKING_H__
+#define CMDLFVIKING_H__
+int CmdLFViking(const char *Cmd);
+int CmdVikingRead(const char *Cmd);
+int CmdVikingClone(const char *Cmd);
+int CmdVikingSim(static char *Cmd);
+#endif
+
diff --git a/client/hid-flasher/usb_cmd.h b/client/hid-flasher/usb_cmd.h
index c8b576fd..46738181 100644
--- a/client/hid-flasher/usb_cmd.h
+++ b/client/hid-flasher/usb_cmd.h
@@ -85,6 +85,7 @@ typedef struct {
 #define CMD_ASK_SIM_TAG                                                   0x021F
 #define CMD_PSK_SIM_TAG                                                   0x0220
 #define CMD_AWID_DEMOD_FSK                                                0x0221
+#define CMD_VIKING_CLONE_TAG                                              0x0223
 #define CMD_T55XX_WAKEUP                                                  0x0224
 
 /* CMD_SET_ADC_MUX: ext1 is 0 for lopkd, 1 for loraw, 2 for hipkd, 3 for hiraw */
diff --git a/client/lualibs/commands.lua b/client/lualibs/commands.lua
index 8cdcfb34..fcf0f07c 100644
--- a/client/lualibs/commands.lua
+++ b/client/lualibs/commands.lua
@@ -56,6 +56,7 @@ local _commands = {
 	CMD_ASK_SIM_TAG =                                                    0x021F,
 	CMD_PSK_SIM_TAG =                                                    0x0220,
 	CMD_AWID_DEMOD_FSK =                                                 0x0221,
+	CMD_VIKING_CLONE_TAG =                                               0x0223,
 	CMD_T55XX_WAKEUP =                                                   0x0224,
 	--/* CMD_SET_ADC_MUX: ext1 is 0 for lopkd, 1 for loraw, 2 for hipkd, 3 for hiraw */
 
diff --git a/client/util.c b/client/util.c
index 5e9fce85..056b5676 100644
--- a/client/util.c
+++ b/client/util.c
@@ -160,6 +160,13 @@ uint64_t bytes_to_num(uint8_t* src, size_t len)
 	return num;
 }
 
+void num_to_bytebits(uint64_t	n, size_t len, uint8_t *dest) {
+	while (len--) {
+		dest[len] = n & 1;
+		n >>= 1;
+	}
+}
+
 // aa,bb,cc,dd,ee,ff,gg,hh, ii,jj,kk,ll,mm,nn,oo,pp
 // to
 // hh,gg,ff,ee,dd,cc,bb,aa, pp,oo,nn,mm,ll,kk,jj,ii
@@ -446,7 +453,7 @@ void binarraytobinstring(char *target, char *source,  int length)
 }
 
 // return parity bit required to match type
-uint8_t GetParity( char *bits, uint8_t type, int length)
+uint8_t GetParity( uint8_t *bits, uint8_t type, int length)
 {
     int x;
 
@@ -458,7 +465,7 @@ uint8_t GetParity( char *bits, uint8_t type, int length)
 }
 
 // add HID parity to binary array: EVEN prefix for 1st half of ID, ODD suffix for 2nd half
-void wiegand_add_parity(char *target, char *source, char length)
+void wiegand_add_parity(uint8_t *target, uint8_t *source, uint8_t length)
 {
     *(target++)= GetParity(source, EVEN, length / 2);
     memcpy(target, source, length);
diff --git a/client/util.h b/client/util.h
index 8bf4f388..6f9a1177 100644
--- a/client/util.h
+++ b/client/util.h
@@ -43,6 +43,7 @@ char * sprint_bin_break(const uint8_t *data, const size_t len, const uint8_t bre
 
 void num_to_bytes(uint64_t n, size_t len, uint8_t* dest);
 uint64_t bytes_to_num(uint8_t* src, size_t len);
+void num_to_bytebits(uint64_t	n, size_t len, uint8_t *dest);
 char * printBits(size_t const size, void const * const ptr);
 uint8_t *SwapEndian64(const uint8_t *src, const size_t len, const uint8_t blockSize);
 
@@ -62,8 +63,8 @@ int param_getstr(const char *line, int paramnum, char * str);
  int hextobinstring( char *target,  char *source);
  int binarraytohex( char *target,  char *source,  int length);
 void binarraytobinstring(char *target,  char *source,  int length);
-uint8_t GetParity( char *string, uint8_t type,  int length);
-void wiegand_add_parity(char *target, char *source, char length);
+uint8_t GetParity( uint8_t *string, uint8_t type,  int length);
+void wiegand_add_parity(uint8_t *target, uint8_t *source, uint8_t length);
 
 void xor(unsigned char *dst, unsigned char *src, size_t len);
 int32_t le24toh(uint8_t data[3]);
diff --git a/common/lfdemod.c b/common/lfdemod.c
index 7297c4e6..1965a0ae 100644
--- a/common/lfdemod.c
+++ b/common/lfdemod.c
@@ -13,17 +13,18 @@
 #include "lfdemod.h"
 #include "common.h"
 
-/* //un_comment to allow debug print calls when used not on device
+//un_comment to allow debug print calls when used not on device
 void dummy(char *fmt, ...){}
 
 #ifndef ON_DEVICE
 #include "ui.h"
+#include "cmdparser.h"
+#include "cmddata.h"
 #define prnt PrintAndLog
 #else 
-
+	uint8_t g_debugMode=0;
 #define prnt dummy
 #endif
-*/
 
 uint8_t justNoise(uint8_t *BitStream, size_t size)
 {
@@ -66,6 +67,81 @@ uint8_t parityTest(uint32_t bits, uint8_t bitLen, uint8_t pType)
 	return (ans == 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) 
+size_t removeParity(uint8_t *BitStream, size_t startIdx, uint8_t pLen, uint8_t pType, size_t bLen)
+{
+	uint32_t parityWd = 0;
+	size_t j = 0, bitCnt = 0;
+	for (int word = 0; word < (bLen); word+=pLen){
+		for (int bit=0; bit < pLen; bit++){
+			parityWd = (parityWd << 1) | BitStream[startIdx+word+bit];
+			BitStream[j++] = (BitStream[startIdx+word+bit]);
+		}
+		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;			
+		}
+		bitCnt+=(pLen-1);
+		parityWd = 0;
+	}
+	// if we got here then all the parities passed
+	//return ID start index and size
+	return bitCnt;
+}
+
+// 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)
+size_t addParity(uint8_t *BitSource, uint8_t *dest, uint8_t sourceLen, uint8_t pLen, uint8_t pType)
+{
+	uint32_t parityWd = 0;
+	size_t j = 0, bitCnt = 0;
+	for (int word = 0; word < sourceLen; word+=pLen-1) {
+		for (int bit=0; bit < pLen-1; bit++){
+			parityWd = (parityWd << 1) | BitSource[word+bit];
+			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;
+		}
+		bitCnt += pLen;
+		parityWd = 0;
+	}
+	// if we got here then all the parities passed
+	//return ID start index and size
+	return bitCnt;
+}
+
+uint32_t bytebits_to_byte(uint8_t *src, size_t numbits)
+{
+	uint32_t num = 0;
+	for(int i = 0 ; i < numbits ; i++)
+	{
+		num = (num << 1) | (*src);
+		src++;
+	}
+	return num;
+}
+
+//least significant bit first
+uint32_t bytebits_to_byteLSBF(uint8_t *src, size_t numbits)
+{
+	uint32_t num = 0;
+	for(int i = 0 ; i < numbits ; i++)
+	{
+		num = (num << 1) | *(src + (numbits-(i+1)));
+	}
+	return num;
+}
+
 //by marshmellow
 //search for given preamble in given BitStream and return success=1 or fail=0 and startIndex and length
 uint8_t preambleSearch(uint8_t *BitStream, uint8_t *preamble, size_t pLen, size_t *size, size_t *startIdx)
@@ -198,6 +274,7 @@ int askdemod(uint8_t *BinStream, size_t *size, int *clk, int *invert, int maxErr
 	if (*clk==0 || start < 0) return -3;
 	if (*invert != 1) *invert = 0;
 	if (amp==1) askAmp(BinStream, *size);
+	if (g_debugMode==2) prnt("DEBUG: clk %d, beststart %d", *clk, start);
 
 	uint8_t initLoopMax = 255;
 	if (initLoopMax > *size) initLoopMax = *size;
@@ -210,6 +287,7 @@ int askdemod(uint8_t *BinStream, size_t *size, int *clk, int *invert, int maxErr
 	size_t errCnt = 0;
 	// if clean clipped waves detected run alternate demod
 	if (DetectCleanAskWave(BinStream, *size, high, low)) {
+		if (g_debugMode==2) prnt("DEBUG: Clean Wave Detected");
 		errCnt = cleanAskRawDemod(BinStream, size, *clk, *invert, high, low);
 		if (askType) //askman
 			return manrawdecode(BinStream, size, 0);	
@@ -551,28 +629,6 @@ int ParadoxdemodFSK(uint8_t *dest, size_t *size, uint32_t *hi2, uint32_t *hi, ui
 	return (int)startIdx;
 }
 
-uint32_t bytebits_to_byte(uint8_t *src, size_t numbits)
-{
-	uint32_t num = 0;
-	for(int i = 0 ; i < numbits ; i++)
-	{
-		num = (num << 1) | (*src);
-		src++;
-	}
-	return num;
-}
-
-//least significant bit first
-uint32_t bytebits_to_byteLSBF(uint8_t *src, size_t numbits)
-{
-	uint32_t num = 0;
-	for(int i = 0 ; i < numbits ; i++)
-	{
-		num = (num << 1) | *(src + (numbits-(i+1)));
-	}
-	return num;
-}
-
 int IOdemodFSK(uint8_t *dest, size_t size)
 {
 	if (justNoise(dest, size)) return -1;
@@ -622,33 +678,6 @@ int VikingDemod_AM(uint8_t *dest, size_t *size) {
 	return (int) startIdx;
 }
 
-// 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) 
-size_t removeParity(uint8_t *BitStream, size_t startIdx, uint8_t pLen, uint8_t pType, size_t bLen)
-{
-	uint32_t parityWd = 0;
-	size_t j = 0, bitCnt = 0;
-	for (int word = 0; word < (bLen); word+=pLen){
-		for (int bit=0; bit < pLen; bit++){
-			parityWd = (parityWd << 1) | BitStream[startIdx+word+bit];
-			BitStream[j++] = (BitStream[startIdx+word+bit]);
-		}
-		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;			
-		}
-		bitCnt+=(pLen-1);
-		parityWd = 0;
-	}
-	// if we got here then all the parities passed
-	//return ID start index and size
-	return bitCnt;
-}
-
 // 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)
@@ -756,7 +785,7 @@ int DetectStrongAskClock(uint8_t dest[], size_t size, uint8_t high, uint8_t low)
 			minClk = i - startwave;
 	}
 	// set clock
-	//prnt("minClk: %d",minClk);
+	if (g_debugMode==2) prnt("DEBUG ASK: detectstrongASKclk smallest wave: %d",minClk);
 	for (uint8_t clkCnt = 0; clkCnt<7; clkCnt++) {
 		if (minClk >= fndClk[clkCnt]-(fndClk[clkCnt]/8) && minClk <= fndClk[clkCnt]+1)
 			return fndClk[clkCnt];
@@ -790,6 +819,7 @@ int DetectASKClock(uint8_t dest[], size_t size, int *clock, int maxErr)
 	if (!clockFnd){
 		if (DetectCleanAskWave(dest, size, peak, low)==1){
 			int ans = DetectStrongAskClock(dest, size, peak, low);
+			if (g_debugMode==2) prnt("DEBUG ASK: detectaskclk Clean Ask Wave Detected: clk %d",ans);
 			for (i=clkEnd-1; i>0; i--){
 				if (clk[i] == ans) {
 					*clock = ans;
@@ -841,7 +871,7 @@ int DetectASKClock(uint8_t dest[], size_t size, int *clock, int maxErr)
 			}
 			//if we found no errors then we can stop here and a low clock (common clocks)
 			//  this is correct one - return this clock
-					//prnt("DEBUG: clk %d, err %d, ii %d, i %d",clk[clkCnt],errCnt,ii,i);
+			if (g_debugMode == 2) prnt("DEBUG ASK: clk %d, err %d, startpos %d, endpos %d",clk[clkCnt],errCnt,ii,i);
 			if(errCnt==0 && clkCnt<7) { 
 				if (!clockFnd) *clock = clk[clkCnt];
 				return ii;
@@ -863,8 +893,8 @@ int DetectASKClock(uint8_t dest[], size_t size, int *clock, int maxErr)
 				best = iii;
 			}
 		}
+		if (g_debugMode == 2) prnt("DEBUG ASK: clk %d, # Errors %d, Current Best Clk %d, bestStart %d",clk[iii],bestErr[iii],clk[best],bestStart[best]);
 	}
-	//if (bestErr[best] > maxErr) return -1;
 	if (!clockFnd) *clock = clk[best];
 	return bestStart[best];
 }
@@ -891,7 +921,7 @@ int DetectPSKClock(uint8_t dest[], size_t size, int clock)
 	uint16_t peaksdet[]={0,0,0,0,0,0,0,0,0};
 	fc = countFC(dest, size, 0);
 	if (fc!=2 && fc!=4 && fc!=8) return -1;
-	//prnt("DEBUG: FC: %d",fc);
+	if (g_debugMode==2) prnt("DEBUG PSK: FC: %d",fc);
 
 	//find first full wave
 	for (i=160; i<loopCnt; i++){
@@ -912,7 +942,7 @@ int DetectPSKClock(uint8_t dest[], size_t size, int clock)
 			}
 		}
 	}
-	//prnt("DEBUG: firstFullWave: %d, waveLen: %d",firstFullWave,fullWaveLen);
+	if (g_debugMode ==2) prnt("DEBUG PSK: firstFullWave: %d, waveLen: %d",firstFullWave,fullWaveLen);
 	
 	//test each valid clock from greatest to smallest to see which lines up
 	for(clkCnt=7; clkCnt >= 1 ; clkCnt--){
@@ -920,7 +950,7 @@ int DetectPSKClock(uint8_t dest[], size_t size, int clock)
 		waveStart = 0;
 		errCnt=0;
 		peakcnt=0;
-		//prnt("DEBUG: clk: %d, lastClkBit: %d",clk[clkCnt],lastClkBit);
+		if (g_debugMode == 2) prnt("DEBUG PSK: clk: %d, lastClkBit: %d",clk[clkCnt],lastClkBit);
 
 		for (i = firstFullWave+fullWaveLen-1; i < loopCnt-2; i++){
 			//top edge of wave = start of new wave 
@@ -933,7 +963,7 @@ int DetectPSKClock(uint8_t dest[], size_t size, int clock)
 					waveLenCnt = waveEnd-waveStart;
 					if (waveLenCnt > fc){ 
 						//if this wave is a phase shift
-						//prnt("DEBUG: phase shift at: %d, len: %d, nextClk: %d, ii: %d, fc: %d",waveStart,waveLenCnt,lastClkBit+clk[clkCnt]-tol,ii+1,fc);
+						if (g_debugMode == 2) prnt("DEBUG PSK: phase shift at: %d, len: %d, nextClk: %d, i: %d, fc: %d",waveStart,waveLenCnt,lastClkBit+clk[clkCnt]-tol,i+1,fc);
 						if (i+1 >= lastClkBit + clk[clkCnt] - tol){ //should be a clock bit
 							peakcnt++;
 							lastClkBit+=clk[clkCnt];
@@ -962,7 +992,7 @@ int DetectPSKClock(uint8_t dest[], size_t size, int clock)
 		if (peaksdet[i] > peaksdet[best]) {
 			best = i;
 		}
-		//prnt("DEBUG: Clk: %d, peaks: %d, errs: %d, bestClk: %d",clk[iii],peaksdet[iii],bestErr[iii],clk[best]);
+		if (g_debugMode == 2) prnt("DEBUG PSK: Clk: %d, peaks: %d, errs: %d, bestClk: %d",clk[i],peaksdet[i],bestErr[i],clk[best]);
 	}
 	return clk[best];
 }
@@ -991,8 +1021,8 @@ int DetectStrongNRZClk(uint8_t *dest, size_t size, int peak, int low){
 			transition1 = i;
 		}
 	}
-	//prnt("DEBUG: LowestTrs: %d",lowestTransition);
 	if (lowestTransition == 255) lowestTransition = 0;
+	if (g_debugMode==2) prnt("DEBUG NRZ: detectstrongNRZclk smallest wave: %d",lowestTransition);
 	return lowestTransition;
 }
 
@@ -1107,7 +1137,7 @@ int DetectNRZClock(uint8_t dest[], size_t size, int clock)
 		} else if (peaksdet[iii] > peaksdet[best]){
 			best = iii;
 		}
-		//prnt("DEBUG: Clk: %d, peaks: %d, maxPeak: %d, bestClk: %d, lowestTrs: %d",clk[iii],peaksdet[iii],maxPeak, clk[best], lowestTransition);
+		if (g_debugMode==2) prnt("DEBUG NRZ: Clk: %d, peaks: %d, maxPeak: %d, bestClk: %d, lowestTrs: %d",clk[iii],peaksdet[iii],maxPeak, clk[best], lowestTransition);
 	}
 
 	return clk[best];
@@ -1268,7 +1298,6 @@ uint8_t detectFSKClk(uint8_t *BitStream, size_t size, uint8_t fcHigh, uint8_t fc
 	uint8_t rfHighest=15, rfHighest2=15, rfHighest3=15;
 
 	for (i=0; i<15; i++){
-		//prnt("DEBUG: RF %d, cnts %d",rfLens[i], rfCnts[i]);
 		//get highest 2 RF values  (might need to get more values to compare or compare all?)
 		if (rfCnts[i]>rfCnts[rfHighest]){
 			rfHighest3=rfHighest2;
@@ -1280,12 +1309,13 @@ uint8_t detectFSKClk(uint8_t *BitStream, size_t size, uint8_t fcHigh, uint8_t fc
 		} else if(rfCnts[i]>rfCnts[rfHighest3]){
 			rfHighest3=i;
 		}
+		if (g_debugMode==2) prnt("DEBUG FSK: RF %d, cnts %d",rfLens[i], rfCnts[i]);
 	}  
 	// set allowed clock remainder tolerance to be 1 large field clock length+1 
 	//   we could have mistakenly made a 9 a 10 instead of an 8 or visa versa so rfLens could be 1 FC off  
 	uint8_t tol1 = fcHigh+1; 
 	
-	//prnt("DEBUG: hightest: 1 %d, 2 %d, 3 %d",rfLens[rfHighest],rfLens[rfHighest2],rfLens[rfHighest3]);
+	if (g_debugMode==2) prnt("DEBUG FSK: most counted rf values: 1 %d, 2 %d, 3 %d",rfLens[rfHighest],rfLens[rfHighest2],rfLens[rfHighest3]);
 
 	// loop to find the highest clock that has a remainder less than the tolerance
 	//   compare samples counted divided by
@@ -1295,6 +1325,7 @@ uint8_t detectFSKClk(uint8_t *BitStream, size_t size, uint8_t fcHigh, uint8_t fc
 		if (rfLens[rfHighest] % clk[ii] < tol1 || rfLens[rfHighest] % clk[ii] > clk[ii]-tol1){
 			if (rfLens[rfHighest2] % clk[ii] < tol1 || rfLens[rfHighest2] % clk[ii] > clk[ii]-tol1){
 				if (rfLens[rfHighest3] % clk[ii] < tol1 || rfLens[rfHighest3] % clk[ii] > clk[ii]-tol1){
+					if (g_debugMode==2) prnt("DEBUG FSK: clk %d divides into the 3 most rf values within tolerance",clk[ii]);
 					break;
 				}
 			}
@@ -1361,7 +1392,6 @@ uint16_t countFC(uint8_t *BitStream, size_t size, uint8_t fskAdj)
 	uint16_t maxCnt1=0;
 	// go through fclens and find which ones are bigest 2  
 	for (i=0; i<15; i++){
-		//prnt("DEBUG: FC %d, Cnt %d",fcLens[i],fcCnts[i]);    
 		// get the 3 best FC values
 		if (fcCnts[i]>maxCnt1) {
 			best3=best2;
@@ -1374,6 +1404,7 @@ uint16_t countFC(uint8_t *BitStream, size_t size, uint8_t fskAdj)
 		} else if(fcCnts[i]>fcCnts[best3]){
 			best3=i;
 		}
+		if (g_debugMode==2) prnt("DEBUG countfc: FC %u, Cnt %u, best fc: %u, best2 fc: %u",fcLens[i],fcCnts[i],fcLens[best1],fcLens[best2]);
 	}
 	if (fcLens[best1]==0) return 0;
 	uint8_t fcH=0, fcL=0;
@@ -1384,13 +1415,13 @@ uint16_t countFC(uint8_t *BitStream, size_t size, uint8_t fskAdj)
 		fcH=fcLens[best2];
 		fcL=fcLens[best1];
 	}
-	//prnt("DEBUG: dd %d > %d",(size-180)/fcH/3,fcCnts[best1]+fcCnts[best2]);
-	if ((size-180)/fcH/3 > fcCnts[best1]+fcCnts[best2]) return 0; //lots of waves not psk or fsk
-
+	if ((size-180)/fcH/3 > fcCnts[best1]+fcCnts[best2]) {
+		if (g_debugMode==2) prnt("DEBUG countfc: fc is too large: %u > %u. Not psk or fsk",(size-180)/fcH/3,fcCnts[best1]+fcCnts[best2]);
+		return 0; //lots of waves not psk or fsk
+	}
 	// TODO: take top 3 answers and compare to known Field clocks to get top 2
 
 	uint16_t fcs = (((uint16_t)fcH)<<8) | fcL;
-	//prnt("DEBUG: Best %d  best2 %d best3 %d",fcLens[best1],fcLens[best2],fcLens[best3]);
 	if (fskAdj) return fcs;	
 	return fcLens[best1];
 }
diff --git a/common/lfdemod.h b/common/lfdemod.h
index 0e1e99ad..20eb6769 100644
--- a/common/lfdemod.h
+++ b/common/lfdemod.h
@@ -16,6 +16,7 @@
 #include <stdint.h>
 
 //generic
+size_t   addParity(uint8_t *BitSource, uint8_t *dest, uint8_t sourceLen, uint8_t pLen, uint8_t pType);
 int      askdemod(uint8_t *BinStream, size_t *size, int *clk, int *invert, int maxErr, uint8_t amp, uint8_t askType);
 int      BiphaseRawDecode(uint8_t * BitStream, size_t *size, int offset, int invert);
 uint32_t bytebits_to_byte(uint8_t* src, size_t numbits);
diff --git a/include/usb_cmd.h b/include/usb_cmd.h
index b8a12966..38f8617a 100644
--- a/include/usb_cmd.h
+++ b/include/usb_cmd.h
@@ -99,6 +99,7 @@ typedef struct{
 #define CMD_ASK_SIM_TAG                                                   0x021F
 #define CMD_PSK_SIM_TAG                                                   0x0220
 #define CMD_AWID_DEMOD_FSK                                                0x0221
+#define CMD_VIKING_CLONE_TAG                                              0x0223
 #define CMD_T55XX_WAKEUP                                                  0x0224