aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/multiple
diff options
context:
space:
mode:
authorinmarket <inmarket@ugfx.org>2016-08-30 19:12:46 +1000
committerinmarket <inmarket@ugfx.org>2016-08-30 19:12:46 +1000
commit81505c8be20b89cd545dfc2fe6d3ed0c86524e89 (patch)
treeca875cf5937e85cb6a7015b746bacb64c42576e6 /drivers/multiple
parentea632d50012c2a65b54792167474bd8d4e6cf0bf (diff)
downloaduGFX-81505c8be20b89cd545dfc2fe6d3ed0c86524e89.tar.gz
uGFX-81505c8be20b89cd545dfc2fe6d3ed0c86524e89.tar.bz2
uGFX-81505c8be20b89cd545dfc2fe6d3ed0c86524e89.zip
New uGFXnetESP8266 driver. A gdisp driver for the ESP8266.
Not tested yet.
Diffstat (limited to 'drivers/multiple')
-rw-r--r--drivers/multiple/uGFXnet/readme.txt2
-rw-r--r--drivers/multiple/uGFXnetESP8266/driver.mk2
-rw-r--r--drivers/multiple/uGFXnetESP8266/gdisp_lld_config.h32
-rw-r--r--drivers/multiple/uGFXnetESP8266/gdisp_lld_uGFXnetESP8266.cpp622
-rw-r--r--drivers/multiple/uGFXnetESP8266/ginput_lld_mouse_config.h41
-rw-r--r--drivers/multiple/uGFXnetESP8266/readme.txt30
-rw-r--r--drivers/multiple/uGFXnetESP8266/uGFXnetProtocol.h34
7 files changed, 762 insertions, 1 deletions
diff --git a/drivers/multiple/uGFXnet/readme.txt b/drivers/multiple/uGFXnet/readme.txt
index 67b37c12..0cb3ee07 100644
--- a/drivers/multiple/uGFXnet/readme.txt
+++ b/drivers/multiple/uGFXnet/readme.txt
@@ -19,7 +19,7 @@ and a touchscreen driver.
2. To your makefile add the following lines:
include $(GFXLIB)/gfx.mk
- include $(GFXLIB)/drivers/multiple/uGFXnet/gdisp_lld.mk
+ include $(GFXLIB)/drivers/multiple/uGFXnet/driver.mk
3. Make sure you have networking libraries included in your Makefile.
diff --git a/drivers/multiple/uGFXnetESP8266/driver.mk b/drivers/multiple/uGFXnetESP8266/driver.mk
new file mode 100644
index 00000000..ed322f52
--- /dev/null
+++ b/drivers/multiple/uGFXnetESP8266/driver.mk
@@ -0,0 +1,2 @@
+GFXINC += $(GFXLIB)/drivers/multiple/uGFXnetESP8266
+GFXSRC += $(GFXLIB)/drivers/multiple/uGFXnetESP8266/gdisp_lld_uGFXnetESP8266.cpp
diff --git a/drivers/multiple/uGFXnetESP8266/gdisp_lld_config.h b/drivers/multiple/uGFXnetESP8266/gdisp_lld_config.h
new file mode 100644
index 00000000..e181d91e
--- /dev/null
+++ b/drivers/multiple/uGFXnetESP8266/gdisp_lld_config.h
@@ -0,0 +1,32 @@
+/*
+ * 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 _GDISP_LLD_CONFIG_H
+#define _GDISP_LLD_CONFIG_H
+
+#if GFX_USE_GDISP
+
+/*===========================================================================*/
+/* Driver hardware support. */
+/*===========================================================================*/
+
+// Calling gdispGFlush() is optional for this driver but can be used by the
+// application to force a display update. eg after streaming.
+
+#define GDISP_HARDWARE_FLUSH TRUE
+#define GDISP_HARDWARE_DRAWPIXEL TRUE
+#define GDISP_HARDWARE_FILLS TRUE
+#define GDISP_HARDWARE_BITFILLS TRUE
+#define GDISP_HARDWARE_PIXELREAD TRUE
+#define GDISP_HARDWARE_SCROLL TRUE
+#define GDISP_HARDWARE_CONTROL TRUE
+
+#define GDISP_LLD_PIXELFORMAT GDISP_PIXELFORMAT_RGB565
+
+#endif /* GFX_USE_GDISP */
+
+#endif /* _GDISP_LLD_CONFIG_H */
diff --git a/drivers/multiple/uGFXnetESP8266/gdisp_lld_uGFXnetESP8266.cpp b/drivers/multiple/uGFXnetESP8266/gdisp_lld_uGFXnetESP8266.cpp
new file mode 100644
index 00000000..7963acab
--- /dev/null
+++ b/drivers/multiple/uGFXnetESP8266/gdisp_lld_uGFXnetESP8266.cpp
@@ -0,0 +1,622 @@
+/*
+ * 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
+ */
+
+// We need to include stdio.h below. Turn off GFILE_NEED_STDIO just for this file to prevent conflicts
+#define GFILE_NEED_STDIO_MUST_BE_OFF
+
+#include "gfx.h"
+
+#if GFX_USE_GDISP
+
+#include <ESP8266WiFi.h>
+
+#define GDISP_DRIVER_VMT GDISPVMT_uGFXnetESP8266
+#include "gdisp_lld_config.h"
+#include "../../../src/gdisp/gdisp_driver.h"
+#include "uGFXnetProtocol.h"
+
+#ifndef GDISP_SCREEN_WIDTH
+ #define GDISP_SCREEN_WIDTH 640
+#endif
+#ifndef GDISP_SCREEN_HEIGHT
+ #define GDISP_SCREEN_HEIGHT 480
+#endif
+#ifndef GDISP_GFXNET_PORT
+ #define GDISP_GFXNET_PORT GNETCODE_DEFAULT_PORT
+#endif
+#ifndef GDISP_DONT_WAIT_FOR_NET_DISPLAY
+ #define GDISP_DONT_WAIT_FOR_NET_DISPLAY FALSE
+#endif
+
+static WiFiServer server(GDISP_GFXNET_PORT);
+static GTimer poller;
+static bool_t uGFXInitDone;
+
+#ifndef GDISP_GFXNET_WIFI_INIT_FUNCTION
+ #define GDISP_GFXNET_WIFI_INIT_FUNCTION uGFXnetArduinoWifiInit
+ #ifndef GDISP_GFXNET_WIFI_SSID
+ #error "uGFXnetArduino: GDISP_GFXNET_WIFI_SSID is not set. You must define the Wifi SSID"
+ #endif
+ #ifndef GDISP_GFXNET_WIFI_PASSWORD
+ #error "uGFXnetArduino: GDISP_GFXNET_WIFI_PASSWORD is not set. You must define the Wifi password"
+ #endif
+
+ static void uGFXnetArduinoWifiInit(WifiServer *ws) {
+ WiFi.begin(GDISP_GFXNET_WIFI_SSID, GDISP_GFXNET_WIFI_PASSWORD);
+ while (WiFi.status() != WL_CONNECTED)
+ gfxYield();
+
+ ws->begin();
+ }
+#else
+ extern "C" void GDISP_GFXNET_WIFI_INIT_FUNCTION(WifiServer *ws);
+#endif
+
+#if GINPUT_NEED_MOUSE
+ // Include mouse support code
+ #define GMOUSE_DRIVER_VMT GMOUSEVMT_uGFXnet
+ #include "../../../src/ginput/ginput_driver_mouse.h"
+
+ // Forward definitions
+ static bool_t NMouseInit(GMouse *m, unsigned driverinstance);
+ static bool_t NMouseRead(GMouse *m, GMouseReading *prd);
+
+ const GMouseVMT const GMOUSE_DRIVER_VMT[1] = {{
+ {
+ GDRIVER_TYPE_MOUSE,
+ GMOUSE_VFLG_NOPOLL|GMOUSE_VFLG_DYNAMICONLY,
+ // Extra flags for testing only
+ //GMOUSE_VFLG_TOUCH|GMOUSE_VFLG_SELFROTATION|GMOUSE_VFLG_DEFAULTFINGER
+ //GMOUSE_VFLG_CALIBRATE|GMOUSE_VFLG_CAL_EXTREMES|GMOUSE_VFLG_CAL_TEST|GMOUSE_VFLG_CAL_LOADFREE
+ //GMOUSE_VFLG_ONLY_DOWN|GMOUSE_VFLG_POORUPDOWN
+ sizeof(GMouse),
+ _gmouseInitDriver, _gmousePostInitDriver, _gmouseDeInitDriver
+ },
+ 1, // z_max
+ 0, // z_min
+ 1, // z_touchon
+ 0, // z_touchoff
+ { // pen_jitter
+ 0, // calibrate
+ 0, // click
+ 0 // move
+ },
+ { // finger_jitter
+ 0, // calibrate
+ 2, // click
+ 2 // move
+ },
+ NMouseInit, // init
+ 0, // deinit
+ NMouseRead, // get
+ 0, // calsave
+ 0 // calload
+ }};
+#endif
+
+#if GNETCODE_VERSION != GNETCODE_VERSION_1_0
+ #error "GDISP: uGFXnetESP8266 - This driver only support protocol V1.0"
+#endif
+#if GDISP_LLD_PIXELFORMAT != GNETCODE_PIXELFORMAT
+ #error "GDISP: uGFXnetESP8266 - The driver pixel format must match the protocol"
+#endif
+
+#define GDISP_FLG_CONNECTED (GDISP_FLG_DRIVER<<0)
+#define GDISP_FLG_HAVEDATA (GDISP_FLG_DRIVER<<1)
+
+#define CLIENTFD WifiClient *
+
+/*===========================================================================*/
+/* Driver local routines . */
+/*===========================================================================*/
+
+typedef struct netPriv {
+ CLIENTFD netfd; // The current client
+ unsigned databytes; // How many bytes have been read
+ uint16_t data[2]; // Buffer for storing data read.
+ #if GINPUT_NEED_MOUSE
+ coord_t mousex, mousey;
+ uint16_t mousebuttons;
+ GMouse * mouse;
+ #endif
+} netPriv;
+
+#if GDISP_GFXNET_UNSAFE_SOCKETS
+ static gfxMutex uGFXnetMutex;
+ #define MUTEX_INIT gfxMutexInit(&uGFXnetMutex)
+ #define MUTEX_ENTER gfxMutexEnter(&uGFXnetMutex)
+ #define MUTEX_EXIT gfxMutexExit(&uGFXnetMutex)
+#else
+ #define MUTEX_INIT
+ #define MUTEX_ENTER
+ #define MUTEX_EXIT
+#endif
+
+static void endcon(GDisplay *g) {
+ netPriv * priv;
+
+ g->flags &= ~GDISP_FLG_CONNECTED;
+ priv = g->priv;
+ priv->netfd->stop();
+ delete priv->netfd;
+ priv->netfd = 0;
+}
+
+/**
+ * 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(CLIENTFD fd, uint16_t *pkt, int len) {
+ // Convert each uint16_t to network order
+ #if GFX_CPU_ENDIAN == GFX_CPU_ENDIAN_LITTLE
+ {
+ int i;
+
+ for(i = 0; i < len; i++)
+ pkt[i] = ((pkt[i]>>8)|(pkt[i]<<8));
+ }
+ #endif
+
+ // Send it
+ len *= sizeof(uint16_t);
+ return fd->write((uint8_t *)pkt, len) == len;
+}
+
+static void rxdata(GDisplay *g) {
+ netPriv * priv;
+ CLIENTFD fd;
+ int len;
+
+ if ((g->flags & GDISP_FLG_HAVEDATA)) {
+ // The higher level is still processing the previous data.
+ // Give it a chance to run by coming back to this data.
+ return;
+ }
+
+ priv = g->priv;
+ fd = priv->netfd;
+
+ MUTEX_ENTER;
+ // Are we still connected?
+ if (!fd->connected()) {
+ MUTEX_EXIT;
+ endcon(g);
+ return;
+ }
+
+ // Is there data available
+ if (!fd->available()) {
+ MUTEX_EXIT;
+ return;
+ }
+
+ // Get the data
+ if ((len = fd->read(((uint8_t *)priv->data)+priv->databytes, sizeof(priv->data)-priv->databytes, 0)) <= 0) {
+ // Socket closed or in error state
+ MUTEX_EXIT;
+ endcon(g);
+ return;
+ }
+ MUTEX_EXIT;
+
+ // Do we have a full reply yet
+ priv->databytes += len;
+ if (priv->databytes < sizeof(priv->data))
+ return;
+ priv->databytes = 0;
+
+ // Convert network byte or to host byte order
+ #if GFX_CPU_ENDIAN == GFX_CPU_ENDIAN_LITTLE
+ priv->data[0] = ((priv->data[0]>>8)|(priv->data[0]<<8))
+ priv->data[1] = ((priv->data[1]>>8)|(priv->data[1]<<8))
+ #endif
+
+ // Process the data received
+ switch(priv->data[0]) {
+ #if GINPUT_NEED_MOUSE
+ case GNETCODE_MOUSE_X: priv->mousex = priv->data[1]; break;
+ case GNETCODE_MOUSE_Y: priv->mousey = priv->data[1]; break;
+ case GNETCODE_MOUSE_B:
+ priv->mousebuttons = priv->data[1];
+ // Treat the button event as the sync signal
+ _gmouseWakeup(priv->mouse);
+ break;
+ #endif
+ case GNETCODE_CONTROL:
+ case GNETCODE_READ:
+ g->flags |= GDISP_FLG_HAVEDATA;
+ break;
+ case GNETCODE_KILL:
+ gfxHalt("GDISP: uGFXnet - Display sent KILL command");
+ break;
+
+ default:
+ // Just ignore unrecognised data
+ break;
+ }
+}
+
+void uGFXnetClientPoller(void *param) {
+ GDisplay *g;
+ (void) param;
+
+ // Is there a new server connection?
+ if (server.hasClient()) {
+
+ // Look for a display that isn't connected
+ for(g = 0; (g = (GDisplay *)gdriverGetNext(GDRIVER_TYPE_DISPLAY, (GDriver *)g));) {
+ // Ignore displays for other controllers
+ #ifdef GDISP_DRIVER_LIST
+ if (gvmt(g) != &GDISPVMT_uGFXnet)
+ continue;
+ #endif
+ if (!(g->flags & GDISP_FLG_CONNECTED)) {
+ netPriv * priv;
+
+ // Reset the priv area
+ priv = g->priv;
+ priv->netfd = new WifiClient(server.available());
+ priv->databytes = 0;
+ priv->mousebuttons = 0;
+
+ // Send the initialisation data (2 words at a time)
+ priv->data[0] = GNETCODE_INIT;
+ priv->data[1] = GNETCODE_VERSION;
+ sendpkt(priv->netfd, priv->data, 2);
+ priv->data[0] = GDISP_SCREEN_WIDTH;
+ priv->data[1] = GDISP_SCREEN_HEIGHT;
+ sendpkt(priv->netfd, priv->data, 2);
+ priv->data[0] = GDISP_LLD_PIXELFORMAT;
+ priv->data[1] = 1; // We have a mouse
+ MUTEX_ENTER;
+ sendpkt(priv->netfd, priv->data, 2);
+ MUTEX_EXIT;
+
+ // The display is now working
+ g->flags |= GDISP_FLG_CONNECTED;
+
+ // Send a redraw all
+ #if GFX_USE_GWIN && GWIN_NEED_WINDOWMANAGER
+ gdispGClear(g, gwinGetDefaultBgColor());
+ gwinRedrawDisplay(g, FALSE);
+ #endif
+ break;
+ }
+ }
+ }
+
+ // Look for a display that is connected so we can check if it has data
+ for(g = 0; (g = (GDisplay *)gdriverGetNext(GDRIVER_TYPE_DISPLAY, (GDriver *)g));) {
+ // Ignore displays for other controllers
+ #ifdef GDISP_DRIVER_LIST
+ if (gvmt(g) != &GDISPVMT_uGFXnet)
+ continue;
+ #endif
+ if ((g->flags & GDISP_FLG_CONNECTED))
+ rxdata(g);
+ }
+}
+
+/*===========================================================================*/
+/* Driver exported functions. */
+/*===========================================================================*/
+
+LLDSPEC bool_t gdisp_lld_init(GDisplay *g) {
+ netPriv * priv;
+
+ // Initialise the receiver thread (if it hasn't been done already)
+ if (!uGFXInitDone) {
+ MUTEX_INIT;
+ // Init and Start the poller
+ GDISP_GFXNET_WIFI_INIT_FUNCTION(&server);
+
+ // Initialise the poller
+ gtimerInit(&poller);
+ gtimerStart(&poller, uGFXnetClientPoller, 0, TRUE, 50);
+ uGFXInitDone = TRUE;
+ }
+
+ // Create a private area for this window
+ if (!(priv = gfxAlloc(sizeof(netPriv))))
+ gfxHalt("GDISP: uGFXnetESP8266 - Memory allocation failed");
+ memset(priv, 0, sizeof(netPriv));
+ g->priv = priv;
+ g->board = 0; // no board interface for this controller
+
+ // Create the associated mouse
+ #if GINPUT_NEED_MOUSE
+ priv->mouse = (GMouse *)gdriverRegister((const GDriverVMT const *)GMOUSE_DRIVER_VMT, g);
+ #endif
+
+ // Initialise the GDISP structure
+ g->g.Orientation = GDISP_ROTATE_0;
+ g->g.Powermode = powerOn;
+ g->g.Backlight = 100;
+ g->g.Contrast = 50;
+ g->g.Width = GDISP_SCREEN_WIDTH;
+ g->g.Height = GDISP_SCREEN_HEIGHT;
+
+ return TRUE;
+}
+
+#if GDISP_HARDWARE_FLUSH
+ LLDSPEC void gdisp_lld_flush(GDisplay *g) {
+ netPriv * priv;
+ uint16_t buf[1];
+
+ #if GDISP_DONT_WAIT_FOR_NET_DISPLAY
+ if (!(g->flags & GDISP_FLG_CONNECTED))
+ return;
+ #else
+ while(!(g->flags & GDISP_FLG_CONNECTED))
+ gfxSleepMilliseconds(200);
+ #endif
+
+ priv = g->priv;
+ buf[0] = GNETCODE_FLUSH;
+ MUTEX_ENTER;
+ sendpkt(priv->netfd, buf, 1);
+ MUTEX_EXIT;
+ }
+#endif
+
+#if GDISP_HARDWARE_DRAWPIXEL
+ LLDSPEC void gdisp_lld_draw_pixel(GDisplay *g) {
+ netPriv * priv;
+ uint16_t buf[4];
+
+ #if GDISP_DONT_WAIT_FOR_NET_DISPLAY
+ if (!(g->flags & GDISP_FLG_CONNECTED))
+ return;
+ #else
+ while(!(g->flags & GDISP_FLG_CONNECTED))
+ gfxSleepMilliseconds(200);
+ #endif
+
+ priv = g->priv;
+ buf[0] = GNETCODE_PIXEL;
+ buf[1] = g->p.x;
+ buf[2] = g->p.y;
+ buf[3] = gdispColor2Native(g->p.color);
+ MUTEX_ENTER;
+ sendpkt(priv->netfd, buf, 4);
+ MUTEX_EXIT;
+ }
+#endif
+
+/* ---- Optional Routines ---- */
+
+#if GDISP_HARDWARE_FILLS
+ LLDSPEC void gdisp_lld_fill_area(GDisplay *g) {
+ netPriv * priv;
+ uint16_t buf[6];
+
+ #if GDISP_DONT_WAIT_FOR_NET_DISPLAY
+ if (!(g->flags & GDISP_FLG_CONNECTED))
+ return;
+ #else
+ while(!(g->flags & GDISP_FLG_CONNECTED))
+ gfxSleepMilliseconds(200);
+ #endif
+
+ priv = g->priv;
+ buf[0] = GNETCODE_FILL;
+ buf[1] = g->p.x;
+ buf[2] = g->p.y;
+ buf[3] = g->p.cx;
+ buf[4] = g->p.cy;
+ buf[5] = gdispColor2Native(g->p.color);
+ MUTEX_ENTER;
+ sendpkt(priv->netfd, buf, 6);
+ MUTEX_EXIT;
+ }
+#endif
+
+#if GDISP_HARDWARE_BITFILLS
+ LLDSPEC void gdisp_lld_blit_area(GDisplay *g) {
+ netPriv * priv;
+ pixel_t * buffer;
+ uint16_t buf[5];
+ coord_t x, y;
+
+ #if GDISP_DONT_WAIT_FOR_NET_DISPLAY
+ if (!(g->flags & GDISP_FLG_CONNECTED))
+ return;
+ #else
+ while(!(g->flags & GDISP_FLG_CONNECTED))
+ gfxSleepMilliseconds(200);
+ #endif
+
+ // Make everything relative to the start of the line
+ buffer = g->p.ptr;
+ buffer += g->p.x2*g->p.y1;
+
+ priv = g->priv;
+ buf[0] = GNETCODE_BLIT;
+ buf[1] = g->p.x;
+ buf[2] = g->p.y;
+ buf[3] = g->p.cx;
+ buf[4] = g->p.cy;
+ MUTEX_ENTER;
+ sendpkt(priv->netfd, buf, 5);
+
+ for(y = 0; y < g->p.cy; y++, buffer += g->p.x2 - g->p.cx) {
+ for(x = 0; x < g->p.cx; x++, buffer++) {
+ buf[0] = gdispColor2Native(buffer[0]);
+ sendpkt(priv->netfd, buf, 1);
+ }
+ }
+ MUTEX_EXIT;
+ }
+#endif
+
+#if GDISP_HARDWARE_PIXELREAD
+ LLDSPEC color_t gdisp_lld_get_pixel_color(GDisplay *g) {
+ netPriv * priv;
+ uint16_t buf[3];
+ color_t data;
+
+ #if GDISP_DONT_WAIT_FOR_NET_DISPLAY
+ if (!(g->flags & GDISP_FLG_CONNECTED))
+ return 0;
+ #else
+ while(!(g->flags & GDISP_FLG_CONNECTED))
+ gfxSleepMilliseconds(200);
+ #endif
+
+ priv = g->priv;
+ buf[0] = GNETCODE_READ;
+ buf[1] = g->p.x;
+ buf[2] = g->p.y;
+ MUTEX_ENTER;
+ sendpkt(priv->netfd, buf, 3);
+ MUTEX_EXIT;
+
+ // Now wait for a reply
+ while(!(g->flags & GDISP_FLG_HAVEDATA) || priv->data[0] != GNETCODE_READ)
+ gfxSleepMilliseconds(1);
+
+ data = gdispNative2Color(priv->data[1]);
+ g->flags &= ~GDISP_FLG_HAVEDATA;
+
+ return data;
+ }
+#endif
+
+#if GDISP_NEED_SCROLL && GDISP_HARDWARE_SCROLL
+ LLDSPEC void gdisp_lld_vertical_scroll(GDisplay *g) {
+ netPriv * priv;
+ uint16_t buf[6];
+
+ #if GDISP_DONT_WAIT_FOR_NET_DISPLAY
+ if (!(g->flags & GDISP_FLG_CONNECTED))
+ return;
+ #else
+ while(!(g->flags & GDISP_FLG_CONNECTED))
+ gfxSleepMilliseconds(200);
+ #endif
+
+ priv = g->priv;
+ buf[0] = GNETCODE_SCROLL;
+ buf[1] = g->p.x;
+ buf[2] = g->p.y;
+ buf[3] = g->p.cx;
+ buf[4] = g->p.cy;
+ buf[5] = g->p.y1;
+ MUTEX_ENTER;
+ sendpkt(priv->netfd, buf, 6);
+ MUTEX_EXIT;
+ }
+#endif
+
+#if GDISP_NEED_CONTROL && GDISP_HARDWARE_CONTROL
+ LLDSPEC void gdisp_lld_control(GDisplay *g) {
+ netPriv * priv;
+ uint16_t buf[3];
+ bool_t allgood;
+
+ #if GDISP_DONT_WAIT_FOR_NET_DISPLAY
+ if (!(g->flags & GDISP_FLG_CONNECTED))
+ return;
+ #else
+ while(!(g->flags & GDISP_FLG_CONNECTED))
+ gfxSleepMilliseconds(200);
+ #endif
+
+ // Check if we might support the code
+ switch(g->p.x) {
+ case GDISP_CONTROL_ORIENTATION:
+ if (g->g.Orientation == (orientation_t)g->p.ptr)
+ return;
+ break;
+ case GDISP_CONTROL_POWER:
+ if (g->g.Powermode == (powermode_t)g->p.ptr)
+ return;
+ break;
+ case GDISP_CONTROL_BACKLIGHT:
+ if (g->g.Backlight == (uint16_t)(int)g->p.ptr)
+ return;
+ if ((uint16_t)(int)g->p.ptr > 100)
+ g->p.ptr = (void *)100;
+ break;
+ default:
+ return;
+ }
+
+ // Send the command
+ priv = g->priv;
+ buf[0] = GNETCODE_CONTROL;
+ buf[1] = g->p.x;
+ buf[2] = (uint16_t)(int)g->p.ptr;
+ MUTEX_ENTER;
+ sendpkt(priv->netfd, buf, 3);
+ MUTEX_EXIT;
+
+ // Now wait for a reply
+ while(!(g->flags & GDISP_FLG_HAVEDATA) || priv->data[0] != GNETCODE_CONTROL)
+ gfxSleepMilliseconds(1);
+
+ // Extract the return status
+ allgood = priv->data[1] ? TRUE : FALSE;
+ g->flags &= ~GDISP_FLG_HAVEDATA;
+
+ // Do nothing more if the operation failed
+ if (!allgood) return;
+
+ // Update the local stuff
+ switch(g->p.x) {
+ case GDISP_CONTROL_ORIENTATION:
+ switch((orientation_t)g->p.ptr) {
+ case GDISP_ROTATE_0:
+ case GDISP_ROTATE_180:
+ g->g.Width = GDISP_SCREEN_WIDTH;
+ g->g.Height = GDISP_SCREEN_HEIGHT;
+ break;
+ case GDISP_ROTATE_90:
+ case GDISP_ROTATE_270:
+ g->g.Height = GDISP_SCREEN_WIDTH;
+ g->g.Width = GDISP_SCREEN_HEIGHT;
+ break;
+ default:
+ return;
+ }
+ g->g.Orientation = (orientation_t)g->p.ptr;
+ break;
+ case GDISP_CONTROL_POWER:
+ g->g.Powermode = (powermode_t)g->p.ptr;
+ break;
+ case GDISP_CONTROL_BACKLIGHT:
+ g->g.Backlight = (uint16_t)(int)g->p.ptr;
+ break;
+ }
+ }
+#endif
+
+#if GINPUT_NEED_MOUSE
+ static bool_t NMouseInit(GMouse *m, unsigned driverinstance) {
+ (void) m;
+ (void) driverinstance;
+ return TRUE;
+ }
+ static bool_t NMouseRead(GMouse *m, GMouseReading *pt) {
+ GDisplay * g;
+ netPriv * priv;
+
+ g = m->display;
+ priv = g->priv;
+
+ pt->x = priv->mousex;
+ pt->y = priv->mousey;
+ pt->z = (priv->mousebuttons & GINPUT_MOUSE_BTN_LEFT) ? 1 : 0;
+ pt->buttons = priv->mousebuttons;
+ return TRUE;
+ }
+#endif /* GINPUT_NEED_MOUSE */
+
+#endif /* GFX_USE_GDISP */
diff --git a/drivers/multiple/uGFXnetESP8266/ginput_lld_mouse_config.h b/drivers/multiple/uGFXnetESP8266/ginput_lld_mouse_config.h
new file mode 100644
index 00000000..576df7ee
--- /dev/null
+++ b/drivers/multiple/uGFXnetESP8266/ginput_lld_mouse_config.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 _LLD_GINPUT_MOUSE_CONFIG_H
+#define _LLD_GINPUT_MOUSE_CONFIG_H
+
+// This driver supports being both a mouse or a touch device (we don't actually know which it really is)
+// When operating in mouse mode a long left button click does not generate a context click.
+// When operating in touch mode we allow sloppier clicks etc
+#if 1
+ #define GINPUT_MOUSE_EVENT_TYPE GEVENT_MOUSE
+ #define GINPUT_MOUSE_CLICK_TIME TIME_INFINITE // Long click != Context Click
+ #define GINPUT_MOUSE_NEED_CALIBRATION FALSE
+ #define GINPUT_MOUSE_LLD_CALIBRATION_LOADSAVE FALSE
+ #define GINPUT_MOUSE_READ_CYCLES 1
+ #define GINPUT_MOUSE_MAX_CALIBRATION_ERROR -1
+ #define GINPUT_MOUSE_MAX_CLICK_JITTER 0
+ #define GINPUT_MOUSE_MAX_MOVE_JITTER 0
+#else
+ #define GINPUT_MOUSE_EVENT_TYPE GEVENT_TOUCH
+ #define GINPUT_MOUSE_CLICK_TIME 700 // Long click = Context Click
+ #define GINPUT_MOUSE_NEED_CALIBRATION FALSE // Can be set to TRUE just for testing
+ #define GINPUT_MOUSE_LLD_CALIBRATION_LOADSAVE FALSE
+ #define GINPUT_MOUSE_READ_CYCLES 1
+ #define GINPUT_MOUSE_MAX_CALIBRATION_ERROR 2
+ #define GINPUT_MOUSE_MAX_CLICK_JITTER 2
+ #define GINPUT_MOUSE_MAX_MOVE_JITTER 2
+#endif
+
+// This driver supports both an "interrupt" mode, and a polled mode
+#define GINPUT_MOUSE_POLL_PERIOD TIME_INFINITE // Interrupt driven by the Window thread
+//#define GINPUT_MOUSE_POLL_PERIOD 25 // Poll driven
+
+// This driver does not require rotation of co-ordinates for orientations other than 0.
+#define GINPUT_MOUSE_NO_ROTATION TRUE
+
+#endif /* _LLD_GINPUT_MOUSE_CONFIG_H */
diff --git a/drivers/multiple/uGFXnetESP8266/readme.txt b/drivers/multiple/uGFXnetESP8266/readme.txt
new file mode 100644
index 00000000..d7ce2178
--- /dev/null
+++ b/drivers/multiple/uGFXnetESP8266/readme.txt
@@ -0,0 +1,30 @@
+To use this driver:
+
+This driver is special in that it implements both the gdisp low level driver
+and a touchscreen driver.
+
+1. Add in your gfxconf.h:
+ a) #define GFX_USE_GDISP TRUE
+ b) Optionally #define GFX_USE_GINPUT TRUE
+ #define GINPUT_USE_MOUSE TRUE
+ c) Any optional high level driver defines (see gdisp.h) eg: GDISP_NEED_MULTITHREAD
+ d) Optionally the following (with appropriate values):
+ #define GDISP_SCREEN_WIDTH 640 // Virtual display width
+ #define GDISP_SCREEN_HEIGHT 480 // Virtual display height
+ #define GDISP_GFXNET_WIFI_INIT_FUNCTION MyWifiStart // Optionally specify if you want to
+ // use your own wifi startup routine.
+ // Prototype...
+ // extern "C" void MyWifiStart(WifiServer *ws);
+ #define GDISP_GFXNET_WIFI_SSID "ssid" // Your wifi SSID.
+ // Not required if GDISP_GFXNET_WIFI_INIT_FUNCTION
+ // is specified.
+ #define GDISP_GFXNET_WIFI_PASSWORD "password" // Your wifi password.
+ // Not required if GDISP_GFXNET_WIFI_INIT_FUNCTION
+ // is specified.
+ #define GDISP_DONT_WAIT_FOR_NET_DISPLAY FALSE // Don't halt waiting for the first connection
+ $define GDISP_GFXNET_PORT 13001 // The TCP port the display sits on
+
+
+2. To your makefile (or Library) add the following lines:
+ include $(GFXLIB)/gfx.mk
+ include $(GFXLIB)/drivers/multiple/uGFXnetESP8266/driver.mk
diff --git a/drivers/multiple/uGFXnetESP8266/uGFXnetProtocol.h b/drivers/multiple/uGFXnetESP8266/uGFXnetProtocol.h
new file mode 100644
index 00000000..521cca0f
--- /dev/null
+++ b/drivers/multiple/uGFXnetESP8266/uGFXnetProtocol.h
@@ -0,0 +1,34 @@
+/*
+ * 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
+ */
+
+#define GNETCODE_VERSION GNETCODE_VERSION_1_0 // The current protocol version
+
+// The list of possible protocol version numbers
+#define GNETCODE_VERSION_1_0 0x0100 // V1.0
+
+// The required pixel format
+#define GNETCODE_PIXELFORMAT GDISP_PIXELFORMAT_RGB565
+
+// The default TCP/IP port
+#define GNETCODE_DEFAULT_PORT 13001
+
+/**
+ * All commands are sent in 16 bit blocks (2 bytes) in network order (BigEndian)
+ * Across all uGFXnet protocol versions, the stream will always start with GNETCODE_INIT (0xFFFF) and then the version number.
+ */
+#define GNETCODE_INIT 0xFFFF // Followed by version,width,height,pixelformat,hasmouse
+#define GNETCODE_FLUSH 0x0000 // No following data
+#define GNETCODE_PIXEL 0x0001 // Followed by x,y,color
+#define GNETCODE_FILL 0x0002 // Followed by x,y,cx,cy,color
+#define GNETCODE_BLIT 0x0003 // Followed by x,y,cx,cy,bits
+#define GNETCODE_READ 0x0004 // Followed by x,y - Response is GNETCODE_READ,color
+#define GNETCODE_SCROLL 0x0005 // Followed by x,y,cx,cy,lines
+#define GNETCODE_CONTROL 0x0006 // Followed by what,data - Response is GNETCODE_CONTROL,0x0000 (fail) or GNETCODE_CONTROL,0x0001 (success)
+#define GNETCODE_MOUSE_X 0x0007 // This is only ever received - never sent. Response is GNETCODE_MOUSE_X,x
+#define GNETCODE_MOUSE_Y 0x0008 // This is only ever received - never sent. Response is GNETCODE_MOUSE_Y,y
+#define GNETCODE_MOUSE_B 0x0009 // This is only ever received - never sent. Response is GNETCODE_MOUSE_B,buttons. This is also the sync signal for mouse updates.
+#define GNETCODE_KILL 0xFFFE // This is only ever received - never sent. Response is GNETCODE_KILL,retcode