diff options
author | inmarket <andrewh@inmarket.com.au> | 2014-11-14 09:10:59 +1000 |
---|---|---|
committer | inmarket <andrewh@inmarket.com.au> | 2014-11-14 09:10:59 +1000 |
commit | 93c9ebaa793d96147784e061102fec3423584fc0 (patch) | |
tree | 2be19e5c602dcc622a2ff411bb0d8698498c5d9c /demos | |
parent | 6bc091035a08f58eb6c60e7cceb01ef29e655e07 (diff) | |
download | uGFX-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.txt | 4 | ||||
-rw-r--r-- | demos/tools/touch_driver_test/demo.mk | 3 | ||||
-rw-r--r-- | demos/tools/touch_driver_test/gfxconf.h | 62 | ||||
-rw-r--r-- | demos/tools/touch_driver_test/main.c | 461 | ||||
-rw-r--r-- | demos/tools/touch_raw_readings/demo.mk | 3 | ||||
-rw-r--r-- | demos/tools/touch_raw_readings/gfxconf.h | 62 | ||||
-rw-r--r-- | demos/tools/touch_raw_readings/main.c | 110 | ||||
-rw-r--r-- | demos/tools/uGFXnetDisplay/demo.mk | 3 | ||||
-rw-r--r-- | demos/tools/uGFXnetDisplay/gfxconf.h | 41 | ||||
-rw-r--r-- | demos/tools/uGFXnetDisplay/main.c | 427 |
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; +} |