From bd4cc2c95b3aa115d67790937d3d943a8a6546cf Mon Sep 17 00:00:00 2001
From: d18c7db <d18c7db@ef4ab9da-24cd-11de-8aaa-f3a34680c41f>
Date: Mon, 20 Jul 2009 08:20:23 +0000
Subject: [PATCH] Added a way to overlay a grid to graph window

---
 cockpit/prox.bat   |   3 +-
 winsrc/command.cpp | 153 +++++++++++++++++++++++----------------------
 winsrc/gui.cpp     |  88 ++++++++++++++++----------
 winsrc/prox.h      |   1 +
 4 files changed, 134 insertions(+), 111 deletions(-)

diff --git a/cockpit/prox.bat b/cockpit/prox.bat
index 06b24edc..4a543363 100644
--- a/cockpit/prox.bat
+++ b/cockpit/prox.bat
@@ -1,3 +1,2 @@
 @echo off
-cd ..\winsrc
-call prox gui
\ No newline at end of file
+call ..\winsrc\prox %1
diff --git a/winsrc/command.cpp b/winsrc/command.cpp
index 455e48c8..bc9fb9dc 100644
--- a/winsrc/command.cpp
+++ b/winsrc/command.cpp
@@ -1798,9 +1798,9 @@ static void CmdThreshold(char *str)
 
 	for(i = 0; i < GraphTraceLen; i++) {
 		if(GraphBuffer[i]>= threshold)
-			GraphBuffer[i]=127;
+			GraphBuffer[i]=1;
 		else
-			GraphBuffer[i]=-128;
+			GraphBuffer[i]=-1;
 	}
 	RepaintGraphWindow();
 }
@@ -2588,6 +2588,14 @@ static void CmdPlot(char *str)
 	ShowGraphWindow();
 }
 
+static void CmdGrid(char *str)
+{
+	int x = 0, y = 0;
+  sscanf(str, "%i %i", &x, &y);
+	SetGraphGrid(x, y);
+	RepaintGraphWindow();
+}
+
 static void CmdHide(char *str)
 {
 	HideGraphWindow();
@@ -2684,12 +2692,6 @@ static void CmdLcd(char *str)
 	}
 }
 
-
-
-static void CmdTest(char *str)
-{
-}
-
 /*
  * Sets the divisor for LF frequency clock: lets the user choose any LF frequency below
  * 600kHz.
@@ -2716,73 +2718,74 @@ static struct {
 	int		offline;  // 1 if the command can be used when in offline mode
 	char		*docString;
 } CommandTable[] = {
-	{"askdemod",			Cmdaskdemod,1,		"<samples per bit> <0|1> -- Attempt to demodulate simple ASK tags"},
-	{"autocorr",			CmdAutoCorr,1,		"<window length> -- Autocorrelation over window"},
-	{"bitsamples",		CmdBitsamples,0,	"    Get raw samples as bitstring"},
-	{"bitstream",			Cmdbitstream,1,		"[clock rate] -- Convert waveform into a bitstream"},
-	{"buffclear",			CmdBuffClear,0,		"    Clear sample buffer and graph window"},
-	{"dec",						CmdDec,1,		"    Decimate samples"},
-	{"detectclock",		Cmddetectclockrate,1, "    Detect clock rate"},
-	{"detectreader",	CmdDetectReader,0, "['l'|'h'] -- Detect external reader field (option 'l' or 'h' to limit to LF or HF)"},
-	{"em410xsim",			CmdEM410xsim,1,		"<UID> -- Simulate EM410x tag"},
-	{"em410xread",		CmdEM410xread,1,	"[clock rate] -- Extract ID from EM410x tag"},
-	{"em410xwatch",		CmdEM410xwatch,0,	"    Watches for EM410x tags"},
-	{"em4x50read",		CmdEM4x50read,1,	"    Extract data from EM4x50 tag"},
-	{"exit",					CmdQuit,1,			"    Exit program"},
-	{"flexdemod",			CmdFlexdemod,1,		"    Demodulate samples for FlexPass"},
-	{"fpgaoff",				CmdFPGAOff,0,		"    Set FPGA off"},							// ## FPGA Control
-	{"fskdemod",			CmdFSKdemod,1,		"    Demodulate graph window as a HID FSK"},
-	{"hexsamples",		CmdHexsamples,0,	"<blocks> -- Dump big buffer as hex bytes"},
-	{"hi14alist",			CmdHi14alist,0,		"    List ISO 14443a history"},				// ## New list command
-	{"hi14areader",		CmdHi14areader,0,	"    Act like an ISO14443 Type A reader"},	// ## New reader command
-	{"hi14asim",			CmdHi14asim,0,		"<UID> -- Fake ISO 14443a tag"},					// ## Simulate 14443a tag
-	{"hi14asnoop",		CmdHi14asnoop,0,	"    Eavesdrop ISO 14443 Type A"},			// ## New snoop command
-	{"hi14bdemod",		CmdHi14bdemod,1,	"    Demodulate ISO14443 Type B from tag"},
-	{"hi14list",			CmdHi14list,0,		"    List ISO 14443 history"},
-	{"hi14read",			CmdHi14read,0,		"    Read HF tag (ISO 14443)"},
-	{"hi14sim",				CmdHi14sim,0,		"    Fake ISO 14443 tag"},
-	{"hi14snoop",			CmdHi14snoop,0,		"    Eavesdrop ISO 14443"},
-	{"hi15demod",			CmdHi15demod,1,		"    Demodulate ISO15693 from tag"},
-	{"hi15read",			CmdHi15read,0,		"    Read HF tag (ISO 15693)"},
-	{"hi15reader",		CmdHi15reader,0,	"    Act like an ISO15693 reader"}, // new command greg
-	{"hi15sim",				CmdHi15tag,0,		"    Fake an ISO15693 tag"}, // new command greg
-	{"hiddemod",			CmdHiddemod,1,		"    Demodulate HID Prox Card II (not optimal)"},
-	{"hide",					CmdHide,1,		"    Hide graph window"},
-	{"hidfskdemod",		CmdHIDdemodFSK,0,	"    Realtime HID FSK demodulator"},
-	{"hidsimtag",			CmdHIDsimTAG,0,		"<ID> -- HID tag simulator"},
-	{"higet",					CmdHi14read_sim,0,	"<samples> -- Get samples HF, 'analog'"},
-	{"hisamples",			CmdHisamples,0,		"    Get raw samples for HF tag"},
-	{"hisampless",		CmdHisampless,0,	"<samples> -- Get signed raw samples, HF tag"},
-	{"hisamplest",		CmdHi14readt,0,		"    Get samples HF, for testing"},
-	{"hisimlisten",		CmdHisimlisten,0,	"    Get HF samples as fake tag"},
-	{"hpf",						CmdHpf,1,		"    Remove DC offset from trace"},
-	{"indalademod",		CmdIndalademod,0,         "['224'] -- Demodulate samples for Indala 64 bit UID (option '224' for 224 bit)"},
-	{"lcd",						CmdLcd,0,			"<HEX command> <count> -- Send command/data to LCD"},
-	{"lcdreset",			CmdLcdReset,0,		"    Hardware reset LCD"},
-	{"load",					CmdLoad,1,		"<filename> -- Load trace (to graph window"},
-	{"locomread",			CmdLoCommandRead,0,		"<off period> <'0' period> <'1' period> <command> ['h'] -- Modulate LF reader field to send command before read (all periods in microseconds) (option 'h' for 134)"},
-	{"loread",				CmdLoread,0,		"['h'] -- Read 125/134 kHz LF ID-only tag (option 'h' for 134)"},
-	{"losamples",			CmdLosamples,0,		"[128 - 16000] -- Get raw samples for LF tag"},
-	{"losim",					CmdLosim,0,		"    Simulate LF tag"},
-	{"ltrim",					CmdLtrim,1,		"<samples> -- Trim samples from left of trace"},
-	{"mandemod",			Cmdmanchesterdemod,1,	"[i] [clock rate] -- Manchester demodulate binary stream (option 'i' to invert output)"},
-	{"manmod",				Cmdmanchestermod,1,	"[clock rate] -- Manchester modulate a binary stream"},
-	{"norm",					CmdNorm,1,		"    Normalize max/min to +/-500"},
-	{"plot",					CmdPlot,1,		"    Show graph window"},
-	{"quit",					CmdQuit,1,			"    Quit program"},
-	{"readmem",				CmdReadmem,0,			"    [address] -- Read memory at decimal address from flash"},
-	{"reset",					CmdReset,0,			"    Reset the Proxmark3"},
-	{"save",					CmdSave,1,		"<filename> -- Save trace (from graph window)"},
-	{"scale",					CmdScale,1,		"<int> -- Set cursor display scale"},
-	{"setlfdivisor",	CmdSetDivisor,0,	"<19 - 255> -- Drive LF antenna at 12Mhz/(divisor+1)"},
-	{"sri512read",		CmdSri512read,0,	"<int> -- Read contents of a SRI512 tag"},
-	{"tibits",				CmdTibits,0,		"    Get raw bits for TI-type LF tag"},
-	{"tidemod",				CmdTidemod,1,		"    Demodulate raw bits for TI-type LF tag"},
-	{"tiread",				CmdTiread,0,		"    Read a TI-type 134 kHz tag"},
-	{"threshold",			CmdThreshold,1,		"    Maximize/minimize every value in the graph window depending on threshold"},
-	{"tune",					CmdTune,0,		"    Measure antenna tuning"},
-	{"vchdemod",			CmdVchdemod,0,		"['clone'] -- Demodulate samples for VeriChip"},
-	{"zerocrossings",	CmdZerocrossings,1,	"    Count time between zero-crossings"},
+	{"askdemod",			Cmdaskdemod,				1, "<samples per bit> <0|1> -- Attempt to demodulate simple ASK tags"},
+	{"autocorr",			CmdAutoCorr,				1, "<window length> -- Autocorrelation over window"},
+	{"bitsamples",		CmdBitsamples,			0, "Get raw samples as bitstring"},
+	{"bitstream",			Cmdbitstream,				1, "[clock rate] -- Convert waveform into a bitstream"},
+	{"buffclear",			CmdBuffClear,				0, "Clear sample buffer and graph window"},
+	{"dec",						CmdDec,							1, "Decimate samples"},
+	{"detectclock",		Cmddetectclockrate,	1, "Detect clock rate"},
+	{"detectreader",	CmdDetectReader,		0, "['l'|'h'] -- Detect external reader field (option 'l' or 'h' to limit to LF or HF)"},
+	{"em410xsim",			CmdEM410xsim,				1, "<UID> -- Simulate EM410x tag"},
+	{"em410xread",		CmdEM410xread,			1, "[clock rate] -- Extract ID from EM410x tag"},
+	{"em410xwatch",		CmdEM410xwatch,			0, "Watches for EM410x tags"},
+	{"em4x50read",		CmdEM4x50read,			1, "Extract data from EM4x50 tag"},
+	{"exit",					CmdQuit,						1, "Exit program"},
+	{"flexdemod",			CmdFlexdemod,				1, "Demodulate samples for FlexPass"},
+	{"fpgaoff",				CmdFPGAOff,					0, "Set FPGA off"},
+	{"fskdemod",			CmdFSKdemod,				1, "Demodulate graph window as a HID FSK"},
+	{"grid",					CmdGrid,						1, "grid x y, overlay grid on graph window, use zero value to turn off either"},
+	{"hexsamples",		CmdHexsamples,			0, "<blocks> -- Dump big buffer as hex bytes"},
+	{"hi14alist",			CmdHi14alist,				0, "List ISO 14443a history"},
+	{"hi14areader",		CmdHi14areader,			0, "Act like an ISO14443 Type A reader"},
+	{"hi14asim",			CmdHi14asim,				0, "<UID> -- Fake ISO 14443a tag"},
+	{"hi14asnoop",		CmdHi14asnoop,			0, "Eavesdrop ISO 14443 Type A"},
+	{"hi14bdemod",		CmdHi14bdemod,			1, "Demodulate ISO14443 Type B from tag"},
+	{"hi14list",			CmdHi14list,				0, "List ISO 14443 history"},
+	{"hi14read",			CmdHi14read,				0, "Read HF tag (ISO 14443)"},
+	{"hi14sim",				CmdHi14sim,					0, "Fake ISO 14443 tag"},
+	{"hi14snoop",			CmdHi14snoop,				0, "Eavesdrop ISO 14443"},
+	{"hi15demod",			CmdHi15demod,				1, "Demodulate ISO15693 from tag"},
+	{"hi15read",			CmdHi15read,				0, "Read HF tag (ISO 15693)"},
+	{"hi15reader",		CmdHi15reader,			0, "Act like an ISO15693 reader"},
+	{"hi15sim",				CmdHi15tag,					0, "Fake an ISO15693 tag"},
+	{"hiddemod",			CmdHiddemod,				1, "Demodulate HID Prox Card II (not optimal)"},
+	{"hide",					CmdHide,						1, "Hide graph window"},
+	{"hidfskdemod",		CmdHIDdemodFSK,			0, "Realtime HID FSK demodulator"},
+	{"hidsimtag",			CmdHIDsimTAG,				0, "<ID> -- HID tag simulator"},
+	{"higet",					CmdHi14read_sim,		0, "<samples> -- Get samples HF, 'analog'"},
+	{"hisamples",			CmdHisamples,				0, "Get raw samples for HF tag"},
+	{"hisampless",		CmdHisampless,			0, "<samples> -- Get signed raw samples, HF tag"},
+	{"hisamplest",		CmdHi14readt,				0, "Get samples HF, for testing"},
+	{"hisimlisten",		CmdHisimlisten,			0, "Get HF samples as fake tag"},
+	{"hpf",						CmdHpf,							1, "Remove DC offset from trace"},
+	{"indalademod",		CmdIndalademod,			0, "['224'] -- Demodulate samples for Indala 64 bit UID (option '224' for 224 bit)"},
+	{"lcd",						CmdLcd,							0, "<HEX command> <count> -- Send command/data to LCD"},
+	{"lcdreset",			CmdLcdReset,				0, "Hardware reset LCD"},
+	{"load",					CmdLoad,						1, "<filename> -- Load trace (to graph window"},
+	{"locomread",			CmdLoCommandRead,		0, "<off period> <'0' period> <'1' period> <command> ['h'] -- Modulate LF reader field to send command before read (all periods in microseconds) (option 'h' for 134)"},
+	{"loread",				CmdLoread,					0, "['h'] -- Read 125/134 kHz LF ID-only tag (option 'h' for 134)"},
+	{"losamples",			CmdLosamples,				0, "[128 - 16000] -- Get raw samples for LF tag"},
+	{"losim",					CmdLosim,						0, "Simulate LF tag"},
+	{"ltrim",					CmdLtrim,						1, "<samples> -- Trim samples from left of trace"},
+	{"mandemod",			Cmdmanchesterdemod,	1, "[i] [clock rate] -- Manchester demodulate binary stream (option 'i' to invert output)"},
+	{"manmod",				Cmdmanchestermod,		1, "[clock rate] -- Manchester modulate a binary stream"},
+	{"norm",					CmdNorm,						1, "Normalize max/min to +/-500"},
+	{"plot",					CmdPlot,						1, "Show graph window"},
+	{"quit",					CmdQuit,						1, "Quit program"},
+	{"readmem",				CmdReadmem,					0, "[address] -- Read memory at decimal address from flash"},
+	{"reset",					CmdReset,						0, "Reset the Proxmark3"},
+	{"save",					CmdSave,						1, "<filename> -- Save trace (from graph window)"},
+	{"scale",					CmdScale,						1, "<int> -- Set cursor display scale"},
+	{"setlfdivisor",	CmdSetDivisor,			0, "<19 - 255> -- Drive LF antenna at 12Mhz/(divisor+1)"},
+	{"sri512read",		CmdSri512read,			0, "<int> -- Read contents of a SRI512 tag"},
+	{"tibits",				CmdTibits,					0, "Get raw bits for TI-type LF tag"},
+	{"tidemod",				CmdTidemod,					1, "Demodulate raw bits for TI-type LF tag"},
+	{"tiread",				CmdTiread,					0, "Read a TI-type 134 kHz tag"},
+	{"threshold",			CmdThreshold,				1, "Maximize/minimize every value in the graph window depending on threshold"},
+	{"tune",					CmdTune,						0, "Measure antenna tuning"},
+	{"vchdemod",			CmdVchdemod,				0, "['clone'] -- Demodulate samples for VeriChip"},
+	{"zerocrossings",	CmdZerocrossings,		1, "Count time between zero-crossings"},
 };
 
 static struct {
diff --git a/winsrc/gui.cpp b/winsrc/gui.cpp
index da83c865..bcc0cbb6 100644
--- a/winsrc/gui.cpp
+++ b/winsrc/gui.cpp
@@ -34,12 +34,13 @@ void dbp(char *str, ...)
 int GraphBuffer[MAX_GRAPH_TRACE_LEN];
 int GraphTraceLen;
 
-HPEN GreyPen, GreenPen, WhitePen, YellowPen;
+HPEN GreyPenLite, GreyPen, GreenPen, WhitePen, YellowPen;
 HBRUSH GreenBrush, YellowBrush;
 
 static int GraphStart = 0;
 static double GraphPixelsPerPoint = 1;
 
+static int PlotGridX = 0, PlotGridY = 0;
 static int CursorAPos;
 static int CursorBPos;
 double CursorScaleFactor = 1.0;
@@ -61,11 +62,17 @@ static HFONT MyFixedFont;
 
 void ExecCmd(char *cmd)
 {
-
 }
+
 int CommandFinished;
 int offset = 64;
 
+void SetGraphGrid(int x, int y)
+{
+	PlotGridX = x;
+	PlotGridY = y;
+}
+
 static void ResizeCommandWindow(void)
 {
 	int w, h;
@@ -108,43 +115,63 @@ static LRESULT CALLBACK
 
 static void PaintGraph(HDC hdc)
 {
+	RECT r;
 	HBRUSH brush;
 	HPEN pen;
+	char str[250];
+	int yMin = INT_MAX;
+	int yMax = INT_MIN;
+	int yMean = 0;
+	int startMax = 0;
+	int absYMax = 1;
+	int n = 0, i = 0;
 
 	brush = GreenBrush;
 	pen = GreenPen;
 
-	if(GraphStart < 0) {
-		GraphStart = 0;
-	}
-
-	RECT r;
 	GetClientRect(GraphWindow, &r);
+	int zeroHeight = (r.top + r.bottom) >> 1;
+
+	// plot X and Y grid lines
+	if ((PlotGridX > 0) && ((PlotGridX * GraphPixelsPerPoint) > 1)) {
+		for(i = offset; i < r.right; i += (int)(PlotGridX * GraphPixelsPerPoint)) {
+			SelectObject(hdc, GreyPenLite);
+			MoveToEx(hdc, r.left + i, r.top, NULL);
+			LineTo(hdc, r.left + i, r.bottom);
+		}
+  }
+
+	if ((PlotGridY > 0) && ((PlotGridY * GraphPixelsPerPoint) > 1)){
+		for(i = 0; i < ((r.top + r.bottom)>>1); i += (int)(PlotGridY * GraphPixelsPerPoint)) {
+			SelectObject(hdc, GreyPenLite);
+			MoveToEx(hdc, r.left, zeroHeight + i, NULL);
+			LineTo(hdc, r.right, zeroHeight + i);
+			MoveToEx(hdc, r.left, zeroHeight - i, NULL);
+			LineTo(hdc, r.right, zeroHeight - i);
+		}
+  }
 
+	// print vertical separator white line on the left of the window
 	SelectObject(hdc, WhitePen);
-
 	MoveToEx(hdc, r.left + offset, r.top, NULL);
 	LineTo(hdc, r.left + offset, r.bottom);
 
-	int zeroHeight = r.top + (r.bottom - r.top) / 2;
+	// print horizontal grey zero axis line
 	SelectObject(hdc, GreyPen);
 	MoveToEx(hdc, r.left, zeroHeight, NULL);
 	LineTo(hdc, r.right, zeroHeight);
 
-	int startMax =
-		(GraphTraceLen - (int)((r.right - r.left - offset) / GraphPixelsPerPoint));
-	if(startMax < 0) {
-		startMax = 0;
-	}
-	if(GraphStart > startMax) {
-		GraphStart = startMax;
-	}
+	startMax = (GraphTraceLen - (int)((r.right - r.left - offset) / GraphPixelsPerPoint));
+	// check boundaries
+	if(startMax < 0) startMax = 0;
+	if(GraphStart > startMax) GraphStart = startMax;
+	if(GraphStart < 0) GraphStart = 0;
 
-	int absYMax = 1;
 
 	SelectObject(hdc, pen);
 
-	int i;
+	// go over the portion of the graph to be displayed and find the largest
+	// absolute value which will be used to auto scale the graph when displayed
 	for(i = GraphStart; ; i++) {
 		if(i >= GraphTraceLen) {
 			break;
@@ -174,11 +201,7 @@ static void PaintGraph(HDC hdc)
 	if(pointsPerLabel <= 0) pointsPerLabel = 1;
 	pointsPerLabel = (int)pow(2.0,pointsPerLabel);
 
-	int yMin = INT_MAX;
-	int yMax = INT_MIN;
-	int yMean = 0;
-	int n = 0;
-
+	// go over the graph and plot samples and labels
 	for(i = GraphStart; ; i++) {
 		if(i >= GraphTraceLen) {
 			break;
@@ -189,12 +212,8 @@ static void PaintGraph(HDC hdc)
 		}
 
 		int y = GraphBuffer[i];
-		if(y < yMin) {
-			yMin = y;
-		}
-		if(y > yMax) {
-			yMax = y;
-		}
+		if(y < yMin) yMin = y;
+		if(y > yMax) yMax = y;
 		yMean += y;
 		n++;
 
@@ -214,13 +233,13 @@ static void PaintGraph(HDC hdc)
 			FillRect(hdc, &f, brush);
 		}
 
+		// plot labels
 		if(((i - GraphStart) % pointsPerLabel == 0) && i != GraphStart) {
 			SelectObject(hdc, WhitePen);
 			MoveToEx(hdc, x, zeroHeight - 8, NULL);
 			LineTo(hdc, x, zeroHeight + 8);
 
-			char str[100];
-			sprintf(str, "+%d", (i - GraphStart));
+			sprintf(str, "+%d", i);
 			SIZE size;
 			GetTextExtentPoint32(hdc, str, strlen(str), &size);
 			TextOut(hdc, x - size.cx, zeroHeight + 8, str, strlen(str));
@@ -229,6 +248,7 @@ static void PaintGraph(HDC hdc)
 			MoveToEx(hdc, x, y, NULL);
 		}
 
+		// plot measurement cursors
 		if(i == CursorAPos || i == CursorBPos) {
 			if(i == CursorAPos) {
 				SelectObject(hdc, CursorAPen);
@@ -247,8 +267,7 @@ static void PaintGraph(HDC hdc)
 		yMean /= n;
 	}
 
-	char str[200];
-
+	// print misc information at bottom of graph window
 	sprintf(str, "@%d   max=%d min=%d mean=%d n=%d/%d    dt=%d [%.3f] zoom=%.3f CursorA=%d [%d] CursorB=%d [%d]",
 		GraphStart, yMax, yMin, yMean, n, GraphTraceLen,
 		CursorBPos - CursorAPos, (CursorBPos - CursorAPos)/CursorScaleFactor, GraphPixelsPerPoint,
@@ -438,6 +457,7 @@ void ShowGui()
 	PrintToScrollback(">> Started prox, built " __DATE__ " " __TIME__);
 	PrintToScrollback(">> Connected to device");
 
+	GreyPenLite = CreatePen(PS_SOLID, 1, RGB(50, 50, 50));
 	GreyPen = CreatePen(PS_SOLID, 1, RGB(100, 100, 100));
 	GreenPen = CreatePen(PS_SOLID, 1, RGB(100, 255, 100));
 	YellowPen = CreatePen(PS_SOLID, 1, RGB(255, 255, 0));
diff --git a/winsrc/prox.h b/winsrc/prox.h
index 5550e595..53449a13 100644
--- a/winsrc/prox.h
+++ b/winsrc/prox.h
@@ -13,6 +13,7 @@ void ShowGui();
 void HideGraphWindow(void);
 void ShowGraphWindow(void);
 void RepaintGraphWindow(void);
+void SetGraphGrid(int x, int y);
 void PrintToScrollback(char *fmt, ...);
 #define MAX_GRAPH_TRACE_LEN (1024*128)
 extern int GraphBuffer[MAX_GRAPH_TRACE_LEN];
-- 
2.39.5