From: skamkar <skamkar@ef4ab9da-24cd-11de-8aaa-f3a34680c41f>
Date: Mon, 13 Jul 2009 04:54:37 +0000 (+0000)
Subject: Added stand-alone mode (no PC) with HID reading and cloning, moved helper functions... 
X-Git-Tag: v1.0.0~568
X-Git-Url: https://git.zerfleddert.de/cgi-bin/gitweb.cgi/proxmark3-svn/commitdiff_plain/955fc5e2f83742dc68d4bc0505314e0da6a840cc

Added stand-alone mode (no PC) with HID reading and cloning, moved helper functions to util.c
---

diff --git a/armsrc/appmain.c b/armsrc/appmain.c
index 77bbbbc4..a137a8fe 100644
--- a/armsrc/appmain.c
+++ b/armsrc/appmain.c
@@ -17,6 +17,7 @@
 // The large multi-purpose buffer, typically used to hold A/D samples,
 // maybe pre-processed in some way.
 DWORD BigBuf[16000];
+int usbattached = 0;
 
 //=============================================================================
 // A buffer where we can queue things up to be sent through the FPGA, for
@@ -67,6 +68,10 @@ void ToSendStuffBit(int b)
 
 void DbpString(char *str)
 {
+	/* this holds up stuff unless we're connected to usb */
+	if (!usbattached)
+		return;
+	
 	UsbCommand c;
 	c.cmd = CMD_DEBUG_PRINT_STRING;
 	c.ext1 = strlen(str);
@@ -79,6 +84,10 @@ void DbpString(char *str)
 
 void DbpIntegers(int x1, int x2, int x3)
 {
+	/* this holds up stuff unless we're connected to usb */
+	if (!usbattached)
+		return;
+
 	UsbCommand c;
 	c.cmd = CMD_DEBUG_PRINT_INTEGERS;
 	c.ext1 = x1;
@@ -320,7 +329,7 @@ void MeasureAntennaTuning(void)
 	UsbSendPacket((BYTE *)&c, sizeof(c));
 }
 
-void SimulateTagLowFrequency(int period)
+void SimulateTagLowFrequency(int period, int ledcontrol)
 {
 	int i;
 	BYTE *tab = (BYTE *)BigBuf;
@@ -345,13 +354,16 @@ void SimulateTagLowFrequency(int period)
 			WDT_HIT();
 		}
 
-		LED_D_ON();
-		if(tab[i]) {
+		if (ledcontrol)
+			LED_D_ON();
+
+		if(tab[i])
 			OPEN_COIL();
-		} else {
+		else
 			SHORT_COIL();
-		}
-		LED_D_OFF();
+		
+		if (ledcontrol)
+			LED_D_OFF();
 
 		while(PIO_PIN_DATA_STATUS & (1<<GPIO_SSC_CLK)) {
 			if(BUTTON_PRESS()) {
@@ -415,7 +427,7 @@ static void fc(int c, int *n) {
 
 // prepare a waveform pattern in the buffer based on the ID given then
 // simulate a HID tag until the button is pressed
-static void CmdHIDsimTAG(int hi, int lo)
+static void CmdHIDsimTAG(int hi, int lo, int ledcontrol)
 {
 	int n=0, i=0;
 	/*
@@ -461,13 +473,16 @@ static void CmdHIDsimTAG(int hi, int lo)
 		}
 	}
 
-	LED_A_ON();
-	SimulateTagLowFrequency(n);
-	LED_A_OFF();
+	if (ledcontrol)
+		LED_A_ON();
+	SimulateTagLowFrequency(n, ledcontrol);
+	
+	if (ledcontrol)
+		LED_A_OFF();
 }
 
 // loop to capture raw HID waveform then FSK demodulate the TAG ID from it
-static void CmdHIDdemodFSK(void)
+static void CmdHIDdemodFSK(int findone, int *high, int *low, int ledcontrol)
 {
 	BYTE *dest = (BYTE *)BigBuf;
 	int m=0, n=0, i=0, idx=0, found=0, lastval=0;
@@ -487,10 +502,12 @@ static void CmdHIDdemodFSK(void)
 
 	for(;;) {
 		WDT_HIT();
-		LED_A_ON();
+		if (ledcontrol)
+			LED_A_ON();
 		if(BUTTON_PRESS()) {
 			DbpString("Stopped");
-			LED_A_OFF();
+			if (ledcontrol)
+				LED_A_OFF();
 			return;
 		}
 
@@ -500,7 +517,8 @@ static void CmdHIDdemodFSK(void)
 		for(;;) {
 			if(SSC_STATUS & (SSC_STATUS_TX_READY)) {
 				SSC_TRANSMIT_HOLDING = 0x43;
-				LED_D_ON();
+				if (ledcontrol)
+					LED_D_ON();
 			}
 			if(SSC_STATUS & (SSC_STATUS_RX_READY)) {
 				dest[i] = (BYTE)SSC_RECEIVE_HOLDING;
@@ -508,7 +526,8 @@ static void CmdHIDdemodFSK(void)
 				// threshold essentially we capture zero crossings for later analysis
 				if(dest[i] < 127) dest[i] = 0; else dest[i] = 1;
 				i++;
-				LED_D_OFF();
+				if (ledcontrol)
+					LED_D_OFF();
 				if(i >= m) {
 					break;
 				}
@@ -607,6 +626,13 @@ static void CmdHIDdemodFSK(void)
 				if (found && (hi|lo)) {
 					DbpString("TAG ID");
 					DbpIntegers(hi, lo, (lo>>1)&0xffff);
+					/* if we're only looking for one tag */
+					if (findone)
+					{
+						*high = hi;
+						*low = lo;
+						return;
+					}
 					hi=0;
 					lo=0;
 					found=0;
@@ -633,6 +659,13 @@ static void CmdHIDdemodFSK(void)
 				if (found && (hi|lo)) {
 					DbpString("TAG ID");
 					DbpIntegers(hi, lo, (lo>>1)&0xffff);
+					/* if we're only looking for one tag */
+					if (findone)
+					{
+						*high = hi;
+						*low = lo;
+						return;
+					}
 					hi=0;
 					lo=0;
 					found=0;
@@ -759,11 +792,11 @@ void UsbPacketReceived(BYTE *packet, int len)
 			break;
 
 		case CMD_HID_DEMOD_FSK:
-			CmdHIDdemodFSK();				// Demodulate HID tag
+			CmdHIDdemodFSK(0, 0, 0, 1);				// Demodulate HID tag
 			break;
 
 		case CMD_HID_SIM_TAG:
-			CmdHIDsimTAG(c->ext1, c->ext2);					// Simulate HID tag by ID
+			CmdHIDsimTAG(c->ext1, c->ext2, 1);					// Simulate HID tag by ID
 			break;
 
 		case CMD_FPGA_MAJOR_MODE_OFF:		// ## FPGA Control
@@ -792,7 +825,7 @@ void UsbPacketReceived(BYTE *packet, int len)
 		}
 		case CMD_SIMULATE_TAG_125K:
 			LED_A_ON();
-			SimulateTagLowFrequency(c->ext1);
+			SimulateTagLowFrequency(c->ext1, 1);
 			LED_A_OFF();
 			break;
 #ifdef WITH_LCD
@@ -887,55 +920,110 @@ void AppMain(void)
 #endif
 
 	for(;;) {
-		UsbPoll(FALSE);
+		usbattached = UsbPoll(FALSE);
 		WDT_HIT();
-	}
-}
-
-void SpinDelayUs(int us)
-{
-	int ticks = (48*us) >> 10;
-
-	// Borrow a PWM unit for my real-time clock
-	PWM_ENABLE = PWM_CHANNEL(0);
-	// 48 MHz / 1024 gives 46.875 kHz
-	PWM_CH_MODE(0) = PWM_CH_MODE_PRESCALER(10);
-	PWM_CH_DUTY_CYCLE(0) = 0;
-	PWM_CH_PERIOD(0) = 0xffff;
-
-	WORD start = (WORD)PWM_CH_COUNTER(0);
 
-	for(;;) {
-		WORD now = (WORD)PWM_CH_COUNTER(0);
-		if(now == (WORD)(start + ticks)) {
-			return;
-		}
-		WDT_HIT();
+		if (BUTTON_HELD(1000) > 0)
+			SamyRun();
 	}
 }
 
-void SpinDelay(int ms)
-{
-	int ticks = (48000*ms) >> 10;
 
-	// Borrow a PWM unit for my real-time clock
-	PWM_ENABLE = PWM_CHANNEL(0);
-	// 48 MHz / 1024 gives 46.875 kHz
-	PWM_CH_MODE(0) = PWM_CH_MODE_PRESCALER(10);
-	PWM_CH_DUTY_CYCLE(0) = 0;
-	PWM_CH_PERIOD(0) = 0xffff;
+// samy's sniff and repeat routine
+void SamyRun()
+{
+	DbpString("Stand-alone mode! No PC necessary.");
 
-	WORD start = (WORD)PWM_CH_COUNTER(0);
+	// 3 possible options? no just 2 for now
+#define OPTS 2
 
-	for(;;) {
-		WORD now = (WORD)PWM_CH_COUNTER(0);
-		if(now == (WORD)(start + ticks)) {
-			return;
-		}
+	int high[OPTS], low[OPTS];
+	
+	// Oooh pretty -- notify user we're in elite samy mode now
+	LED(LED_RED,	200);
+	LED(LED_ORANGE, 200);
+	LED(LED_GREEN,	200);
+	LED(LED_ORANGE, 200);
+	LED(LED_RED,	200);
+	LED(LED_ORANGE, 200);
+	LED(LED_GREEN,	200);
+	LED(LED_ORANGE, 200);
+	LED(LED_RED,	200);
+	
+	int selected = 0;
+	int playing = 0;
+	
+	// Turn on selected LED
+	LED(selected + 1, 0);
+	
+	for (;;)
+	{
+		usbattached = UsbPoll(FALSE);
 		WDT_HIT();
+		
+		// Was our button held down or pressed?
+		int button_pressed = BUTTON_HELD(1000);
+		SpinDelay(300);
+		
+		// Button was held for a second, begin recording
+		if (button_pressed > 0)
+		{
+			LEDsoff();
+			LED(selected + 1, 0);
+			LED(LED_RED2, 0);
+						
+			// record
+			DbpString("Starting recording");
+			
+			/* need this delay to prevent catching some weird data */
+			SpinDelay(500);
+			CmdHIDdemodFSK(1, &high[selected], &low[selected], 0);
+			DbpString("Recorded");
+			DbpIntegers(selected, high[selected], low[selected]);
+			
+			LEDsoff();
+			LED(selected + 1, 0);
+			// Finished recording
+			
+			// If we were previously playing, set playing off
+			// so next button push begins playing what we recorded
+			playing = 0;
+		}
+		
+		// Change where to record (or begin playing)
+		else if (button_pressed)
+		{
+			// Next option if we were previously playing
+			if (playing)
+				selected = (selected + 1) % OPTS;
+			playing = !playing;
+			
+			LEDsoff();
+			LED(selected + 1, 0);
+			
+			// Begin transmitting
+			if (playing)
+			{
+				LED(LED_GREEN, 0);
+				DbpString("Playing");
+				DbpIntegers(selected, high[selected], low[selected]);
+				CmdHIDsimTAG(high[selected], low[selected], 0);
+				DbpString("Done playing");
+				
+				/* We pressed a button so ignore it here with a delay */
+				SpinDelay(300);
+				
+				// when done, we're done playing, move to next option
+				selected = (selected + 1) % OPTS;
+				playing = !playing;
+				LEDsoff();
+				LED(selected + 1, 0);
+			}
+		}
 	}
 }
 
+
 // listen for external reader 
 void ListenReaderField(int limit)
 {
diff --git a/armsrc/apps.h b/armsrc/apps.h
index f2be7904..7e40fdd0 100644
--- a/armsrc/apps.h
+++ b/armsrc/apps.h
@@ -9,10 +9,9 @@
 
 /// appmain.c
 void AppMain(void);
+void SamyRun(void);
 void DbpIntegers(int a, int b, int c);
 void DbpString(char *str);
-void SpinDelay(int ms);
-void SpinDelayUs(int us);
 void ToSendStuffBit(int b);
 void ToSendReset(void);
 void ListenReaderField(int limit);
@@ -78,9 +77,24 @@ void ReaderIso15693(DWORD parameter);	// Simulate an ISO15693 reader - greg
 void SimTagIso15693(DWORD parameter);	// simulate an ISO15693 tag - greg
 
 /// util.h
+#define LED_RED 1
+#define LED_ORANGE 2
+#define LED_GREEN 4
+#define LED_RED2 8
+#define BUTTON_HOLD 1
+#define BUTTON_NO_CLICK 0
+#define BUTTON_SINGLE_CLICK -1
+#define BUTTON_DOUBLE_CLICK -2
+#define BUTTON_ERROR -99
 int strlen(char *str);
 void *memcpy(void *dest, const void *src, int len);
 void *memset(void *dest, int c, int len);
 int memcmp(const void *av, const void *bv, int len);
+void SpinDelay(int ms);
+void SpinDelayUs(int us);
+void LED(int led, int ms);
+void LEDsoff();
+int BUTTON_CLICKED(int ms);
+int BUTTON_HELD(int ms);
 
 #endif
diff --git a/armsrc/util.c b/armsrc/util.c
index b3f0e76e..5af09f88 100644
--- a/armsrc/util.c
+++ b/armsrc/util.c
@@ -51,3 +51,189 @@ int strlen(char *str)
 	}
 	return l;
 }
+
+void LEDsoff()
+{
+	LED_A_OFF();
+	LED_B_OFF();
+	LED_C_OFF();
+	LED_D_OFF();
+}
+
+// LEDs: R(C) O(A) G(B) -- R(D) [1, 2, 4 and 8]
+void LED(int led, int ms)
+{
+	if (led & LED_RED)
+		LED_C_ON();
+	if (led & LED_ORANGE)
+		LED_A_ON();
+	if (led & LED_GREEN)
+		LED_B_ON();
+	if (led & LED_RED2)
+		LED_D_ON();
+
+	if (!ms)
+		return;
+
+	SpinDelay(ms);
+
+	if (led & LED_RED)
+		LED_C_OFF();
+	if (led & LED_ORANGE)
+		LED_A_OFF();
+	if (led & LED_GREEN)
+		LED_B_OFF();
+	if (led & LED_RED2)
+		LED_D_OFF();
+}
+	
+
+// Determine if a button is double clicked, single clicked,
+// not clicked, or held down (for ms || 1sec)
+// In general, don't use this function unless you expect a
+// double click, otherwise it will waste 500ms -- use BUTTON_HELD instead
+int BUTTON_CLICKED(int ms)
+{
+	// Up to 500ms in between clicks to mean a double click
+	int ticks = (48000 * (ms ? ms : 1000)) >> 10;
+
+	// If we're not even pressed, forget about it!
+	if (!BUTTON_PRESS())
+		return BUTTON_NO_CLICK;
+
+	// Borrow a PWM unit for my real-time clock
+	PWM_ENABLE = PWM_CHANNEL(0);
+	// 48 MHz / 1024 gives 46.875 kHz
+	PWM_CH_MODE(0) = PWM_CH_MODE_PRESCALER(10);
+	PWM_CH_DUTY_CYCLE(0) = 0;
+	PWM_CH_PERIOD(0) = 0xffff;
+	
+	WORD start = (WORD)PWM_CH_COUNTER(0);
+	
+	int letoff = 0;
+	for(;;)
+	{
+		WORD now = (WORD)PWM_CH_COUNTER(0);
+		
+		// We haven't let off the button yet
+		if (!letoff)
+		{
+			// We just let it off!
+			if (!BUTTON_PRESS())
+			{
+				letoff = 1;
+
+				// reset our timer for 500ms
+				start = (WORD)PWM_CH_COUNTER(0);
+				ticks = (48000 * (500)) >> 10;
+			}
+
+			// Still haven't let it off
+			else
+				// Have we held down a full second?
+				if (now == (WORD)(start + ticks))
+					return BUTTON_HOLD;
+		}
+
+		// We already let off, did we click again?
+		else
+			// Sweet, double click!
+			if (BUTTON_PRESS())
+				return BUTTON_DOUBLE_CLICK;
+
+			// Have we ran out of time to double click?
+			else
+				if (now == (WORD)(start + ticks))
+					// At least we did a single click
+					return BUTTON_SINGLE_CLICK;
+
+		WDT_HIT();
+	}
+
+	// We should never get here
+	return BUTTON_ERROR;
+}
+
+// Determine if a button is held down
+int BUTTON_HELD(int ms)
+{
+	// If button is held for one second
+	int ticks = (48000 * (ms ? ms : 1000)) >> 10;
+
+	// If we're not even pressed, forget about it!
+	if (!BUTTON_PRESS())
+		return BUTTON_NO_CLICK;
+	
+	// Borrow a PWM unit for my real-time clock
+	PWM_ENABLE = PWM_CHANNEL(0);
+	// 48 MHz / 1024 gives 46.875 kHz
+	PWM_CH_MODE(0) = PWM_CH_MODE_PRESCALER(10);
+	PWM_CH_DUTY_CYCLE(0) = 0;
+	PWM_CH_PERIOD(0) = 0xffff;
+	
+	WORD start = (WORD)PWM_CH_COUNTER(0);
+	
+	for(;;)
+	{
+		WORD now = (WORD)PWM_CH_COUNTER(0);
+		
+		// As soon as our button let go, we didn't hold long enough
+		if (!BUTTON_PRESS())
+			return BUTTON_SINGLE_CLICK;
+
+		// Have we waited the full second?
+		else
+			if (now == (WORD)(start + ticks))
+				return BUTTON_HOLD;
+		
+		WDT_HIT();
+	}
+
+	// We should never get here
+	return BUTTON_ERROR;
+}
+
+void SpinDelayUs(int us)
+{
+	int ticks = (48*us) >> 10;
+	
+	// Borrow a PWM unit for my real-time clock
+	PWM_ENABLE = PWM_CHANNEL(0);
+	// 48 MHz / 1024 gives 46.875 kHz
+	PWM_CH_MODE(0) = PWM_CH_MODE_PRESCALER(10);
+	PWM_CH_DUTY_CYCLE(0) = 0;
+	PWM_CH_PERIOD(0) = 0xffff;
+	
+	WORD start = (WORD)PWM_CH_COUNTER(0);
+	
+	for(;;) {
+		WORD now = (WORD)PWM_CH_COUNTER(0);
+		if(now == (WORD)(start + ticks)) {
+			return;
+		}
+		WDT_HIT();
+	}
+}
+
+void SpinDelay(int ms)
+{
+	int ticks = (48000*ms) >> 10;
+
+	// Borrow a PWM unit for my real-time clock
+	PWM_ENABLE = PWM_CHANNEL(0);
+	// 48 MHz / 1024 gives 46.875 kHz
+	PWM_CH_MODE(0) = PWM_CH_MODE_PRESCALER(10);
+	PWM_CH_DUTY_CYCLE(0) = 0;
+	PWM_CH_PERIOD(0) = 0xffff;
+
+	WORD start = (WORD)PWM_CH_COUNTER(0);
+
+	for(;;)
+	{
+		WORD now = (WORD)PWM_CH_COUNTER(0);
+		if (now == (WORD)(start + ticks))
+			return;
+
+		WDT_HIT();
+	}
+}