aboutsummaryrefslogtreecommitdiffstats
path: root/demos
diff options
context:
space:
mode:
authorinmarket <andrewh@inmarket.com.au>2014-11-14 09:10:59 +1000
committerinmarket <andrewh@inmarket.com.au>2014-11-14 09:10:59 +1000
commit93c9ebaa793d96147784e061102fec3423584fc0 (patch)
tree2be19e5c602dcc622a2ff411bb0d8698498c5d9c /demos
parent6bc091035a08f58eb6c60e7cceb01ef29e655e07 (diff)
downloaduGFX-93c9ebaa793d96147784e061102fec3423584fc0.tar.gz
uGFX-93c9ebaa793d96147784e061102fec3423584fc0.tar.bz2
uGFX-93c9ebaa793d96147784e061102fec3423584fc0.zip
Move the uGFX based tools into a sub-directory of demos so they can be compiled using the standard build system facility for building demo's.
Diffstat (limited to 'demos')
-rw-r--r--demos/readme.txt4
-rw-r--r--demos/tools/touch_driver_test/demo.mk3
-rw-r--r--demos/tools/touch_driver_test/gfxconf.h62
-rw-r--r--demos/tools/touch_driver_test/main.c461
-rw-r--r--demos/tools/touch_raw_readings/demo.mk3
-rw-r--r--demos/tools/touch_raw_readings/gfxconf.h62
-rw-r--r--demos/tools/touch_raw_readings/main.c110
-rw-r--r--demos/tools/uGFXnetDisplay/demo.mk3
-rw-r--r--demos/tools/uGFXnetDisplay/gfxconf.h41
-rw-r--r--demos/tools/uGFXnetDisplay/main.c427
10 files changed, 1175 insertions, 1 deletions
diff --git a/demos/readme.txt b/demos/readme.txt
index 3530c8e4..a29ce9f6 100644
--- a/demos/readme.txt
+++ b/demos/readme.txt
@@ -2,7 +2,7 @@ This folder contains a few demos which explain how to use the library.
Only the main files are contained. No compile-able projects
-All demos and examples stand under the BSD license as declared below and
+Most demos and examples stand under the BSD license as declared below and
within each file:
/*
@@ -34,3 +34,5 @@ within each file:
*/
Files under the 3rdparty directory are licensed as per the original contributor.
+Files under the tools directory are licensed with either the uGFX license or the BSD
+license - see each tool demo source code for its specific license.
diff --git a/demos/tools/touch_driver_test/demo.mk b/demos/tools/touch_driver_test/demo.mk
new file mode 100644
index 00000000..3af3fbda
--- /dev/null
+++ b/demos/tools/touch_driver_test/demo.mk
@@ -0,0 +1,3 @@
+DEMODIR = $(GFXLIB)/demos/tools/touch_driver_test
+GFXINC += $(DEMODIR)
+GFXSRC += $(DEMODIR)/main.c
diff --git a/demos/tools/touch_driver_test/gfxconf.h b/demos/tools/touch_driver_test/gfxconf.h
new file mode 100644
index 00000000..3d93a138
--- /dev/null
+++ b/demos/tools/touch_driver_test/gfxconf.h
@@ -0,0 +1,62 @@
+/*
+ * Copyright (c) 2012, 2013, Joel Bodenmann aka Tectu <joel@unormal.org>
+ * Copyright (c) 2012, 2013, Andrew Hannam aka inmarket
+ *
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ * * Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * * Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * * Neither the name of the <organization> nor the
+ * names of its contributors may be used to endorse or promote products
+ * derived from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+ * DISCLAIMED. IN NO EVENT SHALL <COPYRIGHT HOLDER> BE LIABLE FOR ANY
+ * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+ * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+ * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
+ * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+ * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#ifndef _GFXCONF_H
+#define _GFXCONF_H
+
+/* The operating system to use. One of these must be defined - preferably in your Makefile */
+//#define GFX_USE_OS_CHIBIOS FALSE
+//#define GFX_USE_OS_WIN32 FALSE
+//#define GFX_USE_OS_LINUX FALSE
+//#define GFX_USE_OS_OSX FALSE
+
+/* GFX sub-systems to turn on */
+#define GFX_USE_GDISP TRUE
+#define GFX_USE_GWIN TRUE
+#define GFX_USE_GEVENT TRUE
+#define GFX_USE_GTIMER TRUE
+#define GFX_USE_GINPUT TRUE
+
+/* Features for the GDISP sub-system. */
+#define GDISP_NEED_VALIDATION TRUE
+#define GDISP_NEED_CLIP TRUE
+#define GDISP_NEED_TEXT TRUE
+#define GDISP_NEED_MULTITHREAD TRUE
+
+/* Builtin Fonts */
+#define GDISP_INCLUDE_FONT_UI2 TRUE
+
+/* Features for the GWIN sub-system. */
+#define GWIN_NEED_CONSOLE TRUE
+
+/* Features for the GINPUT sub-system. */
+#define GINPUT_NEED_MOUSE TRUE
+#define GINPUT_TOUCH_STARTRAW TRUE
+
+#endif /* _GFXCONF_H */
diff --git a/demos/tools/touch_driver_test/main.c b/demos/tools/touch_driver_test/main.c
new file mode 100644
index 00000000..13136a57
--- /dev/null
+++ b/demos/tools/touch_driver_test/main.c
@@ -0,0 +1,461 @@
+/*
+ * Copyright (c) 2012, 2013, Joel Bodenmann aka Tectu <joel@unormal.org>
+ * Copyright (c) 2012, 2013, Andrew Hannam aka inmarket
+ *
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ * * Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * * Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * * Neither the name of the <organization> nor the
+ * names of its contributors may be used to endorse or promote products
+ * derived from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+ * DISCLAIMED. IN NO EVENT SHALL <COPYRIGHT HOLDER> BE LIABLE FOR ANY
+ * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+ * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+ * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
+ * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+ * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include "gfx.h"
+
+// We get nasty and look at some internal structures - get the relevant information
+#include "src/gdriver/sys_defs.h"
+#include "src/ginput/driver_mouse.h"
+
+#include <string.h>
+
+static GConsoleObject gc;
+static GListener gl;
+static font_t font;
+static coord_t bWidth, bWidth2, bHeight;
+static GHandle ghc;
+static coord_t swidth, sheight;
+
+static void DrawHeader(const char *title, bool_t btnNext, bool_t btnPrev, bool_t btnPlusMinus) {
+ #if GDISP_NEED_CLIP
+ gdispSetClip(0, 0, swidth, sheight);
+ #endif
+ gdispFillStringBox(0, 0, swidth, bHeight, "Touch Calibration", font, Red, White, justifyLeft);
+ if (btnNext)
+ gdispFillStringBox(swidth-1*bWidth, 0, bWidth , bHeight, "Next", font, Black, Gray, justifyCenter);
+ if (btnPrev)
+ gdispFillStringBox(swidth-2*bWidth, 0, bWidth-1, bHeight, "Prev", font, Black, Gray, justifyCenter);
+ if (btnPlusMinus) {
+ gdispFillStringBox(swidth-2*bWidth-1*bWidth2, 0, bWidth2-1, bHeight, "+", font, Black, Gray, justifyCenter);
+ gdispFillStringBox(swidth-2*bWidth-2*bWidth2, 0, bWidth2-1, bHeight, "-", font, Black, Gray, justifyCenter);
+ }
+ gwinClear(ghc);
+ gwinSetColor(ghc, Yellow);
+ gwinPrintf(ghc, "\n%s\n\n", title);
+ gwinSetColor(ghc, White);
+}
+
+#define BTN_NONE 0
+#define BTN_NEXT 1
+#define BTN_PREV 2
+#define BTN_PLUS 3
+#define BTN_MINUS 4
+
+static int CheckButtons(GEventMouse *pem) {
+ if (pem->y < bHeight && (pem->buttons & GMETA_MOUSE_UP)) {
+ if (pem->x >= swidth-1*bWidth)
+ return BTN_NEXT;
+ if (pem->x >= swidth-2*bWidth)
+ return BTN_PREV;
+ if (pem->x >= swidth-2*bWidth-1*bWidth2)
+ return BTN_PLUS;
+ if (pem->x >= swidth-2*bWidth-2*bWidth2)
+ return BTN_MINUS;
+ }
+ return BTN_NONE;
+}
+
+/*------------------------------------------------------------------------*
+ * GINPUT Touch Driver Calibrator. *
+ *------------------------------------------------------------------------*/
+int main(void) {
+ GSourceHandle gs;
+ GEventMouse *pem;
+ bool_t isFirstTime;
+ bool_t isCalibrated;
+ bool_t isTouch;
+ bool_t isFinger;
+ const char * isFingerText;
+ const char * deviceText;
+ GMouse * m;
+ GMouseVMT * vmt;
+ GMouseJitter * pjit;
+ uint32_t calerr;
+
+ gfxInit(); // Initialize the display
+
+ // Get the display dimensions
+ swidth = gdispGetWidth();
+ sheight = gdispGetHeight();
+
+ // Create our title
+ font = gdispOpenFont("UI2");
+ gwinSetDefaultFont(font);
+ bWidth = gdispGetStringWidth("Next", font);
+ bHeight = gdispGetStringWidth("Prev", font);
+ if (bHeight > bWidth) bWidth = bHeight;
+ bWidth += 4;
+ bWidth2 = gdispGetStringWidth("+", font)*2;
+ bHeight = gdispGetStringWidth("-", font)*2;
+ if (bHeight > bWidth2) bWidth2 = bHeight;
+ bWidth2 += 4;
+ bHeight = gdispGetFontMetric(font, fontHeight)*2+2;
+
+ // Create our main display window
+ {
+ GWindowInit wi;
+
+ gwinClearInit(&wi);
+ wi.show = TRUE; wi.x = 0; wi.y = bHeight; wi.width = swidth; wi.height = sheight-bHeight;
+ ghc = gwinConsoleCreate(&gc, &wi);
+ }
+
+ // Initialize the listener
+ geventListenerInit(&gl);
+
+ // Copy the current mouse's VMT so we can play with it.
+ m = (GMouse *)gdriverGetInstance(GDRIVER_TYPE_MOUSE, 0);
+ if (!m) gfxHalt("No mouse instance 0");
+ vmt = gfxAlloc(sizeof(GMouseVMT));
+ if (!vmt) gfxHalt("Could not allocate memory for mouse VMT");
+ memcpy(vmt, m->d.vmt, sizeof(GMouseVMT));
+
+ // Swap VMT's on the current mouse to our RAM copy
+ m->d.vmt = (const GDriverVMT *)vmt;
+
+ // Listen for events
+ gs = ginputGetMouse(0);
+ geventAttachSource(&gl, gs, GLISTEN_MOUSEDOWNMOVES|GLISTEN_MOUSEMETA);
+
+ // Get initial display settings for buttons
+ isFirstTime = TRUE;
+ isCalibrated = (vmt->d.flags & GMOUSE_VFLG_CALIBRATE) ? FALSE : TRUE;
+ calerr = 0;
+
+ /*
+ * Test: Device Type
+ */
+
+StepDeviceType:
+ DrawHeader("1. Device Type", isCalibrated, isCalibrated && !isFirstTime, isCalibrated);
+
+ // Get the type of device and the current mode
+ isTouch = (vmt->d.flags & GMOUSE_VFLG_TOUCH) ? TRUE : FALSE;
+ isFinger = (m->flags & GMOUSE_FLG_FINGERMODE) ? TRUE : FALSE;
+ pjit = isFinger ? &vmt->finger_jitter : &vmt->pen_jitter;
+ isFingerText = isFinger ? "finger" : "pen";
+ deviceText = isTouch ? isFingerText : "mouse";
+
+ gwinPrintf(ghc, "This is detected as a %s device\n\n", isTouch ? "TOUCH" : "MOUSE");
+ gwinPrintf(ghc, "It is currently in %s mode\n\n", isFinger ? "FINGER" : "PEN");
+
+ if (!isCalibrated)
+ gwinPrintf(ghc, "Press and release your %s to move on to the next test.\n", deviceText);
+ else {
+ gwinPrintf(ghc, "Press + for pen or - for finger.\n");
+ if (isFirstTime)
+ gwinPrintf(ghc, "Press Next to continue.\n");
+ else
+ gwinPrintf(ghc, "Press Next or Back to continue.\n");
+ }
+
+ while(1) {
+ pem = (GEventMouse *)geventEventWait(&gl, TIME_INFINITE);
+ if (isCalibrated) {
+ switch (CheckButtons(pem)) {
+ case BTN_NEXT:
+ break;
+ case BTN_PREV:
+ if (!isFirstTime)
+ goto StepDrawing;
+ continue;
+ case BTN_PLUS:
+ m->flags &= ~GMOUSE_FLG_FINGERMODE;
+ goto StepDeviceType;
+ case BTN_MINUS:
+ m->flags |= GMOUSE_FLG_FINGERMODE;
+ goto StepDeviceType;
+ default:
+ continue;
+ }
+ break;
+ }
+ if ((pem->buttons & GMETA_MOUSE_UP))
+ break;
+ }
+
+ /*
+ * Test: Mouse raw reading
+ */
+
+StepRawReading:
+ DrawHeader("2. Raw Mouse Output", FALSE, FALSE, FALSE);
+ if (isTouch)
+ gwinPrintf(ghc, "Press and hold on the surface.\n\n");
+ else
+ gwinPrintf(ghc, "Press and hold the mouse button.\n\n");
+ gwinPrintf(ghc, "The raw values coming from your mouse driver will display.\n\n");
+ gwinPrintf(ghc, "Make sure the x and y values change as you move.\n\n");
+
+ gwinPrintf(ghc, "Release your %s to move on to the next test.\n", deviceText);
+
+ // Make sure we are in uncalibrated mode
+ m->flags &= ~(GMOUSE_FLG_CALIBRATE|GMOUSE_FLG_CLIP);
+
+ // For this test turn on ALL mouse movement events
+ geventAttachSource(&gl, gs, GLISTEN_MOUSEDOWNMOVES|GLISTEN_MOUSEUPMOVES|GLISTEN_MOUSEMETA|GLISTEN_MOUSENOFILTER);
+
+ while(1) {
+ // Always sleep a bit first to enable other events. We actually don't
+ // mind missing events for this test.
+ gfxSleepMilliseconds(100);
+ pem = (GEventMouse *)geventEventWait(&gl, TIME_INFINITE);
+ gwinPrintf(ghc, "%u, %u z=%u b=0x%04x\n", pem->x, pem->y, pem->z, pem->buttons & ~GINPUT_MISSED_MOUSE_EVENT);
+ if ((pem->buttons & GMETA_MOUSE_UP))
+ break;
+ }
+
+ // Reset to calibrated condition
+ if (isCalibrated) {
+ m->flags |= GMOUSE_FLG_CLIP;
+ if ((vmt->d.flags & GMOUSE_VFLG_CALIBRATE))
+ m->flags |= GMOUSE_FLG_CALIBRATE;
+ }
+
+ // Reset to just changed movements.
+ geventAttachSource(&gl, gs, GLISTEN_MOUSEDOWNMOVES|GLISTEN_MOUSEMETA);
+
+ /*
+ * Test: Calibration
+ */
+
+StepCalibrate:
+ DrawHeader("3. Calibration Jitter", isCalibrated, isCalibrated, isCalibrated);
+ if ((vmt->d.flags & GMOUSE_VFLG_CALIBRATE)) {
+ gwinPrintf(ghc, "You will be presented with a number of points to touch.\nPress them in turn.\n\n"
+ "If the calibration repeatedly fails, increase the jitter for %s calibration and try again.\n\n", isFingerText);
+ gwinPrintf(ghc, "Pressing the surface for longer gives more accurate results.\n\n");
+ if (calerr)
+ gwinPrintf(ghc, "Last calibration error ^ 2 = %u\n", calerr);
+ gwinPrintf(ghc, "Calibration jitter (%s) = %u\n", isFingerText, pjit->calibrate);
+ if (isCalibrated)
+ gwinPrintf(ghc, "Press + or - to adjust.\n");
+ } else {
+ gwinPrintf(ghc, "This device does not need calibration.\n\n");
+ }
+ if (isCalibrated)
+ gwinPrintf(ghc, "Press Next or Back to continue.\n");
+ else
+ gwinPrintf(ghc, "Press and release your %s to move on to start calibration.\n", deviceText);
+
+ while(1) {
+ pem = (GEventMouse *)geventEventWait(&gl, TIME_INFINITE);
+ if (isCalibrated) {
+ switch (CheckButtons(pem)) {
+ case BTN_NEXT:
+ break;
+ case BTN_PREV:
+ goto StepRawReading;
+ case BTN_PLUS:
+ gwinPrintf(ghc, "Calibration jitter (%s) = %u", isFingerText, ++pjit->calibrate);
+ continue;
+ case BTN_MINUS:
+ gwinPrintf(ghc, "Calibration jitter (%s) = %u", isFingerText, --pjit->calibrate);
+ continue;
+ default:
+ continue;
+ }
+ break;
+ }
+ if ((pem->buttons & GMETA_MOUSE_UP))
+ break;
+ }
+
+ // Calibrate
+ if ((vmt->d.flags & GMOUSE_VFLG_CALIBRATE)) {
+ calerr = ginputCalibrateMouse(0);
+ if (calerr)
+ goto StepCalibrate;
+ isCalibrated = TRUE;
+ }
+
+ /*
+ * Test: Mouse coords
+ */
+
+StepMouseCoords:
+ DrawHeader("4. Show Mouse Coordinates", TRUE, TRUE, TRUE);
+ if (isTouch)
+ gwinPrintf(ghc, "Press and hold on the surface.\n\n");
+ else
+ gwinPrintf(ghc, "Press and hold the mouse button.\n\n");
+ gwinPrintf(ghc, "Check the coordinates against where it should be on the screen.\n\n");
+ gwinPrintf(ghc, "X should be 0 to %u\nY should be 0 to %u\n\n", swidth-1, sheight-1);
+ gwinPrintf(ghc, "Press + to retry using extremes or - for normal calibration.\n");
+ gwinPrintf(ghc, "Press Next or Back to continue.\n");
+
+ // For this test normal mouse movement events
+ geventAttachSource(&gl, gs, GLISTEN_MOUSEDOWNMOVES|GLISTEN_MOUSEMETA);
+
+ while(1) {
+ // Always sleep a bit first to enable other events. We actually don't
+ // mind missing events for this test.
+ gfxSleepMilliseconds(100);
+ pem = (GEventMouse *)geventEventWait(&gl, TIME_INFINITE);
+
+ switch (CheckButtons(pem)) {
+ case BTN_NEXT:
+ break;
+ case BTN_PREV:
+ goto StepCalibrate;
+ case BTN_PLUS:
+ vmt->d.flags |= GMOUSE_VFLG_CAL_EXTREMES;
+ goto StepCalibrate;
+ case BTN_MINUS:
+ vmt->d.flags &= ~GMOUSE_VFLG_CAL_EXTREMES;
+ goto StepCalibrate;
+ default:
+ gwinPrintf(ghc, "%u, %u\n", pem->x, pem->y);
+ continue;
+ }
+ break;
+ }
+
+ // Reset to just changed movements.
+ geventAttachSource(&gl, gs, GLISTEN_MOUSEDOWNMOVES|GLISTEN_MOUSEMETA);
+
+ /*
+ * Test: Mouse movement jitter
+ */
+
+StepMovementJitter:
+ DrawHeader("5. Movement Jitter", TRUE, TRUE, TRUE);
+ if (isTouch)
+ gwinPrintf(ghc, "Press firmly on the surface and move around as if to draw.\n\n");
+ else
+ gwinPrintf(ghc, "Press and hold the mouse button and move around as if to draw.\n\n");
+
+ gwinPrintf(ghc, "Dots will display in this window. Ensure that when you stop moving your %s that "
+ "new dots stop displaying.\nNew dots should only display when your %s is moving.\n\n"
+ "Adjust %s movement jitter to the smallest value that this reliably works for.\n\n", deviceText, deviceText, isFingerText);
+ gwinPrintf(ghc, "Movement jitter (%s) = %u\n", isFingerText, pjit->move);
+ gwinPrintf(ghc, "Press + or - to adjust.\n");
+ gwinPrintf(ghc, "Press Next or Back to continue.\n\n");
+
+ while(1) {
+ pem = (GEventMouse *)geventEventWait(&gl, TIME_INFINITE);
+ switch (CheckButtons(pem)) {
+ case BTN_NEXT:
+ break;
+ case BTN_PREV:
+ goto StepMouseCoords;
+ case BTN_PLUS:
+ gwinPrintf(ghc, "Movement jitter (%s) = %u", isFingerText, ++pjit->move);
+ continue;
+ case BTN_MINUS:
+ gwinPrintf(ghc, "Movement jitter (%s) = %u", isFingerText, --pjit->move);
+ continue;
+ default:
+ if ((pem->buttons & GINPUT_MOUSE_BTN_LEFT))
+ gwinPrintf(ghc, ".");
+ continue;
+ }
+ break;
+ }
+
+ /*
+ * Test: Click Jitter
+ */
+
+StepClickJitter:
+ gwinClear(ghc);
+ gwinSetColor(ghc, Yellow);
+ gwinPrintf(ghc, "\n6. Click Jitter\n\n");
+
+ gwinSetColor(ghc, White);
+ if (isTouch)
+ gwinPrintf(ghc, "Press and release the touch surface to \"click\".\nTry both short and long presses.\n");
+ else
+ gwinPrintf(ghc, "Click the mouse with the left and right buttons.\n\n");
+ gwinPrintf(ghc, "A yellow dash is a left (or short) click.\n"
+ "A red x is a right (or long) click.\n\n"
+ "Adjust %s click jitter to the smallest value that this reliably works for.\n"
+ "Note: moving your %s during a click cancels it.\n\n", isFingerText, deviceText);
+ gwinPrintf(ghc, "Click jitter (%s) = %u\n", isFingerText, pjit->click);
+ gwinPrintf(ghc, "Press + or - to adjust.\n");
+ gwinPrintf(ghc, "Press Next or Back to continue.\n\n");
+
+ while(1) {
+ pem = (GEventMouse *)geventEventWait(&gl, TIME_INFINITE);
+ switch (CheckButtons(pem)) {
+ case BTN_NEXT:
+ break;
+ case BTN_PREV:
+ goto StepMovementJitter;
+ case BTN_PLUS:
+ gwinPrintf(ghc, "Click jitter (%s) = %u", isFingerText, ++pjit->click);
+ continue;
+ case BTN_MINUS:
+ gwinPrintf(ghc, "Click jitter (%s) = %u", isFingerText, --pjit->click);
+ continue;
+ default:
+ if ((pem->buttons & GMETA_MOUSE_CLICK)) {
+ gwinSetColor(ghc, Yellow);
+ gwinPrintf(ghc, "-");
+ }
+ if ((pem->buttons & GMETA_MOUSE_CXTCLICK)) {
+ gwinSetColor(ghc, Red);
+ gwinPrintf(ghc, "x");
+ }
+ continue;
+ }
+ break;
+ }
+
+ /*
+ * Test: Polling frequency
+ */
+
+StepDrawing:
+ gwinClear(ghc);
+ gwinSetColor(ghc, Yellow);
+ gwinPrintf(ghc, "\n7. Drawing\n\n");
+
+ gwinSetColor(ghc, White);
+ gwinPrintf(ghc, "Press firmly on the surface (or press and hold the mouse button) and move around as if to draw.\n\n");
+ gwinPrintf(ghc, "A green line will follow your %s.\n\n", deviceText);
+ gwinPrintf(ghc, "Pressing Next will start the tests again but with the option of changing pen/finger mode.\n\n");
+ gwinPrintf(ghc, "Press Next or Back to continue.\n\n");
+
+ while(1) {
+ pem = (GEventMouse *)geventEventWait(&gl, TIME_INFINITE);
+ if (pem->y < bHeight && pem->x >= swidth-2*bWidth) {
+ if ((pem->buttons & GMETA_MOUSE_UP)) {
+ if (pem->x >= swidth-bWidth)
+ break;
+ goto StepClickJitter;
+ }
+ }
+ gdispDrawPixel(pem->x, pem->y, Green);
+ }
+
+ // Can't let this really exit
+ isFirstTime = FALSE;
+ goto StepDeviceType;
+}
diff --git a/demos/tools/touch_raw_readings/demo.mk b/demos/tools/touch_raw_readings/demo.mk
new file mode 100644
index 00000000..dbc3746e
--- /dev/null
+++ b/demos/tools/touch_raw_readings/demo.mk
@@ -0,0 +1,3 @@
+DEMODIR = $(GFXLIB)/demos/tools/touch_raw_readings
+GFXINC += $(DEMODIR)
+GFXSRC += $(DEMODIR)/main.c
diff --git a/demos/tools/touch_raw_readings/gfxconf.h b/demos/tools/touch_raw_readings/gfxconf.h
new file mode 100644
index 00000000..3d93a138
--- /dev/null
+++ b/demos/tools/touch_raw_readings/gfxconf.h
@@ -0,0 +1,62 @@
+/*
+ * Copyright (c) 2012, 2013, Joel Bodenmann aka Tectu <joel@unormal.org>
+ * Copyright (c) 2012, 2013, Andrew Hannam aka inmarket
+ *
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ * * Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * * Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * * Neither the name of the <organization> nor the
+ * names of its contributors may be used to endorse or promote products
+ * derived from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+ * DISCLAIMED. IN NO EVENT SHALL <COPYRIGHT HOLDER> BE LIABLE FOR ANY
+ * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+ * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+ * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
+ * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+ * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#ifndef _GFXCONF_H
+#define _GFXCONF_H
+
+/* The operating system to use. One of these must be defined - preferably in your Makefile */
+//#define GFX_USE_OS_CHIBIOS FALSE
+//#define GFX_USE_OS_WIN32 FALSE
+//#define GFX_USE_OS_LINUX FALSE
+//#define GFX_USE_OS_OSX FALSE
+
+/* GFX sub-systems to turn on */
+#define GFX_USE_GDISP TRUE
+#define GFX_USE_GWIN TRUE
+#define GFX_USE_GEVENT TRUE
+#define GFX_USE_GTIMER TRUE
+#define GFX_USE_GINPUT TRUE
+
+/* Features for the GDISP sub-system. */
+#define GDISP_NEED_VALIDATION TRUE
+#define GDISP_NEED_CLIP TRUE
+#define GDISP_NEED_TEXT TRUE
+#define GDISP_NEED_MULTITHREAD TRUE
+
+/* Builtin Fonts */
+#define GDISP_INCLUDE_FONT_UI2 TRUE
+
+/* Features for the GWIN sub-system. */
+#define GWIN_NEED_CONSOLE TRUE
+
+/* Features for the GINPUT sub-system. */
+#define GINPUT_NEED_MOUSE TRUE
+#define GINPUT_TOUCH_STARTRAW TRUE
+
+#endif /* _GFXCONF_H */
diff --git a/demos/tools/touch_raw_readings/main.c b/demos/tools/touch_raw_readings/main.c
new file mode 100644
index 00000000..d6c97920
--- /dev/null
+++ b/demos/tools/touch_raw_readings/main.c
@@ -0,0 +1,110 @@
+/*
+ * Copyright (c) 2012, 2013, Joel Bodenmann aka Tectu <joel@unormal.org>
+ * Copyright (c) 2012, 2013, Andrew Hannam aka inmarket
+ *
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ * * Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * * Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * * Neither the name of the <organization> nor the
+ * names of its contributors may be used to endorse or promote products
+ * derived from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+ * DISCLAIMED. IN NO EVENT SHALL <COPYRIGHT HOLDER> BE LIABLE FOR ANY
+ * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+ * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+ * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
+ * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+ * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include "gfx.h"
+
+// We get nasty and look at some internal structures - get the relevant information
+#include "src/gdriver/sys_defs.h"
+#include "src/ginput/driver_mouse.h"
+
+#include <string.h>
+
+static GConsoleObject gc;
+static GListener gl;
+static font_t font;
+static coord_t bHeight;
+static GHandle ghc;
+static coord_t swidth, sheight;
+
+/*------------------------------------------------------------------------*
+ * GINPUT Touch Driver Calibrator. *
+ *------------------------------------------------------------------------*/
+int main(void) {
+ GSourceHandle gs;
+ GEventMouse *pem;
+ GMouse * m;
+ GMouseVMT * vmt;
+
+ gfxInit(); // Initialize the display
+
+ // Get the display dimensions
+ swidth = gdispGetWidth();
+ sheight = gdispGetHeight();
+
+ // Create our title
+ font = gdispOpenFont("UI2");
+ gwinSetDefaultFont(font);
+ bHeight = gdispGetFontMetric(font, fontHeight)+4;
+ gdispFillStringBox(0, 0, swidth, bHeight, "Raw Touch Readings", font, Red, White, justifyCenter);
+
+ // Create our main display writing window
+ {
+ GWindowInit wi;
+
+ gwinClearInit(&wi);
+ wi.show = TRUE; wi.x = 0; wi.y = bHeight; wi.width = swidth; wi.height = sheight-bHeight;
+ ghc = gwinConsoleCreate(&gc, &wi);
+ }
+
+ // Initialize the listener
+ geventListenerInit(&gl);
+
+ // Copy the current mouse's VMT so we can play with it.
+ m = (GMouse *)gdriverGetInstance(GDRIVER_TYPE_MOUSE, 0);
+ if (!m) gfxHalt("No mouse instance 0");
+ vmt = gfxAlloc(sizeof(GMouseVMT));
+ if (!vmt) gfxHalt("Could not allocate memory for mouse VMT");
+ memcpy(vmt, m->d.vmt, sizeof(GMouseVMT));
+
+ // Swap VMT's on the current mouse to our RAM copy
+ m->d.vmt = (const GDriverVMT *)vmt;
+
+ // Listen for events
+ gs = ginputGetMouse(0);
+ geventAttachSource(&gl, gs, GLISTEN_MOUSEDOWNMOVES|GLISTEN_MOUSEMETA);
+
+ // Make sure we are in uncalibrated pen mode
+ m->flags &= ~(GMOUSE_FLG_CALIBRATE|GMOUSE_FLG_CLIP|GMOUSE_FLG_FINGERMODE);
+
+ // Pretend we are a mouse, turn off all touch processing, turn off move and click filtering
+ vmt->d.flags &= ~(GMOUSE_VFLG_TOUCH | GMOUSE_VFLG_ONLY_DOWN | GMOUSE_VFLG_POORUPDOWN);
+ vmt->pen_jitter.move = 0;
+ vmt->pen_jitter.click = 0;
+
+ // For this test turn on ALL mouse movement events
+ geventAttachSource(&gl, gs, GLISTEN_MOUSEDOWNMOVES|GLISTEN_MOUSEUPMOVES|GLISTEN_MOUSEMETA|GLISTEN_MOUSENOFILTER);
+
+ while(1) {
+ pem = (GEventMouse *)geventEventWait(&gl, TIME_INFINITE);
+ gwinPrintf(ghc, "%u, %u z=%u b=0x%04x\n", pem->x, pem->y, pem->z, pem->buttons & ~GINPUT_MISSED_MOUSE_EVENT);
+
+ // Always sleep a bit first to enable other events. We actually don't mind missing events.
+ gfxSleepMilliseconds(100);
+ }
+}
diff --git a/demos/tools/uGFXnetDisplay/demo.mk b/demos/tools/uGFXnetDisplay/demo.mk
new file mode 100644
index 00000000..e8bae51e
--- /dev/null
+++ b/demos/tools/uGFXnetDisplay/demo.mk
@@ -0,0 +1,3 @@
+DEMODIR = $(GFXLIB)/demos/tools/uGFXnetDisplay
+GFXINC += $(DEMODIR)
+GFXSRC += $(DEMODIR)/main.c
diff --git a/demos/tools/uGFXnetDisplay/gfxconf.h b/demos/tools/uGFXnetDisplay/gfxconf.h
new file mode 100644
index 00000000..4df44bc4
--- /dev/null
+++ b/demos/tools/uGFXnetDisplay/gfxconf.h
@@ -0,0 +1,41 @@
+/*
+ * This file is subject to the terms of the GFX License. If a copy of
+ * the license was not distributed with this file, you can obtain one at:
+ *
+ * http://ugfx.org/license.html
+ */
+
+#ifndef _GFXCONF_H
+#define _GFXCONF_H
+
+/* The operating system to use. One of these must be defined - preferably in your Makefile */
+//#define GFX_USE_OS_CHIBIOS FALSE
+//#define GFX_USE_OS_WIN32 FALSE
+//#define GFX_USE_OS_LINUX FALSE
+//#define GFX_USE_OS_OSX FALSE
+
+/* GFX sub-systems to turn on */
+#define GFX_USE_GDISP TRUE
+#define GFX_USE_GEVENT TRUE
+#define GFX_USE_GTIMER TRUE
+#define GFX_USE_GINPUT TRUE
+
+/* Features for the GDISP sub-system. */
+#define GDISP_NEED_VALIDATION TRUE
+#define GDISP_NEED_TEXT TRUE
+#define GDISP_NEED_CONTROL TRUE
+#define GDISP_NEED_SCROLL TRUE
+#define GDISP_NEED_PIXELREAD TRUE
+#define GDISP_NEED_STREAMING TRUE
+
+/* Builtin Fonts */
+#define GDISP_INCLUDE_FONT_UI2 TRUE
+
+/* Features for the GINPUT sub-system. */
+#define GINPUT_NEED_MOUSE TRUE
+
+/* We need to use this specific pixel format to match the network protocol */
+#define GDISP_PIXELFORMAT GDISP_PIXELFORMAT_RGB565
+
+#endif /* _GFXCONF_H */
+
diff --git a/demos/tools/uGFXnetDisplay/main.c b/demos/tools/uGFXnetDisplay/main.c
new file mode 100644
index 00000000..47274a31
--- /dev/null
+++ b/demos/tools/uGFXnetDisplay/main.c
@@ -0,0 +1,427 @@
+/*
+ * This file is subject to the terms of the GFX License. If a copy of
+ * the license was not distributed with this file, you can obtain one at:
+ *
+ * http://ugfx.org/license.html
+ */
+
+#include "gfx.h"
+#include "drivers/multiple/uGFXnet/uGFXnetProtocol.h"
+
+#ifndef GDISP_GFXNET_PORT
+ #define GDISP_GFXNET_PORT GNETCODE_DEFAULT_PORT
+#endif
+// This definition is only required for for O/S's that don't support a command line eg ChibiOS
+// It is ignored by those that do support a command line.
+#ifndef GDISP_GFXNET_HOST
+ #define GDISP_GFXNET_HOST "127.0.0.1" // Change this to your uGFXnet host.
+#endif
+
+// Do we wish to use old style socket calls. Some socket libraries only support the old version.
+// It is better to use the new version where possible however as it also supports IPv6.
+#ifndef OLD_STYLE_SOCKETS
+ #define OLD_STYLE_SOCKETS FALSE
+#endif
+
+// Which operating systems support a command line
+#if defined(WIN32) || GFX_USE_OS_WIN32 || GFX_USE_OS_OSX || GFX_USE_OS_LINUX
+ #define EMBEDED_OS FALSE
+#else
+ #define EMBEDED_OS TRUE
+#endif
+
+#if GNETCODE_VERSION != GNETCODE_VERSION_1_0
+ #error "This uGFXnet display only supports protocol V1.0"
+#endif
+#if GDISP_PIXELFORMAT != GNETCODE_PIXELFORMAT
+ #error "Oops - The uGFXnet protocol requires a different pixel format. Try defining GDISP_PIXELFORMAT in your gfxconf.h file."
+#endif
+
+#include <stdio.h>
+#include <string.h>
+#include <stdlib.h>
+
+#if defined(WIN32) || GFX_USE_OS_WIN32
+ #if OLD_STYLE_SOCKETS
+ #include <winsock.h>
+ #else
+ #include <ws2tcpip.h>
+ #include <winsock2.h>
+ #endif
+ #define SOCKET_TYPE SOCKET
+
+ static void StopSockets(void) {
+ WSACleanup();
+ }
+ static void StartSockets(void) {
+ WSADATA wsaData;
+ if (WSAStartup(MAKEWORD(2,2), &wsaData) != 0)
+ gfxHalt("GDISP: uGFXnet - WSAStartup failed");
+ atexit(StopSockets);
+ }
+
+#elif GFX_USE_OS_LINUX || GFX_USE_OS_OSX
+ #include <sys/types.h>
+ #include <sys/socket.h>
+ #include <netinet/in.h>
+ #include <arpa/inet.h>
+ #include <netdb.h>
+
+ #define closesocket(fd) close(fd)
+ #define ioctlsocket(fd,cmd,arg) ioctl(fd,cmd,arg)
+ #define StartSockets()
+ #define SOCKET_TYPE int
+
+#else
+ #include <lwip/sockets.h>
+ #include <lwip/netdb.h>
+
+ #if GDISP_GFXNET_CUSTOM_LWIP_STARTUP
+ extern void Start_LWIP(void); // Where the application does the lwip stack setup
+ #define StartSockets() Start_LWIP();
+ #else
+ #include "lwipthread.h"
+ #define StartSockets() gfxThreadClose(gfxThreadCreate(wa_lwip_thread, LWIP_THREAD_STACK_SIZE, NORMAL_PRIORITY, lwip_thread, 0))
+ #endif
+
+ #if !LWIP_SOCKET
+ #error "GDISP: uGFXnet - LWIP_SOCKETS must be defined in your lwipopts.h file"
+ #endif
+ #if !LWIP_COMPAT_SOCKETS
+ #error "GDISP: uGFXnet - LWIP_COMPAT_SOCKETS must be defined in your lwipopts.h file"
+ #endif
+ #if !LWIP_DNS
+ #error "GDISP: uGFXnet - LWIP_DNS must be defined in your lwipopts.h file"
+ #endif
+ #define SOCKET_TYPE int
+
+ // Mutex protection is required for LWIP
+ #if !GDISP_GFXNET_UNSAFE_SOCKETS
+ #warning "GDISP: uGFXnet - LWIP sockets are not thread-safe. GDISP_GFXNET_UNSAFE_SOCKETS has been turned on for you."
+ #undef GDISP_GFXNET_UNSAFE_SOCKETS
+ #define GDISP_GFXNET_UNSAFE_SOCKETS TRUE
+ #endif
+#endif
+
+#if GFX_USE_GINPUT && GINPUT_NEED_MOUSE
+ static GListener gl;
+#endif
+static SOCKET_TYPE netfd = (SOCKET_TYPE)-1;
+static font_t font;
+
+#define STRINGOF_RAW(s) #s
+#define STRINGOF(s) STRINGOF_RAW(s)
+
+#if EMBEDED_OS
+ #define cmd_args
+ #define proto_args void
+ #define xhost GDISP_GFXNET_HOST
+ #define xport STRINGOF(GDISP_GFXNET_HOST)
+ #define xportnum GDISP_GFXNET_HOST
+#else
+ #define cmd_args argc, argv
+ #define proto_args int argc, char **argv
+ static char * xhost;
+ static char * xport;
+ #if OLD_STYLE_SOCKETS
+ static int xportnum = GDISP_GFXNET_PORT;
+ #endif
+#endif
+
+/**
+ * Get a whole packet of data.
+ * Len is specified in the number of uint16_t's we want as our protocol only talks uint16_t's.
+ * If the connection closes before we get all the data - the call returns FALSE.
+ */
+static bool_t getpkt(uint16_t *pkt, int len) {
+ int got;
+ int have;
+
+ // Get the packet of data
+ len *= sizeof(uint16_t);
+ have = 0;
+ while(len && (got = recv(netfd, ((char *)pkt)+have, len, 0)) > 0) {
+ have += got;
+ len -= got;
+ }
+ if (len)
+ return FALSE;
+
+ // Convert each uint16_t to host order
+ for(got = 0, have /= 2; got < have; got++)
+ pkt[got] = ntohs(pkt[got]);
+
+ return TRUE;
+}
+
+/**
+ * Send a whole packet of data.
+ * Len is specified in the number of uint16_t's we want to send as our protocol only talks uint16_t's.
+ * Note that contents of the packet are modified to ensure it will cross the wire in the correct format.
+ * If the connection closes before we send all the data - the call returns FALSE.
+ */
+static bool_t sendpkt(uint16_t *pkt, int len) {
+ int i;
+
+ // Convert each uint16_t to network order
+ for(i = 0; i < len; i++)
+ pkt[i] = htons(pkt[i]);
+
+ // Send it
+ len *= sizeof(uint16_t);
+ return send(netfd, (const char *)pkt, len, 0) == len;
+}
+
+#if GFX_USE_GINPUT && GINPUT_NEED_MOUSE
+ /**
+ * We use a separate thread to capture mouse events and send them down the pipe.
+ * We do the send in a single transaction to prevent it getting interspersed with
+ * any reply we need to send on the main thread.
+ */
+ static DECLARE_THREAD_STACK(waNetThread, 512);
+ static DECLARE_THREAD_FUNCTION(NetThread, param) {
+ GEventMouse *pem;
+ uint16_t cmd[2];
+ uint16_t lbuttons;
+ coord_t lx, ly;
+ (void) param;
+
+ // Initialize the mouse and the listener.
+ geventListenerInit(&gl);
+ geventAttachSource(&gl, ginputGetMouse(0), GLISTEN_MOUSEDOWNMOVES|GLISTEN_MOUSEMETA);
+ lbuttons = 0;
+ lx = ly = -1;
+
+ while(1) {
+ // Get a (mouse) event
+ pem = (GEventMouse *)geventEventWait(&gl, TIME_INFINITE);
+ if (pem->type != GEVENT_MOUSE && pem->type != GEVENT_TOUCH)
+ continue;
+
+ // Nothing to do if the socket is not open
+ if (netfd == (SOCKET)-1)
+ continue;
+
+ // Nothing to do if the mouse data has not changed
+ if (lx == pem->x && ly == pem->y && lbuttons == pem->current_buttons)
+ continue;
+
+ // Transfer mouse data that has changed
+ if (lx != pem->x) {
+ lx = pem->x;
+ cmd[0] = GNETCODE_MOUSE_X;
+ cmd[1] = lx;
+ sendpkt(cmd, 2);
+ }
+ if (ly != pem->y) {
+ ly = pem->y;
+ cmd[0] = GNETCODE_MOUSE_Y;
+ cmd[1] = ly;
+ sendpkt(cmd, 2);
+ }
+ // We always send the buttons as it also acts as a mouse sync signal
+ lbuttons = pem->current_buttons;
+ cmd[0] = GNETCODE_MOUSE_B;
+ cmd[1] = lbuttons;
+ sendpkt(cmd, 2);
+ }
+ return 0;
+ }
+#endif
+
+/**
+ * Do the connection to the remote host.
+ * We have two prototypes here - one for embedded systems and one for systems with a command line.
+ * We have two methods of using the sockets library - one very old style and the other the more modern approach.
+ */
+static SOCKET_TYPE doConnect(proto_args) {
+ SOCKET_TYPE fd;
+
+ #if !EMBEDED_OS
+ (void) argc;
+
+ // Parse the command line arguments
+ xhost = 0;
+ xport = 0;
+ while (*++argv) {
+ if (!xhost)
+ xhost = argv[0];
+ else if (!xport) {
+ xport = argv[0];
+ #if OLD_STYLE_SOCKETS
+ if (sscanf(xport, "%i", &xportnum) != 1 || xportnum >= 65536 || xportnum <= 0) {
+ fprintf(stderr, "Error: Bad port specification '%s'\n\n", xport);
+ goto usage;
+ }
+ #endif
+ } else {
+ fprintf(stderr, "Error: Unknown argument '%s'\n\n", argv[0]);
+ goto usage;
+ }
+ }
+
+ // Check the command line arguments were valid.
+ if (!xport)
+ xport = STRINGOF(GDISP_GFXNET_PORT);
+ if (!xhost) {
+ usage:
+ fprintf(stderr, "Usage: uGFXnetDisplay host [port]\n");
+ exit(1);
+ }
+ #endif
+
+ #if OLD_STYLE_SOCKETS
+ struct sockaddr_in serv_addr;
+ struct hostent * h;
+
+ h = gethostbyname(xhost);
+ if (!h)
+ // Error: Unable to find an ip-address for the specified server
+ return (SOCKET_TYPE)-1;
+ memset(&serv_addr, 0, sizeof(serv_addr));
+ serv_addr.sin_port = htons(xportnum);
+ serv_addr.sin_family = h->h_addrtype;
+ memcpy(&serv_addr.sin_addr, h->h_addr_list[0], h->h_length);
+ if ((fd = socket(serv_addr.sin_family, SOCK_STREAM, 0)) == (SOCKET_TYPE)-1)
+ // Error: Socket failed
+ return (SOCKET_TYPE)-1;
+ if (connect(fd, (struct sockaddr *)&serv_addr, sizeof(serv_addr)) == -1) {
+ // Error: Could not connect to the specified server
+ closesocket(fd);
+ fd = (SOCKET_TYPE)-1;
+ }
+
+ #else
+ struct addrinfo hints, *servinfo, *p;
+
+ memset(&hints, 0, sizeof hints);
+ hints.ai_family = AF_UNSPEC;
+ hints.ai_socktype = SOCK_STREAM;
+ fd = (SOCKET_TYPE)-1;
+
+ if (getaddrinfo(xhost, xport, &hints, &servinfo) != 0)
+ // Error: Unable to find an ip-address for the specified server
+ return (SOCKET_TYPE)-1;
+ for(p = servinfo; p; p = p->ai_next) {
+ if ((fd = socket(p->ai_family, p->ai_socktype, p->ai_protocol)) == (SOCKET_TYPE)-1)
+ continue;
+ if (connect(fd, p->ai_addr, p->ai_addrlen) == -1) {
+ closesocket(fd);
+ fd = (SOCKET_TYPE)-1;
+ continue;
+ }
+ break;
+ }
+ freeaddrinfo(servinfo);
+ #endif
+
+ return fd;
+}
+
+/**
+ * Our main function.
+ * There are two prototypes - one for systems with a command line and one for embedded systems without one.
+ */
+int main(proto_args) {
+ uint16_t cmd[5];
+ unsigned cnt;
+
+
+ // Initialize and clear the display
+ gfxInit();
+ font = gdispOpenFont("UI2");
+
+ // Open the connection
+ gdispDrawStringBox(0, 0, gdispGetWidth(), gdispGetHeight(), "Connecting to host...", font, White, justifyCenter);
+ StartSockets();
+ netfd = doConnect(cmd_args);
+ if (netfd == (SOCKET_TYPE)-1)
+ gfxHalt("Could not connect to the specified server");
+ gdispClear(Black);
+
+ // Get the initial packet from the host
+ if (!getpkt(cmd, 2)) goto alldone;
+ if (cmd[0] != GNETCODE_INIT || cmd[1] != GNETCODE_VERSION)
+ gfxHalt("Oops - The protocol doesn't look like one we understand");
+
+ // Get the rest of the initial arguments
+ if (!getpkt(cmd, 4)) goto alldone; // cmd[] = width, height, pixelformat, hasmouse
+
+ // We will ignore size mismatches but the pixel format must match
+ if (cmd[2] != GDISP_PIXELFORMAT)
+ gfxHalt("Oops - The remote display is using a different pixel format to us.\nTry defining GDISP_PIXELFORMAT in your gfxconf.h file.");
+
+ #if GFX_USE_GINPUT && GINPUT_NEED_MOUSE
+ // Start the mouse thread if needed
+ if (cmd[3])
+ gfxThreadClose(gfxThreadCreate(waNetThread, sizeof(waNetThread), HIGH_PRIORITY, NetThread, 0));
+ #endif
+
+ // Process incoming instructions
+ while(getpkt(cmd, 1)) {
+ switch(cmd[0]) {
+ case GNETCODE_FLUSH:
+ gdispFlush();
+ break;
+ case GNETCODE_PIXEL:
+ if (!getpkt(cmd, 3)) goto alldone; // cmd[] = x, y, color
+ gdispDrawPixel(cmd[0], cmd[1], cmd[2]);
+ break;
+ case GNETCODE_FILL:
+ if (!getpkt(cmd, 5)) goto alldone; // cmd[] = x, y, cx, cy, color
+ gdispFillArea(cmd[0], cmd[1], cmd[2], cmd[3], cmd[4]);
+ break;
+ case GNETCODE_BLIT:
+ if (!getpkt(cmd, 4)) goto alldone; // cmd[] = x, y, cx, cy - Followed by cx * cy pixels
+ gdispStreamStart(cmd[0],cmd[1],cmd[2],cmd[3]);
+ for(cnt = (unsigned)cmd[2] * cmd[3]; cnt; cnt--) {
+ if (!getpkt(cmd, 1)) goto alldone;
+ gdispStreamColor(cmd[0]);
+ }
+ gdispStreamStop();
+ break;
+ #if GDISP_NEED_PIXELREAD
+ case GNETCODE_READ:
+ if (!getpkt(cmd, 2)) goto alldone; // cmd[] = x, y - Response is GNETCODE_READ,color
+ cmd[1] = gdispGetPixelColor(cmd[0], cmd[1]);
+ cmd[0] = GNETCODE_READ;
+ if (!sendpkt(cmd, 2)) goto alldone;
+ break;
+ #endif
+ #if GDISP_NEED_SCROLL
+ case GNETCODE_SCROLL:
+ if (!getpkt(cmd, 5)) goto alldone; // cmd[] = x, y, cx, cy, lines
+ gdispVerticalScroll(cmd[0], cmd[1], cmd[2], cmd[3], cmd[4], Black);
+ break;
+ #endif
+ case GNETCODE_CONTROL:
+ if (!getpkt(cmd, 2)) goto alldone; // cmd[] = what,data - Response is GNETCODE_CONTROL, 0x0000 (fail) or GNETCODE_CONTROL, 0x0001 (success)
+ gdispControl(cmd[0], (void *)(unsigned)cmd[1]);
+ switch(cmd[0]) {
+ case GDISP_CONTROL_ORIENTATION:
+ cmd[1] = (uint16_t)gdispGetOrientation() == cmd[1] ? 1 : 0;
+ break;
+ case GDISP_CONTROL_POWER:
+ cmd[1] = (uint16_t)gdispGetPowerMode() == cmd[1] ? 1 : 0;
+ break;
+ case GDISP_CONTROL_BACKLIGHT:
+ cmd[1] = (uint16_t)gdispGetBacklight() == cmd[1] ? 1 : 0;
+ break;
+ default:
+ cmd[1] = 0;
+ break;
+ }
+ cmd[0] = GNETCODE_CONTROL;
+ if (!sendpkt(cmd, 2)) goto alldone;
+ break;
+ default:
+ gfxHalt("Oops - The host has sent invalid commands");
+ break;
+ }
+ }
+
+alldone:
+ closesocket(netfd);
+ gfxHalt("Connection closed");
+ return 0;
+}