summaryrefslogtreecommitdiff
path: root/glcddrivers
diff options
context:
space:
mode:
Diffstat (limited to 'glcddrivers')
-rw-r--r--glcddrivers/Makefile49
-rw-r--r--glcddrivers/avrctl.c30
-rw-r--r--glcddrivers/avrctl.h8
-rw-r--r--glcddrivers/ax206dpf.c992
-rw-r--r--glcddrivers/ax206dpf.h300
-rw-r--r--glcddrivers/common.c5
-rw-r--r--glcddrivers/config.c9
-rw-r--r--glcddrivers/config.h3
-rw-r--r--glcddrivers/dm140gink.c24
-rw-r--r--glcddrivers/dm140gink.h15
-rw-r--r--glcddrivers/driver.c61
-rw-r--r--glcddrivers/driver.h99
-rw-r--r--glcddrivers/drivers.c50
-rw-r--r--glcddrivers/drivers.h17
-rw-r--r--glcddrivers/framebuffer.c313
-rw-r--r--glcddrivers/framebuffer.h20
-rw-r--r--glcddrivers/futabaMDM166A.c27
-rw-r--r--glcddrivers/futabaMDM166A.h12
-rw-r--r--glcddrivers/g15daemon.c22
-rw-r--r--glcddrivers/g15daemon.h12
-rw-r--r--glcddrivers/gu126x64D-K610A4.c29
-rw-r--r--glcddrivers/gu126x64D-K610A4.h11
-rw-r--r--glcddrivers/gu140x32f.c20
-rw-r--r--glcddrivers/gu140x32f.h11
-rw-r--r--glcddrivers/gu256x64-372.c32
-rw-r--r--glcddrivers/gu256x64-372.h10
-rw-r--r--glcddrivers/gu256x64-3900.c26
-rw-r--r--glcddrivers/gu256x64-3900.h12
-rw-r--r--glcddrivers/hd61830.c31
-rw-r--r--glcddrivers/hd61830.h7
-rw-r--r--glcddrivers/ili9341.c395
-rw-r--r--glcddrivers/ili9341.h53
-rw-r--r--glcddrivers/image.c40
-rw-r--r--glcddrivers/image.h13
-rw-r--r--glcddrivers/ks0108.c32
-rw-r--r--glcddrivers/ks0108.h12
-rw-r--r--glcddrivers/network.c35
-rw-r--r--glcddrivers/network.h9
-rw-r--r--glcddrivers/noritake800.c155
-rw-r--r--glcddrivers/noritake800.h12
-rw-r--r--glcddrivers/picoLCD_256x64.c553
-rw-r--r--glcddrivers/picoLCD_256x64.h106
-rw-r--r--glcddrivers/port.c53
-rw-r--r--glcddrivers/port.h4
-rw-r--r--glcddrivers/sed1330.c33
-rw-r--r--glcddrivers/sed1330.h9
-rw-r--r--glcddrivers/sed1520.c32
-rw-r--r--glcddrivers/sed1520.h8
-rw-r--r--glcddrivers/serdisp.c409
-rw-r--r--glcddrivers/serdisp.h98
-rw-r--r--glcddrivers/simlcd.c114
-rw-r--r--glcddrivers/simlcd.h12
-rw-r--r--glcddrivers/ssd1306.c340
-rw-r--r--glcddrivers/ssd1306.h53
-rw-r--r--glcddrivers/t6963c.c55
-rw-r--r--glcddrivers/t6963c.h8
-rw-r--r--glcddrivers/vncserver.c211
-rw-r--r--glcddrivers/vncserver.h50
58 files changed, 4590 insertions, 571 deletions
diff --git a/glcddrivers/Makefile b/glcddrivers/Makefile
index acb1577..8c2b3d6 100644
--- a/glcddrivers/Makefile
+++ b/glcddrivers/Makefile
@@ -6,8 +6,8 @@
CXXFLAGS += -fPIC
-VERMAJOR = 1
-VERMINOR = 0
+VERMAJOR = 2
+VERMINOR = 1
VERMICRO = 0
BASENAME = libglcddrivers.so
@@ -25,17 +25,52 @@ LIBS += $(shell pkg-config --libs libhid)
DEFINES += -DHAVE_LIBHID
endif
+
+ifeq ($(shell pkg-config --exists libusb && echo 1), 1)
+ DEFINES += -DHAVE_LIBUSB
+ ifdef HAVE_DRIVER_AX206DPF
+ OBJS += ax206dpf.o
+ INCLUDES += $(shell pkg-config --cflags libusb)
+ LIBS += $(shell pkg-config --libs libusb)
+ DEFINES += -DHAVE_DRIVER_AX206DPF
+ endif
+ ifdef HAVE_DRIVER_picoLCD_256x64
+ OBJS += picoLCD_256x64.o
+ INCLUDES += $(shell pkg-config --cflags libusb)
+ LIBS += $(shell pkg-config --libs libusb)
+ DEFINES += -DHAVE_DRIVER_picoLCD_256x64
+ endif
+endif
+
+ifeq ($(HAVE_DRIVER_VNCSERVER), 1)
+ifeq ($(shell libvncserver-config --version >/dev/null && echo 1), 1)
+ DEFINES += -DHAVE_DRIVER_VNCSERVER
+ OBJS += vncserver.o
+ INCLUDES += $(shell libvncserver-config --cflags)
+ LIBS += $(shell libvncserver-config --libs)
+endif
+endif
+
+ifeq ($(HAVE_DRIVER_SSD1306), 1)
+ DEFINES += -DHAVE_DRIVER_SSD1306
+ OBJS += ssd1306.o
+ LIBS += -lwiringPi
+endif
+
+ifeq ($(HAVE_DRIVER_ILI9341), 1)
+ DEFINES += -DHAVE_DRIVER_ILI9341
+ OBJS += ili9341.o
+ LIBS += -lwiringPi
+endif
+
### Implicit rules:
%.o: %.c
- $(CXX) $(CXXFLAGS) -c $(DEFINES) $(INCLUDES) $<
+ $(CXX) $(CXXEXTRA) $(CXXFLAGS) -c $(DEFINES) $(INCLUDES) $<
# Dependencies:
-MAKEDEP = g++ -MM -MG
-DEPFILE = .dependencies
-$(DEPFILE): Makefile
- @$(MAKEDEP) $(DEFINES) $(INCLUDES) $(OBJS:%.o=%.c) > $@
+DEPFILE = $(OBJS:%.o=%.d)
-include $(DEPFILE)
diff --git a/glcddrivers/avrctl.c b/glcddrivers/avrctl.c
index b0e09b9..2261d95 100644
--- a/glcddrivers/avrctl.c
+++ b/glcddrivers/avrctl.c
@@ -6,7 +6,8 @@
* This file is released under the GNU General Public License. Refer
* to the COPYING file distributed with this package.
*
- * (c) 2005 Andreas Regel <andreas.regel AT powarman.de>
+ * (c) 2005-2010 Andreas Regel <andreas.regel AT powarman.de>
+ * (c) 2011 Wolfgang Astleitner <mrwastl AT users.sourceforge.net>
*/
#include <stdint.h>
@@ -50,10 +51,8 @@ const int kBufferHeight = 128;
cDriverAvrCtl::cDriverAvrCtl(cDriverConfig * config)
-: config(config)
+: cDriver(config)
{
- oldConfig = new cDriverConfig(*config);
-
port = new cSerialPort();
//width = config->width;
@@ -64,7 +63,6 @@ cDriverAvrCtl::cDriverAvrCtl(cDriverConfig * config)
cDriverAvrCtl::~cDriverAvrCtl()
{
delete port;
- delete oldConfig;
}
int cDriverAvrCtl::Init()
@@ -176,6 +174,27 @@ void cDriverAvrCtl::Clear()
memset(newLCD[x], 0, (kBufferHeight + 7) / 8);
}
+
+void cDriverAvrCtl::SetPixel(int x, int y, uint32_t data)
+{
+ if (x >= width || y >= height)
+ return;
+
+ if (config->upsideDown)
+ {
+ x = width - 1 - x;
+ y = height - 1 - y;
+ }
+
+ int offset = 7 - (y % 8);
+ if (data == GRAPHLCD_White)
+ newLCD[x][y / 8] |= (1 << offset);
+ else
+ newLCD[x][y / 8] &= ( 0xFF ^ (1 << offset) );
+}
+
+
+#if 0
void cDriverAvrCtl::Set8Pixels(int x, int y, unsigned char data)
{
if (x >= width || y >= height)
@@ -200,6 +219,7 @@ void cDriverAvrCtl::Set8Pixels(int x, int y, unsigned char data)
}
}
}
+#endif
void cDriverAvrCtl::Refresh(bool refreshAll)
{
diff --git a/glcddrivers/avrctl.h b/glcddrivers/avrctl.h
index 557b7d2..a7ecb42 100644
--- a/glcddrivers/avrctl.h
+++ b/glcddrivers/avrctl.h
@@ -6,7 +6,8 @@
* This file is released under the GNU General Public License. Refer
* to the COPYING file distributed with this package.
*
- * (c) 2005 Andreas Regel <andreas.regel AT powarman.de>
+ * (c) 2005-2010 Andreas Regel <andreas.regel AT powarman.de>
+ * (c) 2011 Wolfgang Astleitner <mrwastl AT users.sourceforge.net>
*/
#ifndef _GLCDDRIVERS_AVRCTL_H_
@@ -26,8 +27,6 @@ private:
cSerialPort * port;
unsigned char ** newLCD; // wanted state
unsigned char ** oldLCD; // current state
- cDriverConfig * config;
- cDriverConfig * oldConfig;
int refreshCounter;
int WaitForAck(void);
@@ -48,7 +47,8 @@ public:
virtual int DeInit();
virtual void Clear();
- virtual void Set8Pixels(int x, int y, unsigned char data);
+ virtual void SetPixel(int x, int y, uint32_t data);
+ //virtual void Set8Pixels(int x, int y, unsigned char data);
virtual void Refresh(bool refreshAll = false);
virtual void SetBrightness(unsigned int percent);
};
diff --git a/glcddrivers/ax206dpf.c b/glcddrivers/ax206dpf.c
new file mode 100644
index 0000000..acae61d
--- /dev/null
+++ b/glcddrivers/ax206dpf.c
@@ -0,0 +1,992 @@
+/*
+ * GraphLCD driver library
+ *
+ * ax206dpf.h - AX206dpf driver class
+ * Output goes to AX 206 based photoframe
+ *
+ * based on:
+ * simlcd device
+ * (c) 2001-2004 Carsten Siebholz <c.siebholz AT t-online.de>
+ * (c) 2011 Dirk Heiser
+ * (c) 2011 Wolfgang Astleitner <mrwastl AT users.sourceforge.net>
+ *
+ * includes code from:
+ * http://sourceforge.net/projects/dpf-ax/
+ *
+ * Original copyright:
+ *
+ * Copyright (C) 2008 Jeroen Domburg <picframe@spritesmods.com>
+ * Modified from sample code by:
+ * Copyright (C) 2005 Michael Reinelt <michael@reinelt.co.at>
+ * Copyright (C) 2005, 2006, 2007 The LCD4Linux Team <lcd4linux-devel@users.sourceforge.net>
+ * Mods by <hackfin@section5.ch>
+ *
+ * This file is released under the GNU General Public License. Refer
+ * to the COPYING file distributed with this package.
+ *
+ * (c) 2011 Lutz Neumann <superelchi AT wolke7.net>
+ *
+ * HISTORY
+ *
+ * v0.1 - 10 Aug 2011 - Inital release
+ * v0.2 - 20 Aug 2011 - Optimized display data transfer
+ * SetBrightness() implemented
+ * Multi-display support
+ * v0.3 - 02 Sep 2011 - Fixed multi-thread problem
+ *
+ *
+ */
+
+#include <stdio.h>
+#include <syslog.h>
+#include <cstring>
+#include <algorithm>
+#include <pthread.h>
+#include <time.h>
+#include <usb.h>
+
+#include "common.h"
+#include "config.h"
+
+#include "ax206dpf.h"
+
+
+namespace GLCD
+{
+
+static pthread_mutex_t libax_mutex;
+
+
+cDriverAX206DPF::cDriverAX206DPF(cDriverConfig * config)
+: cDriver(config)
+{
+}
+
+int cDriverAX206DPF::Init(void)
+{
+ zoom = 1;
+ portrait = false;
+ numxdisplays = numydisplays = 1;
+ sizex = sizey = bpp = 0;
+
+ for (unsigned int i = 0; i < MAX_DPFS; i++)
+ {
+ dh[i] = (DISPLAYHANDLE *) malloc(sizeof(DISPLAYHANDLE));
+ dh[i]->attached = false;
+ dh[i]->address[0] = 0;
+ dh[i]->dpfh = NULL;
+ dh[i]->LCD = NULL;
+ }
+
+ lastbrightness = config->brightness ? config->brightness : 100;
+
+ for (unsigned int i = 0; i < config->options.size(); i++)
+ {
+ if (config->options[i].name == "Portrait") {
+ portrait = config->options[i].value == "yes";
+ }
+ else if (config->options[i].name == "Zoom") {
+ int z = strtol(config->options[i].value.c_str(), (char **) NULL, 0);
+ if (z > 0 && z <= 4)
+ zoom = z;
+ else
+ syslog(LOG_ERR, "%s error: zoom %d not supported, using default (%d)!\n",config->name.c_str(), z, zoom);
+ }
+ else if (config->options[i].name == "Horizontal") {
+ int h = strtol(config->options[i].value.c_str(), (char **) NULL, 0);
+ if (h > 0 && h <= 4)
+ numxdisplays = h;
+ else
+ syslog(LOG_ERR, "%s error: Horizontal=%d not supported, using default (%d)!\n",config->name.c_str(), h, numxdisplays);
+ }
+ else if (config->options[i].name == "Vertical") {
+ int v = strtol(config->options[i].value.c_str(), (char **) NULL, 0);
+ if (v > 0 && v <= 4)
+ numydisplays = v;
+ else
+ syslog(LOG_ERR, "%s error: Vertical=%d not supported, using default (%d)!\n",config->name.c_str(), v, numydisplays);
+ }
+ else if (config->options[i].name == "Flip") {
+ flips = config->options[i].value;
+ for (unsigned int j = 0; j < flips.size(); j++)
+ {
+ if (flips[j] != 'y' && flips[j] != 'n')
+ {
+ syslog(LOG_ERR, "%s error: flips=%s - illegal character, only 'y' and 'n' supported, using default!\n",config->name.c_str(), flips.c_str());
+ flips = "";
+ break;
+ }
+ }
+ }
+ }
+
+ // See if we have too many displays
+ if (numxdisplays * numydisplays > MAX_DPFS)
+ syslog(LOG_ERR, "%s: too many displays (%dx%d). Max is %d!\n",config->name.c_str(), numxdisplays, numydisplays, MAX_DPFS);
+
+ // Init all displays
+ numdisplays = 0;
+ int error = 0;
+ for (unsigned int i = 0; i < numxdisplays * numydisplays; i++)
+ {
+ error = InitSingleDisplay(i);
+ if (error < 0)
+ return -1;
+ numdisplays++;
+ }
+
+ if (sizex == 0)
+ {
+ // no displays detected
+ sizex = (portrait) ? DEFAULT_HEIGHT : DEFAULT_WIDTH;
+ sizey = (portrait) ? DEFAULT_WIDTH : DEFAULT_HEIGHT;
+ bpp = DEFAULT_BPP;
+ }
+
+ // setup temp transfer LCD array
+ tempLCD = (unsigned char *) malloc(sizex * sizey * bpp);
+
+ width = sizex * numxdisplays;
+ height = sizey * numydisplays;
+
+ if (zoom > 1)
+ {
+ height /= zoom;
+ width /= zoom;
+ }
+
+ ResetMinMax();
+
+ *oldConfig = *config;
+
+ if (numdisplays == 1)
+ syslog(LOG_INFO, "%s: AX206DPF initialized (%dx%d).\n", config->name.c_str(), width, height);
+ else
+ {
+ unsigned n = 0;
+ for (unsigned int i = 0; i < numdisplays; i++)
+ if (dh[i]->attached) n++;
+ syslog(LOG_INFO, "%s: using %d display(s) (%d online, %d offline).\n", config->name.c_str(), numdisplays, n, numdisplays - n);
+ }
+
+ lastscan = time(NULL);
+
+ return 0;
+}
+
+bool cDriverAX206DPF::RescanUSB()
+{
+ bool ret = false;
+ usb_find_busses();
+ if (usb_find_devices() > 0)
+ {
+ unsigned int a = 0, b = 0;
+ for (unsigned int i = 0; i < numdisplays; i++)
+ {
+ if (dh[i]->attached) a |= 0x01 << i;
+ DeInitSingleDisplay(i);
+ }
+ for (unsigned int i = 0; i < numdisplays; i++)
+ {
+ InitSingleDisplay(i);
+ if (dh[i]->attached) b |= 0x01 << i;
+ }
+ ret = a != b;
+ }
+ return ret;
+}
+
+int cDriverAX206DPF::InitSingleDisplay(unsigned int di)
+{
+ char index;
+
+ if (config->device.length() != 4 || config->device.compare(0, 3, "dpf"))
+ index = '0';
+ else
+ index = config->device.at(3);
+
+ char device[5];
+ sprintf(device, "usb%c", index + di);
+ int error = dpf_open(device, &dh[di]->dpfh);
+ if (error < 0)
+ {
+ dh[di]->dpfh = NULL;
+ dh[di]->attached = false;
+ return 0;
+ }
+ dh[di]->attached = true;
+ struct usb_device *dev = usb_device(dh[di]->dpfh->dev.udev);
+ char *s1 = dev->bus->dirname;
+ char *s2 = dev->filename;
+ if (strlen(s1) > 3) s1 = (char *) "???";
+ if (strlen(s2) > 3) s2 = (char *) "???";
+ sprintf(dh[di]->address, "%s:%s", s1, s2);
+
+ // See, if we have to rotate the display
+ dh[di]->isPortrait = dh[di]->dpfh->width < dh[di]->dpfh->height;
+ dh[di]->rotate90 = dh[di]->isPortrait != portrait;
+ dh[di]->flip = (!dh[di]->isPortrait && dh[di]->rotate90); // adjust to make rotate por/land = physical por/land
+ if (flips.size() >= di + 1 && flips[di] == 'y')
+ dh[di]->flip = !dh[di]->flip;
+
+ if (sizex == 0)
+ {
+ // this is the first display found
+ // Get width / height from this display (all displays have same geometry)
+ sizex = ((!dh[di]->rotate90) ? dh[di]->dpfh->width : dh[di]->dpfh->height);
+ sizey = ((!dh[di]->rotate90) ? dh[di]->dpfh->height : dh[di]->dpfh->width);
+ bpp = dh[di]->dpfh->bpp;
+ }
+ else
+ {
+ // make sure alle displays have the same geometry
+ if ((!(sizex == dh[di]->dpfh->width && sizey == dh[di]->dpfh->height) &&
+ !(sizex == dh[di]->dpfh->height && sizey == dh[di]->dpfh->width)) ||
+ bpp != (unsigned int) dh[di]->dpfh->bpp)
+ {
+ syslog(LOG_INFO, "%s: all displays must have same geometry. Display %d has not. Giving up.\n", config->name.c_str(), di);
+ return -1;
+ }
+ }
+ // setup physical lcd arrays
+ dh[di]->LCD = (unsigned char *) malloc(dh[di]->dpfh->height * dh[di]->dpfh->width * dh[di]->dpfh->bpp);
+ ClearSingleDisplay(di);
+
+ // Set Display Brightness
+ SetSingleDisplayBrightness(di, lastbrightness);
+
+
+ // Reorder displays
+ bool changed = false;
+ for (unsigned int i = 0; i < MAX_DPFS - 1; i++)
+ {
+ for (unsigned int j = i + 1; j < MAX_DPFS; j++)
+ {
+ if (strcmp(dh[i]->address, dh[j]->address) < 0)
+ {
+ DISPLAYHANDLE *h = dh[i];
+ dh[i] = dh[j];
+ dh[j] = h;
+ changed = true;
+ }
+ }
+ }
+
+ //for (unsigned int i = 0; i < MAX_DPFS; i++)
+ // fprintf(stderr, "Display %d at %s\n", i, (dh[i]->attached) ? dh[i]->address : "-none-");
+ //fprintf(stderr, "\n");
+
+ //fprintf(stderr, "Display %d at %s attached.\n", di, dh[di]->address);
+ //syslog(LOG_INFO, "%s: display %d at %s attached\n", config->name.c_str(), di, dh[di]->address);
+
+ return 0;
+}
+
+void cDriverAX206DPF::DeInitSingleDisplay(unsigned int di)
+{
+ if (dh[di]->dpfh != NULL)
+ dpf_close(dh[di]->dpfh);
+ dh[di]->dpfh = NULL;
+
+ if (dh[di]->LCD != NULL)
+ free(dh[di]->LCD);
+ dh[di]->LCD = NULL;
+
+ dh[di]->attached = false;
+ dh[di]->address[0] = 0;
+}
+
+int cDriverAX206DPF::DeInit(void)
+{
+ // close displays & free lcd arrays
+ for (unsigned int i = 0; i< numdisplays; i++)
+ DeInitSingleDisplay(i);
+
+ if (tempLCD)
+ free(tempLCD);
+
+ return 0;
+}
+
+
+void cDriverAX206DPF::ResetMinMax(void)
+{
+ for (unsigned int i = 0; i < numydisplays; i++)
+ {
+ if (dh[i]->attached)
+ {
+ dh[i]->minx = dh[i]->dpfh->width - 1;
+ dh[i]->maxx = 0;
+ dh[i]->miny = dh[i]->dpfh->height - 1;
+ dh[i]->maxy = 0;
+ }
+ }
+}
+
+int cDriverAX206DPF::CheckSetup(void)
+{
+ if (config->width != oldConfig->width ||
+ config->height != oldConfig->height)
+ {
+ DeInit();
+ Init();
+ return 0;
+ }
+
+ if (config->brightness != oldConfig->brightness)
+ {
+ oldConfig->brightness = config->brightness;
+ SetBrightness(config->brightness);
+ }
+
+ if (config->upsideDown != oldConfig->upsideDown ||
+ config->invert != oldConfig->invert)
+ {
+ oldConfig->upsideDown = config->upsideDown;
+ oldConfig->invert = config->invert;
+ return 1;
+ }
+ return 0;
+}
+
+void cDriverAX206DPF::ClearSingleDisplay(unsigned int di)
+{
+ if (dh[di]->attached)
+ {
+ memset(dh[di]->LCD, 0, dh[di]->dpfh->width * dh[di]->dpfh->height * dh[di]->dpfh->bpp); //Black
+ dh[di]->minx = 0;
+ dh[di]->maxx = dh[di]->dpfh->width - 1;
+ dh[di]->miny = 0;
+ dh[di]->maxy = dh[di]->dpfh->height - 1;
+ }
+}
+
+void cDriverAX206DPF::Clear(void)
+{
+ for (unsigned int i = 0; i < numdisplays; i++)
+ ClearSingleDisplay(i);
+}
+
+#define _RGB565_0(p) \
+ (( ((p >> 16) & 0xf8) ) | (((p >> 8) & 0xe0) >> 5))
+#define _RGB565_1(p) \
+ (( ((p >> 8) & 0x1c) << 3 ) | (((p) & 0xf8) >> 3))
+
+void cDriverAX206DPF::SetPixel(int x, int y, uint32_t data)
+{
+ bool changed = false;
+
+ if (config->upsideDown)
+ {
+ // global upside down orientation
+ x = width - 1 - x;
+ y = height - 1 -y;
+ }
+
+ int sx = sizex / zoom;
+ int sy = sizey / zoom;
+ int di = (y / sy) * numxdisplays + (x / sx);
+ int lx = (x % sx) * zoom;
+ int ly = (y % sy) * zoom;
+
+ if (!dh[di]->attached)
+ return;
+
+ if (dh[di]->flip)
+ {
+ // local upside down orientation
+ lx = sizex - 1 - lx;
+ ly = sizey - 1 - ly;
+ }
+
+ if (dh[di]->rotate90)
+ {
+ // wrong Orientation, rotate
+ int i = ly;
+ ly = (dh[di]->dpfh->height) - 1 - lx;
+ lx = i;
+ }
+
+ if (lx < 0 || lx >= (int) dh[di]->dpfh->width || ly < 0 || ly >= (int) dh[di]->dpfh->height)
+ {
+ syslog(LOG_INFO, "x/y out of bounds (x=%d, y=%d, di=%d, rot=%d, flip=%d, lx=%d, ly=%d)\n", x, y, di, dh[di]->rotate90, dh[di]->flip, lx, ly);
+ return;
+ }
+
+ unsigned char c1 = _RGB565_0(data);
+ unsigned char c2 = _RGB565_1(data);
+
+ if (zoom == 1)
+ {
+ unsigned int i = (ly * dh[di]->dpfh->width + lx) * dh[di]->dpfh->bpp;
+ if (dh[di]->LCD[i] != c1 || dh[di]->LCD[i+1] != c2)
+ {
+ dh[di]->LCD[i] = c1;
+ dh[di]->LCD[i+1] = c2;
+ changed = true;
+ }
+ }
+ else
+ {
+ for (int dy = 0; dy < zoom; dy++)
+ {
+ unsigned int i = ((ly + dy) * dh[di]->dpfh->width + lx) * dh[di]->dpfh->bpp;
+ for (int dx = 0; dx < zoom * dh[di]->dpfh->bpp; dx += dh[di]->dpfh->bpp)
+ {
+ if (dh[di]->LCD[i+dx] != c1 || dh[di]->LCD[i+dx+1] != c2)
+ {
+ dh[di]->LCD[i+dx] = c1;
+ dh[di]->LCD[i+dx+1] = c2;
+ changed = true;
+ }
+ }
+ }
+ }
+
+ if (changed)
+ {
+ if (lx < dh[di]->minx) dh[di]->minx = lx;
+ if (lx > dh[di]->maxx) dh[di]->maxx = lx;
+ if (ly < dh[di]->miny) dh[di]->miny = ly;
+ if (ly > dh[di]->maxy) dh[di]->maxy = ly;
+ }
+}
+
+void cDriverAX206DPF::Refresh(bool refreshAll)
+{
+ short rect[4];
+
+ if (CheckSetup() > 0)
+ refreshAll = true;
+
+ for (unsigned int di = 0; di < numdisplays; di++)
+ {
+ if (!dh[di]->attached)
+ {
+ time_t current = time(NULL);
+ if (current - lastscan >= USB_SCAN_INTERVALL)
+ {
+ lastscan = current;
+ if (RescanUSB())
+ ; //return; // something changed, wait for next refresh
+ }
+ }
+
+ if (!dh[di]->attached)
+ continue;
+
+ if (refreshAll)
+ {
+ dh[di]->minx = 0; dh[di]->miny = 0;
+ dh[di]->maxx = dh[di]->dpfh->width - 1; dh[di]->maxy = dh[di]->dpfh->height - 1;
+ }
+ //fprintf(stderr, "%d: (%d,%d)-(%d,%d) ", di, dh[di]->minx, dh[di]->miny, dh[di]->maxx, dh[di]->maxy);
+ if (dh[di]->minx > dh[di]->maxx || dh[di]->miny > dh[di]->maxy)
+ continue;
+
+ unsigned int cpylength = (dh[di]->maxx - dh[di]->minx + 1) * dh[di]->dpfh->bpp;
+ unsigned char *ps = dh[di]->LCD + (dh[di]->miny * dh[di]->dpfh->width + dh[di]->minx) * dh[di]->dpfh->bpp;
+ unsigned char *pd = tempLCD;
+ for (int y = dh[di]->miny; y <= dh[di]->maxy; y++)
+ {
+ memcpy(pd, ps, cpylength);
+ ps += dh[di]->dpfh->width * dh[di]->dpfh->bpp;
+ pd += cpylength;
+ }
+
+ rect[0] = dh[di]->minx; rect[1] = dh[di]->miny; rect[2] = dh[di]->maxx + 1; rect[3] = dh[di]->maxy + 1;
+ pthread_mutex_lock(&libax_mutex);
+ int err = dpf_screen_blit(dh[di]->dpfh, tempLCD, rect);
+ pthread_mutex_unlock(&libax_mutex);
+ if (err < 0)
+ {
+ //fprintf(stderr, "Display %d detached (err=%d).\n", di, err);
+ syslog(LOG_INFO, "%s: display %d communication error (%d). Display detached\n", config->name.c_str(), di, err);
+ DeInitSingleDisplay(di);
+ RescanUSB();
+ lastscan = time(NULL);
+ }
+ }
+
+ ResetMinMax();
+ //fprintf(stderr, "\n");
+}
+
+uint32_t cDriverAX206DPF::GetBackgroundColor(void)
+{
+ return GRAPHLCD_Black;
+}
+
+void cDriverAX206DPF::SetSingleDisplayBrightness(unsigned int di, unsigned int percent)
+{
+ if (!dh[di]->attached)
+ return;
+
+ LIBDPF::DPFValue val;
+ val.type = LIBDPF::TYPE_INTEGER;
+
+ // Brightness can be 0 .. 7
+ if (percent == 0)
+ val.value.integer = 0;
+ else if (percent >= 100)
+ val.value.integer = 7;
+ else
+ val.value.integer = (((percent * 10) + 167) * 6) / 1000;
+ pthread_mutex_lock(&libax_mutex);
+ dpf_setproperty(dh[di]->dpfh, PROPERTY_BRIGHTNESS, &val);
+ pthread_mutex_unlock(&libax_mutex);
+}
+
+void cDriverAX206DPF::SetBrightness(unsigned int percent)
+{
+ lastbrightness = percent;
+
+ for (unsigned int i = 0; i < numdisplays; i++)
+ {
+ SetSingleDisplayBrightness(i, percent);
+ }
+}
+
+bool cDriverAX206DPF::GetDriverFeature(const std::string & Feature, int & value)
+{
+ if (strcasecmp(Feature.c_str(), "depth") == 0) {
+ value = 16;
+ return true;
+ } else if (strcasecmp(Feature.c_str(), "ismonochrome") == 0) {
+ value = false;
+ return true;
+ } else if (strcasecmp(Feature.c_str(), "isgreyscale") == 0 || strcasecmp(Feature.c_str(), "isgrayscale") == 0) {
+ value = false;
+ return true;
+ } else if (strcasecmp(Feature.c_str(), "iscolour") == 0 || strcasecmp(Feature.c_str(), "iscolor") == 0) {
+ value = true;
+ return true;
+ } else if (strcasecmp(Feature.c_str(), "touch") == 0 || strcasecmp(Feature.c_str(), "touchscreen") == 0) {
+ value = false;
+ return true;
+ }
+ value = 0;
+ return false;
+}
+
+} // end of namespace GLCD
+
+//##########################################################################################
+//
+// ** START OF UGLY HACK ** START OF UGLY HACK ** START OF UGLY HACK ** START OF UGLY HACK *
+//
+// Because I choose NOT to include the static library libdpf.a and/or their header- and
+// source-files from the original dpf-ax hack, I did some creative copy & paste from there
+// to this place. I will delete this stuff when a usable shared library of libpdf exists.
+//
+//##########################################################################################
+
+namespace LIBDPF
+{
+// -------------------------------------------------------------------
+// START SELECTIVE COPY & PASTE "dpflib.c"
+// -------------------------------------------------------------------
+/** DPF access library for AX206 based HW
+ *
+ * 12/2010 <hackfin@section5.ch>
+ *
+ * This is an ugly hack, because we use existing SCSI vendor specific
+ * extensions to pass on our requests to the DPF.
+ *
+ * One day we might use a proper protocol like netpp.
+ *
+ */
+
+#include <unistd.h>
+#include <stdio.h>
+#include <errno.h>
+#include <string.h>
+#include <scsi/scsi.h>
+#include <scsi/sg.h>
+#include <sys/ioctl.h>
+
+/** Vendor command for our hacks */
+static
+unsigned char g_excmd[16] = {
+ 0xcd, 0, 0, 0,
+ 0, 6, 0, 0,
+ 0, 0, 0, 0,
+ 0, 0, 0, 0
+};
+
+int wrap_scsi(DPFContext *h, unsigned char *cmd, int cmdlen, char out,
+ unsigned char *data, unsigned long block_len)
+{
+ int error;
+ //if (h->mode == MODE_USB) {
+ error = emulate_scsi(h->dev.udev, cmd, cmdlen, out, data, block_len);
+ //} else {
+ // error = do_scsi(h->dev.fd, cmd, cmdlen, out, data, block_len);
+ //}
+ return error;
+}
+
+static
+int probe(DPFHANDLE h)
+{
+ int ret;
+
+ // We abuse a command that just responds with a '0' status in the
+ // original firmware.
+ static unsigned char buf[5];
+
+
+ static
+ unsigned char cmd[16] = {
+ 0xcd, 0, 0, 0,
+ 0, 3, 0, 0,
+ 0, 0, 0, 0,
+ 0, 0, 0, 0
+ };
+
+ cmd[5] = 3;
+ ret = wrap_scsi(h, cmd, sizeof(cmd), DIR_IN, 0, 0);
+
+ switch (ret) {
+ case 0:
+ // The original protocol.
+ fprintf(stderr,
+ "Warning: This firmware can not lock the flash\n");
+ break;
+ case 1:
+ // The improved hack
+ h->flags |= FLAG_CAN_LOCK;
+ break;
+ }
+
+ cmd[5] = 2; // get LCD parameters
+ ret = wrap_scsi(h, cmd, sizeof(cmd), DIR_IN, buf, 5);
+ h->width = (buf[0]) | (buf[1] << 8);
+ h->height = (buf[2]) | (buf[3] << 8);
+ h->bpp = 2;
+
+ return ret;
+}
+
+
+int dpf_open(const char *dev, DPFHANDLE *h)
+{
+ int error = 0;
+ DPFContext *dpf;
+ int i;
+ usb_dev_handle *u;
+
+ //int fd;
+
+ if (!dev) {
+ fprintf(stderr, "Please specify a string like 'usb0' or a sg device\n");
+ return DEVERR_OPEN;
+ }
+
+ if (strncmp(dev, "usb", 3) == 0) {
+ i = dev[3] - '0';
+ u = dpf_usb_open(i);
+ if (!u) return DEVERR_OPEN;
+ //i = MODE_USB;
+ } else {
+ return DEVERR_OPEN;
+ }
+ //} else {
+ // fprintf(stderr, "Opening generic SCSI device '%s'\n", dev);
+ // if (sgdev_open(dev, &fd) < 0) return DEVERR_OPEN;
+ // i = MODE_SG;
+ //}
+
+ dpf = (DPFHANDLE) malloc(sizeof(DPFContext));
+ if (!dpf) return DEVERR_MALLOC;
+
+ dpf->flags = 0;
+ dpf->mode = i;
+
+ //if (dpf->mode == MODE_USB) {
+ dpf->dev.udev = u;
+ error = probe(dpf);
+ //fprintf(stderr, "Got LCD dimensions: %dx%d\n", dpf->width, dpf->height);
+ //} else {
+ // dpf->dev.fd = fd;
+ //}
+
+ *h = dpf;
+ return error;
+}
+
+void dpf_close(DPFContext *h)
+{
+ //switch (h->mode) {
+ // case MODE_SG:
+ // close(h->dev.fd);
+ // break;
+ // case MODE_USB:
+ usb_release_interface(h->dev.udev, 0);
+ usb_close(h->dev.udev);
+ // break;
+ //}
+ free(h);
+}
+
+const char *dev_errstr(int err)
+{
+ switch (err) {
+ case DEVERR_FILE: return "File I/O error";
+ case DEVERR_OPEN: return "File open error";
+ case DEVERR_HEX: return "Hex file error";
+ case DEVERR_CHK: return "Checksum error";
+ case DEVERR_IO: return "Common I/O error";
+ default: return "Unknown error";
+ }
+}
+
+#define RGB565_0(r, g, b) \
+ (( ((r) & 0xf8) ) | (((g) & 0xe0) >> 5))
+#define RGB565_1(r, g, b) \
+ (( ((g) & 0x1c) << 3 ) | (((b) & 0xf8) >> 3))
+
+int dpf_setcol(DPFContext *h, const unsigned char *rgb)
+{
+ unsigned char *cmd = g_excmd;
+
+ cmd[6] = USBCMD_SETPROPERTY;
+ cmd[7] = PROPERTY_FGCOLOR;
+ cmd[8] = PROPERTY_FGCOLOR >> 8;
+
+ cmd[9] = RGB565_0(rgb[0], rgb[1], rgb[2]);
+ cmd[10] = RGB565_1(rgb[0], rgb[1], rgb[2]);
+
+ return wrap_scsi(h, cmd, sizeof(g_excmd), DIR_OUT, NULL, 0);
+}
+
+int dpf_screen_blit(DPFContext *h,
+ const unsigned char *buf, short rect[4])
+{
+ unsigned long len = (rect[2] - rect[0]) * (rect[3] - rect[1]);
+ len <<= 1;
+ unsigned char *cmd = g_excmd;
+
+ cmd[6] = USBCMD_BLIT;
+ cmd[7] = rect[0];
+ cmd[8] = rect[0] >> 8;
+ cmd[9] = rect[1];
+ cmd[10] = rect[1] >> 8;
+ cmd[11] = rect[2] - 1;
+ cmd[12] = (rect[2] - 1) >> 8;
+ cmd[13] = rect[3] - 1;
+ cmd[14] = (rect[3] - 1) >> 8;
+ cmd[15] = 0;
+
+ return wrap_scsi(h, cmd, sizeof(g_excmd), DIR_OUT,
+ (unsigned char*) buf, len);
+}
+
+int dpf_setproperty(DPFContext *h, int token, const DPFValue *value)
+{
+ unsigned char *cmd = g_excmd;
+
+ cmd[6] = USBCMD_SETPROPERTY;
+ cmd[7] = token;
+ cmd[8] = token >> 8;
+
+ switch (value->type) {
+ case TYPE_INTEGER:
+ cmd[9] = value->value.integer;
+ cmd[10] = value->value.integer >> 8;
+ break;
+ default:
+ break;
+ }
+
+ return wrap_scsi(h, cmd, sizeof(g_excmd), DIR_OUT, NULL, 0);
+}
+
+// -------------------------------------------------------------------
+// END SELECTIVE COPY & PASTE "dpflib.c"
+// -------------------------------------------------------------------
+
+// -------------------------------------------------------------------
+// START SELECTIVE COPY & PASTE "rawusb.c"
+// -------------------------------------------------------------------
+
+/* Low level USB code to access DPF.
+ *
+ * (c) 2010, 2011 <hackfin@section5.ch>
+ *
+ * This currently uses the SCSI command set
+ *
+ * The reason for this is that we want to access the hacked frame
+ * non-root and without having to wait for the SCSI interface to
+ * intialize.
+ *
+ * Later, we'll replace the SCSI command stuff.
+ */
+
+#define ENDPT_OUT 1
+#define ENDPT_IN 0x81
+
+struct known_device {
+ const char *desc;
+ unsigned short vid;
+ unsigned short pid;
+} g_known_devices[] = {
+ { "AX206 DPF", 0x1908, 0x0102 },
+ { 0 , 0, 0 } /* NEVER REMOVE THIS */
+};
+
+int handle_error(const char *txt)
+{
+ fprintf(stderr, "Error: %s\n", txt);
+ return -1;
+}
+
+void usb_flush(usb_dev_handle *dev)
+{
+ char buf[20];
+ usb_bulk_read(dev, ENDPT_IN, buf, 3, 1000);
+}
+
+int check_known_device(struct usb_device *d)
+{
+ struct known_device *dev = g_known_devices;
+
+ while (dev->desc) {
+ if ((d->descriptor.idVendor == dev->vid) &&
+ (d->descriptor.idProduct == dev->pid)) {
+ //fprintf(stderr, "Found %s at %s:%s\n", dev->desc, d->bus->dirname, d->filename);
+ return 1;
+ }
+ dev++;
+ }
+ return 0;
+}
+
+static struct usb_device *find_dev(int index)
+{
+ struct usb_bus *b;
+ struct usb_device *d;
+ int enumeration = 0;
+
+ b = usb_get_busses();
+
+ while (b) {
+ d = b->devices;
+ while (d) {
+ if (check_known_device(d)) {
+ if (enumeration == index) return d;
+ else enumeration++;
+ }
+
+#ifdef HAVE_DEBUG
+ printf("%04x %04x\n",
+ d->descriptor.idVendor,
+ d->descriptor.idProduct);
+#endif
+ d = d->next;
+ }
+ b = b->next;
+ }
+ return NULL;
+}
+
+unsigned char g_buf[] = {
+ 0x55, 0x53, 0x42, 0x43, // dCBWSignature
+ 0xde, 0xad, 0xbe, 0xef, // dCBWTag
+ 0x00, 0x80, 0x00, 0x00, // dCBWLength
+ 0x00, // bmCBWFlags: 0x80: data in (dev to host), 0x00: Data out
+ 0x00, // bCBWLUN
+ 0x10, // bCBWCBLength
+
+ // SCSI cmd:
+ 0xcd, 0x00, 0x00, 0x00,
+ 0x00, 0x06, 0x11, 0xf8,
+ 0x70, 0x00, 0x40, 0x00,
+ 0x00, 0x00, 0x00, 0x00,
+};
+
+int emulate_scsi(usb_dev_handle *dev, unsigned char *cmd, int cmdlen, char out,
+ unsigned char *data, unsigned long block_len)
+{
+ int len;
+ int ret;
+ static unsigned char ansbuf[13]; // Do not change size.
+
+ g_buf[14] = cmdlen;
+ memcpy(&g_buf[15], cmd, cmdlen);
+
+ g_buf[8] = block_len;
+ g_buf[9] = block_len >> 8;
+ g_buf[10] = block_len >> 16;
+ g_buf[11] = block_len >> 24;
+
+ ret = usb_bulk_write(dev, ENDPT_OUT, (char*)g_buf, sizeof(g_buf), 1000);
+ if (ret < 0) return ret;
+
+ if (out == DIR_OUT) {
+ if (data) {
+ ret = usb_bulk_write(dev, ENDPT_OUT, (char* )data,
+ block_len, 3000);
+ if (ret != (int) block_len) {
+ perror("bulk write");
+ return ret;
+ }
+ }
+ } else if (data) {
+ ret = usb_bulk_read(dev, ENDPT_IN, (char *) data, block_len, 4000);
+ if (ret != (int) block_len) {
+ perror("bulk data read");
+ }
+ }
+ // get ACK:
+ len = sizeof(ansbuf);
+ int retry = 0;
+ do {
+ ret = usb_bulk_read(dev, ENDPT_IN, (char *) ansbuf, len, 5000);
+ if (ret != len) {
+ perror("bulk ACK read");
+ ret = DEVERR_TIMEOUT;
+ }
+ retry++;
+ } while (ret == DEVERR_TIMEOUT && retry < 5);
+ if (strncmp((char *) ansbuf, "USBS", 4)) {
+ return handle_error("Got invalid reply\n");
+ }
+ // pass back return code set by peer:
+ return ansbuf[12];
+}
+
+usb_dev_handle *dpf_usb_open(int index)
+{
+ struct usb_device *d;
+ usb_dev_handle *usb_dev;
+
+ usb_init();
+ usb_find_busses();
+ usb_find_devices();
+
+ d = find_dev(index);
+ if (!d) {
+ handle_error("No matching USB device found!");
+ return NULL;
+ }
+
+ usb_dev = usb_open(d);
+ if (usb_dev == NULL) {
+ handle_error("Failed to open usb device!");
+ return NULL;
+ }
+ usb_claim_interface(usb_dev, 0);
+ return usb_dev;
+}
+
+// -------------------------------------------------------------------
+// END SELECTIVE COPY & PASTE "rawusb.c"
+// -------------------------------------------------------------------
+
+
+} // end of namespace LIBDPF
+
+//##########################################################################################
+// ** END OF UGLY HACK ** END OF UGLY HACK ** END OF UGLY HACK ** END OF UGLY HACK *
+//##########################################################################################
diff --git a/glcddrivers/ax206dpf.h b/glcddrivers/ax206dpf.h
new file mode 100644
index 0000000..d683ccf
--- /dev/null
+++ b/glcddrivers/ax206dpf.h
@@ -0,0 +1,300 @@
+/*
+ * GraphLCD driver library
+ *
+ * ax206dpf.h - AX206dpf driver class
+ * Output goes to AX 206 based photoframe
+ * based on:
+ * simlcd device
+ * (c) 2001-2004 Carsten Siebholz <c.siebholz AT t-online.de>
+ * (c) 2011 Dirk Heiser
+ * (c) 2011 Wolfgang Astleitner <mrwastl AT users.sourceforge.net>
+ *
+ * includes code from:
+ * http://sourceforge.net/projects/dpf-ax/
+ *
+ * Original copyright:
+ *
+ * Copyright (C) 2008 Jeroen Domburg <picframe@spritesmods.com>
+ * Modified from sample code by:
+ * Copyright (C) 2005 Michael Reinelt <michael@reinelt.co.at>
+ * Copyright (C) 2005, 2006, 2007 The LCD4Linux Team <lcd4linux-devel@users.sourceforge.net>
+ * Mods by <hackfin@section5.ch>
+ *
+ * This file is released under the GNU General Public License. Refer
+ * to the COPYING file distributed with this package.
+ *
+ * (c) 2011 Lutz Neumann <superelchi AT wolke7.net>
+ *
+ */
+
+#ifndef _GLCDDRIVERS_AX206DPF_H_
+#define _GLCDDRIVERS_AX206DPF_H_
+
+#include "driver.h"
+
+namespace LIBDPF {
+struct dpf_context;
+typedef dpf_context DPFContext;
+}
+
+namespace GLCD
+{
+#define MAX_DPFS 4
+
+#define DEFAULT_WIDTH 320
+#define DEFAULT_HEIGHT 240
+#define DEFAULT_BPP 2
+
+#define USB_SCAN_INTERVALL 10 // seconds between usb scans for missing displays
+
+typedef struct display_handle {
+ bool attached;
+ char address[8];
+ bool isPortrait;
+ bool rotate90;
+ bool flip;
+ int minx, maxx;
+ int miny, maxy;
+ LIBDPF::DPFContext *dpfh;
+ unsigned char * LCD;
+} DISPLAYHANDLE;
+
+
+class cDriverConfig;
+
+class cDriverAX206DPF : public cDriver
+{
+private:
+ unsigned char * tempLCD; // temp transfer buffer
+
+ bool portrait; // portrait or landscape mode
+ int zoom; // pixel zoom factor
+ unsigned int numdisplays; // number of detected displays
+ unsigned int numxdisplays; // number of displays (horizontal)
+ unsigned int numydisplays; // number of displays (vertical)
+ unsigned int sizex; // logical horizontal size of one display
+ unsigned int sizey; // logical vertical size of one display
+ unsigned int bpp; // bits per pixel
+
+ DISPLAYHANDLE *dh[MAX_DPFS];
+ std::string flips;
+ time_t lastscan;
+ int lastbrightness;
+
+
+ int CheckSetup();
+ void ResetMinMax();
+ bool RescanUSB();
+ int InitSingleDisplay(unsigned int);
+ void DeInitSingleDisplay(unsigned int);
+ void ClearSingleDisplay(unsigned int);
+ void SetSingleDisplayBrightness(unsigned int, unsigned int);
+
+public:
+ cDriverAX206DPF(cDriverConfig * config);
+
+ virtual int Init();
+ virtual int DeInit();
+
+ virtual void Clear();
+ virtual void SetPixel(int x, int y, uint32_t data);
+ virtual void Refresh(bool refreshAll = false);
+ virtual uint32_t GetBackgroundColor(void);
+ virtual void SetBrightness(unsigned int);
+ virtual bool GetDriverFeature (const std::string & Feature, int & value);
+};
+
+} // end of namespace GLCD
+
+
+//##########################################################################################
+//
+// ** START OF UGLY HACK ** START OF UGLY HACK ** START OF UGLY HACK ** START OF UGLY HACK *
+//
+// Because I choose NOT to include the static library libdpf.a and/or their header- and
+// source-files from the original dpf-ax hack, I did some creative copy & paste from there
+// to this place. I will delete this stuff when a usable shared library of libpdf exists.
+//
+//##########################################################################################
+
+// -------------------------------------------------------------------
+// START SELECTIVE COPY & PASTE "dpf.h"
+// -------------------------------------------------------------------
+
+/** libdpf header file
+ *
+ * (c) 2010, 2011 <hackfin@section5.ch>
+ *
+ */
+
+// -------------------------------------------------------------------
+// START SELECTIVE COPY & PASTE "usbuser.h"
+// -------------------------------------------------------------------
+
+#include <usb.h>
+
+namespace LIBDPF
+{
+
+/* USB user commands
+ *
+ * Only temporary. Should move to dpflib or into a dclib configuration.
+ *
+ */
+
+#define PROTOCOL_VERSION 1
+
+/** Our vendor specific USB commands to do stuff on the DPF */
+
+#define USBCMD_GETPROPERTY 0x00 ///< Get property
+#define USBCMD_SETPROPERTY 0x01 ///< Set property
+#define USBCMD_MEMREAD 0x04 ///< Memory read
+#define USBCMD_APPLOAD 0x05 ///< Load and run applet
+#define USBCMD_FILLRECT 0x11 ///< Fill screen rectangle
+#define USBCMD_BLIT 0x12 ///< Blit to screen
+#define USBCMD_COPYRECT 0x13 ///< Copy screen rectangle
+#define USBCMD_FLASHLOCK 0x20 ///< Lock USB for flash access
+#define USBCMD_PROBE 0xff ///< Get version code (probe)
+
+/* Some special return codes */
+#define USB_IN_SEQUENCE 0x7f ///< We're inside a command sequence
+
+// Property handling:
+
+#define PROPERTY_BRIGHTNESS 0x01
+#define PROPERTY_FGCOLOR 0x02
+#define PROPERTY_BGCOLOR 0x03
+#define PROPERTY_ORIENTATION 0x10
+
+// -------------------------------------------------------------------
+// END SELECTIVE COPY & PASTE "usbuser.h"
+// -------------------------------------------------------------------
+
+#define ADDR unsigned int
+
+//#define MODE_SG 0x00 ///< generic device mode (original)
+//#define MODE_USB 0x01 ///< libusb operation mode (hacked)
+#define FLAG_CAN_LOCK 0x80 ///< Has the locking feature (new firmware)
+
+enum {
+ DEVERR_FILE = -16,
+ DEVERR_OPEN,
+ DEVERR_HEX,
+ DEVERR_CHK,
+ DEVERR_IO,
+ DEVERR_MALLOC,
+ DEVERR_TIMEOUT,
+};
+
+/** The DPF context structure */
+
+typedef
+struct dpf_context {
+ unsigned char mode;
+ unsigned char flags;
+ union {
+ usb_dev_handle *udev;
+ int fd;
+ } dev;
+ unsigned int width;
+ unsigned int height;
+ int bpp;
+ int proto;
+ char* buff;
+ unsigned char* oldpix;
+ int offx;
+ int offy;
+} DPFContext;
+
+/** A value proxy for the property API */
+typedef struct dpf_proxy {
+ union {
+ short integer;
+ char *sequence;
+ } value;
+ char type;
+} DPFValue;
+
+enum {
+ TYPE_INTEGER,
+ TYPE_STRING,
+};
+
+#define DPFHANDLE struct dpf_context *
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/**
+ Opens the DPF device. if dev is not NULL, open device, otherwise, look for
+ USB device.
+ */
+int dpf_open(const char *dev, DPFHANDLE *h);
+
+/** Close DPF device */
+void dpf_close(DPFHANDLE h);
+
+/** Blit data to screen
+ *
+ * \param buf buffer to 16 bpp RGB 565 image data
+ * \param rect rectangle tuple: [x0, y0, x1, y1]
+ */
+
+int dpf_screen_blit(DPFHANDLE h, const unsigned char *buf, short rect[4]);
+
+/** Set property on DPF
+ * \param token Property token
+ * \param value Pointer to value
+ */
+int dpf_setproperty(DPFHANDLE h, int token, const DPFValue *value);
+
+/* USB raw */
+
+int emulate_scsi(usb_dev_handle *d, unsigned char *cmd, int cmdlen, char out,
+ unsigned char *data, unsigned long block_len);
+
+const char *dev_errstr(int err);
+
+// Private stuff:
+usb_dev_handle *dpf_usb_open(int index);
+int sgdev_open(const char *portname, int *fd);
+
+#ifdef __cplusplus
+}
+#endif
+
+// Some internal address offsets. They may change, but so far all types
+// seem to have the same
+//
+// w: word, <n>: length, [LE, BE]
+//
+// FIXME: Use packed struct later.
+
+// FIXME: Should be 0x0020, once we have the firmware replaced
+#define OFFSET_PROPS 0x3f0020 ///< w[2]:LE : Resolution X, Y
+
+// -------------------------------------------------------------------
+// END SELECTIVE COPY & PASTE "dpf.h"
+// -------------------------------------------------------------------
+
+// -------------------------------------------------------------------
+// START SELECTIVE COPY & PASTE "sglib.h"
+// -------------------------------------------------------------------
+
+/* generic SCSI device stuff: */
+
+#define DIR_IN 0
+#define DIR_OUT 1
+
+// -------------------------------------------------------------------
+// END SELECTIVE COPY & PASTE "sglib.h"
+// -------------------------------------------------------------------
+
+} // end of namespace LIBDPF_HACK
+
+//##########################################################################################
+// ** END OF UGLY HACK ** END OF UGLY HACK ** END OF UGLY HACK ** END OF UGLY HACK *
+//##########################################################################################
+
+#endif //_GLCDDRIVERS_AX206DPF_H_
diff --git a/glcddrivers/common.c b/glcddrivers/common.c
index 0d0fad9..40a3048 100644
--- a/glcddrivers/common.c
+++ b/glcddrivers/common.c
@@ -9,7 +9,8 @@
* This file is released under the GNU General Public License. Refer
* to the COPYING file distributed with this package.
*
- * (c) 2004 Andreas Regel <andreas.regel AT powarman.de>
+ * (c) 2004 Andreas Regel <andreas.regel AT powarman.de>
+ * (c) 2010-2012 Wolfgang Astleitner <mrwastl AT users sourceforge net>
*/
#include <ctype.h>
@@ -219,7 +220,7 @@ std::string trim(const std::string & s)
start++;
}
end = s.length() - 1;
- while (end >= 0)
+ while (end > start)
{
if (!isspace(s[end]))
break;
diff --git a/glcddrivers/config.c b/glcddrivers/config.c
index ef88279..15338b6 100644
--- a/glcddrivers/config.c
+++ b/glcddrivers/config.c
@@ -6,7 +6,8 @@
* This file is released under the GNU General Public License. Refer
* to the COPYING file distributed with this package.
*
- * (c) 2004 Andreas Regel <andreas.regel AT powarman.de>
+ * (c) 2004 Andreas Regel <andreas.regel AT powarman.de>
+ * (c) 2011 Wolfgang Astleitner <mrwastl AT users sourceforge net>
*/
#include <syslog.h>
@@ -214,6 +215,12 @@ bool cConfig::Load(const std::string & filename)
continue;
if (line[0] == '[' && line[line.length() - 1] == ']')
{
+ // no ':' in section names
+ if (line.substr(1, line.length() - 2).find(':') != std::string::npos) {
+ syslog(LOG_ERR, "Config error: section name may not contain a ':', erraneous line: '%s'\n", line.c_str());
+ file.close();
+ return false;
+ }
if (!inSections)
inSections = true;
else
diff --git a/glcddrivers/config.h b/glcddrivers/config.h
index 8caa77e..1c744e8 100644
--- a/glcddrivers/config.h
+++ b/glcddrivers/config.h
@@ -6,7 +6,8 @@
* This file is released under the GNU General Public License. Refer
* to the COPYING file distributed with this package.
*
- * (c) 2004 Andreas Regel <andreas.regel AT powarman.de>
+ * (c) 2004 Andreas Regel <andreas.regel AT powarman.de>
+ * (c) 2011 Wolfgang Astleitner <mrwastl AT users sourceforge net>
*/
#ifndef _GLCDDRIVERS_CONFIG_H_
diff --git a/glcddrivers/dm140gink.c b/glcddrivers/dm140gink.c
index c7efdba..4f73c42 100644
--- a/glcddrivers/dm140gink.c
+++ b/glcddrivers/dm140gink.c
@@ -7,7 +7,8 @@
* This file is released under the GNU General Public License. Refer
* to the COPYING file distributed with this package.
*
- * (c) 2004 Stephan Skrodzki
+ * (c) 2004 Stephan Skrodzki
+ * (c) 2011-2013 Wolfgang Astleitner <mrwastl AT users.sourceforge.net>
*/
#include <fcntl.h>
@@ -30,16 +31,10 @@ namespace GLCD
{
cDriverDM140GINK::cDriverDM140GINK(cDriverConfig * config)
-: config(config),
+: cDriver(config),
fd(-1),
framebuff(0)
{
- oldConfig = new cDriverConfig(*config);
-}
-
-cDriverDM140GINK::~cDriverDM140GINK()
-{
- delete oldConfig;
}
/* hack - fix improper signed char handling - it's seeing 0x80 as a negative value*/
@@ -92,7 +87,7 @@ int cDriverDM140GINK::SendReport(const char *cbuf, size_t size)
//**************************************************************
if((err = ioctl(fd, HIDIOCSUSAGE, &uref)) < 0)
{
- syslog(LOG_INFO, "%s: Error with sending the USAGE ioctl %d,0x%02X;size:%d\n", config->name.c_str(), i, (int)buf[i],size);
+ syslog(LOG_INFO, "%s: Error with sending the USAGE ioctl %d,0x%02X;size:%d\n", config->name.c_str(), (int)i, (int)buf[i], (int)size);
return err;
}
uref.usage_code = 0xffa10006; //unused?
@@ -254,7 +249,7 @@ int cDriverDM140GINK::CheckSetup()
return 0;
}
-void cDriverDM140GINK::SetPixel(int x, int y)
+void cDriverDM140GINK::SetPixel(int x, int y, uint32_t data)
{
if (x >= width || y >= height)
return;
@@ -267,7 +262,10 @@ void cDriverDM140GINK::SetPixel(int x, int y)
int offset = (y/8) * width + x;
char mask = (1 << (7 - (y%8)));
- framebuff[offset] |= mask;
+ if (data == GRAPHLCD_White)
+ framebuff[offset] |= mask;
+ else
+ framebuff[offset] &= (0xFF ^ mask);
}
void cDriverDM140GINK::Clear()
@@ -275,6 +273,7 @@ void cDriverDM140GINK::Clear()
memset(framebuff, 0, screensize);
}
+#if 0
void cDriverDM140GINK::Set8Pixels(int x, int y, unsigned char data)
{
x &= 0xFFF8;
@@ -282,9 +281,10 @@ void cDriverDM140GINK::Set8Pixels(int x, int y, unsigned char data)
for (int n = 0; n < 8; ++n)
{
if (data & (0x80 >> n)) // if bit is set
- SetPixel(x + n, y);
+ SetPixel(x + n, y, GRAPHLCD_White);
}
}
+#endif
void cDriverDM140GINK::Refresh(bool refreshAll)
{
diff --git a/glcddrivers/dm140gink.h b/glcddrivers/dm140gink.h
index 526263a..10bfea6 100644
--- a/glcddrivers/dm140gink.h
+++ b/glcddrivers/dm140gink.h
@@ -7,7 +7,8 @@
* This file is released under the GNU General Public License. Refer
* to the COPYING file distributed with this package.
*
- * (c) 2004 Stephan Skrodzki
+ * (c) 2004 Stephan Skrodzki
+ * (c) 2011-2013 Wolfgang Astleitner <mrwastl AT users.sourceforge.net>
*/
#ifndef _GLCDDRIVERS_DM140GINK_H_
@@ -24,13 +25,10 @@ class cDriverConfig;
class cDriverDM140GINK : public cDriver
{
private:
- cDriverConfig * config;
- cDriverConfig * oldConfig;
-
int fd;
- int vendor;
- int product;
+ signed short vendor;
+ signed short product;
char *framebuff;
@@ -38,17 +36,16 @@ private:
int SendReport(const char *buf, size_t size);
int CheckSetup();
- void SetPixel(int x, int y);
public:
cDriverDM140GINK(cDriverConfig * config);
- virtual ~cDriverDM140GINK();
virtual int Init();
virtual int DeInit();
virtual void Clear();
- virtual void Set8Pixels(int x, int y, unsigned char data);
+ virtual void SetPixel(int x, int y, uint32_t data);
+ //virtual void Set8Pixels(int x, int y, unsigned char data);
virtual void Refresh(bool refreshAll = false);
};
diff --git a/glcddrivers/driver.c b/glcddrivers/driver.c
index b1b6286..ea13eaf 100644
--- a/glcddrivers/driver.c
+++ b/glcddrivers/driver.c
@@ -9,23 +9,47 @@
* This file is released under the GNU General Public License. Refer
* to the COPYING file distributed with this package.
*
- * (c) 2004 Andreas Regel <andreas.regel AT powarman.de>
+ * (c) 2004-2010 Andreas Regel <andreas.regel AT powarman.de>
+ * (c) 2010-2013 Wolfgang Astleitner <mrwastl AT users sourceforge net>
*/
#include "common.h"
#include "driver.h"
-
+#include "config.h"
namespace GLCD
{
-cDriver::cDriver()
+cTouchEvent::cTouchEvent() : x(0), y(0), touch(0)
+{
+}
+
+cDriver::cDriver(cDriverConfig * config)
: width(0),
- height(0)
+ height(0),
+ config(config)
+{
+ fgcol = GetDefaultForegroundColor();
+ bgcol = GetDefaultBackgroundColor();
+ oldConfig = new cDriverConfig(*config);
+}
+
+cDriver::~cDriver(void)
{
+ delete oldConfig;
+}
+
+const std::string cDriver::ConfigName() {
+ return (config) ? config->name : "";
+}
+
+const std::string cDriver::DriverName() {
+ return (config) ? config->driver : "";
}
-void cDriver::SetScreen(const unsigned char * data, int wid, int hgt, int lineSize)
+
+//void cDriver::SetScreen(const unsigned char * data, int wid, int hgt, int lineSize)
+void cDriver::SetScreen(const uint32_t * data, int wid, int hgt)
{
int x, y;
@@ -34,11 +58,19 @@ void cDriver::SetScreen(const unsigned char * data, int wid, int hgt, int lineSi
if (hgt > height)
hgt = height;
- Clear();
+ //Clear();
if (data)
{
for (y = 0; y < hgt; y++)
{
+ for (x = 0; x < wid; x++)
+ {
+// printf("%s:%s(%d) - %03d * %03d (linesize %02d), %08x\n", __FILE__, __FUNCTION__, __LINE__, x, y, lineSize, data[y * lineSize + x]);
+ SetPixel(x, y, data[y * wid + x]);
+ }
+ }
+ }
+/*
for (x = 0; x < (wid / 8); x++)
{
Set8Pixels(x * 8, y, data[y * lineSize + x]);
@@ -48,7 +80,24 @@ void cDriver::SetScreen(const unsigned char * data, int wid, int hgt, int lineSi
Set8Pixels((wid / 8) * 8, y, data[y * lineSize + wid / 8] & bitmaskl[wid % 8 - 1]);
}
}
+*/
+}
+
+void cDriver::Set8Pixels(int x, int y, unsigned char data)
+{
+ int n;
+ // calling GetForegroundColor() and GetBackgroundColor() is slow in some situations.
+ // will be replaced through setting object-wide (incl. derived objs) class members
+ uint32_t fg = GetForegroundColor();
+ uint32_t bg = GetBackgroundColor();
+
+ // guarante that x starts at a position divisible by 8
+ x &= 0xFFF8;
+
+ for (n = 0; n < 8; ++n) {
+ SetPixel(x + n, y, (data & (0x80 >> n)) ? fg : bg);
}
}
+
} // end of namespace
diff --git a/glcddrivers/driver.h b/glcddrivers/driver.h
index 1d82eaa..3e28a3f 100644
--- a/glcddrivers/driver.h
+++ b/glcddrivers/driver.h
@@ -9,38 +9,123 @@
* This file is released under the GNU General Public License. Refer
* to the COPYING file distributed with this package.
*
- * (c) 2004 Andreas Regel <andreas.regel AT powarman.de>
+ * (c) 2004-2010 Andreas Regel <andreas.regel AT powarman.de>
+ * (c) 2010-2013 Wolfgang Astleitner <mrwastl AT users sourceforge net>
*/
#ifndef _GLCDDRIVERS_DRIVER_H_
#define _GLCDDRIVERS_DRIVER_H_
#include <stdint.h>
+#include "../glcdgraphics/bitmap.h"
+
+// for strcasecmp
+#include <strings.h>
namespace GLCD
{
+class cGLCDEvent {
+public:
+ virtual ~cGLCDEvent() {}
+};
+
+class cTouchEvent : public cGLCDEvent {
+public:
+ int x;
+ int y;
+ int touch;
+ cTouchEvent();
+};
+
+class cDriverConfig;
+
class cDriver
{
protected:
- int width;
- int height;
+ int width;
+ int height;
+ uint32_t bgcol;
+ uint32_t fgcol;
+ cDriverConfig * config;
+ cDriverConfig * oldConfig;
+
+ virtual bool GetDriverFeature (const std::string & Feature, int & value) { return false; }
+ virtual uint32_t GetDefaultBackgroundColor(void) { return GRAPHLCD_Black; }
+ uint32_t GetDefaultForegroundColor(void) { return GetDefaultBackgroundColor() ^ 0x00FFFFFF; }
public:
- cDriver();
- virtual ~cDriver() {}
+ cDriver(cDriverConfig * config);
+ virtual ~cDriver();
int Width() const { return width; }
int Height() const { return height; }
+
+ const std::string ConfigName();
+ const std::string DriverName();
virtual int Init() { return 0; }
virtual int DeInit() { return 0; }
virtual void Clear() {}
- virtual void Set8Pixels(int x, int y, unsigned char data) {}
- virtual void SetScreen(const unsigned char * data, int width, int height, int lineSize);
+ virtual void SetPixel(int x, int y, uint32_t data) {}
+ void Set8Pixels(int x, int y, unsigned char data);
+// virtual void SetScreen(const unsigned char * data, int width, int height, int lineSize);
+ virtual void SetScreen(const uint32_t *data, int width, int height);
virtual void Refresh(bool refreshAll = false) {}
virtual void SetBrightness(unsigned int percent) {}
+
+
+ virtual bool SetFeature (const std::string & Feature, int value) { return false; }
+
+ uint32_t GetBackgroundColor(bool driverdefault=false) {
+ return (
+ (driverdefault || bgcol == GRAPHLCD_ERRCOL || bgcol == GRAPHLCD_Transparent)
+ ? GetDefaultBackgroundColor()
+ : bgcol
+ );
+ }
+ uint32_t GetForegroundColor(bool driverdefault=false) {
+ return (
+ (driverdefault || fgcol == GRAPHLCD_ERRCOL || fgcol == GRAPHLCD_Transparent)
+ ? GetDefaultForegroundColor()
+ : fgcol
+ );
+ }
+
+ // not to be overridden, override GetDriverFeature() instead
+ // the following feature names (case insensitive!) are guaranteed to give results:
+ // 'depth' colour depth, default: 1
+ // 'ismonochrome' is lcd a monochrome display?, default: true (1)
+ // the following feature names are pre-defined but default to false (0)
+ // 'isgreyscale', 'isgrayscale' is lcd a greyscale display?
+ // 'iscolour', 'iscolor' is lcd a colour display?
+ // 'touch', 'touchscreen' is a touchscreen supported and available?
+ bool GetFeature (const std::string & Feature, int & value) {
+ if (GetDriverFeature(Feature, value)) {
+ return true;
+ } else if (strcasecmp(Feature.c_str(), "depth") == 0) {
+ value = 1;
+ return true;
+ } else if (strcasecmp(Feature.c_str(), "ismonochrome") == 0) {
+ value = 1; // true == 1, false == 0
+ return true;
+ } else if (strcasecmp(Feature.c_str(), "isgreyscale") == 0 || strcasecmp(Feature.c_str(), "isgrayscale") == 0) {
+ value = 0; // true == 1, false == 0
+ return true;
+ } else if (strcasecmp(Feature.c_str(), "iscolour") == 0 || strcasecmp(Feature.c_str(), "iscolor") == 0) {
+ value = 0; // true == 1, false == 0
+ return true;
+ } else if (strcasecmp(Feature.c_str(), "touch") == 0 || strcasecmp(Feature.c_str(), "touchscreen") == 0) {
+ value = 0; // true == 1, false == 0
+ return true;
+ }
+ value = 0;
+ return false;
+ }
+
+ virtual cGLCDEvent * GetEvent(void) { return NULL; }
+
};
} // end of namespace
diff --git a/glcddrivers/drivers.c b/glcddrivers/drivers.c
index 946ab39..4c7e67a 100644
--- a/glcddrivers/drivers.c
+++ b/glcddrivers/drivers.c
@@ -33,6 +33,21 @@
#ifdef HAVE_LIBHID
#include "futabaMDM166A.h"
#endif
+#ifdef HAVE_DRIVER_AX206DPF
+#include "ax206dpf.h"
+#endif
+#ifdef HAVE_DRIVER_picoLCD_256x64
+#include "picoLCD_256x64.h"
+#endif
+#ifdef HAVE_DRIVER_VNCSERVER
+#include "vncserver.h"
+#endif
+#ifdef HAVE_DRIVER_SSD1306
+#include "ssd1306.h"
+#endif
+#ifdef HAVE_DRIVER_ILI9341
+#include "ili9341.h"
+#endif
namespace GLCD
{
@@ -60,6 +75,21 @@ tDriver drivers[] =
#endif
{"serdisp", kDriverSerDisp},
{"g15daemon", kDriverG15daemon},
+#ifdef HAVE_DRIVER_AX206DPF
+ {"ax206dpf", kDriverAX206DPF},
+#endif
+#ifdef HAVE_DRIVER_picoLCD_256x64
+ {"picolcd256x64", kDriverPicoLCD_256x64},
+#endif
+#ifdef HAVE_DRIVER_VNCSERVER
+ {"vncserver", kDriverVncServer},
+#endif
+#ifdef HAVE_DRIVER_SSD1306
+ {"ssd1306", kDriverSSD1306},
+#endif
+#ifdef HAVE_DRIVER_ILI9341
+ {"ili9341", kDriverILI9341},
+#endif
{"", kDriverUnknown}
};
@@ -122,6 +152,26 @@ cDriver * CreateDriver(int driverID, cDriverConfig * config)
return new cDriverSerDisp(config);
case kDriverG15daemon:
return new cDriverG15daemon(config);
+#ifdef HAVE_DRIVER_AX206DPF
+ case kDriverAX206DPF:
+ return new cDriverAX206DPF(config);
+#endif
+#ifdef HAVE_DRIVER_picoLCD_256x64
+ case kDriverPicoLCD_256x64:
+ return new cDriverPicoLCD_256x64(config);
+#endif
+#ifdef HAVE_DRIVER_VNCSERVER
+ case kDriverVncServer:
+ return new cDriverVncServer(config);
+#endif
+#ifdef HAVE_DRIVER_SSD1306
+ case kDriverSSD1306:
+ return new cDriverSSD1306(config);
+#endif
+#ifdef HAVE_DRIVER_ILI9341
+ case kDriverILI9341:
+ return new cDriverILI9341(config);
+#endif
case kDriverUnknown:
default:
return NULL;
diff --git a/glcddrivers/drivers.h b/glcddrivers/drivers.h
index b088713..970b01e 100644
--- a/glcddrivers/drivers.h
+++ b/glcddrivers/drivers.h
@@ -40,7 +40,22 @@ enum eDriver
kDriverNetwork = 14,
kDriverGU126X64D_K610A4 = 15,
kDriverDM140GINK = 16,
- kDriverFutabaMDM166A = 17,
+ kDriverFutabaMDM166A = 17,
+#ifdef HAVE_DRIVER_AX206DPF
+ kDriverAX206DPF = 18,
+#endif
+#ifdef HAVE_DRIVER_picoLCD_256x64
+ kDriverPicoLCD_256x64 = 19,
+#endif
+#ifdef HAVE_DRIVER_VNCSERVER
+ kDriverVncServer = 20,
+#endif
+#ifdef HAVE_DRIVER_SSD1306
+ kDriverSSD1306 = 21,
+#endif
+#ifdef HAVE_DRIVER_ILI9341
+ kDriverILI9341 = 22,
+#endif
kDriverSerDisp = 100,
kDriverG15daemon = 200
};
diff --git a/glcddrivers/framebuffer.c b/glcddrivers/framebuffer.c
index ef96cde..254f487 100644
--- a/glcddrivers/framebuffer.c
+++ b/glcddrivers/framebuffer.c
@@ -7,7 +7,8 @@
* This file is released under the GNU General Public License. Refer
* to the COPYING file distributed with this package.
*
- * (c) 2004 Stephan Skrodzki
+ * (c) 2004 Stephan Skrodzki
+ * (c) 2011 Wolfgang Astleitner <mrwastl AT users.sourceforge.net>
*/
#include <fcntl.h>
@@ -28,20 +29,15 @@ namespace GLCD
{
cDriverFramebuffer::cDriverFramebuffer(cDriverConfig * config)
-: config(config),
+: cDriver(config),
offbuff(0),
fbfd(-1)
{
- oldConfig = new cDriverConfig(*config);
-}
-
-cDriverFramebuffer::~cDriverFramebuffer()
-{
- delete oldConfig;
}
int cDriverFramebuffer::Init()
{
+#if 0
// default values
width = config->width;
if (width <= 0)
@@ -49,7 +45,10 @@ int cDriverFramebuffer::Init()
height = config->height;
if (height <= 0)
height = 240;
+#endif
zoom = 1;
+ damage = 0;
+ depth = 1;
for (unsigned int i = 0; i < config->options.size(); i++)
{
@@ -62,11 +61,34 @@ int cDriverFramebuffer::Init()
syslog(LOG_ERR, "%s error: zoom %d not supported, using default (%d)!\n",
config->name.c_str(), z, zoom);
}
+ else if (config->options[i].name == "ReportDamage" || config->options[i].name == "Damage" )
+ {
+ if (config->options[i].value == "none") {
+ damage = 0;
+ } else if (config->options[i].value == "ugly") {
+ damage = 1;
+ } else if (config->options[i].value == "udlfb") {
+ damage = 2;
+ } else if (config->options[i].value == "auto") {
+ damage = -1;
+ }
+ else
+ syslog(LOG_ERR, "%s error: ReportDamage='%s' not supported, continuing w/o damage reporting!\n",
+ config->name.c_str(), config->options[i].value.c_str());
+ }
}
- // Open the file for reading and writing
- fbfd = open("/dev/fb0", O_RDWR);
- if (1 == fbfd)
+ if (config->device == "")
+ {
+ fbfd = open("/dev/fb0", O_RDWR);
+ }
+ else
+ {
+ fbfd = open(config->device.c_str(), O_RDWR);
+ }
+
+ //fbfd = open("/dev/fb0", O_RDWR);
+ if (fbfd < 0)
{
syslog(LOG_ERR, "%s: cannot open framebuffer device.\n", config->name.c_str());
return -1;
@@ -87,11 +109,78 @@ int cDriverFramebuffer::Init()
return -1;
}
+ if ( ! ( vinfo.bits_per_pixel == 8 || vinfo.bits_per_pixel == 16 || vinfo.bits_per_pixel == 24 || vinfo.bits_per_pixel == 32 ) )
+ {
+ syslog(LOG_ERR, "%s: bpp %d not supported.\n", config->name.c_str(), vinfo.bits_per_pixel);
+ return -1;
+ }
+
+ // get colour info
+ if (vinfo.bits_per_pixel > 8) {
+ rlen = vinfo.red.length;
+ glen = vinfo.green.length;
+ blen = vinfo.blue.length;
+ alen = vinfo.transp.length;
+
+ roff = vinfo.red.offset;
+ goff = vinfo.green.offset;
+ boff = vinfo.blue.offset;
+ aoff = vinfo.transp.offset;
+ } else {
+ // init colour map
+ struct fb_cmap cmap;
+ uint16_t r[256], g[256], b[256];
+ int i;
+
+ // RGB332 code from fbsplash-project taken as guideline
+ for ( i = 0; i < 256; i ++ ) {
+ r[i] = (( i & 0xe0) << 8) + ((i & 0x20) ? 0x1fff : 0);
+ g[i] = (( i & 0x1c) << 11) + ((i & 0x04) ? 0x1fff : 0);
+ b[i] = (( i & 0x03) << 14) + ((i & 0x01) ? 0x3fff : 0);
+ }
+ cmap.start = 0;
+ cmap.len = 256;
+ cmap.red = r;
+ cmap.green = g;
+ cmap.blue = b;
+ cmap.transp = 0;
+ if (ioctl(fbfd, FBIOPUTCMAP, &cmap)) {
+ syslog(LOG_ERR, "%s: Error setting colour map for bpp=8.\n", config->name.c_str());
+ return -1;
+ }
+ }
+
// Figure out the size of the screen in bytes
screensize = vinfo.xres * vinfo.yres * vinfo.bits_per_pixel / 8;
syslog(LOG_INFO, "%s: V01: xres: %d, yres %d, vyres: %d, bpp: %d, linelenght: %d\n", config->name.c_str(),vinfo.xres,vinfo.yres,vinfo.yres_virtual,vinfo.bits_per_pixel,finfo.line_length);
+ // auto calc w/h depending on zoom
+ if (zoom == 1) {
+ width = vinfo.xres >> 1;
+ height = vinfo.yres >> 1;
+ } else {
+ width = vinfo.xres;
+ height = vinfo.yres;
+ }
+ depth = vinfo.bits_per_pixel;
+
+ // init bounding box
+ bbox[0] = width - 1; // x top
+ bbox[1] = height - 1; // y top
+ bbox[2] = 0; // x bottom
+ bbox[3] = 0; // y bottom
+
+
+ // damage reporting == auto: detect framebuffer driver
+ if (damage == -1) {
+ if (strncasecmp(finfo.id, "udlfb", 16) == 0) {
+ damage = 2; // udlfb
+ } else { /* not supported / not detected */
+ damage = 0; // not detected -> no damage reporting
+ }
+ }
+
// reserve another memory to draw into
offbuff = new char[screensize];
if (!offbuff)
@@ -150,10 +239,12 @@ int cDriverFramebuffer::CheckSetup()
return 0;
}
-void cDriverFramebuffer::SetPixel(int x, int y)
+void cDriverFramebuffer::SetPixel(int x, int y, uint32_t data)
{
int location;
- int outcol;
+ unsigned char col1, col2, col3, alpha = 0;
+ uint32_t colraw;
+ int changed = 0;
if (x >= width || y >= height)
return;
@@ -164,72 +255,112 @@ void cDriverFramebuffer::SetPixel(int x, int y)
y = height - 1 - y;
}
- // Figure out where in memory to put the pixel
- location = (x*(1+zoom)+vinfo.xoffset) * (vinfo.bits_per_pixel/8) +
- (y*(1+zoom)+vinfo.yoffset) * finfo.line_length;
- if (vinfo.bits_per_pixel <= 8)
- {
- outcol = 15;
- }
- else
- {
- outcol = 255;
- }
+ // Figure out where in memory to put the pixel
+ location = ( (x << zoom) + vinfo.xoffset) * (vinfo.bits_per_pixel >> 3) +
+ ( (y << zoom) + vinfo.yoffset) * finfo.line_length;
if (vinfo.bits_per_pixel <= 8)
{
- *(offbuff + location) = outcol;
- if (zoom == 1)
- {
- *(offbuff + location + 1) = outcol;
- *(offbuff + location + finfo.line_length) = outcol;
- *(offbuff + location + finfo.line_length + 1) = outcol;
+ col1 = ((data & 0x00FF0000) >> (16 + 5) << 5) | // RRRg ggbb
+ ((data & 0x0000FF00) >> ( 8 + 5) << 2) | // rrrG GGbb
+ ((data & 0x000000FF) >> ( 6) ); // rrrg ggBB
+ if ( *(offbuff + location) != col1) {
+ changed = 1;
+ *(offbuff + location) = col1;
+ if (zoom == 1)
+ {
+ *(offbuff + location + 1) = col1;
+ *(offbuff + location + finfo.line_length) = col1;
+ *(offbuff + location + finfo.line_length + 1) = col1;
+ }
}
}
else if (vinfo.bits_per_pixel <= 16)
{
- *(offbuff + location) = outcol;
- *(offbuff + location + 1) = outcol;
- if (zoom == 1)
- {
- *(offbuff + location + 2) = outcol;
- *(offbuff + location + 3) = outcol;
- *(offbuff + location + finfo.line_length) = outcol;
- *(offbuff + location + finfo.line_length + 1) = outcol;
- *(offbuff + location + finfo.line_length + 2) = outcol;
- *(offbuff + location + finfo.line_length + 3) = outcol;
+
+
+ colraw = ((data & 0x00FF0000) >> (16 + 8 - rlen) << roff) | // red
+ ((data & 0x0000FF00) >> ( 8 + 8 - glen) << goff) | // green
+ ((data & 0x000000FF) >> ( 0 + 8 - blen) << boff); // blue
+ col1 = colraw & 0x0000FF;
+ col2 = (colraw & 0x00FF00) >> 8;
+ if ( *(offbuff + location) != col1 || *(offbuff + location + 1) != col2 ) {
+ changed = 1;
+ *(offbuff + location) = col1;
+ *(offbuff + location + 1) = col2;
+ if (zoom == 1)
+ {
+ *(offbuff + location + 2) = col1;
+ *(offbuff + location + 3) = col2;
+ *(offbuff + location + finfo.line_length) = col1;
+ *(offbuff + location + finfo.line_length + 1) = col2;
+ *(offbuff + location + finfo.line_length + 2) = col1;
+ *(offbuff + location + finfo.line_length + 3) = col2;
+ }
}
}
else
{
- *(offbuff + location) = outcol;
- *(offbuff + location + 1) = outcol;
- *(offbuff + location + 2) = outcol;
- *(offbuff + location + 3) = 0; /* should be transparency */
- if (zoom == 1)
- {
- *(offbuff + location + 4) = outcol;
- *(offbuff + location + 5) = outcol;
- *(offbuff + location + 6) = outcol;
- *(offbuff + location + 7) = 0;
- *(offbuff + location + finfo.line_length) = outcol;
- *(offbuff + location + finfo.line_length + 1) = outcol;
- *(offbuff + location + finfo.line_length + 2) = outcol;
- *(offbuff + location + finfo.line_length + 3) = 0;
- *(offbuff + location + finfo.line_length + 4) = outcol;
- *(offbuff + location + finfo.line_length + 5) = outcol;
- *(offbuff + location + finfo.line_length + 6) = outcol;
- *(offbuff + location + finfo.line_length + 7) = 0;
+ // remap graphlcd colour representation to framebuffer rep.
+ colraw = ((data & 0x00FF0000) >> (16 + 8 - rlen) << roff) | // red
+ ((data & 0x0000FF00) >> ( 8 + 8 - glen) << goff) | // green
+ ((data & 0x000000FF) >> ( 0 + 8 - blen) << boff); // blue
+ col1 = (colraw & 0x000000FF);
+ col2 = (colraw & 0x0000FF00) >> 8;
+ col3 = (colraw & 0x00FF0000) >> 16;
+
+ if (vinfo.bits_per_pixel == 32) {
+ colraw |= ((data & 0xFF000000) >> (24 + 8 - alen) << aoff); // transp.
+ alpha = (colraw & 0xFF000000) >> 24;
+ }
+
+ if ( *(offbuff + location) != col1 || *(offbuff + location + 1) != col2 || *(offbuff + location + 2) != col3 ) {
+ int pos = 0;
+ changed = 1;
+ *(offbuff + location + pos++) = col1;
+ *(offbuff + location + pos++) = col2;
+ *(offbuff + location + pos++) = col3;
+ if (vinfo.bits_per_pixel > 24)
+ *(offbuff + location + pos++) = alpha; /* should be transparency */
+ if (zoom == 1)
+ {
+ *(offbuff + location + pos++) = col1;
+ *(offbuff + location + pos++) = col2;
+ *(offbuff + location + pos++) = col3;
+ if (vinfo.bits_per_pixel > 24)
+ *(offbuff + location + pos++) = alpha;
+ pos = 0;
+ *(offbuff + location + finfo.line_length + pos++) = col1;
+ *(offbuff + location + finfo.line_length + pos++) = col2;
+ *(offbuff + location + finfo.line_length + pos++) = col3;
+ if (vinfo.bits_per_pixel > 24)
+ *(offbuff + location + finfo.line_length + pos++) = alpha;
+ *(offbuff + location + finfo.line_length + pos++) = col1;
+ *(offbuff + location + finfo.line_length + pos++) = col2;
+ *(offbuff + location + finfo.line_length + pos++) = col3;
+ if (vinfo.bits_per_pixel > 24)
+ *(offbuff + location + finfo.line_length + pos++) = alpha;
+ }
}
}
+
+ if (changed) {
+ // bounding box changed?
+ if (x < bbox[0]) bbox[0] = x;
+ if (y < bbox[1]) bbox[1] = y;
+ if (x > bbox[2]) bbox[2] = x;
+ if (y > bbox[3]) bbox[3] = y;
+ }
}
void cDriverFramebuffer::Clear()
{
memset(offbuff, 0, screensize);
+ processDamage();
}
+#if 0
void cDriverFramebuffer::Set8Pixels(int x, int y, unsigned char data)
{
int n;
@@ -239,13 +370,77 @@ void cDriverFramebuffer::Set8Pixels(int x, int y, unsigned char data)
for (n = 0; n < 8; ++n)
{
if (data & (0x80 >> n)) // if bit is set
- SetPixel(x + n, y);
+ SetPixel(x + n, y, GRAPHLCD_White);
}
}
+#endif
void cDriverFramebuffer::Refresh(bool refreshAll)
{
memcpy(fbp, offbuff, screensize);
+ processDamage();
+}
+
+bool cDriverFramebuffer::GetDriverFeature (const std::string & Feature, int & value) {
+ if (offbuff) {
+ if (strcasecmp(Feature.c_str(), "depth") == 0) {
+ value = depth;
+ return true;
+ } else if (strcasecmp(Feature.c_str(), "ismonochrome") == 0) {
+ value = 0;
+ return true;
+ } else if (strcasecmp(Feature.c_str(), "isgreyscale") == 0 || strcasecmp(Feature.c_str(), "isgrayscale") == 0) {
+ value = 0;
+ return true;
+ } else if (strcasecmp(Feature.c_str(), "iscolour") == 0 || strcasecmp(Feature.c_str(), "iscolor") == 0) {
+ value = 1;
+ return true;
+#if 0
+ } else if (strcasecmp(Feature.c_str(), "touch") == 0 || strcasecmp(Feature.c_str(), "touchscreen") == 0) {
+ if (...) {
+ value = (...) ? 1 : 0;
+ }
+ return true;
+#endif
+ }
+ }
+ value = 0;
+ return false;
+}
+
+
+/* defines for different damage processing calls needed by _update() */
+#define DLFB_IOCTL_REPORT_DAMAGE 0xAA
+void cDriverFramebuffer::processDamage (void) {
+ switch (damage) {
+ case 1: // ugly
+ {
+ unsigned char buf[3] = "\n";
+ write(fbfd,buf,2);
+ }
+ break;
+ case 2: // udlfb
+ {
+ struct fb_rect {
+ int x; int y; int w; int h;
+ } damage = {0, 0, 0, 0};
+ damage.x = bbox[0] << zoom;
+ damage.y = bbox[1] << zoom;
+ damage.w = (bbox[2] - bbox[0] + 1) << zoom;
+ damage.h = (bbox[3] - bbox[1] + 1) << zoom;
+
+ ioctl(fbfd, DLFB_IOCTL_REPORT_DAMAGE, &damage);
+ }
+ break;
+ default: // no damage reporting
+ break;
+ }
+
+ /* reset bounding box */
+ bbox[0] = width - 1;
+ bbox[1] = height - 1;
+ bbox[2] = 0;
+ bbox[3] = 0;
}
} // end of namespace
diff --git a/glcddrivers/framebuffer.h b/glcddrivers/framebuffer.h
index 79d1d77..7949ad3 100644
--- a/glcddrivers/framebuffer.h
+++ b/glcddrivers/framebuffer.h
@@ -7,7 +7,8 @@
* This file is released under the GNU General Public License. Refer
* to the COPYING file distributed with this package.
*
- * (c) 2004 Stephan Skrodzki
+ * (c) 2004 Stephan Skrodzki
+ * (c) 2011-2013 Wolfgang Astleitner <mrwastl AT users.sourceforge.net>
*/
#ifndef _GLCDDRIVERS_FRAMEBUFFER_H_
@@ -25,9 +26,6 @@ class cDriverConfig;
class cDriverFramebuffer : public cDriver
{
private:
- unsigned char ** LCD;
- cDriverConfig * config;
- cDriverConfig * oldConfig;
char *offbuff;
int fbfd;
struct fb_var_screeninfo vinfo;
@@ -35,19 +33,25 @@ private:
long int screensize;
void *fbp;
int zoom;
+ int damage;
+ int bbox[4];
+ int depth;
+ uint32_t roff, boff, goff, aoff;
+ uint32_t rlen, blen, glen, alen;
int CheckSetup();
- void SetPixel(int x, int y);
-
+ void processDamage (void);
+protected:
+ virtual bool GetDriverFeature (const std::string & Feature, int & value);
public:
cDriverFramebuffer(cDriverConfig * config);
- virtual ~cDriverFramebuffer();
virtual int Init();
virtual int DeInit();
virtual void Clear();
- virtual void Set8Pixels(int x, int y, unsigned char data);
+ virtual void SetPixel(int x, int y, uint32_t data);
+ //virtual void Set8Pixels(int x, int y, unsigned char data);
virtual void Refresh(bool refreshAll = false);
};
diff --git a/glcddrivers/futabaMDM166A.c b/glcddrivers/futabaMDM166A.c
index 2fc8d67..dfa74b2 100644
--- a/glcddrivers/futabaMDM166A.c
+++ b/glcddrivers/futabaMDM166A.c
@@ -1,12 +1,15 @@
/*
* GraphLCD driver library
*
- * (C) 2010 Andreas Brachold <vdr07 AT deltab de>
-
+ * futatbaMDM166A.c - Futaba MDM166A LCD
+ * Output goes to a Futaba MDM166A LCD
+ *
* This file is released under the GNU General Public License.
*
* See the files README and COPYING for details.
*
+ * (c) 2010 Andreas Brachold <vdr07 AT deltab de>
+ * (c) 2011 Wolfgang Astleitner <mrwastl AT users.sourceforge.net>
*/
#include <stdlib.h>
@@ -215,26 +218,22 @@ const char *cHIDQueue::hiderror(hid_return ret) const
case HID_RET_TIMEOUT:
return "timeout";
#endif
+ default:
+ return "unknown error or timeout";
}
return "unknown error";
}
cDriverFutabaMDM166A::cDriverFutabaMDM166A(cDriverConfig * config)
-: config(config)
+: cDriver(config)
, m_pDrawMem(0)
, m_pVFDMem(0)
{
- oldConfig = new cDriverConfig(*config);
m_nRefreshCounter = 0;
lastIconState = 0;
}
-cDriverFutabaMDM166A::~cDriverFutabaMDM166A()
-{
- delete oldConfig;
-}
-
int cDriverFutabaMDM166A::Init()
{
// default values
@@ -335,7 +334,7 @@ void cDriverFutabaMDM166A::Clear()
m_pDrawMem[n] = 0x00;
}
-void cDriverFutabaMDM166A::SetPixel(int x, int y)
+void cDriverFutabaMDM166A::SetPixel(int x, int y, uint32_t data)
{
byte c;
int n;
@@ -357,9 +356,14 @@ void cDriverFutabaMDM166A::SetPixel(int x, int y)
n = x + ((y / 8) * width);
c = 0x80 >> (y % 8);
- m_pDrawMem[n] |= c;
+ //m_pDrawMem[n] |= c;
+ if (data == GRAPHLCD_White)
+ m_pDrawMem[n] |= c;
+ else
+ m_pDrawMem[n] &= (0xFF ^ c);
}
+#if 0
void cDriverFutabaMDM166A::Set8Pixels(int x, int y, byte data)
{
int n;
@@ -373,6 +377,7 @@ void cDriverFutabaMDM166A::Set8Pixels(int x, int y, byte data)
SetPixel(x + n, y);
}
}
+#endif
void cDriverFutabaMDM166A::Refresh(bool refreshAll)
{
diff --git a/glcddrivers/futabaMDM166A.h b/glcddrivers/futabaMDM166A.h
index ca1783d..65323be 100644
--- a/glcddrivers/futabaMDM166A.h
+++ b/glcddrivers/futabaMDM166A.h
@@ -1,12 +1,15 @@
/*
* GraphLCD driver library
*
- * (C) 2010 Andreas Brachold <vdr07 AT deltab de>
+ * futatbaMDM166A.h - Futaba MDM166A LCD
+ * Output goes to a Futaba MDM166A LCD
*
* This file is released under the GNU General Public License.
*
* See the files README and COPYING for details.
*
+ * (c) 2010 Andreas Brachold <vdr07 AT deltab de>
+ * (c) 2011 Wolfgang Astleitner <mrwastl AT users.sourceforge.net>
*/
#ifndef _GLCDDRIVERS_FutabaMDM166A_H_
@@ -40,8 +43,6 @@ namespace GLCD
class cDriverFutabaMDM166A : public cDriver, cHIDQueue
{
- cDriverConfig * config;
- cDriverConfig * oldConfig;
unsigned char *m_pDrawMem; // the draw "memory"
unsigned char *m_pVFDMem; // the double buffed display "memory"
unsigned int m_iSizeYb;
@@ -50,20 +51,19 @@ namespace GLCD
int CheckSetup();
protected:
void ClearVFDMem();
- void SetPixel(int x, int y);
void icons(unsigned int state);
bool SendCmdClock();
bool SendCmdShutdown();
public:
cDriverFutabaMDM166A(cDriverConfig * config);
- virtual ~cDriverFutabaMDM166A();
virtual int Init();
virtual int DeInit();
virtual void Clear();
- virtual void Set8Pixels(int x, int y, byte data);
+ virtual void SetPixel(int x, int y, uint32_t data);
+ //virtual void Set8Pixels(int x, int y, byte data);
virtual void Refresh(bool refreshAll = false);
virtual void SetBrightness(unsigned int percent);
diff --git a/glcddrivers/g15daemon.c b/glcddrivers/g15daemon.c
index e275b38..daa0b9b 100644
--- a/glcddrivers/g15daemon.c
+++ b/glcddrivers/g15daemon.c
@@ -7,6 +7,8 @@
* This file is released under the GNU General Public License. Refer
* to the COPYING file distributed with this package.
*
+* (c) 2005-2010 Andreas Regel <andreas.regel AT powarman.de>
+* (c) 2011-2012 Wolfgang Astleitner <mrwastl AT users.sourceforge.net>
*/
#include <fcntl.h>
@@ -105,16 +107,10 @@ namespace GLCD
{
cDriverG15daemon::cDriverG15daemon(cDriverConfig * config)
-: config(config),
+: cDriver(config),
offbuff(0),
sockfd(-1)
{
- oldConfig = new cDriverConfig(*config);
-}
-
-cDriverG15daemon::~cDriverG15daemon()
-{
- delete oldConfig;
}
int cDriverG15daemon::Init()
@@ -150,8 +146,8 @@ int cDriverG15daemon::Init()
int cDriverG15daemon::DeInit()
{
- if (offbuff);
- delete[] offbuff;
+ if (offbuff)
+ delete[] offbuff;
if (-1 != sockfd)
close(sockfd);
@@ -180,7 +176,7 @@ int cDriverG15daemon::CheckSetup()
return 0;
}
-void cDriverG15daemon::SetPixel(int x, int y)
+void cDriverG15daemon::SetPixel(int x, int y, uint32_t data)
{
if (x >= width || y >= height)
return;
@@ -191,7 +187,7 @@ void cDriverG15daemon::SetPixel(int x, int y)
y = height - 1 - y;
}
- offbuff[x + (width * y)] = 1;
+ offbuff[x + (width * y)] = ( (data == GRAPHLCD_White) ? 1 : 0 );
}
void cDriverG15daemon::Clear()
@@ -199,6 +195,7 @@ void cDriverG15daemon::Clear()
memset(offbuff, 0, screensize);
}
+#if 0
void cDriverG15daemon::Set8Pixels(int x, int y, unsigned char data)
{
int n;
@@ -208,9 +205,10 @@ void cDriverG15daemon::Set8Pixels(int x, int y, unsigned char data)
for (n = 0; n < 8; ++n)
{
if (data & (0x80 >> n)) // if bit is set
- SetPixel(x + n, y);
+ SetPixel(x + n, y, GRAPHLCD_White);
}
}
+#endif
void cDriverG15daemon::Refresh(bool refreshAll)
{
diff --git a/glcddrivers/g15daemon.h b/glcddrivers/g15daemon.h
index c91ef17..c7c216a 100644
--- a/glcddrivers/g15daemon.h
+++ b/glcddrivers/g15daemon.h
@@ -4,6 +4,8 @@
* g15daemon.h - pseudo device for the g15daemon
* Output goes to the g15daemon which then displays it
*
+ * (c) 2005-2010 Andreas Regel <andreas.regel AT powarman.de>
+ * (c) 2011-2013 Wolfgang Astleitner <mrwastl AT users.sourceforge.net>
*/
#ifndef _GLCDDRIVERS_G15DAEMON_H_
@@ -20,27 +22,21 @@ class cDriverConfig;
class cDriverG15daemon : public cDriver
{
private:
- unsigned char ** LCD;
- cDriverConfig * config;
- cDriverConfig * oldConfig;
char *offbuff;
int sockfd;
long int screensize;
- char *fbp;
- int zoom;
int CheckSetup();
- void SetPixel(int x, int y);
public:
cDriverG15daemon(cDriverConfig * config);
- virtual ~cDriverG15daemon();
virtual int Init();
virtual int DeInit();
virtual void Clear();
- virtual void Set8Pixels(int x, int y, unsigned char data);
+ virtual void SetPixel(int x, int y, uint32_t data);
+ //virtual void Set8Pixels(int x, int y, unsigned char data);
virtual void Refresh(bool refreshAll = false);
};
diff --git a/glcddrivers/gu126x64D-K610A4.c b/glcddrivers/gu126x64D-K610A4.c
index 711e672..6770467 100644
--- a/glcddrivers/gu126x64D-K610A4.c
+++ b/glcddrivers/gu126x64D-K610A4.c
@@ -18,7 +18,8 @@
* This file is released under the GNU General Public License. Refer
* to the COPYING file distributed with this package.
*
- * (c) 2007 Alexander Rieger (Alexander.Rieger AT inka.de)
+ * (c) 2007 Alexander Rieger (Alexander.Rieger AT inka.de)
+ * (c) 2011 Wolfgang Astleitner <mrwastl AT users.sourceforge.net>
*/
#include <errno.h>
@@ -90,9 +91,8 @@ static const long ADJUST_FACTOR = 100; // used to adjust timing
//-----------------------------------------------------------------------------
cDriverGU126X64D_K610A4::cDriverGU126X64D_K610A4(cDriverConfig * config)
- : port (0)
- , config (config)
- , oldConfig (0)
+ : cDriver (config)
+ , port (0)
, myNumRows (0)
, myDrawMem (0)
, myVFDMem (0)
@@ -104,14 +104,8 @@ cDriverGU126X64D_K610A4::cDriverGU126X64D_K610A4(cDriverConfig * config)
, myDataPendingCounter(0)
, myLogFlags (0)
{
- oldConfig = new cDriverConfig(*config);
} // cDriverGU126X64D_K610A4::cDriverGU126X64D_K610A4()
-//-----------------------------------------------------------------------------
-cDriverGU126X64D_K610A4::~cDriverGU126X64D_K610A4()
-{
- delete oldConfig;
-} // cDriverGU126X64D_K610A4::cDriverGU126X64D_K610A4()
//-----------------------------------------------------------------------------
int cDriverGU126X64D_K610A4::Init()
@@ -417,7 +411,7 @@ int cDriverGU126X64D_K610A4::write(unsigned char data)
} // cDriverGU126X64D_K610A4::write()
//-----------------------------------------------------------------------------
-void cDriverGU126X64D_K610A4::setPixel(int x, int y)
+void cDriverGU126X64D_K610A4::SetPixel(int x, int y, uint32_t data)
{
if (!myDrawMem ) return;
if (x >= width || x < 0) return;
@@ -431,9 +425,13 @@ void cDriverGU126X64D_K610A4::setPixel(int x, int y)
unsigned char c = 0x80 >> (y % 8);
- myDrawMem[x][y/8] = myDrawMem[x][y/8] | c;
-} // cDriverGU126X64D_K610A4::setPixel()
+ if (data == GRAPHLCD_White)
+ myDrawMem[x][y/8] |= c;
+ else
+ myDrawMem[x][y/8] &= ( 0xFF ^ c );
+} // cDriverGU126X64D_K610A4::SetPixel()
+#if 0
//-----------------------------------------------------------------------------
void cDriverGU126X64D_K610A4::Set8Pixels(int x, int y, unsigned char data)
{
@@ -444,10 +442,11 @@ void cDriverGU126X64D_K610A4::Set8Pixels(int x, int y, unsigned char data)
{
if ((data & (0x80 >> n)) != 0) // if bit is set
{
- setPixel(x + n, y);
+ setPixel(x + n, y, GRAPHLCD_White);
} // if
} // for
} // cDriverGU126X64D_K610A4::Set8Pixels()
+#endif
//-----------------------------------------------------------------------------
void cDriverGU126X64D_K610A4::Refresh(bool refreshAll)
@@ -796,7 +795,7 @@ int cDriverGU126X64D_K610A4::cmdWriteText(const char *theText)
if (isLogEnabled(LL_VFD_CMD))
{
- syslog(LOG_INFO, "-%2dB: WRITE_TEXT : '%s'", strlen(theText), theText);
+ syslog(LOG_INFO, "-%2dB: WRITE_TEXT : '%s'", (int)strlen(theText), theText);
} // if
for (const char *p = theText; *p != '\0'; ++p)
diff --git a/glcddrivers/gu126x64D-K610A4.h b/glcddrivers/gu126x64D-K610A4.h
index 3d6c29c..422705f 100644
--- a/glcddrivers/gu126x64D-K610A4.h
+++ b/glcddrivers/gu126x64D-K610A4.h
@@ -18,7 +18,8 @@
* This file is released under the GNU General Public License. Refer
* to the COPYING file distributed with this package.
*
- * (c) 2007 Alexander Rieger (Alexander.Rieger AT inka.de)
+ * (c) 2007 Alexander Rieger (Alexander.Rieger AT inka.de)
+ * (c) 2011 Wolfgang Astleitner <mrwastl AT users.sourceforge.net>
*/
#ifndef _GLCDDRIVERS_GU126X64D_K610A4_H_
@@ -45,7 +46,6 @@ public:
// constructor/destructor
//---------------------------------------------------------------------------
cDriverGU126X64D_K610A4(cDriverConfig * config);
- virtual ~cDriverGU126X64D_K610A4();
//---------------------------------------------------------------------------
// from cDriver
@@ -54,7 +54,8 @@ public:
virtual int DeInit();
virtual void Clear();
- virtual void Set8Pixels(int x, int y, unsigned char data);
+ virtual void SetPixel (int x, int y, uint32_t data);
+ //virtual void Set8Pixels(int x, int y, unsigned char data);
virtual void Refresh(bool refreshAll = false);
virtual void SetBrightness(unsigned int percent);
@@ -68,7 +69,6 @@ public:
, FONT_FIX_BIG
};
- void setPixel (int x, int y);
int cmdReset ();
int cmdPower (bool fOn);
@@ -108,9 +108,6 @@ private:
//---------------------------------------------------------------------------
cParallelPort *port;
- cDriverConfig *config;
- cDriverConfig *oldConfig;
-
int myNumRows;
unsigned char **myDrawMem;
unsigned char **myVFDMem;
diff --git a/glcddrivers/gu140x32f.c b/glcddrivers/gu140x32f.c
index c3990a3..3cf568e 100644
--- a/glcddrivers/gu140x32f.c
+++ b/glcddrivers/gu140x32f.c
@@ -14,7 +14,9 @@
* This file is released under the GNU General Public License. Refer
* to the COPYING file distributed with this package.
*
- * (c) 2003 Andreas Brachold <vdr04 AT deltab.de>
+ * (c) 2003 Andreas Brachold <vdr04 AT deltab.de>
+ * (c) 2005-2010 Andreas Regel <andreas.regel AT powarman.de>
+ * (c) 2011 Wolfgang Astleitner <mrwastl AT users.sourceforge.net>
*/
#include <errno.h>
@@ -96,12 +98,10 @@ static const std::string kWiringWindows = "Windows";
cDriverGU140X32F::cDriverGU140X32F(cDriverConfig * config)
-: config(config),
+: cDriver(config),
m_pDrawMem(0),
m_pVFDMem(0)
{
- oldConfig = new cDriverConfig(*config);
-
port = new cParallelPort();
m_nRefreshCounter = 0;
@@ -110,7 +110,6 @@ cDriverGU140X32F::cDriverGU140X32F(cDriverConfig * config)
cDriverGU140X32F::~cDriverGU140X32F()
{
delete port;
- delete oldConfig;
}
int cDriverGU140X32F::Init()
@@ -326,7 +325,7 @@ void cDriverGU140X32F::Write(unsigned char nFlags, unsigned char bData, unsigned
nSleepDeInit();
}
-void cDriverGU140X32F::SetPixel(int x, int y)
+void cDriverGU140X32F::SetPixel(int x, int y, uint32_t data)
{
unsigned char c;
int n;
@@ -348,9 +347,13 @@ void cDriverGU140X32F::SetPixel(int x, int y)
n = x + ((y / 8) * width);
c = 0x80 >> (y % 8);
- m_pDrawMem[n] |= c;
+ if (data == GRAPHLCD_White)
+ m_pDrawMem[n] |= c;
+ else
+ m_pDrawMem[n] &= (0xFF ^ c);
}
+#if 0
void cDriverGU140X32F::Set8Pixels(int x, int y, unsigned char data)
{
int n;
@@ -361,9 +364,10 @@ void cDriverGU140X32F::Set8Pixels(int x, int y, unsigned char data)
for (n = 0; n < 8; ++n)
{
if (data & (0x80 >> n)) // if bit is set
- SetPixel(x + n, y);
+ SetPixel(x + n, y, GRAPHLCD_White);
}
}
+#endif
void cDriverGU140X32F::Refresh(bool refreshAll)
{
diff --git a/glcddrivers/gu140x32f.h b/glcddrivers/gu140x32f.h
index c0b87f2..2a94f03 100644
--- a/glcddrivers/gu140x32f.h
+++ b/glcddrivers/gu140x32f.h
@@ -14,7 +14,9 @@
* This file is released under the GNU General Public License. Refer
* to the COPYING file distributed with this package.
*
- * (c) 2003 Andreas Brachold <vdr04 AT deltab.de>
+ * (c) 2003 Andreas Brachold <vdr04 AT deltab.de>
+ * (c) 2005-2010 Andreas Regel <andreas.regel AT powarman.de>
+ * (c) 2011 Wolfgang Astleitner <mrwastl AT users.sourceforge.net>
*/
#ifndef _GLCDDRIVERS_GU140X32F_H_
@@ -37,9 +39,6 @@ class cDriverGU140X32F : public cDriver
cParallelPort * port;
- cDriverConfig * config;
- cDriverConfig * oldConfig;
-
int m_iSizeYb;
int m_nRefreshCounter;
unsigned char *m_pDrawMem; // the draw "memory"
@@ -51,7 +50,6 @@ class cDriverGU140X32F : public cDriver
protected:
void ClearVFDMem();
- void SetPixel(int x, int y);
void Write(unsigned char nFlags, unsigned char bData, unsigned int nMicroSecBusyTime);
public:
@@ -62,7 +60,8 @@ public:
virtual int DeInit();
virtual void Clear();
- virtual void Set8Pixels(int x, int y, unsigned char data);
+ virtual void SetPixel(int x, int y, uint32_t data);
+ //virtual void Set8Pixels(int x, int y, unsigned char data);
virtual void Refresh(bool refreshAll = false);
virtual void SetBrightness(unsigned int percent);
diff --git a/glcddrivers/gu256x64-372.c b/glcddrivers/gu256x64-372.c
index 049253e..1709568 100644
--- a/glcddrivers/gu256x64-372.c
+++ b/glcddrivers/gu256x64-372.c
@@ -4,6 +4,7 @@
* gu256x64-372.c - 8-bit driver module for Noritake GU256x64-372
* VFD displays. The VFD is operating in its 8-bit
* mode connected to a single PC parallel port.
+ * Should also work for GU256x64-355 and -352.
*
* based on:
* gu256x32f driver module for graphlcd
@@ -16,7 +17,8 @@
* This file is released under the GNU General Public License. Refer
* to the COPYING file distributed with this package.
*
- * (c) 2004 Andreas 'randy' Weinberger (randy AT smue.org)
+ * (c) 2004-2011 Andreas 'randy' Weinberger (randy AT smue.org)
+ * (c) 2011-2012 Wolfgang Astleitner <mrwastl AT users.sourceforge.net>
*/
#include <errno.h>
@@ -83,10 +85,8 @@ const unsigned char kWindowsCDLO = 0x08; //
cDriverGU256X64_372::cDriverGU256X64_372(cDriverConfig * config)
-: config(config)
+: cDriver(config)
{
- oldConfig = new cDriverConfig(*config);
-
port = new cParallelPort();
m_nRefreshCounter = 0;
@@ -94,7 +94,6 @@ cDriverGU256X64_372::cDriverGU256X64_372(cDriverConfig * config)
cDriverGU256X64_372::~cDriverGU256X64_372()
{
- delete oldConfig;
delete port;
}
@@ -322,12 +321,12 @@ void cDriverGU256X64_372::GU256X64Cmd(unsigned char data)
if (m_bSleepIsInit)
nSleepInit();
- port->WriteControl(CDHI | WRHI | RDLO);
+ port->WriteControl(CDHI | WRHI);
port->WriteData(data);
nSleep(100 + (100 * config->adjustTiming) - m_nTimingAdjustCmd);
- port->WriteControl(CDHI | WRLO | RDLO);
+ port->WriteControl(CDHI | WRLO);
nSleep(100 + (100 * config->adjustTiming) - m_nTimingAdjustCmd);
- port->WriteControl(CDHI | WRHI | RDLO);
+ port->WriteControl(CDHI | WRHI);
nSleep(100 + (100 * config->adjustTiming) - m_nTimingAdjustCmd);
}
@@ -336,16 +335,16 @@ void cDriverGU256X64_372::GU256X64Data(unsigned char data)
if (m_bSleepIsInit)
nSleepInit();
- port->WriteControl(CDLO | WRHI | RDLO);
+ port->WriteControl(CDLO | WRHI);
port->WriteData(data);
nSleep(100 + (100 * config->adjustTiming) - m_nTimingAdjustCmd);
- port->WriteControl(CDLO | WRLO | RDLO);
+ port->WriteControl(CDLO | WRLO);
nSleep(100 + (100 * config->adjustTiming) - m_nTimingAdjustCmd);
- port->WriteControl(CDLO | WRHI | RDLO);
+ port->WriteControl(CDLO | WRHI);
nSleep(100 + (100 * config->adjustTiming) - m_nTimingAdjustCmd);
}
-void cDriverGU256X64_372::SetPixel(int x, int y)
+void cDriverGU256X64_372::SetPixel(int x, int y, uint32_t data)
{
unsigned char c;
@@ -365,9 +364,13 @@ void cDriverGU256X64_372::SetPixel(int x, int y)
c = 0x80 >> (y % 8);
- m_pDrawMem[x][y/8] = m_pDrawMem[x][y/8] | c;
+ if (data == GRAPHLCD_White)
+ m_pDrawMem[x][y/8] |= c;
+ else
+ m_pDrawMem[x][y/8] &= ( 0xFF ^ c );
}
+#if 0
void cDriverGU256X64_372::Set8Pixels(int x, int y, unsigned char data)
{
int n;
@@ -378,9 +381,10 @@ void cDriverGU256X64_372::Set8Pixels(int x, int y, unsigned char data)
for (n = 0; n < 8; ++n)
{
if (data & (0x80 >> n)) // if bit is set
- SetPixel(x + n, y);
+ SetPixel(x + n, y, GRAPHLCD_White);
}
}
+#endif
void cDriverGU256X64_372::Refresh(bool refreshAll)
{
diff --git a/glcddrivers/gu256x64-372.h b/glcddrivers/gu256x64-372.h
index 7d92561..a0d511f 100644
--- a/glcddrivers/gu256x64-372.h
+++ b/glcddrivers/gu256x64-372.h
@@ -16,7 +16,8 @@
* This file is released under the GNU General Public License. Refer
* to the COPYING file distributed with this package.
*
- * (c) 2004 Andreas 'randy' Weinberger (randy AT smue.org)
+ * (c) 2004-2011 Andreas 'randy' Weinberger (randy AT smue.org)
+ * (c) 2011 Wolfgang Astleitner <mrwastl AT users.sourceforge.net>
*/
#ifndef _GLCDDRIVERS_GU256X64_372_H_
@@ -34,9 +35,6 @@ class cDriverGU256X64_372 : public cDriver
{
cParallelPort * port;
- cDriverConfig * config;
- cDriverConfig * oldConfig;
-
int m_iSizeYb;
int m_nRefreshCounter;
@@ -57,7 +55,6 @@ class cDriverGU256X64_372 : public cDriver
protected:
void ClearVFDMem();
- void SetPixel(int x, int y);
void GU256X64Cmd(unsigned char data);
void GU256X64Data(unsigned char data);
@@ -69,7 +66,8 @@ public:
virtual int DeInit();
virtual void Clear();
- virtual void Set8Pixels(int x, int y, unsigned char data);
+ virtual void SetPixel(int x, int y, uint32_t data);
+ //virtual void Set8Pixels(int x, int y, unsigned char data);
virtual void Refresh(bool refreshAll = false);
virtual void SetBrightness(unsigned int percent);
diff --git a/glcddrivers/gu256x64-3900.c b/glcddrivers/gu256x64-3900.c
index d9279dc..8a2dafc 100644
--- a/glcddrivers/gu256x64-3900.c
+++ b/glcddrivers/gu256x64-3900.c
@@ -20,7 +20,9 @@
* This file is released under the GNU General Public License. Refer
* to the COPYING file distributed with this package.
*
- * (c) 2004 Ralf Mueller (ralf AT bj-ig.de)
+ * (c) 2004 Ralf Mueller (ralf AT bj-ig.de)
+ * (c) 2005-2010 Andreas Regel <andreas.regel AT powarman.de>
+ * (c) 2011-2012 Wolfgang Astleitner <mrwastl AT users.sourceforge.net>
*/
#include <errno.h>
@@ -102,19 +104,12 @@ static const int kInterfaceSerial = 1; // serial mode
cDriverGU256X64_3900::cDriverGU256X64_3900(cDriverConfig * config)
-: config(config)
+: cDriver(config)
{
- oldConfig = new cDriverConfig(*config);
-
portFd = -1;
m_nRefreshCounter = 0;
}
-cDriverGU256X64_3900::~cDriverGU256X64_3900()
-{
- delete oldConfig;
-}
-
int cDriverGU256X64_3900::Init()
{
int x;
@@ -262,7 +257,7 @@ int cDriverGU256X64_3900::DeInit()
if (portFd >= 0)
{
close(portFd);
- portFd =- 1;
+ portFd = -1;
}
}
if (port)
@@ -503,7 +498,7 @@ void cDriverGU256X64_3900::Write(unsigned char data)
WriteParallel(data);
}
-void cDriverGU256X64_3900::SetPixel(int x, int y)
+void cDriverGU256X64_3900::SetPixel(int x, int y, uint32_t data)
{
unsigned char c;
@@ -523,9 +518,13 @@ void cDriverGU256X64_3900::SetPixel(int x, int y)
c = 0x80 >> (y % 8);
- m_pDrawMem[x][y/8] = m_pDrawMem[x][y/8] | c;
+ if (data == GRAPHLCD_White)
+ m_pDrawMem[x][y/8] |= c;
+ else
+ m_pDrawMem[x][y/8] &= ( 0xFF ^ c );
}
+#if 0
void cDriverGU256X64_3900::Set8Pixels(int x, int y, unsigned char data)
{
int n;
@@ -536,9 +535,10 @@ void cDriverGU256X64_3900::Set8Pixels(int x, int y, unsigned char data)
for (n = 0; n < 8; ++n)
{
if (data & (0x80 >> n)) // if bit is set
- SetPixel(x + n, y);
+ SetPixel(x + n, y, GRAPHLCD_White);
}
}
+#endif
void cDriverGU256X64_3900::Refresh(bool refreshAll)
{
diff --git a/glcddrivers/gu256x64-3900.h b/glcddrivers/gu256x64-3900.h
index 2201417..9703a04 100644
--- a/glcddrivers/gu256x64-3900.h
+++ b/glcddrivers/gu256x64-3900.h
@@ -20,7 +20,9 @@
* This file is released under the GNU General Public License. Refer
* to the COPYING file distributed with this package.
*
- * (c) 2004 Ralf Mueller (ralf AT bj-ig.de)
+ * (c) 2004 Ralf Mueller (ralf AT bj-ig.de)
+ * (c) 2005-2010 Andreas Regel <andreas.regel AT powarman.de>
+ * (c) 2011 Wolfgang Astleitner <mrwastl AT users.sourceforge.net>
*/
#ifndef _GLCDDRIVERS_GU256X64_3900_H_
@@ -39,9 +41,6 @@ class cDriverGU256X64_3900 : public cDriver
cParallelPort * port;
int portFd;
- cDriverConfig * config;
- cDriverConfig * oldConfig;
-
int m_iSizeYb;
int m_nRefreshCounter;
int interface;
@@ -59,7 +58,6 @@ class cDriverGU256X64_3900 : public cDriver
protected:
void ClearVFDMem();
- void SetPixel(int x, int y);
int InitSerialPort();
int InitParallelPort();
void InitNormalDisplay();
@@ -70,13 +68,13 @@ protected:
void Write(unsigned char data);
public:
cDriverGU256X64_3900(cDriverConfig * config);
- virtual ~cDriverGU256X64_3900();
virtual int Init();
virtual int DeInit();
virtual void Clear();
- virtual void Set8Pixels(int x, int y, unsigned char data);
+ virtual void SetPixel(int x, int y, uint32_t data);
+ //virtual void Set8Pixels(int x, int y, unsigned char data);
virtual void Refresh(bool refreshAll = false);
virtual void SetBrightness(unsigned int percent);
diff --git a/glcddrivers/hd61830.c b/glcddrivers/hd61830.c
index 7f0bd53..25f39ff 100644
--- a/glcddrivers/hd61830.c
+++ b/glcddrivers/hd61830.c
@@ -7,6 +7,8 @@
* to the COPYING file distributed with this package.
*
* (c) 2001-2004 Carsten Siebholz <c.siebholz AT t-online.de>
+ * (c) 2005-2010 Andreas Regel <andreas.regel AT powarman.de>
+ * (c) 2011 Wolfgang Astleitner <mrwastl AT users.sourceforge.net>
*/
#include <syslog.h>
@@ -55,10 +57,8 @@ namespace GLCD
cDriverHD61830::cDriverHD61830(cDriverConfig * config)
-: config(config)
+: cDriver(config)
{
- oldConfig = new cDriverConfig(*config);
-
port = new cParallelPort();
useSleepInit = false;
@@ -70,7 +70,6 @@ cDriverHD61830::cDriverHD61830(cDriverConfig * config)
cDriverHD61830::~cDriverHD61830()
{
delete port;
- delete oldConfig;
}
int cDriverHD61830::Init()
@@ -301,6 +300,29 @@ void cDriverHD61830::Clear()
memset(newLCD[x], 0, height);
}
+
+void cDriverHD61830::SetPixel(int x, int y, uint32_t data)
+{
+ if (x >= width || y >= height)
+ return;
+
+ int pos = x % 8;
+ if (config->upsideDown)
+ {
+ x = width - 1 - x;
+ y = height - 1 - y;
+ //} else {
+ pos = 7 - pos; // reverse bit position
+ }
+
+ if (data == GRAPHLCD_White)
+ newLCD[x / 8][y] |= ( 1 << pos );
+ else
+ newLCD[x / 8][y] &= ( 0xFF ^ ( 1 << pos ) );
+}
+
+
+#if 0
void cDriverHD61830::Set8Pixels(int x, int y, unsigned char data)
{
if (x >= width || y >= height)
@@ -319,6 +341,7 @@ void cDriverHD61830::Set8Pixels(int x, int y, unsigned char data)
newLCD[x / 8][y] = newLCD[x / 8][y] | data;
}
}
+#endif
void cDriverHD61830::Refresh(bool refreshAll)
{
diff --git a/glcddrivers/hd61830.h b/glcddrivers/hd61830.h
index 50f3b26..4d70446 100644
--- a/glcddrivers/hd61830.h
+++ b/glcddrivers/hd61830.h
@@ -7,6 +7,8 @@
* to the COPYING file distributed with this package.
*
* (c) 2001-2004 Carsten Siebholz <c.siebholz AT t-online.de>
+ * (c) 2005-2010 Andreas Regel <andreas.regel AT powarman.de>
+ * (c) 2011 Wolfgang Astleitner <mrwastl AT users.sourceforge.net>
*/
#ifndef _GLCDDRIVERS_HD61830_H_
@@ -27,8 +29,6 @@ private:
unsigned char ** newLCD; // wanted state
unsigned char ** oldLCD; // current state
- cDriverConfig * config;
- cDriverConfig * oldConfig;
int refreshCounter;
long timeForPortCmdInNs;
bool useSleepInit;
@@ -45,7 +45,8 @@ public:
virtual int DeInit();
virtual void Clear();
- virtual void Set8Pixels(int x, int y, unsigned char data);
+ virtual void SetPixel(int x, int y, uint32_t data);
+ //virtual void Set8Pixels(int x, int y, unsigned char data);
virtual void Refresh(bool refreshAll = false);
};
diff --git a/glcddrivers/ili9341.c b/glcddrivers/ili9341.c
new file mode 100644
index 0000000..54627d4
--- /dev/null
+++ b/glcddrivers/ili9341.c
@@ -0,0 +1,395 @@
+/*
+ * GraphLCD driver library
+ *
+ * ili9341.c - ILI9341 TFT driver class
+ *
+ * This file is released under the GNU General Public License. Refer
+ * to the COPYING file distributed with this package.
+ *
+ * (c) 2015 Andreas Regel <andreas.regel AT powarman.de>
+ */
+
+#include <stdint.h>
+#include <syslog.h>
+#include <unistd.h>
+#include <cstring>
+
+#include <wiringPi.h>
+#include <wiringPiSPI.h>
+
+#include "common.h"
+#include "config.h"
+#include "ili9341.h"
+
+
+namespace GLCD
+{
+
+const int kLcdWidth = 320;
+const int kLcdHeight = 240;
+
+const int kSpiBus = 0;
+
+const int kGpioPwm = 13;
+const int kGpioReset = 23;
+const int kGpioDC = 24;
+
+const uint8_t kCmdNop = 0x00;
+const uint8_t kCmdSleepOut = 0x11;
+const uint8_t kCmdGammaSet = 0x26;
+const uint8_t kCmdDisplayOn = 0x29;
+const uint8_t kCmdColumnAddressSet = 0x2A;
+const uint8_t kCmdPageAddressSet = 0x2B;
+const uint8_t kCmdMemoryWrite = 0x2C;
+const uint8_t kCmdMemoryAccessControl = 0x36;
+const uint8_t kCmdPixelFormatSet = 0x3A;
+const uint8_t kCmdFrameRateControl = 0xB1;
+const uint8_t kCmdDisplayFunctionControl = 0xB6;
+
+const uint8_t kCmdPowerControl1 = 0xC0;
+const uint8_t kCmdPowerControl2 = 0xC1;
+const uint8_t kCmdVcomControl1 = 0xC5;
+const uint8_t kCmdVcomControl2 = 0xC7;
+const uint8_t kCmdPositiveGammaControl = 0xE0;
+const uint8_t kCmdNegativeGammaControl = 0xE1;
+
+const uint8_t kCmdPowerControlA = 0xCB;
+const uint8_t kCmdPowerControlB = 0xCF;
+const uint8_t kCmdDriverTimingControlA = 0xE8;
+const uint8_t kCmdDriverTimingControlB = 0xEA;
+const uint8_t kCmdPowerOnSequenceControl = 0xED;
+const uint8_t kCmdUnknownEF = 0xEF;
+const uint8_t kCmdEnable3G = 0xF2;
+const uint8_t kCmdPumpRatioControl = 0xF7;
+
+
+cDriverILI9341::cDriverILI9341(cDriverConfig * config)
+: cDriver(config)
+{
+ refreshCounter = 0;
+
+ wiringPiSetupGpio();
+}
+
+cDriverILI9341::~cDriverILI9341()
+{
+}
+
+int cDriverILI9341::Init()
+{
+ width = config->width;
+ if (width <= 0)
+ width = kLcdWidth;
+ height = config->height;
+ if (height <= 0)
+ height = kLcdHeight;
+
+ for (unsigned int i = 0; i < config->options.size(); i++)
+ {
+ if (config->options[i].name == "")
+ {
+ }
+ }
+
+ // setup lcd array (wanted state)
+ newLCD = new uint32_t[width * height];
+ if (newLCD)
+ {
+ memset(newLCD, 0, width * height * sizeof(uint32_t));
+ }
+ // setup lcd array (current state)
+ oldLCD = new uint32_t[width * height];
+ if (oldLCD)
+ {
+ memset(oldLCD, 0, width * height * sizeof(uint32_t));
+ }
+
+ if (config->device == "")
+ {
+ return -1;
+ }
+
+ pinMode(kGpioReset, OUTPUT);
+ pinMode(kGpioDC, OUTPUT);
+
+ pinMode(kGpioPwm, PWM_OUTPUT);
+ SetBrightness(config->brightness);
+
+ digitalWrite(kGpioReset, HIGH);
+ digitalWrite(kGpioDC, LOW);
+
+ wiringPiSPISetup(kSpiBus, 64000000);
+
+ /* reset display */
+ Reset();
+
+ WriteCommand(kCmdUnknownEF);
+ WriteData(0x03);
+ WriteData(0x80);
+ WriteData(0x02);
+ WriteCommand(kCmdPowerControlB);
+ WriteData(0x00);
+ WriteData(0xC1);
+ WriteData(0x30);
+ WriteCommand(kCmdPowerOnSequenceControl);
+ WriteData(0x64);
+ WriteData(0x03);
+ WriteData(0x12);
+ WriteData(0x81);
+ WriteCommand(kCmdDriverTimingControlA);
+ WriteData(0x85);
+ WriteData(0x00);
+ WriteData(0x78);
+ WriteCommand(kCmdPowerControlA);
+ WriteData(0x39);
+ WriteData(0x2C);
+ WriteData(0x00);
+ WriteData(0x34);
+ WriteData(0x02);
+ WriteCommand(kCmdPumpRatioControl);
+ WriteData(0x20);
+ WriteCommand(kCmdDriverTimingControlB);
+ WriteData(0x00);
+ WriteData(0x00);
+
+ WriteCommand(kCmdPowerControl1);
+ WriteData(0x23);
+ WriteCommand(kCmdPowerControl2);
+ WriteData(0x10);
+ WriteCommand(kCmdVcomControl1);
+ WriteData(0x3e);
+ WriteData(0x28);
+ WriteCommand(kCmdVcomControl2);
+ WriteData(0x86);
+ WriteCommand(kCmdMemoryAccessControl);
+ WriteData(0x48);
+ WriteCommand(kCmdPixelFormatSet);
+ WriteData(0x55);
+ WriteCommand(kCmdFrameRateControl);
+ WriteData(0x00);
+ WriteData(0x18);
+ WriteCommand(kCmdDisplayFunctionControl);
+ WriteData(0x08);
+ WriteData(0x82);
+ WriteData(0x27);
+ WriteCommand(kCmdEnable3G);
+ WriteData(0x00);
+ WriteCommand(kCmdGammaSet);
+ WriteData(0x01);
+ WriteCommand(kCmdPositiveGammaControl);
+ WriteData(0x0F);
+ WriteData(0x31);
+ WriteData(0x2B);
+ WriteData(0x0C);
+ WriteData(0x0E);
+ WriteData(0x08);
+ WriteData(0x4E);
+ WriteData(0xF1);
+ WriteData(0x37);
+ WriteData(0x07);
+ WriteData(0x10);
+ WriteData(0x03);
+ WriteData(0x0E);
+ WriteData(0x09);
+ WriteData(0x00);
+ WriteCommand(kCmdNegativeGammaControl);
+ WriteData(0x00);
+ WriteData(0x0E);
+ WriteData(0x14);
+ WriteData(0x03);
+ WriteData(0x11);
+ WriteData(0x07);
+ WriteData(0x31);
+ WriteData(0xC1);
+ WriteData(0x48);
+ WriteData(0x08);
+ WriteData(0x0F);
+ WriteData(0x0C);
+ WriteData(0x31);
+ WriteData(0x36);
+ WriteData(0x0F);
+ WriteCommand(kCmdSleepOut);
+ usleep(120000);
+ WriteCommand(kCmdDisplayOn);
+
+ *oldConfig = *config;
+
+ // clear display
+ Clear();
+
+ syslog(LOG_INFO, "%s: ILI9341 initialized.\n", config->name.c_str());
+ return 0;
+}
+
+int cDriverILI9341::DeInit()
+{
+ // free lcd array (wanted state)
+ if (newLCD)
+ {
+ delete[] newLCD;
+ }
+ // free lcd array (current state)
+ if (oldLCD)
+ {
+ delete[] oldLCD;
+ }
+
+ return 0;
+}
+
+int cDriverILI9341::CheckSetup()
+{
+ if (config->device != oldConfig->device ||
+ config->width != oldConfig->width ||
+ config->height != oldConfig->height)
+ {
+ DeInit();
+ Init();
+ return 0;
+ }
+
+ if (config->upsideDown != oldConfig->upsideDown)
+ {
+ oldConfig->upsideDown = config->upsideDown;
+ return 1;
+ }
+ return 0;
+}
+
+void cDriverILI9341::Clear()
+{
+ memset(newLCD, 0, width * height * sizeof(uint32_t));
+}
+
+
+void cDriverILI9341::SetPixel(int x, int y, uint32_t data)
+{
+ if (x >= width || y >= height)
+ return;
+
+ if (config->upsideDown)
+ {
+ x = width - 1 - x;
+ y = height - 1 - y;
+ }
+
+ newLCD[y * width + x] = data;
+}
+
+
+void cDriverILI9341::Refresh(bool refreshAll)
+{
+ int y;
+
+ if (CheckSetup() == 1)
+ refreshAll = true;
+
+ if (config->refreshDisplay > 0)
+ {
+ refreshCounter = (refreshCounter + 1) % config->refreshDisplay;
+ if (!refreshAll && !refreshCounter)
+ refreshAll = true;
+ }
+
+ refreshAll = true;
+ if (refreshAll)
+ {
+ SetWindow(0, 0, height - 1, width - 1);
+ WriteCommand(kCmdMemoryWrite);
+ for (y = 0; y < width; y++)
+ {
+ uint8_t line[height * 2];
+ uint32_t * pixel = &newLCD[width - 1 - y];
+
+ for (int x = 0; x < (height * 2); x += 2)
+ {
+ line[x] = ((*pixel & 0x00F80000) >> 16)
+ | ((*pixel & 0x0000E000) >> 13);
+ line[x + 1] = ((*pixel & 0x00001C00) >> 5)
+ | ((*pixel & 0x000000F8) >> 3);
+ pixel += width;
+ }
+ WriteData((uint8_t *) line, height * 2);
+ }
+ memcpy(oldLCD, newLCD, width * height * sizeof(uint32_t));
+ // and reset RefreshCounter
+ refreshCounter = 0;
+ }
+ else
+ {
+ // draw only the changed bytes
+ }
+}
+
+void cDriverILI9341::SetBrightness(unsigned int percent)
+{
+ uint32_t value;
+
+ if (percent == 0)
+ value = 0;
+ else if (percent <= 10)
+ value = 4;
+ else if (percent <= 20)
+ value = 8;
+ else if (percent <= 30)
+ value = 16;
+ else if (percent <= 40)
+ value = 32;
+ else if (percent <= 50)
+ value = 64;
+ else if (percent <= 60)
+ value = 128;
+ else if (percent <= 70)
+ value = 192;
+ else if (percent <= 80)
+ value = 320;
+ else if (percent <= 90)
+ value = 512;
+ else
+ value = 1023;
+
+ pwmWrite(kGpioPwm, value);
+}
+
+void cDriverILI9341::Reset()
+{
+ digitalWrite(kGpioReset, HIGH);
+ usleep(10000);
+ digitalWrite(kGpioReset, LOW);
+ usleep(20000);
+ digitalWrite(kGpioReset, HIGH);
+ usleep(150000);
+}
+
+void cDriverILI9341::SetWindow(uint16_t x0, uint16_t y0, uint16_t x1, uint16_t y1)
+{
+ WriteCommand(kCmdColumnAddressSet);
+ WriteData(x0 >> 8);
+ WriteData(x0);
+ WriteData(x1 >> 8);
+ WriteData(x1);
+ WriteCommand(kCmdPageAddressSet);
+ WriteData(y0 >> 8);
+ WriteData(y0);
+ WriteData(y1 >> 8);
+ WriteData(y1);
+}
+
+void cDriverILI9341::WriteCommand(uint8_t command)
+{
+ digitalWrite(kGpioDC, LOW);
+ wiringPiSPIDataRW(kSpiBus, &command, 1);
+ digitalWrite(kGpioDC, HIGH);
+}
+
+void cDriverILI9341::WriteData(uint8_t data)
+{
+ wiringPiSPIDataRW(kSpiBus, &data, 1);
+}
+
+void cDriverILI9341::WriteData(uint8_t * buffer, uint32_t length)
+{
+ wiringPiSPIDataRW(kSpiBus, buffer, length);
+}
+
+} // end of namespace
diff --git a/glcddrivers/ili9341.h b/glcddrivers/ili9341.h
new file mode 100644
index 0000000..d729971
--- /dev/null
+++ b/glcddrivers/ili9341.h
@@ -0,0 +1,53 @@
+/*
+ * GraphLCD driver library
+ *
+ * ili9341.h - ILI9341 OLED driver class
+ *
+ * This file is released under the GNU General Public License. Refer
+ * to the COPYING file distributed with this package.
+ *
+ * (c) 2015 Andreas Regel <andreas.regel AT powarman.de>
+ */
+
+#ifndef _GLCDDRIVERS_ILI9341_H_
+#define _GLCDDRIVERS_ILI9341_H_
+
+#include "driver.h"
+
+namespace GLCD
+{
+
+class cDriverConfig;
+
+class cDriverILI9341 : public cDriver
+{
+private:
+ uint32_t * newLCD; // wanted state
+ uint32_t * oldLCD; // current state
+ int refreshCounter;
+
+ int CheckSetup();
+
+ void Reset();
+ void SetWindow(uint16_t x0, uint16_t x1, uint16_t y0, uint16_t y1);
+ void WriteCommand(uint8_t command);
+ void WriteData(uint8_t data);
+ void WriteData(uint8_t * buffer, uint32_t length);
+
+public:
+ cDriverILI9341(cDriverConfig * config);
+ virtual ~cDriverILI9341();
+
+ virtual int Init();
+ virtual int DeInit();
+
+ virtual void Clear();
+ virtual void SetPixel(int x, int y, uint32_t data);
+ //virtual void Set8Pixels(int x, int y, unsigned char data);
+ virtual void Refresh(bool refreshAll = false);
+ virtual void SetBrightness(unsigned int percent);
+};
+
+} // end of namespace
+
+#endif
diff --git a/glcddrivers/image.c b/glcddrivers/image.c
index a07ce54..a3d123f 100644
--- a/glcddrivers/image.c
+++ b/glcddrivers/image.c
@@ -7,7 +7,9 @@
* This file is released under the GNU General Public License. Refer
* to the COPYING file distributed with this package.
*
- * (c) 2004 Andreas Regel <andreas.regel AT powarman.de>
+ * (c) 2004-2010 Andreas Regel <andreas.regel AT powarman.de>
+ * (c) 2010-2011 Wolfgang Astleitner <mrwastl AT users sourceforge net>
+ Andreas 'randy' Weinberger
*/
#include <stdio.h>
@@ -23,15 +25,13 @@ namespace GLCD
{
cDriverImage::cDriverImage(cDriverConfig * config)
-: config(config)
+: cDriver(config)
{
- oldConfig = new cDriverConfig(*config);
}
cDriverImage::~cDriverImage()
{
DeInit();
- delete oldConfig;
}
int cDriverImage::Init()
@@ -51,12 +51,13 @@ int cDriverImage::Init()
}
}
- newLCD = new unsigned char[lineSize * height];
+// newLCD = new unsigned char[lineSize * height];
+ newLCD = new uint32_t[width * height];
if (newLCD)
- memset(newLCD, 0, lineSize * height);
- oldLCD = new unsigned char[lineSize * height];
+ memset(newLCD, 0, width * height);
+ oldLCD = new uint32_t[width * height];
if (oldLCD)
- memset(oldLCD, 0, lineSize * height);
+ memset(oldLCD, 0, width * height);
counter = 0;
@@ -109,6 +110,7 @@ void cDriverImage::Clear()
memset(newLCD, 0, lineSize * height);
}
+#if 0
void cDriverImage::Set8Pixels(int x, int y, unsigned char data)
{
if (x >= width || y >= height)
@@ -127,6 +129,28 @@ void cDriverImage::Set8Pixels(int x, int y, unsigned char data)
newLCD[lineSize * y + x / 8] |= ReverseBits(data);
}
}
+#endif
+
+void cDriverImage::SetPixel(int x, int y, uint32_t data)
+{
+ if (x >= width || y >= height)
+ return;
+
+ int cols = (width + 7 ) >> 3;
+ int pos = x % 8;
+ if (config->upsideDown)
+ {
+ x = width - 1 - x;
+ y = height - 1 - y;
+ } else {
+ pos = 7 - pos; // reverse bit position
+ }
+
+ if (data == GRAPHLCD_White)
+ newLCD[y * cols + (x >> 3)] |= ( 1 << pos );
+ else
+ newLCD[y * cols + (x >> 3)] &= ( 0xFF ^ ( 1 << pos) );
+}
void cDriverImage::Refresh(bool refreshAll)
{
diff --git a/glcddrivers/image.h b/glcddrivers/image.h
index 3e39e3f..2d3cb71 100644
--- a/glcddrivers/image.h
+++ b/glcddrivers/image.h
@@ -7,7 +7,9 @@
* This file is released under the GNU General Public License. Refer
* to the COPYING file distributed with this package.
*
- * (c) 2004 Andreas Regel <andreas.regel AT powarman.de>
+ * (c) 2004-2010 Andreas Regel <andreas.regel AT powarman.de>
+ * (c) 2010-2011 Wolfgang Astleitner <mrwastl AT users sourceforge net>
+ Andreas 'randy' Weinberger
*/
#ifndef _GLCDDRIVERS_IMAGE_H_
@@ -24,10 +26,8 @@ class cDriverConfig;
class cDriverImage : public cDriver
{
private:
- unsigned char * newLCD;
- unsigned char * oldLCD;
- cDriverConfig * config;
- cDriverConfig * oldConfig;
+ uint32_t * newLCD;
+ uint32_t * oldLCD;
int lineSize;
int counter;
@@ -41,7 +41,8 @@ public:
virtual int DeInit();
virtual void Clear();
- virtual void Set8Pixels(int x, int y, unsigned char data);
+ virtual void SetPixel(int x, int y, uint32_t data);
+ //virtual void Set8Pixels(int x, int y, unsigned char data);
virtual void Refresh(bool refreshAll = false);
};
diff --git a/glcddrivers/ks0108.c b/glcddrivers/ks0108.c
index de9c505..042f286 100644
--- a/glcddrivers/ks0108.c
+++ b/glcddrivers/ks0108.c
@@ -6,7 +6,8 @@
* This file is released under the GNU General Public License. Refer
* to the COPYING file distributed with this package.
*
- * (c) 2003 Andreas 'randy' Weinberger <vdr AT smue.org>
+ * (c) 2003-2011 Andreas 'randy' Weinberger <vdr AT smue.org>
+ * (c) 2011 Wolfgang Astleitner <mrwastl AT users.sourceforge.net>
*/
#include <syslog.h>
@@ -41,10 +42,8 @@ const unsigned char kCS2LO = 0x04;
cDriverKS0108::cDriverKS0108(cDriverConfig * config)
-: config(config)
+: cDriver(config)
{
- oldConfig = new cDriverConfig(*config);
-
port = new cParallelPort();
refreshCounter = 0;
@@ -55,7 +54,6 @@ cDriverKS0108::cDriverKS0108(cDriverConfig * config)
cDriverKS0108::~cDriverKS0108()
{
delete port;
- delete oldConfig;
}
int cDriverKS0108::Init()
@@ -420,6 +418,29 @@ void cDriverKS0108::Clear()
memset(LCD[x], 0, height);
}
+
+void cDriverKS0108::SetPixel(int x, int y, uint32_t data)
+{
+ if (x >= width || y >= height)
+ return;
+
+ int pos = x % 8;
+ if (config->upsideDown)
+ {
+ x = width - 1 - x;
+ y = height - 1 - y;
+ } else {
+ pos = 7 - pos; // reverse bit position
+ }
+
+ if (data == GRAPHLCD_White)
+ LCD[x / 8][y] |= (1 << pos);
+ else
+ LCD[x / 8][y] &= ( 0xFF ^ (1 << pos) );
+}
+
+
+#if 0
void cDriverKS0108::Set8Pixels(int x, int y, unsigned char data)
{
if (x >= width || y >= height)
@@ -438,6 +459,7 @@ void cDriverKS0108::Set8Pixels(int x, int y, unsigned char data)
LCD[x / 8][y] = LCD[x / 8][y] | ReverseBits(data);
}
}
+#endif
void cDriverKS0108::Refresh(bool refreshAll)
{
diff --git a/glcddrivers/ks0108.h b/glcddrivers/ks0108.h
index 66ac425..d9016c0 100644
--- a/glcddrivers/ks0108.h
+++ b/glcddrivers/ks0108.h
@@ -6,7 +6,8 @@
* This file is released under the GNU General Public License. Refer
* to the COPYING file distributed with this package.
*
- * (c) 2003 Andreas 'randy' Weinberger <vdr AT smue.org>
+ * (c) 2003-2011 Andreas 'randy' Weinberger <vdr AT smue.org>
+ * (c) 2011-2013 Wolfgang Astleitner <mrwastl AT users.sourceforge.net>
*/
#ifndef _GLCDDRIVERS_KS0108_H_
@@ -30,8 +31,6 @@ private:
int refreshCounter;
long timeForPortCmdInNs;
long timeForLCDInNs;
- cDriverConfig * config;
- cDriverConfig * oldConfig;
bool useSleepInit;
int CheckSetup();
@@ -49,10 +48,6 @@ private:
int CELO;
int CDHI;
int CDLO;
- int CS1HI;
- int CS1LO;
- int CS2HI;
- int CS2LO;
int CS1;
int CS2;
@@ -69,7 +64,8 @@ public:
virtual int DeInit();
virtual void Clear();
- virtual void Set8Pixels(int x, int y, unsigned char data);
+ virtual void SetPixel(int x, int y, uint32_t data);
+ //virtual void Set8Pixels(int x, int y, unsigned char data);
virtual void Refresh(bool refreshAll = false);
};
diff --git a/glcddrivers/network.c b/glcddrivers/network.c
index 485f8ea..5000fda 100644
--- a/glcddrivers/network.c
+++ b/glcddrivers/network.c
@@ -7,7 +7,8 @@
* This file is released under the GNU General Public License. Refer
* to the COPYING file distributed with this package.
*
- * (c) 2004 Andreas Regel <andreas.regel AT powarman.de>
+ * (c) 2004 Andreas Regel <andreas.regel AT powarman.de>
+ * (c) 2011 Wolfgang Astleitner <mrwastl AT users.sourceforge.net>
*/
#include <stdio.h>
@@ -29,19 +30,13 @@ namespace GLCD
{
cDriverNetwork::cDriverNetwork(cDriverConfig * config)
-: config(config)
+: cDriver(config)
{
- oldConfig = new cDriverConfig(*config);
childTid = 0;
running = false;
clientConnected = false;
}
-cDriverNetwork::~cDriverNetwork()
-{
- delete oldConfig;
-}
-
int cDriverNetwork::Init()
{
width = config->width;
@@ -122,6 +117,29 @@ void cDriverNetwork::Clear()
memset(newLCD, 0, lineSize * height);
}
+
+void cDriverNetwork::SetPixel(int x, int y, uint32_t data)
+{
+ if (x >= width || y >= height)
+ return;
+
+ int pos = x % 8;
+ if (config->upsideDown)
+ {
+ x = width - 1 - x;
+ y = height - 1 - y;
+ } else {
+ pos = 7 - pos; // reverse bit position
+ }
+
+ if (data == GRAPHLCD_White)
+ newLCD[lineSize * y + x / 8] |= (1 << pos);
+ else
+ newLCD[lineSize * y + x / 8] &= ( 0xFF ^ (1 << pos) );
+}
+
+
+#if 0
void cDriverNetwork::Set8Pixels(int x, int y, unsigned char data)
{
if (x >= width || y >= height)
@@ -140,6 +158,7 @@ void cDriverNetwork::Set8Pixels(int x, int y, unsigned char data)
newLCD[lineSize * y + x / 8] |= ReverseBits(data);
}
}
+#endif
void cDriverNetwork::Refresh(bool refreshAll)
{
diff --git a/glcddrivers/network.h b/glcddrivers/network.h
index 4664f4c..9251c50 100644
--- a/glcddrivers/network.h
+++ b/glcddrivers/network.h
@@ -7,7 +7,8 @@
* This file is released under the GNU General Public License. Refer
* to the COPYING file distributed with this package.
*
- * (c) 2004 Andreas Regel <andreas.regel AT powarman.de>
+ * (c) 2004 Andreas Regel <andreas.regel AT powarman.de>
+ * (c) 2011 Wolfgang Astleitner <mrwastl AT users.sourceforge.net>
*/
#ifndef _GLCDDRIVERS_NETWORK_H_
@@ -28,8 +29,6 @@ class cDriverNetwork : public cDriver
private:
unsigned char * newLCD;
unsigned char * oldLCD;
- cDriverConfig * config;
- cDriverConfig * oldConfig;
int lineSize;
bool running;
pthread_t childTid;
@@ -41,13 +40,13 @@ private:
public:
cDriverNetwork(cDriverConfig * config);
- virtual ~cDriverNetwork();
virtual int Init();
virtual int DeInit();
virtual void Clear();
- virtual void Set8Pixels(int x, int y, unsigned char data);
+ virtual void SetPixel(int x, int y, uint32_t data);
+ //virtual void Set8Pixels(int x, int y, unsigned char data);
virtual void Refresh(bool refreshAll = false);
};
diff --git a/glcddrivers/noritake800.c b/glcddrivers/noritake800.c
index 89ae898..05eed6e 100644
--- a/glcddrivers/noritake800.c
+++ b/glcddrivers/noritake800.c
@@ -27,7 +27,9 @@
* This file is released under the GNU General Public License. Refer
* to the COPYING file distributed with this package.
*
- * (c) 2004 - 2011 Lucian Muresan <lucianm AT users.sourceforge.net>
+ * (c) 2004-2011 Lucian Muresan <lucianm AT users.sourceforge.net>
+ * (c) 2005-2010 Andreas Regel <andreas.regel AT powarman.de>
+ * (c) 2011 Wolfgang Astleitner <mrwastl AT users.sourceforge.net>
*/
#include <errno.h>
@@ -89,7 +91,7 @@ static const std::string kWiringMZ = "MZ";
#define SETPOSITION 0xff
-cDriverNoritake800::cDriverNoritake800(cDriverConfig * config)
+cDriverNoritake800::cDriverNoritake800(cDriverConfig * config) : cDriver(config)
{
int x = 0;
m_bGraphScreen0_On = true;
@@ -97,18 +99,15 @@ cDriverNoritake800::cDriverNoritake800(cDriverConfig * config)
// default initilaization for the wiring
m_nWiring = WIRING_LIQUIDMP3;
- m_Config = config;
- m_oldConfig = new cDriverConfig(* config);
-
m_pport = new cParallelPort();
m_nTimingAdjustCmd = 0;
m_nRefreshCounter = 0;
- width = m_Config->width; // 128
+ width = config->width; // 128
if (width <= 0)
width = 128;
- height = m_Config->height; // 64
+ height = config->height; // 64
if (height <= 0)
height = 64;
m_iSizeYb = (height + 7)/8; // 8
@@ -116,15 +115,15 @@ cDriverNoritake800::cDriverNoritake800(cDriverConfig * config)
//
// initialize wiring
//
- for (unsigned int i = 0; i < m_Config->options.size(); i++)
+ for (unsigned int i = 0; i < config->options.size(); i++)
{
- if (m_Config->options[i].name == "Wiring")
+ if (config->options[i].name == "Wiring")
{
- if (m_Config->options[i].value == kWiringLiquidmp3)
+ if (config->options[i].value == kWiringLiquidmp3)
{
m_nWiring = WIRING_LIQUIDMP3;
}
- else if (m_Config->options[i].value == kWiringMZ)
+ else if (config->options[i].value == kWiringMZ)
{
m_nWiring = WIRING_MZ;
}
@@ -182,7 +181,6 @@ cDriverNoritake800::~cDriverNoritake800()
}
delete[] m_pDrawMem;
delete[] m_pWiringMaskCache;
- delete m_oldConfig;
delete m_pport;
}
@@ -211,27 +209,27 @@ int cDriverNoritake800::DeInit()
int cDriverNoritake800::CheckSetup()
{
- if (m_Config->device != m_oldConfig->device ||
- m_Config->port != m_oldConfig->port ||
- m_Config->width != m_oldConfig->width ||
- m_Config->height != m_oldConfig->height)
+ if (config->device != oldConfig->device ||
+ config->port != oldConfig->port ||
+ config->width != oldConfig->width ||
+ config->height != oldConfig->height)
{
DeInit();
Init();
return 0;
}
- if (m_Config->brightness != m_oldConfig->brightness)
+ if (config->brightness != oldConfig->brightness)
{
- m_oldConfig->brightness = m_Config->brightness;
- SetBrightness(m_Config->brightness);
+ oldConfig->brightness = config->brightness;
+ SetBrightness(config->brightness);
}
- if (m_Config->upsideDown != m_oldConfig->upsideDown ||
- m_Config->invert != m_oldConfig->invert)
+ if (config->upsideDown != oldConfig->upsideDown ||
+ config->invert != oldConfig->invert)
{
- m_oldConfig->upsideDown = m_Config->upsideDown;
- m_oldConfig->invert = m_Config->invert;
+ oldConfig->upsideDown = config->upsideDown;
+ oldConfig->invert = config->invert;
return 1;
}
return 0;
@@ -242,23 +240,31 @@ int cDriverNoritake800::Init()
int x;
struct timeval tv1, tv2;
- if (m_Config->device == "")
+ if (config->device == "" && m_pport->IsDirectIO())
{
// use DirectIO
- if (m_pport->Open(m_Config->port) != 0)
+ syslog(LOG_INFO, "INFO (cDriverNoritake800::Init): using Direct IO port access\n");
+ if (m_pport->Open(config->port) != 0)
+ {
+ syslog(LOG_ERR, "ERROR (cDriverNoritake800::Init): cannot open configured port %x, Err: %s\n", config->port, strerror(errno));
return -1;
+ }
uSleep(10);
}
else
{
// use ppdev
- if (m_pport->Open(m_Config->device.c_str()) != 0)
+ syslog(LOG_INFO, "INFO (cDriverNoritake800::Init): using PPDEV port access\n");
+ if (m_pport->Open(config->device.c_str()) != 0)
+ {
+ syslog(LOG_ERR, "ERROR (cDriverNoritake800::Init): cannot open configured device %s, Err: %s\n", config->device.c_str(), strerror(errno));
return -1;
+ }
}
if (nSleepInit() != 0)
{
- syslog(LOG_ERR, "%s: INFO: cannot change wait parameters Err: %s (cDriver::Init)\n", m_Config->name.c_str(), strerror(errno));
+ syslog(LOG_INFO, "INFO (cDriverNoritake800::Init): cannot change wait parameters Err: %s\n", strerror(errno));
m_bSleepIsInit = false;
}
else
@@ -266,9 +272,14 @@ int cDriverNoritake800::Init()
m_bSleepIsInit = true;
}
+ // claim port if not already done
+ if (!m_pport->Claim())
+ {
+ syslog(LOG_ERR, "ERROR (cDriverNoritake800::Init): cannot claim port Err: %s\n", strerror(errno));
+ return -1;
+ }
// benchmark port access
- m_pport->Claim();
- syslog(LOG_DEBUG, "%s: benchmark started.\n", m_Config->name.c_str());
+ syslog(LOG_DEBUG, "%s: benchmark started.\n", config->name.c_str());
gettimeofday(&tv1, 0);
int nBenchIterations = 10000;
for (x = 0; x < nBenchIterations; x++)
@@ -279,7 +290,8 @@ int cDriverNoritake800::Init()
nSleepDeInit();
// calculate port command duration in nanoseconds
m_nTimingAdjustCmd = long(double((tv2.tv_sec - tv1.tv_sec) * 1000000000 + (tv2.tv_usec - tv1.tv_usec) * 1000) / double(nBenchIterations));
- syslog(LOG_DEBUG, "%s: benchmark stopped. Time for Port Command: %ldns\n", m_Config->name.c_str(), m_nTimingAdjustCmd);
+ syslog(LOG_DEBUG, "%s: benchmark stopped. Time for Port Command: %ldns\n", config->name.c_str(), m_nTimingAdjustCmd);
+
m_pport->Release();
// initialize display
@@ -289,13 +301,13 @@ int cDriverNoritake800::Init()
for (n=0; n < 15; n++)
{
N800Cmd(0x62);
- nSleep(100 + (100 * m_Config->adjustTiming) - m_nTimingAdjustCmd);
+ nSleep(100 + (100 * config->adjustTiming) - m_nTimingAdjustCmd);
N800Cmd(n);
- nSleep(100 + (100 * m_Config->adjustTiming) - m_nTimingAdjustCmd);
+ nSleep(100 + (100 * config->adjustTiming) - m_nTimingAdjustCmd);
N800Data(0xff);
- nSleep(100 + (100 * m_Config->adjustTiming) - m_nTimingAdjustCmd);
+ nSleep(100 + (100 * config->adjustTiming) - m_nTimingAdjustCmd);
}
- nSleep(100 + (100 * m_Config->adjustTiming) - m_nTimingAdjustCmd);
+ nSleep(100 + (100 * config->adjustTiming) - m_nTimingAdjustCmd);
N800Cmd(LAYERSOFF | LAYER0ON); // layer 0 of the graphic RAM on
@@ -311,15 +323,15 @@ int cDriverNoritake800::Init()
m_pport->Release();
- *m_oldConfig = *m_Config;
+ //*oldConfig = *config;
// Set Display SetBrightness
- SetBrightness(m_Config->brightness);
+ SetBrightness(config->brightness);
// clear display
ClearVFDMem();
Refresh(true);
- syslog(LOG_INFO, "%s: initialization done.\n", m_Config->name.c_str());
+ syslog(LOG_INFO, "INFO (cDriverNoritake800::Init): initialization done.\n");
return 0;
}
@@ -333,14 +345,19 @@ void cDriverNoritake800::Refresh(bool refreshAll)
if (!m_pVFDMem || !m_pDrawMem)
return;
- if (m_Config->refreshDisplay > 0)
+ if (config->refreshDisplay > 0)
{
- m_nRefreshCounter = (m_nRefreshCounter + 1) % m_Config->refreshDisplay;
+ m_nRefreshCounter = (m_nRefreshCounter + 1) % config->refreshDisplay;
if (m_nRefreshCounter == 0)
refreshAll = true;
}
- m_pport->Claim();
+ if (!m_pport->Claim())
+ {
+ syslog(LOG_ERR, "ERROR (cDriverNoritake800::Refresh): cannot claim port Err: %s\n", strerror(errno));
+ return;
+ }
+
for (xb = 0; xb < width; ++xb)
{
for (yb = 0; yb < m_iSizeYb; ++yb)
@@ -355,57 +372,74 @@ void cDriverNoritake800::Refresh(bool refreshAll)
m_nRefreshCounter = 0;
// actually write to display
N800WriteByte(
- (m_pVFDMem[xb][yb]) ^ ((m_Config->invert != 0) ? 0xff : 0x00),
+ (m_pVFDMem[xb][yb]) ^ ((config->invert != 0) ? 0xff : 0x00),
xb,
yb,
0);
}
}
}
+
m_pport->Release();
}
void cDriverNoritake800::N800Cmd(unsigned char data)
{
+ if (!m_pport->Claim())
+ {
+ syslog(LOG_ERR, "ERROR (cDriverNoritake800::N800Cmd): cannot claim port Err: %s\n", strerror(errno));
+ return;
+ }
+
if (m_bSleepIsInit)
nSleepInit();
// set direction to "port_output" & C/D to C
- m_pport->WriteControl(m_pWiringMaskCache[0x00]);
+ m_pport->SetDirection(kForward);
// write to data port
m_pport->WriteData(data);
- nSleep(100 + (100 * m_Config->adjustTiming) - m_nTimingAdjustCmd);
+ nSleep(100 + (100 * config->adjustTiming) - m_nTimingAdjustCmd);
// set /WR on the control port
m_pport->WriteControl(m_pWiringMaskCache[VFDSGN_WR]);
- nSleep(100 + (100 * m_Config->adjustTiming) - m_nTimingAdjustCmd);
+ nSleep(100 + (100 * config->adjustTiming) - m_nTimingAdjustCmd);
// reset /WR on the control port
m_pport->WriteControl(m_pWiringMaskCache[0x00]);
- nSleep(100 + (100 * m_Config->adjustTiming) - m_nTimingAdjustCmd);
+ nSleep(100 + (100 * config->adjustTiming) - m_nTimingAdjustCmd);
// set direction to "port_input"
- m_pport->WriteControl(LPT_CTL_HI_DIR | m_pWiringMaskCache[0x00]);
+ m_pport->SetDirection(kReverse);
+
+ m_pport->Release();
}
void cDriverNoritake800::N800Data(unsigned char data)
{
+ if (!m_pport->Claim())
+ {
+ syslog(LOG_ERR, "ERROR (cDriverNoritake800::N800Data): cannot claim port Err: %s\n", strerror(errno));
+ return;
+ }
+
if (m_bSleepIsInit)
nSleepInit();
// set direction to "port_output" & C/D to C
- m_pport->WriteControl(m_pWiringMaskCache[VFDSGN_CD]);
+ m_pport->SetDirection(kForward);
// write to data port
m_pport->WriteData(data);
- nSleep(100 + (100 * m_Config->adjustTiming) - m_nTimingAdjustCmd);
+ nSleep(100 + (100 * config->adjustTiming) - m_nTimingAdjustCmd);
// set /WR on the control port
m_pport->WriteControl(m_pWiringMaskCache[VFDSGN_CD | VFDSGN_WR]);
- nSleep(100 + (100 * m_Config->adjustTiming) - m_nTimingAdjustCmd);
+ nSleep(100 + (100 * config->adjustTiming) - m_nTimingAdjustCmd);
// reset /WR on the control port
m_pport->WriteControl(m_pWiringMaskCache[VFDSGN_CD]);
- nSleep(100 + (100 * m_Config->adjustTiming) - m_nTimingAdjustCmd);
+ nSleep(100 + (100 * config->adjustTiming) - m_nTimingAdjustCmd);
// set direction to "port_input"
- m_pport->WriteControl(LPT_CTL_HI_DIR | m_pWiringMaskCache[0x00]);
+ m_pport->SetDirection(kReverse);
+
+ m_pport->Release();
}
-void cDriverNoritake800::SetPixel(int x, int y)
+void cDriverNoritake800::SetPixel(int x, int y, uint32_t data)
{
unsigned char c;
@@ -417,7 +451,7 @@ void cDriverNoritake800::SetPixel(int x, int y)
if (y >= height || y < 0)
return;
- if (m_Config->upsideDown)
+ if (config->upsideDown)
{
x = width - 1 - x;
y = height - 1 - y;
@@ -425,9 +459,13 @@ void cDriverNoritake800::SetPixel(int x, int y)
c = 0x80 >> (y % 8);
- m_pDrawMem[x][y/8] |= c;
+ if (data == GRAPHLCD_White)
+ m_pDrawMem[x][y/8] |= c;
+ else
+ m_pDrawMem[x][y/8] &= ( 0xFF ^ c);
}
+#if 0
void cDriverNoritake800::Set8Pixels(int x, int y, unsigned char data)
{
int n;
@@ -441,9 +479,16 @@ void cDriverNoritake800::Set8Pixels(int x, int y, unsigned char data)
SetPixel(x + n, y);
}
}
+#endif
void cDriverNoritake800::SetBrightness(unsigned int percent)
{
+ if (!m_pport->Claim())
+ {
+ syslog(LOG_ERR, "ERROR (cDriverNoritake800::SetBrightness): cannot claim port Err: %s\n", strerror(errno));
+ return;
+ }
+
// display can do 16 brightness levels,
// 0 = light
// 15 = dark
@@ -455,8 +500,8 @@ void cDriverNoritake800::SetBrightness(unsigned int percent)
}
unsigned int darkness = 16 - (unsigned int)((double)percent * 16.0 / 100.0);
- m_pport->Claim();
N800Cmd(0x40 + (darkness & 0xf));
+
m_pport->Release();
}
diff --git a/glcddrivers/noritake800.h b/glcddrivers/noritake800.h
index f34c476..5d72974 100644
--- a/glcddrivers/noritake800.h
+++ b/glcddrivers/noritake800.h
@@ -27,7 +27,9 @@
* This file is released under the GNU General Public License. Refer
* to the COPYING file distributed with this package.
*
- * (c) 2004 - 2011 Lucian Muresan <lucianm AT users.sourceforge.net>
+ * (c) 2004-2011 Lucian Muresan <lucianm AT users.sourceforge.net>
+ * (c) 2005-2010 Andreas Regel <andreas.regel AT powarman.de>
+ * (c) 2011 Wolfgang Astleitner <mrwastl AT users.sourceforge.net>
*/
#ifndef _GLCDDRIVERS_NORITAKE800_H_
@@ -43,11 +45,9 @@ class cParallelPort;
class cDriverNoritake800 : public cDriver
{
+private:
cParallelPort * m_pport;
- cDriverConfig * m_Config;
- cDriverConfig * m_oldConfig;
-
int m_iSizeYb;
int m_nRefreshCounter;
int m_nWiring;
@@ -80,8 +80,8 @@ public:
virtual int DeInit();
virtual void Clear();
- virtual void SetPixel(int x, int y);
- virtual void Set8Pixels(int x, int y, unsigned char data);
+ virtual void SetPixel(int x, int y, uint32_t data);
+ //virtual void Set8Pixels(int x, int y, unsigned char data);
virtual void Refresh(bool refreshAll = false);
virtual void SetBrightness(unsigned int percent);
diff --git a/glcddrivers/picoLCD_256x64.c b/glcddrivers/picoLCD_256x64.c
new file mode 100644
index 0000000..8cef04d
--- /dev/null
+++ b/glcddrivers/picoLCD_256x64.c
@@ -0,0 +1,553 @@
+/*
+ * GraphLCD driver library
+ *
+ * PicoLCD_256x64.c - picoLCD Graphic 256x64
+ * Output goes to a picoLCD Graphic 256x64 LCD
+ *
+ * Driver is based on lcd4linux driver by Nicu Pavel, Mini-Box.com <npavel@mini-box.com>
+ *
+ * This file is released under the GNU General Public License.
+ *
+ * See the files README and COPYING for details.
+ *
+ * 2012 by Jochen Koch <linuxfan1992 AT web de>
+ */
+
+#include <stdlib.h>
+#include <string.h>
+#include <errno.h>
+#include <time.h>
+#include <stdint.h>
+
+
+#include <stdio.h>
+#include <syslog.h>
+#include <cstring>
+
+#include "common.h"
+#include "config.h"
+#include "picoLCD_256x64.h"
+
+namespace GLCD {
+
+cDriverPicoLCD_256x64::cDriverPicoLCD_256x64(cDriverConfig * config)
+: cDriver(config)
+, pLG_framebuffer(0)
+{
+ dirty = 1;
+ inverted = 0;
+ gpo = 0;
+ read_timeout = 0;
+}
+
+int cDriverPicoLCD_256x64::Init()
+{
+ DEBUG("picoLCD Graphic initialization");
+
+ // default values
+ width = config->width;
+ if (width <= 0 || width > SCREEN_W)
+ width = SCREEN_W;
+ height = config->height;
+ if (height <= 0 || height > SCREEN_H)
+ height = SCREEN_H;
+
+ *oldConfig = *config;
+
+ if (drv_pLG_open() < 0) {
+ return -1;
+ }
+
+ /* Init framebuffer buffer */
+ pLG_framebuffer = (unsigned char *)malloc(SCREEN_W * SCREEN_H / 8 * sizeof(unsigned char));
+ if (!pLG_framebuffer)
+ {
+ INFO("picoLCD_256x64: frame buffer could not be allocated: malloc() failed");
+ return -1;
+ }
+
+ /* clear display */
+ Clear();
+ drv_pLG_clear();
+ DEBUG("zeroed");
+
+ // inverted display
+ inverted = (config->invert ? 0xff : 0);
+ // Set Display SetBrightness
+ SetBacklight(config->backlight);
+ // Set Display SetContrast
+ SetContrast(config->contrast);
+
+ return 0;
+}
+
+
+int cDriverPicoLCD_256x64::DeInit()
+{
+
+ DEBUG("picoLCD_256x64: shutting down.");
+
+ /* clear display */
+ Clear();
+ drv_pLG_clear();
+ drv_pLG_close();
+
+ if (pLG_framebuffer) {
+ free(pLG_framebuffer);
+ pLG_framebuffer = NULL;
+ }
+ return 0;
+}
+
+
+int cDriverPicoLCD_256x64::CheckSetup()
+{
+ if (config->width != oldConfig->width ||
+ config->height != oldConfig->height)
+ {
+ DeInit();
+ return Init();
+ }
+
+ if (config->backlight != oldConfig->backlight)
+ {
+ oldConfig->backlight = config->backlight;
+ SetBacklight(config->backlight);
+ }
+
+ if (config->contrast != oldConfig->contrast)
+ {
+ oldConfig->contrast = config->contrast;
+ SetContrast(config->contrast);
+ }
+
+ if (config->upsideDown != oldConfig->upsideDown ||
+ config->invert != oldConfig->invert)
+ {
+ oldConfig->upsideDown = config->upsideDown;
+ oldConfig->invert = config->invert;
+ inverted = (config->invert ? 0xff : 0);
+ return 1;
+ }
+ return 0;
+}
+
+
+void cDriverPicoLCD_256x64::Clear()
+{
+ for (unsigned int n = 0; pLG_framebuffer && n < (SCREEN_W * SCREEN_H / 8); n++)
+ pLG_framebuffer[n] = 0x00;
+}
+
+
+void cDriverPicoLCD_256x64::SetPixel(int x, int y, uint32_t data)
+{
+ unsigned char c;
+ int n;
+
+ if (!pLG_framebuffer)
+ return;
+
+ if (x >= width || x < 0)
+ return;
+ if (y >= height || y < 0)
+ return;
+
+ if (config->upsideDown)
+ {
+ x = width - 1 - x;
+ y = height - 1 - y;
+ }
+
+ n = x + ((y / 8) * SCREEN_W);
+ c = 0x01 << (y % 8);
+
+ if (data == GRAPHLCD_White)
+ pLG_framebuffer[n] |= c;
+ else
+ pLG_framebuffer[n] &= (0xFF ^ c);
+
+ /* display needs to be redrawn from frame buffer */
+ dirty = 1;
+}
+
+
+void cDriverPicoLCD_256x64::Refresh(bool refreshAll)
+{
+ unsigned char cmd3[64] = { OUT_REPORT_CMD_DATA }; /* send command + data */
+ unsigned char cmd4[64] = { OUT_REPORT_DATA }; /* send data only */
+
+ int index, x, s;
+ unsigned char cs, line;
+
+ if (!pLG_framebuffer)
+ return;
+
+ s = CheckSetup();
+ if ((s > 0) || dirty)
+ refreshAll = true;
+
+ /* do not redraw display if frame buffer has not changed */
+ if (!refreshAll) {
+ DEBUG("Skipping");
+ return;
+ }
+ DEBUG("entered");
+
+ for (cs = 0; cs < 4; cs++)
+ {
+ unsigned char chipsel = (cs << 2); //chipselect
+ for (line = 0; line < 8; line++)
+ {
+ //ha64_1.setHIDPkt(OUT_REPORT_CMD_DATA, 8+3+32, 8, chipsel, 0x02, 0x00, 0x00, 0xb8|j, 0x00, 0x00, 0x40);
+ cmd3[0] = OUT_REPORT_CMD_DATA;
+ cmd3[1] = chipsel;
+ cmd3[2] = 0x02;
+ cmd3[3] = 0x00;
+ cmd3[4] = 0x00;
+ cmd3[5] = 0xb8 | line;
+ cmd3[6] = 0x00;
+ cmd3[7] = 0x00;
+ cmd3[8] = 0x40;
+ cmd3[9] = 0x00;
+ cmd3[10] = 0x00;
+ cmd3[11] = 32;
+
+ //ha64_2.setHIDPkt(OUT_REPORT_DATA, 4+32, 4, chipsel | 0x01, 0x00, 0x00, 32);
+ cmd4[0] = OUT_REPORT_DATA;
+ cmd4[1] = chipsel | 0x01;
+ cmd4[2] = 0x00;
+ cmd4[3] = 0x00;
+ cmd4[4] = 32;
+
+ for (index = 0; index < 32; index++)
+ {
+ x=64*cs+index;
+ cmd3[12 + index] = pLG_framebuffer[line * SCREEN_W + x] ^ inverted;
+ }
+ for (index = 32; index < 64; index++)
+ {
+ x=64*cs+index;
+ cmd4[5 + (index - 32)] = pLG_framebuffer[line * SCREEN_W + x] ^ inverted;
+ }
+ drv_pLG_send(cmd3, 44);
+ drv_pLG_send(cmd4, 38);
+ }
+ }
+ /* mark display as up-to-date */
+ dirty = 0;
+}
+
+
+/*
+ * Sets the backlight brightness of the display.
+ *
+ */
+void cDriverPicoLCD_256x64::SetBacklight(unsigned int onoff)
+{
+ unsigned char cmd[2] = { 0x91 }; /* set backlight */
+
+ cmd[1] = (onoff>0 ? 0xff : 0);
+ drv_pLG_send(cmd, 2);
+}
+
+
+void cDriverPicoLCD_256x64::SetContrast(unsigned int val)
+{
+ unsigned char cmd[2] = { 0x92 }; /* set contrast */
+
+ if (val > 10)
+ val = 10;
+
+ cmd[1] = 0x99+val*(0xff-0x99)/10;
+ drv_pLG_send(cmd, 2);
+}
+
+/****************************************/
+/*** hardware dependant functions ***/
+/****************************************/
+
+int cDriverPicoLCD_256x64::drv_pLG_open(void)
+{
+ struct usb_bus *busses, *bus;
+ struct usb_device *dev;
+ char driver[1024];
+ char product[1024];
+ char manufacturer[1024];
+ char serialnumber[1024];
+ int ret;
+
+ lcd = NULL;
+
+ INFO("scanning for picoLCD 256x64...");
+
+ usb_init();
+ usb_find_busses();
+ usb_find_devices();
+ busses = usb_get_busses();
+
+ for (bus = busses; bus; bus = bus->next) {
+ for (dev = bus->devices; dev; dev = dev->next) {
+ if ((dev->descriptor.idVendor == picoLCD_VENDOR) && (dev->descriptor.idProduct == picoLCD_DEVICE)) {
+
+ DEBUG1("found picoLCD on bus %s device %s", bus->dirname, dev->filename);
+
+ lcd = usb_open(dev);
+
+ ret = usb_get_driver_np(lcd, 0, driver, sizeof(driver));
+
+ if (ret == 0) {
+ DEBUG1("interface 0 already claimed by '%s'", driver);
+ DEBUG(" attempting to detach driver...");
+ if (usb_detach_kernel_driver_np(lcd, 0) < 0) {
+ DEBUG("usb_detach_kernel_driver_np() failed!");
+ return -1;
+ }
+ }
+
+ usb_set_configuration(lcd, 1);
+ usleep(100);
+
+ if (usb_claim_interface(lcd, 0) < 0) {
+ DEBUG("picoLCD_256x64: usb_claim_interface() failed!");
+ return -1;
+ }
+
+ usb_set_altinterface(lcd, 0);
+
+ usb_get_string_simple(lcd, dev->descriptor.iProduct, product, sizeof(product));
+ usb_get_string_simple(lcd, dev->descriptor.iManufacturer, manufacturer, sizeof(manufacturer));
+ usb_get_string_simple(lcd, dev->descriptor.iSerialNumber, serialnumber, sizeof(serialnumber));
+
+ INFO1("Manufacturer='%s' Product='%s' SerialNumber='%s\n'", manufacturer, product, serialnumber);
+
+ return 0;
+ }
+ }
+ }
+ INFO("could not find a picoLCD");
+ return -1;
+}
+
+
+int cDriverPicoLCD_256x64::drv_pLG_read(unsigned char *data, int size)
+{
+ return usb_interrupt_read(lcd, USB_ENDPOINT_IN + 1, (char *) data, size, read_timeout);
+}
+
+
+void cDriverPicoLCD_256x64::drv_pLG_send(unsigned char *data, int size)
+{
+ int __attribute__ ((unused)) ret;
+ ret = usb_interrupt_write(lcd, USB_ENDPOINT_OUT + 1, (char *) data, size, 1000);
+}
+
+
+int cDriverPicoLCD_256x64::drv_pLG_close(void)
+{
+ usb_release_interface(lcd, 0);
+ usb_close(lcd);
+
+ return 0;
+}
+
+
+void cDriverPicoLCD_256x64::drv_pLG_clear(void)
+{
+ unsigned char cmd[3] = { 0x93, 0x01, 0x00 }; /* init display */
+ unsigned char cmd2[9] = { OUT_REPORT_CMD }; /* init display */
+ unsigned char cmd3[64] = { OUT_REPORT_CMD_DATA }; /* clear screen */
+ unsigned char cmd4[64] = { OUT_REPORT_CMD_DATA }; /* clear screen */
+
+ int init, index;
+ unsigned char cs, line;
+
+
+ DEBUG("entering\n");
+ drv_pLG_send(cmd, 3);
+
+ for (init = 0; init < 4; init++) {
+ unsigned char cs = ((init << 2) & 0xFF);
+
+ cmd2[0] = OUT_REPORT_CMD;
+ cmd2[1] = cs;
+ cmd2[2] = 0x02;
+ cmd2[3] = 0x00;
+ cmd2[4] = 0x64;
+ cmd2[5] = 0x3F;
+ cmd2[6] = 0x00;
+ cmd2[7] = 0x64;
+ cmd2[8] = 0xC0;
+
+ drv_pLG_send(cmd2, 9);
+ }
+
+ for (cs = 0; cs < 4; cs++) {
+ unsigned char chipsel = (cs << 2); //chipselect
+ for (line = 0; line < 8; line++) {
+ //ha64_1.setHIDPkt(OUT_REPORT_CMD_DATA, 8+3+32, 8, cs, 0x02, 0x00, 0x00, 0xb8|j, 0x00, 0x00, 0x40);
+ cmd3[0] = OUT_REPORT_CMD_DATA;
+ cmd3[1] = chipsel;
+ cmd3[2] = 0x02;
+ cmd3[3] = 0x00;
+ cmd3[4] = 0x00;
+ cmd3[5] = 0xb8 | line;
+ cmd3[6] = 0x00;
+ cmd3[7] = 0x00;
+ cmd3[8] = 0x40;
+ cmd3[9] = 0x00;
+ cmd3[10] = 0x00;
+ cmd3[11] = 32;
+
+ unsigned char temp = 0;
+
+ for (index = 0; index < 32; index++) {
+ cmd3[12 + index] = temp;
+ }
+
+ drv_pLG_send(cmd3, 64);
+
+ //ha64_2.setHIDPkt(OUT_REPORT_DATA, 4+32, 4, cs | 0x01, 0x00, 0x00, 32);
+
+ cmd4[0] = OUT_REPORT_DATA;
+ cmd4[1] = chipsel | 0x01;
+ cmd4[2] = 0x00;
+ cmd4[3] = 0x00;
+ cmd4[4] = 32;
+
+ for (index = 32; index < 64; index++) {
+ temp = 0x00;
+ cmd4[5 + (index - 32)] = temp;
+ }
+ drv_pLG_send(cmd4, 64);
+ }
+ }
+}
+
+#ifdef ENABLE_GPIO_KEYPAD
+/**************************************\
+* *
+* Routines for GPI, GPO & Keypad *
+* *
+\**************************************/
+
+#define _USBLCD_MAX_DATA_LEN 24
+#define IN_REPORT_KEY_STATE 0x11
+
+typedef enum {
+ WIDGET_KEY_UP = 1,
+ WIDGET_KEY_DOWN = 2,
+ WIDGET_KEY_LEFT = 4,
+ WIDGET_KEY_RIGHT = 8,
+ WIDGET_KEY_CONFIRM = 16,
+ WIDGET_KEY_CANCEL = 32,
+ WIDGET_KEY_PRESSED = 64,
+ WIDGET_KEY_RELEASED = 128
+} KEYPADKEY;
+
+int cDriverPicoLCD_256x64::drv_pLG_gpi( __attribute__ ((unused))
+ int num)
+{
+ int ret;
+ unsigned char read_packet[_USBLCD_MAX_DATA_LEN];
+ ret = drv_pLG_read(read_packet, _USBLCD_MAX_DATA_LEN);
+ if ((ret > 0) && (read_packet[0] == IN_REPORT_KEY_STATE)) {
+// DEBUG("picoLCD: pressed key= 0x%02x\n", read_packet[1]);
+ return read_packet[1];
+ }
+ return 0;
+}
+
+
+int cDriverPicoLCD_256x64::drv_pLG_gpo(int num, int val)
+{
+ unsigned char cmd[2] = { 0x81 }; /* set GPO */
+
+ if (num < 0)
+ num = 0;
+ if (num > 7)
+ num = 7;
+
+ if (val < 0)
+ val = 0;
+ if (val > 1)
+ val = 1;
+
+ /* set led bit to 1 or 0 */
+ if (val)
+ gpo |= 1 << num;
+ else
+ gpo &= ~(1 << num);
+
+ cmd[1] = gpo;
+ drv_pLG_send(cmd, 2);
+
+ return val;
+}
+
+
+void cDriverPicoLCD_256x64::drv_pLG_update_keypad(void)
+{
+ static int pressed_key = 0;
+
+ int ret;
+ unsigned char read_packet[_USBLCD_MAX_DATA_LEN];
+ ret = drv_pLG_read(read_packet, _USBLCD_MAX_DATA_LEN);
+ if ((ret > 0) && (read_packet[0] == IN_REPORT_KEY_STATE)) {
+// DEBUG("picoLCD: pressed key= 0x%02x\n", read_packet[1]);
+ int new_pressed_key = read_packet[1];
+ if (pressed_key != new_pressed_key) {
+ /* negative values mark a key release */
+// drv_generic_keypad_press(-pressed_key);
+// drv_generic_keypad_press(new_pressed_key);
+ pressed_key = new_pressed_key;
+ }
+ }
+}
+
+
+int cDriverPicoLCD_256x64::drv_pLG_keypad(const int num)
+{
+ int val;
+ int new_num = num;
+
+ if (new_num == 0)
+ return 0;
+ else if (new_num > 0)
+ val = WIDGET_KEY_PRESSED;
+ else {
+ /* negative values mark a key release */
+ new_num = -num;
+ val = WIDGET_KEY_RELEASED;
+ }
+
+ switch (new_num) {
+ case 1:
+ val += WIDGET_KEY_CANCEL;
+ break;
+ case 2:
+ val += WIDGET_KEY_LEFT;
+ break;
+ case 3:
+ val += WIDGET_KEY_RIGHT;
+ break;
+ case 5:
+ val += WIDGET_KEY_UP;
+ break;
+ case 6:
+ val += WIDGET_KEY_CONFIRM;
+ break;
+ case 7:
+ val += WIDGET_KEY_DOWN;
+ break;
+ default:
+ fprintf(stderr,"picoLCD_256x64: unknown keypad value %d", num);
+ }
+
+ return val;
+}
+#endif
+
+// /namespace
+}
+
diff --git a/glcddrivers/picoLCD_256x64.h b/glcddrivers/picoLCD_256x64.h
new file mode 100644
index 0000000..4f8ce75
--- /dev/null
+++ b/glcddrivers/picoLCD_256x64.h
@@ -0,0 +1,106 @@
+/*
+ * GraphLCD driver library
+ *
+ * PicoLCD_256x64.h - picoLCD Graphic 256x64
+ * Output goes to a picoLCD Graphic 256x64 LCD
+ *
+ * Driver is based on lcd4linux driver by Nicu Pavel, Mini-Box.com <npavel@mini-box.com>
+ *
+ * This file is released under the GNU General Public License.
+ *
+ * See the files README and COPYING for details.
+ *
+ * 2012 by Jochen Koch <linuxfan1992 AT web de>
+ */
+
+#ifndef _GLCDDRIVERS_PicoLCD_256x64_H_
+#define _GLCDDRIVERS_PicoLCD_256x64_H_
+
+#include "driver.h"
+#include "stdio.h"
+#include <usb.h>
+#include <syslog.h>
+
+#define HAVE_STDBOOL_H
+
+#define picoLCD_VENDOR 0x04d8
+#define picoLCD_DEVICE 0xc002
+
+#define OUT_REPORT_LED_STATE 0x81
+#define OUT_REPORT_LCD_BACKLIGHT 0x91
+#define OUT_REPORT_LCD_CONTRAST 0x92
+
+#define OUT_REPORT_CMD 0x94
+#define OUT_REPORT_DATA 0x95
+#define OUT_REPORT_CMD_DATA 0x96
+
+#define SCREEN_H 64
+#define SCREEN_W 256
+
+#ifdef HAVE_DEBUG
+#define DEBUG(x) fprintf(stderr,"picoLCD_256x64: %s(): " #x "\n", __FUNCTION__);
+#define DEBUG1(x,...) fprintf(stderr,"picoLCD_256x64: %s(): " #x "\n", __FUNCTION__, __VA_ARGS__);
+#else
+#define DEBUG(x)
+#define DEBUG1(x,...)
+#endif
+
+#define INFO(x) syslog(LOG_INFO, "picoLCD_256x64: %s\n", x);
+#define INFO1(x,...) syslog(LOG_INFO, "picoLCD_256x64: " #x "\n", __VA_ARGS__);
+
+namespace GLCD
+{
+ class cDriverConfig;
+
+ class cDriverPicoLCD_256x64 : public cDriver
+ {
+ /* "dirty" marks the display to be redrawn from frame buffer */
+ int dirty;
+
+ /* USB read timeout in ms (the picoLCD 256x64 times out on every read
+ unless a key has been pressed!) */
+ int read_timeout;
+
+ unsigned char *pLG_framebuffer;
+
+ /* used to display white text on black background or inverse */
+ unsigned char inverted;
+
+ unsigned int gpo;
+
+ usb_dev_handle *lcd;
+
+ int CheckSetup();
+ protected:
+ int drv_pLG_open(void);
+ int drv_pLG_read(unsigned char *data, int size);
+ void drv_pLG_send(unsigned char *data, int size);
+ int drv_pLG_close(void);
+ void drv_pLG_clear(void);
+#ifdef ENABLE_GPIO_KEYPAD
+ // GPI, GPO, Keypad
+ int drv_pLG_gpi(int num);
+ int drv_pLG_gpo(int num, int val);
+ void drv_pLG_update_keypad(void);
+ int drv_pLG_keypad(const int num);
+#endif
+
+ public:
+ cDriverPicoLCD_256x64(cDriverConfig * config);
+
+ virtual int Init();
+ virtual int DeInit();
+
+ virtual void Clear();
+ virtual void SetPixel(int x, int y, uint32_t data);
+ //virtual void Set8Pixels(int x, int y, byte data);
+ virtual void Refresh(bool refreshAll = false);
+
+ virtual void SetBacklight(unsigned int percent);
+ virtual void SetContrast(unsigned int percent);
+ };
+};
+#endif
+
+
+
diff --git a/glcddrivers/port.c b/glcddrivers/port.c
index d6e8e34..cfb4156 100644
--- a/glcddrivers/port.c
+++ b/glcddrivers/port.c
@@ -6,7 +6,8 @@
* This file is released under the GNU General Public License. Refer
* to the COPYING file distributed with this package.
*
- * (c) 2004 Andreas Regel <andreas.regel AT powarman.de>
+ * (c) 2004 Andreas Regel <andreas.regel AT powarman.de>
+ * (c) 2011-2012 Wolfgang Astleitner <mrwastl AT users.sourceforge.net>
*/
#include <errno.h>
@@ -16,6 +17,7 @@
#include <syslog.h>
#include <unistd.h>
#include <termios.h>
+#include <pthread.h>
#include <sys/io.h>
#include <sys/ioctl.h>
#include <linux/ppdev.h>
@@ -25,29 +27,42 @@
#include "port.h"
+#if defined(__linux__) && (defined(__i386__) || defined(__x86_64__))
+ #define __HAS_DIRECTIO__ 1
+#endif
+
namespace GLCD
{
+static pthread_mutex_t claimport_mutex;
+
static inline int port_in(int port)
{
+#ifdef __HAS_DIRECTIO__
unsigned char value;
__asm__ volatile ("inb %1,%0"
: "=a" (value)
: "d" ((unsigned short) port));
return value;
+#else
+ return 0;
+#endif
}
static inline void port_out(unsigned short int port, unsigned char val)
{
+#ifdef __HAS_DIRECTIO__
__asm__ volatile ("outb %0,%1\n"
:
: "a" (val), "d" (port));
+#endif
}
cParallelPort::cParallelPort()
: fd(-1),
port(0),
- usePPDev(false)
+ usePPDev(false),
+ portClaimed(false)
{
}
@@ -57,6 +72,7 @@ cParallelPort::~cParallelPort()
int cParallelPort::Open(int portIO)
{
+#ifdef __HAS_DIRECTIO__
usePPDev = false;
port = portIO;
@@ -79,6 +95,10 @@ int cParallelPort::Open(int portIO)
}
}
return 0;
+#else
+ syslog(LOG_ERR, "glcd drivers: ERROR: direct IO/parport is not available on this architecture / operating system\n");
+ return -1;
+#endif
}
int cParallelPort::Open(const char * device)
@@ -93,7 +113,7 @@ int cParallelPort::Open(const char * device)
return -1;
}
- if (ioctl(fd, PPCLAIM, NULL) == -1)
+ if (!Claim())
{
syslog(LOG_ERR, "glcd drivers: ERROR cannot claim %s. Err:%s (cParallelPort::Init)\n",
device, strerror(errno));
@@ -102,7 +122,7 @@ int cParallelPort::Open(const char * device)
}
int mode = PARPORT_MODE_PCSPP;
- if (ioctl(fd, PPSETMODE, &mode) == -1)
+ if (ioctl(fd, PPSETMODE, &mode) != 0)
{
syslog(LOG_ERR, "glcd drivers: ERROR cannot setmode %s. Err:%s (cParallelPort::Init)\n",
device, strerror(errno));
@@ -130,6 +150,7 @@ int cParallelPort::Close()
}
else
{
+#ifdef __HAS_DIRECTIO__
if (port < 0x400)
{
if (ioperm(port, 3, 0) == -1)
@@ -144,20 +165,34 @@ int cParallelPort::Close()
return -1;
}
}
+#else
+ return -1; // should never make it until here ...
+#endif
}
return 0;
}
-void cParallelPort::Claim()
+bool cParallelPort::Claim()
{
- if (usePPDev)
- ioctl(fd, PPCLAIM);
+ if (!IsPortClaimed())
+ {
+ if (usePPDev)
+ portClaimed = (ioctl(fd, PPCLAIM) == 0);
+ else
+ portClaimed = (pthread_mutex_lock(&claimport_mutex) == 0);
+ }
+ return IsPortClaimed();
}
void cParallelPort::Release()
{
- if (usePPDev)
- ioctl(fd, PPRELEASE);
+ if (IsPortClaimed())
+ {
+ if (usePPDev)
+ portClaimed = !(ioctl(fd, PPRELEASE) == 0);
+ else
+ portClaimed = !(pthread_mutex_unlock(&claimport_mutex) == 0);
+ }
}
void cParallelPort::SetDirection(int direction)
diff --git a/glcddrivers/port.h b/glcddrivers/port.h
index 2920461..6fcd635 100644
--- a/glcddrivers/port.h
+++ b/glcddrivers/port.h
@@ -33,6 +33,7 @@ private:
int fd;
int port;
bool usePPDev;
+ bool portClaimed;
public:
cParallelPort();
@@ -45,8 +46,9 @@ public:
bool IsDirectIO() const { return (!usePPDev); }
int GetPortHandle() const { return ((usePPDev) ? fd : port); }
- void Claim();
+ bool Claim();
void Release();
+ bool IsPortClaimed() const { return (portClaimed); }
void SetDirection(int direction);
unsigned char ReadControl();
diff --git a/glcddrivers/sed1330.c b/glcddrivers/sed1330.c
index e993ca0..872cf89 100644
--- a/glcddrivers/sed1330.c
+++ b/glcddrivers/sed1330.c
@@ -14,7 +14,9 @@
* This file is released under the GNU General Public License. Refer
* to the COPYING file distributed with this package.
*
- * (c) 2003 Roland Praml <praml.roland AT t-online.de>
+ * (c) 2003 Roland Praml <praml.roland AT t-online.de>
+ * (c) 2005-2010 Andreas Regel <andreas.regel AT powarman.de>
+ * (c) 2011 Wolfgang Astleitner <mrwastl AT users.sourceforge.net>
*/
#include <syslog.h>
@@ -129,10 +131,8 @@ const unsigned char kYASEDWCSLO = kSelectLow;
cDriverSED1330::cDriverSED1330(cDriverConfig * config)
-: config(config)
+: cDriver(config)
{
- oldConfig = new cDriverConfig(*config);
-
port = new cParallelPort();
refreshCounter = 0;
@@ -141,7 +141,6 @@ cDriverSED1330::cDriverSED1330(cDriverConfig * config)
cDriverSED1330::~cDriverSED1330()
{
delete port;
- delete oldConfig;
}
int cDriverSED1330::Init()
@@ -539,6 +538,29 @@ void cDriverSED1330::Clear()
memset(newLCD[x], 0, height);
}
+
+void cDriverSED1330::SetPixel(int x, int y, uint32_t data)
+{
+ if (x >= width || y >= height)
+ return;
+
+ int pos = x % 8;
+ if (config->upsideDown)
+ {
+ x = width - 1 - x;
+ y = height - 1 - y;
+ } else {
+ pos = 7 - pos; // reverse bit position
+ }
+
+ if (data == GRAPHLCD_White)
+ newLCD[x / 8][y] |= (1 << pos);
+ else
+ newLCD[x / 8][y] &= ( 0xFF ^ (1 << pos) );
+}
+
+
+#if 0
void cDriverSED1330::Set8Pixels(int x, int y, unsigned char data)
{
if (x >= width || y >= height)
@@ -557,6 +579,7 @@ void cDriverSED1330::Set8Pixels(int x, int y, unsigned char data)
newLCD[x / 8][y] = newLCD[x / 8][y] | ReverseBits(data);
}
}
+#endif
void cDriverSED1330::Refresh(bool refreshAll)
{
diff --git a/glcddrivers/sed1330.h b/glcddrivers/sed1330.h
index 354b853..ad2eef5 100644
--- a/glcddrivers/sed1330.h
+++ b/glcddrivers/sed1330.h
@@ -14,7 +14,9 @@
* This file is released under the GNU General Public License. Refer
* to the COPYING file distributed with this package.
*
- * (c) 2003 Roland Praml <praml.roland AT t-online.de>
+ * (c) 2003 Roland Praml <praml.roland AT t-online.de>
+ * (c) 2005-2010 Andreas Regel <andreas.regel AT powarman.de>
+ * (c) 2011 Wolfgang Astleitner <mrwastl AT users.sourceforge.net>
*/
#ifndef _GLCDDRIVERS_SED1330_H_
@@ -37,8 +39,6 @@ private:
unsigned char ** oldLCD; // current state
int refreshCounter;
long timeForPortCmdInNs;
- cDriverConfig * config;
- cDriverConfig * oldConfig;
bool useSleepInit;
int oscillatorFrequency;
@@ -69,7 +69,8 @@ public:
virtual int DeInit();
virtual void Clear();
- virtual void Set8Pixels(int x, int y, unsigned char data);
+ virtual void SetPixel(int x, int y, uint32_t data);
+ //virtual void Set8Pixels(int x, int y, unsigned char data);
virtual void Refresh(bool refreshAll = false);
};
diff --git a/glcddrivers/sed1520.c b/glcddrivers/sed1520.c
index c0b1b27..4692c64 100644
--- a/glcddrivers/sed1520.c
+++ b/glcddrivers/sed1520.c
@@ -6,7 +6,8 @@
* This file is released under the GNU General Public License. Refer
* to the COPYING file distributed with this package.
*
- * (c) 2003 Andreas 'randy' Weinberger <vdr AT smue.org>
+ * (c) 2003-2011 Andreas 'randy' Weinberger <vdr AT smue.org>
+ * (c) 2011 Wolfgang Astleitner <mrwastl AT users.sourceforge.net>
*/
#include <syslog.h>
@@ -45,10 +46,8 @@ const unsigned char kLEDLO = 0x00;
cDriverSED1520::cDriverSED1520(cDriverConfig * config)
-: config(config)
+: cDriver(config)
{
- oldConfig = new cDriverConfig(*config);
-
port = new cParallelPort();
refreshCounter = 0;
@@ -57,7 +56,6 @@ cDriverSED1520::cDriverSED1520(cDriverConfig * config)
cDriverSED1520::~cDriverSED1520()
{
delete port;
- delete oldConfig;
}
int cDriverSED1520::Init()
@@ -303,6 +301,29 @@ void cDriverSED1520::Clear()
memset(LCD[x], 0, height);
}
+
+void cDriverSED1520::SetPixel (int x, int y, uint32_t data)
+{
+ if (x >= width || y >= height)
+ return;
+
+ int pos = x % 8;
+ if (config->upsideDown)
+ {
+ x = width - 1 - x;
+ y = height - 1 - y;
+ } else {
+ pos = 7 - pos; // reverse bit position
+ }
+
+ if (data == GRAPHLCD_White)
+ LCD[x / 8][y] |= ( 1 << pos );
+ else
+ LCD[x / 8][y] &= (0xFF ^ ( 1 << pos ));
+}
+
+
+#if 0
void cDriverSED1520::Set8Pixels (int x, int y, unsigned char data)
{
if (x >= width || y >= height)
@@ -321,6 +342,7 @@ void cDriverSED1520::Set8Pixels (int x, int y, unsigned char data)
LCD[x / 8][y] = LCD[x / 8][y] | ReverseBits(data);
}
}
+#endif
void cDriverSED1520::Refresh(bool refreshAll)
{
diff --git a/glcddrivers/sed1520.h b/glcddrivers/sed1520.h
index 931d51b..e72befc 100644
--- a/glcddrivers/sed1520.h
+++ b/glcddrivers/sed1520.h
@@ -6,7 +6,8 @@
* This file is released under the GNU General Public License. Refer
* to the COPYING file distributed with this package.
*
- * (c) 2003 Andreas 'randy' Weinberger <vdr AT smue.org>
+ * (c) 2003-2011 Andreas 'randy' Weinberger <vdr AT smue.org>
+ * (c) 2011 Wolfgang Astleitner <mrwastl AT users.sourceforge.net>
*/
#ifndef _GLCDDRIVERS_SED1520_H_
@@ -29,8 +30,6 @@ private:
unsigned char ** LCD_page; // paged lcd display "memory"
int refreshCounter;
long timeForPortCmdInNs;
- cDriverConfig * config;
- cDriverConfig * oldConfig;
bool useSleepInit;
int SEAD;
@@ -63,7 +62,8 @@ public:
virtual int DeInit();
virtual void Clear();
- virtual void Set8Pixels(int x, int y, unsigned char data);
+ virtual void SetPixel(int x, int y, uint32_t data);
+ //virtual void Set8Pixels(int x, int y, unsigned char data);
virtual void Refresh(bool refreshAll = false);
};
diff --git a/glcddrivers/serdisp.c b/glcddrivers/serdisp.c
index b092659..1fac5ba 100644
--- a/glcddrivers/serdisp.c
+++ b/glcddrivers/serdisp.c
@@ -7,7 +7,7 @@
* This file is released under the GNU General Public License. Refer
* to the COPYING file distributed with this package.
*
- * (c) 2003-2010 Wolfgang Astleitner <mrwastl AT users.sourceforge.net>
+ * (c) 2003-2013 Wolfgang Astleitner <mrwastl AT users.sourceforge.net>
*/
#include <stdio.h>
@@ -19,6 +19,11 @@
#include "config.h"
#include "serdisp.h"
+// for memcpy
+#include <string.h>
+
+#include <map>
+
#define SERDISP_VERSION(a,b) ((long)(((a) << 8) + (b)))
#define SERDISP_VERSION_GET_MAJOR(_c) ((int)( (_c) >> 8 ))
#define SERDISP_VERSION_GET_MINOR(_c) ((int)( (_c) & 0xFF ))
@@ -29,23 +34,26 @@
#define FEATURE_BACKLIGHT 0x03
#define FEATURE_ROTATE 0x04
-#define SD_COL_BLACK 0xFF000000
-#define SD_COL_WHITE 0xFFFFFFFF
+// taken from serdisp_gpevents.h
+#define SDGPT_SIMPLETOUCH 0x10 /* simple touch screen event, type: SDGP_evpkt_simpletouch_t */
+#define SDGPT_GENERICTOUCH 0x11 /* generic touch screen event, type: SDGP_evpkt_generictouch_t */
+
+#define SDGPT_TOUCHDOWN 0x0
+#define SDGPT_TOUCHUP 0x1
+#define SDGPT_TOUCHMOVE 0x2
namespace GLCD
{
-cDriverSerDisp::cDriverSerDisp(cDriverConfig * config)
-: config(config)
-{
- oldConfig = new cDriverConfig(*config);
+static void wrapEventListener(void* dd, SDGP_event_t* recylce);
+
+static std::map<void* ,tTouchEvent*> touchEvents;
- dd = (void *) NULL;
-}
-cDriverSerDisp::~cDriverSerDisp(void)
+cDriverSerDisp::cDriverSerDisp(cDriverConfig * config)
+: cDriver(config)
{
- delete oldConfig;
+ dd = (void *) NULL;
}
int cDriverSerDisp::Init(void)
@@ -58,10 +66,27 @@ int cDriverSerDisp::Init(void)
std::string optionstring = "";
std::string wiringstring;
+ int chk_major = 0;
+ std::string libname = "";
// dynamically load serdisplib using dlopen() & co.
+ sdhnd = NULL;
+ chk_major = 3; // max major version to check
+
+ while ( ! sdhnd && chk_major > 0) {
+ libname = "libserdisp.so.";
+ libname.push_back (chk_major + '0');
+ sdhnd = dlopen(libname.c_str(), RTLD_LAZY);
+ if (!sdhnd) { // try /usr/local/lib
+ libname.insert(0, "/usr/local/lib/");
+ sdhnd = dlopen(libname.c_str(), RTLD_LAZY);
+ }
+ chk_major --;
+ }
- sdhnd = dlopen("libserdisp.so", RTLD_LAZY);
+ if (!sdhnd) { // try libserdisp.so without major version
+ sdhnd = dlopen("libserdisp.so", RTLD_LAZY);
+ }
if (!sdhnd) { // try /usr/local/lib
sdhnd = dlopen("/usr/local/lib/libserdisp.so", RTLD_LAZY);
}
@@ -76,102 +101,63 @@ int cDriverSerDisp::Init(void)
/* pre-init some flags, function pointers, ... */
supports_options = 0;
- fg_colour = 1;
- bg_colour = -1;
+ fgcol = GRAPHLCD_Black; /* set foreground colour to black */
+ bgcol = GRAPHLCD_ERRCOL;
// get serdisp version
fp_serdisp_getversioncode = (long int (*)()) dlsym(sdhnd, "serdisp_getversioncode");
if (dlerror()) { // no serdisp_getversioncode() -> version of serdisplib is < 1.95
- syslog(LOG_DEBUG, "%s: INFO: symbol serdisp_getversioncode unknown: autodetecting pre 1.95 serdisplib version (cDriver::Init)\n",
- config->name.c_str());
-
- fp_SDCONN_open = (void*(*)(const char*)) dlsym(sdhnd, "SDCONN_open");
- if (dlerror()) { // no SDCONN_open() -> version of serdisplib is < 1.93
- serdisp_version = SERDISP_VERSION(1,92);
- syslog(LOG_DEBUG, "%s: INFO: detected serdisplib version <= 1.92 (cDriver::Init)\n", config->name.c_str());
-
- fp_PP_open = (void*(*)(const char*))dlsym(sdhnd, "PP_open");
- if ( (errmsg = dlerror()) != NULL ) { // should not happen
- syslog(LOG_ERR, "%s: error: cannot load symbol %s. Err:%s (cDriver::Init)\n",
- config->name.c_str(), "PP_open", errmsg);
- return -1;
- }
- fp_PP_close = (void*(*)(void*))dlsym(sdhnd, "PP_close");
- if ( (errmsg = dlerror()) != NULL ) { // should not happen
- syslog(LOG_ERR, "%s: error: cannot load symbol %s. Err:%s (cDriver::Init)\n",
- config->name.c_str(), "PP_close", errmsg);
- return -1;
- }
- } else {
- serdisp_version = SERDISP_VERSION(1,94); // no serdisp_getversioncode, but SDCONN_open: 1.93 or 1.94
- syslog(LOG_DEBUG, "%s: INFO: detected serdisplib version 1.93 or 1.94 (cDriver::Init)\n", config->name.c_str());
+ syslog(LOG_ERR, "%s: error: serdisplib version >= 1.95 required\n", config->name.c_str());
+ return -1;
+ }
- fp_serdisp_quit = (void (*)(void*)) dlsym(sdhnd, "serdisp_quit");
- if ( (errmsg = dlerror()) != NULL ) { // should not happen
- syslog(LOG_ERR, "%s: error: cannot load symbol %s. Err:%s (cDriver::Init)\n",
- config->name.c_str(), "serdisp_quit", errmsg);
- return -1;
- }
- }
+ serdisp_version = fp_serdisp_getversioncode();
+ syslog(LOG_DEBUG, "%s: INFO: detected serdisplib version %d.%d (cDriver::Init)\n",
+ config->name.c_str(), SERDISP_VERSION_GET_MAJOR(serdisp_version), SERDISP_VERSION_GET_MINOR(serdisp_version));
- fp_serdisp_setpixcol = (void (*)(void*, int, int, long int)) dlsym(sdhnd, "serdisp_setpixel");
- if ( (errmsg = dlerror()) != NULL ) { // should not happen
- syslog(LOG_ERR, "%s: error: cannot load symbol %s. Err:%s (cDriver::Init)\n",
- config->name.c_str(), "serdisp_setpixel", errmsg);
- return -1;
- }
- fg_colour = 1; /* set foreground to 'pixel on' */
- } else { // serdisp version >= 1.95
- serdisp_version = fp_serdisp_getversioncode();
- syslog(LOG_DEBUG, "%s: INFO: detected serdisplib version %d.%d (cDriver::Init)\n",
- config->name.c_str(), SERDISP_VERSION_GET_MAJOR(serdisp_version), SERDISP_VERSION_GET_MINOR(serdisp_version));
+ fp_SDCONN_open = (void*(*)(const char*)) dlsym(sdhnd, "SDCONN_open");
+ if ( (errmsg = dlerror()) != NULL ) { // should not happen
+ syslog(LOG_ERR, "%s: error: cannot load symbol %s. Err:%s (cDriver::Init)\n",
+ config->name.c_str(), "SDCONN_open", errmsg);
+ return -1;
+ }
+ fp_serdisp_quit = (void (*)(void*)) dlsym(sdhnd, "serdisp_quit");
+ if ( (errmsg = dlerror()) != NULL ) { // should not happen
+ syslog(LOG_ERR, "%s: error: cannot load symbol %s. Err:%s (cDriver::Init)\n",
+ config->name.c_str(), "serdisp_quit", errmsg);
+ return -1;
+ }
+ fp_serdisp_setcolour = (void (*)(void*, int, int, long int)) dlsym(sdhnd, "serdisp_setcolour");
+ if ( (errmsg = dlerror()) != NULL ) { // should not happen
+ syslog(LOG_ERR, "%s: error: cannot load symbol %s. Err:%s (cDriver::Init)\n",
+ config->name.c_str(), "serdisp_setcolour", errmsg);
+ return -1;
+ }
+ if (serdisp_version >= SERDISP_VERSION(1,96) ) {
+ supports_options = 1;
- fp_SDCONN_open = (void*(*)(const char*)) dlsym(sdhnd, "SDCONN_open");
+ fp_serdisp_isoption = (int (*)(void*, const char*)) dlsym(sdhnd, "serdisp_isoption");
if ( (errmsg = dlerror()) != NULL ) { // should not happen
syslog(LOG_ERR, "%s: error: cannot load symbol %s. Err:%s (cDriver::Init)\n",
- config->name.c_str(), "SDCONN_open", errmsg);
+ config->name.c_str(), "serdisp_isoption", errmsg);
return -1;
}
- fp_serdisp_quit = (void (*)(void*)) dlsym(sdhnd, "serdisp_quit");
+ fp_serdisp_setoption = (void (*)(void*, const char*, long int)) dlsym(sdhnd, "serdisp_setoption");
if ( (errmsg = dlerror()) != NULL ) { // should not happen
syslog(LOG_ERR, "%s: error: cannot load symbol %s. Err:%s (cDriver::Init)\n",
- config->name.c_str(), "serdisp_quit", errmsg);
+ config->name.c_str(), "serdisp_setoption", errmsg);
return -1;
}
- fp_serdisp_setpixcol = (void (*)(void*, int, int, long int)) dlsym(sdhnd, "serdisp_setcolour");
+ fp_serdisp_getoption = (long int (*)(void*, const char*, int*)) dlsym(sdhnd, "serdisp_getoption");
if ( (errmsg = dlerror()) != NULL ) { // should not happen
syslog(LOG_ERR, "%s: error: cannot load symbol %s. Err:%s (cDriver::Init)\n",
- config->name.c_str(), "serdisp_setcolour", errmsg);
+ config->name.c_str(), "serdisp_getoption", errmsg);
return -1;
}
- fg_colour = SD_COL_BLACK; /* set foreground colour to black */
-
- if (serdisp_version >= SERDISP_VERSION(1,96) ) {
- supports_options = 1;
-
- fp_serdisp_isoption = (int (*)(void*, const char*)) dlsym(sdhnd, "serdisp_isoption");
- if ( (errmsg = dlerror()) != NULL ) { // should not happen
- syslog(LOG_ERR, "%s: error: cannot load symbol %s. Err:%s (cDriver::Init)\n",
- config->name.c_str(), "serdisp_isoption", errmsg);
- return -1;
- }
- fp_serdisp_setoption = (void (*)(void*, const char*, long int)) dlsym(sdhnd, "serdisp_setoption");
- if ( (errmsg = dlerror()) != NULL ) { // should not happen
- syslog(LOG_ERR, "%s: error: cannot load symbol %s. Err:%s (cDriver::Init)\n",
- config->name.c_str(), "serdisp_setoption", errmsg);
- return -1;
- }
- fp_serdisp_getoption = (long int (*)(void*, const char*, int*)) dlsym(sdhnd, "serdisp_getoption");
- if ( (errmsg = dlerror()) != NULL ) { // should not happen
- syslog(LOG_ERR, "%s: error: cannot load symbol %s. Err:%s (cDriver::Init)\n",
- config->name.c_str(), "serdisp_getoption", errmsg);
- return -1;
- }
- } /* >= 1.96 */
- }
+ } /* >= 1.96 */
// load other symbols that will be required
fp_serdisp_init = (void*(*)(void*, const char*, const char*)) dlsym(sdhnd, "serdisp_init");
@@ -230,6 +216,24 @@ int cDriverSerDisp::Init(void)
return -1;
}
+ fp_serdisp_getcolours = (int (*)(void*)) dlsym(sdhnd, "serdisp_getcolours");
+ if ( (errmsg = dlerror()) != NULL ) { // should not happen
+ syslog(LOG_ERR, "%s: error: cannot load symbol %s. Err:%s (cDriver::Init)\n",
+ config->name.c_str(), "serdisp_getcolours", errmsg);
+ return -1;
+ }
+
+ // don't care if the following functions are not available
+ fp_serdisp_getdepth = (int (*)(void*)) dlsym(sdhnd, "serdisp_getdepth");
+
+ fp_SDGPI_search = (uint8_t (*)(void*, const char*)) dlsym(sdhnd, "SDGPI_search");
+ fp_SDGPI_isenabled = (int (*)(void*, uint8_t)) dlsym(sdhnd, "SDGPI_isenabled");
+ fp_SDGPI_enable = (int (*)(void*, uint8_t, int)) dlsym(sdhnd, "SDGPI_enable");
+ fp_SDEVLP_add_listener = (int (*)(void*, uint8_t, fp_eventlistener_t)) dlsym(sdhnd, "SDEVLP_add_listener");
+ fp_serdisp_defaultdevice = (const char* (*)(const char*)) dlsym(sdhnd, "serdisp_defaultdevice");
+
+
+
// done loading all required symbols
// setting up the display
@@ -245,12 +249,12 @@ int cDriverSerDisp::Init(void)
} else if (config->options[i].name == "Wiring") {
wiringstring = config->options[i].value;
} else if (config->options[i].name == "FGColour") {
- fg_colour = strtoul(config->options[i].value.c_str(), (char **)NULL, 0);
- fg_colour |= 0xFF000000L; /* force alpha to 0xFF */
+ fgcol = (uint32_t)strtoul(config->options[i].value.c_str(), (char **)NULL, 0);
+ fgcol |= 0xFF000000; /* force alpha to 0xFF */
fg_forced = 1;
} else if (config->options[i].name == "BGColour") {
- bg_colour = strtoul(config->options[i].value.c_str(), (char **)NULL, 0);
- bg_colour |= 0xFF000000L; /* force alpha to 0xFF */
+ bgcol = (uint32_t)strtoul(config->options[i].value.c_str(), (char **)NULL, 0);
+ bgcol |= 0xFF000000; /* force alpha to 0xFF */
bg_forced = 1;
}
}
@@ -266,22 +270,13 @@ int cDriverSerDisp::Init(void)
}
- if (config->device == "")
+ if (config->device == "" && config->port > 0) /* port will only be used if device is not set */
{
// use DirectIO
-
- // neither device nor port is set
- if (config->port == 0)
- return -1;
-
char temp[10];
snprintf(temp, 8, "0x%x", config->port);
- if (serdisp_version < SERDISP_VERSION(1,93) ) {
- sdcd = fp_PP_open(temp);
- } else {
- sdcd = fp_SDCONN_open(temp);
- }
+ sdcd = fp_SDCONN_open(temp);
if (sdcd == 0) {
syslog(LOG_ERR, "%s: error: unable to open port 0x%x for display %s. (cDriver::Init)\n",
@@ -293,9 +288,13 @@ int cDriverSerDisp::Init(void)
}
else
{
- // use ppdev
- if (serdisp_version < SERDISP_VERSION(1,93) ) {
- sdcd = fp_PP_open(config->device.c_str());
+ if (config->device == "") {
+ if (fp_serdisp_defaultdevice) { // supported only in serdisplib >= v2.00
+ sdcd = fp_SDCONN_open(fp_serdisp_defaultdevice(controller.c_str()));
+ } else {
+ // neither device nor port is set and getting default device expression is not supported -> exit
+ return -1;
+ }
} else {
sdcd = fp_SDCONN_open(config->device.c_str());
}
@@ -307,10 +306,7 @@ int cDriverSerDisp::Init(void)
}
}
- if (serdisp_version < SERDISP_VERSION(1,95) )
- dd = fp_serdisp_init(sdcd, controller.c_str(), "");
- else
- dd = fp_serdisp_init(sdcd, controller.c_str(), optionstring.c_str());
+ dd = fp_serdisp_init(sdcd, controller.c_str(), optionstring.c_str());
if (!dd)
{
@@ -322,9 +318,9 @@ int cDriverSerDisp::Init(void)
// self-emitting displays (like OLEDs): default background colour => black
if ( supports_options && fp_serdisp_isoption(dd, "SELFEMITTING") && (fp_serdisp_getoption(dd, "SELFEMITTING", 0)) ) {
if (!bg_forced)
- bg_colour = SD_COL_BLACK; /* set background colour to black */
+ bgcol = GRAPHLCD_Black; /* set background colour to black */
if (!fg_forced)
- fg_colour = SD_COL_WHITE; /* set foreground colour to white */
+ fgcol = GRAPHLCD_White; /* set foreground colour to white */
}
width = config->width;
@@ -367,22 +363,28 @@ int cDriverSerDisp::Init(void)
// clear display
Clear();
+ touchEvent = new tTouchEvent;
+ touchEvent->touchChanged = false;
+ touchEvents[dd] = touchEvent;
+
syslog(LOG_INFO, "%s: SerDisp with %s initialized.\n", config->name.c_str(), controller.c_str());
return 0;
}
int cDriverSerDisp::DeInit(void)
{
- if (serdisp_version < SERDISP_VERSION(1,93) ) {
- fp_serdisp_close(dd);
- fp_PP_close(sdcd);
- sdcd = NULL;
- } else {
- //fp_serdisp_quit(dd);
- /* use serdisp_close instead of serdisp_quit so that showpic and showtext are usable together with serdisplib */
- fp_serdisp_close(dd);
- }
- (int) dlclose(sdhnd);
+ if (!dd)
+ return 0;
+
+ touchEvents.erase(dd);
+ delete touchEvent;
+ touchEvent = NULL;
+
+ //fp_serdisp_quit(dd);
+ /* use serdisp_close instead of serdisp_quit so that showpic and showtext are usable together with serdisplib */
+ fp_serdisp_close(dd);
+
+ dlclose(sdhnd);
sdhnd = NULL;
return 0;
@@ -434,6 +436,7 @@ int cDriverSerDisp::CheckSetup()
update = true;
}
+#if 0
/* driver dependend options */
if ( supports_options ) {
for (unsigned int i = 0; i < config->options.size(); i++) {
@@ -448,7 +451,7 @@ int cDriverSerDisp::CheckSetup()
}
}
}
-
+#endif
if (update)
return 1;
@@ -457,16 +460,17 @@ int cDriverSerDisp::CheckSetup()
void cDriverSerDisp::Clear(void)
{
- if (bg_colour == -1)
+ if (bgcol == GRAPHLCD_ERRCOL) // bgcol not set
fp_serdisp_clearbuffer(dd);
- else { /* if bg_colour is set, draw background 'by hand' */
+ else { /* if bgcol is set, draw background 'by hand' */
int x,y;
for (y = 0; y < fp_serdisp_getheight(dd); y++)
for (x = 0; x < fp_serdisp_getwidth(dd); x++)
- fp_serdisp_setpixcol(dd, x, y, bg_colour); /* >= 1.95: serdisp_setcolour(), < 1.95: serdisp_setpixel() */
+ fp_serdisp_setcolour(dd, x, y, (long)bgcol);
}
}
+#if 0
void cDriverSerDisp::Set8Pixels(int x, int y, unsigned char data) {
int i, start, pixel;
@@ -476,12 +480,50 @@ void cDriverSerDisp::Set8Pixels(int x, int y, unsigned char data) {
for (i = 0; i < 8; i++) {
pixel = data & (1 << i);
- if (pixel)
- fp_serdisp_setpixcol(dd, start + i, y, fg_colour); /* >= 1.95: serdisp_setcolour(), < 1.95: serdisp_setpixel() */
- else if (!pixel && bg_colour != -1) /* if bg_colour is set: use it if pixel is not set */
- fp_serdisp_setpixcol(dd, start + i, y, bg_colour); /* >= 1.95: serdisp_setcolour(), < 1.95: serdisp_setpixel() */
+ if (pixel) {
+ SetPixel(start + i, y, (long)fgcol);
+ } else if (!pixel && bgcol != GRAPHLCD_ERRCOL) { /* if bgcol is set: use it if pixel is not set */
+ SetPixel(start + i, y, (long)bgcol);
+ }
}
}
+#endif
+
+void cDriverSerDisp::SetPixel(int x, int y, uint32_t data)
+{
+ fp_serdisp_setcolour(dd, x, y, (long)data);
+}
+
+#if 0
+// temporarily overwrite SetScreen() until problem with 'to Clear() or not to Clear()' is solved
+void cDriverSerDisp::SetScreen(const unsigned char * data, int wid, int hgt, int lineSize)
+{
+ int x, y;
+
+ if (wid > width)
+ wid = width;
+ if (hgt > height)
+ hgt = height;
+
+ //Clear();
+ if (data)
+ {
+ for (y = 0; y < hgt; y++)
+ {
+ for (x = 0; x < (wid / 8); x++)
+ {
+ Set8Pixels(x * 8, y, data[y * lineSize + x]);
+ }
+ if (width % 8)
+ {
+ Set8Pixels((wid / 8) * 8, y, data[y * lineSize + wid / 8] & bitmaskl[wid % 8 - 1]);
+ }
+ }
+ } else {
+ Clear();
+ }
+}
+#endif
void cDriverSerDisp::Refresh(bool refreshAll)
{
@@ -495,9 +537,114 @@ void cDriverSerDisp::Refresh(bool refreshAll)
}
void cDriverSerDisp::SetBrightness(unsigned int percent)
-{
- if ( supports_options && (fp_serdisp_isoption(dd, "BRIGHTNESS") == 1) ) /* if == 1: option is existing AND r/w */
- fp_serdisp_setoption(dd, "BRIGHTNESS", (long)percent);
+{
+ if ( dd && supports_options && (fp_serdisp_isoption(dd, "BRIGHTNESS") == 1) ) /* if == 1: option is existing AND r/w */
+ fp_serdisp_setoption(dd, "BRIGHTNESS", (long)percent);
+}
+
+uint32_t cDriverSerDisp::GetDefaultBackgroundColor(void) {
+ if ( dd && supports_options && fp_serdisp_isoption(dd, "SELFEMITTING") && (fp_serdisp_getoption(dd, "SELFEMITTING", 0)) ) {
+ return GRAPHLCD_Black;
+ }
+ return GRAPHLCD_White;
+}
+
+
+bool cDriverSerDisp::SetFeature (const std::string & Feature, int value)
+{
+ if (dd && (strcasecmp(Feature.c_str(), "TOUCHSCREEN") == 0 || strcasecmp(Feature.c_str(), "TOUCH") == 0)) {
+ if (fp_SDGPI_search && fp_SDGPI_isenabled && fp_SDGPI_enable) {
+ uint8_t gpid = fp_SDGPI_search(dd, Feature.c_str());
+ if (gpid == 0xFF)
+ return false;
+
+ int ena = fp_SDGPI_isenabled(dd, gpid);
+ bool enable = (value == 1) ? true : false;
+ if (ena == enable) { // already enabled or disabled
+ return true;
+ } else {
+ bool rc = (fp_SDGPI_enable(dd, gpid, ((enable) ? 1 : 0)) >= 0) ? true : false;
+
+ if (enable && rc && fp_SDEVLP_add_listener) {
+ fp_SDEVLP_add_listener(dd, gpid, wrapEventListener);
+ }
+ return true;
+ }
+ }
+ }
+ return false;
+}
+
+bool cDriverSerDisp::GetDriverFeature (const std::string & Feature, int & value) {
+ if (dd) {
+ if (strcasecmp(Feature.c_str(), "depth") == 0) {
+ value = fp_serdisp_getdepth(dd);
+ return true;
+ } else if (strcasecmp(Feature.c_str(), "ismonochrome") == 0) {
+ value = (fp_serdisp_getdepth(dd) == 1) ? 1 : 0;
+ return true;
+ } else if (strcasecmp(Feature.c_str(), "isgreyscale") == 0 || strcasecmp(Feature.c_str(), "isgrayscale") == 0) {
+ value = (fp_serdisp_getdepth(dd) > 1 && fp_serdisp_getdepth(dd) < 8) ? 1 : 0;
+ return true;
+ } else if (strcasecmp(Feature.c_str(), "iscolour") == 0 || strcasecmp(Feature.c_str(), "iscolor") == 0) {
+ value = (fp_serdisp_getdepth(dd) >= 8) ? 1 : 0;
+ return true;
+ } else if (strcasecmp(Feature.c_str(), "touch") == 0 || strcasecmp(Feature.c_str(), "touchscreen") == 0) {
+ if (fp_SDGPI_search && fp_SDGPI_isenabled) {
+ uint8_t gpid = fp_SDGPI_search(dd, Feature.c_str());
+ value = (gpid != 0xFF && fp_SDGPI_isenabled(dd, gpid)) ? 1 : 0;
+ }
+ return true;
+ }
+ }
+ value = 0;
+ return false;
+}
+
+cGLCDEvent * cDriverSerDisp::GetEvent(void) {
+ tTouchEvent* tev = touchEvents[dd];
+ if (tev && tev->touchChanged == false)
+ return NULL;
+
+ cTouchEvent * ev = new cTouchEvent();
+
+ ev->x = tev->touchX;
+ ev->y = tev->touchY;
+ ev->touch = tev->touchT;
+ tev->touchChanged = false;
+
+ return ev;
+}
+
+static void wrapEventListener(void* dd, SDGP_event_t* event) {
+ if (!event) return;
+ if (event->type == SDGPT_SIMPLETOUCH) {
+ SDGP_evpkt_simpletouch_t simpletouch;
+ memcpy(&simpletouch, &event->data, sizeof(SDGP_evpkt_simpletouch_t));
+
+ tTouchEvent* tev = touchEvents[dd];
+ if (tev) {
+ tev->touchChanged = true;
+ tev->touchX = simpletouch.norm_x;
+ tev->touchY = simpletouch.norm_y;
+ tev->touchT = simpletouch.norm_touch;
+ }
+ } else if (event->type == SDGPT_GENERICTOUCH) {
+ SDGP_evpkt_generictouch_t generictouch;
+ memcpy(&generictouch, &event->data, sizeof(SDGP_evpkt_generictouch_t));
+
+ /* ignore all but SDGPT_TOUCHDOWN events */
+ if (generictouch.type != SDGPT_TOUCHDOWN)
+ return;
+
+ tTouchEvent* tev = touchEvents[dd];
+ if (tev) {
+ tev->touchChanged = true;
+ tev->touchX = generictouch.norm_x;
+ tev->touchY = generictouch.norm_y;
+ tev->touchT = (int)generictouch.norm_touch;
+ }
+ }
}
} // end of namespace
diff --git a/glcddrivers/serdisp.h b/glcddrivers/serdisp.h
index c84874e..31fcdad 100644
--- a/glcddrivers/serdisp.h
+++ b/glcddrivers/serdisp.h
@@ -7,32 +7,84 @@
* This file is released under the GNU General Public License. Refer
* to the COPYING file distributed with this package.
*
- * (c) 2003-2010 Wolfgang Astleitner <mrwastl AT users.sourceforge.net>
+ * (c) 2003-2013 Wolfgang Astleitner <mrwastl AT users.sourceforge.net>
*/
#ifndef _GLCDDRIVERS_SERDISP_H_
#define _GLCDDRIVERS_SERDISP_H_
#include "driver.h"
-
+#include <sys/time.h>
namespace GLCD
{
+/* event-type for GPIs, GPOs, and data exchange messages. min. size: 16 byte, max size: 12 + 64) */
+typedef struct SDGP_event_s { /* 16 to 78 bytes */
+ /* byte 0 */
+ uint8_t type; /* one of SDGPT_* */
+ uint8_t cmdid; /* command-ID (one of SD_CMD_*) */
+ uint8_t devid; /* device ID, 0 == local */
+ uint8_t subid; /* gp-ID or page-ID */
+ /* byte 4 */
+ struct timeval timestamp; /* timestamp (8 bytes) */
+ /* byte 12 */
+ union {
+ int32_t value; /* if single value event: value */
+ struct { /* if streaming event or package: */
+ uint16_t length; /* length of stream if known or 0 if some stop tag is used */
+ uint8_t word_size; /* stream elements are bytes/chars (0 or 1), shorts (2), or longs (4) */
+ uint8_t _reserved; /* reserved for later use */
+ };
+ uint8_t data[64]; /* if data-package type: max. 64 byte payload */
+ };
+} SDGP_event_t;
+
+/* event-payload-type for simple touchscreen events (no multitouch or similar) */
+typedef struct SDGP_evpkt_simpletouch_s { /* 16 bytes */
+ /* 12 bytes */
+ int16_t raw_x; /* raw coordinate X */
+ int16_t raw_y; /* raw coordinate Y */
+ int16_t raw_touch; /* raw touch value */
+ int16_t norm_x; /* normalised coordinate X (norm_x <= dd->width) */
+ int16_t norm_y; /* normalised coordinate Y (norm_y <= dd->height) */
+ int16_t norm_touch; /* normalised touch value */
+} SDGP_evpkt_simpletouch_t;
+
+/* event-payload-type for generic touchscreen events (only importat stuff is defined here, rest is ignored (read only!) */
+typedef struct SDGP_evpkt_generictouch_s { /* 16 bytes */
+ uint8_t type; /* event type: 0: up, 1: down, 2: move */
+ uint8_t flags; /* 0000 000x ... 0: binary touch, 1: touch with pressure information */
+ /* xxxx 0000 ... 0000: union not used */
+ /* 0001: raw touch information included in union */
+ /* 0010: reserved */
+ /* 0011: reserved */
+ int16_t norm_x; /* normalised coordinate X (norm_x <= dd->width) */
+ int16_t norm_y; /* normalised coordinate Y (norm_y <= dd->height) */
+ uint16_t norm_touch; /* normalised touch value */
+ /* ignore all union stuff */
+} SDGP_evpkt_generictouch_t;
+
+
+typedef struct {
+ bool touchChanged;
+ int touchX;
+ int touchY;
+ int touchT;
+} tTouchEvent;
+
+
+typedef void (*fp_eventlistener_t) (void* dd, SDGP_event_t* recylce);
+
class cDriverConfig;
class cDriverSerDisp : public cDriver
{
private:
- cDriverConfig * config;
- cDriverConfig * oldConfig;
-
long serdisp_version;
int supports_options;
- long fg_colour;
- long bg_colour;
void* sdhnd; // serdisplib handle
void* dd; // display descriptor
@@ -42,39 +94,57 @@ private:
void* (*fp_SDCONN_open) (const char sdcdev[]);
- void* (*fp_PP_open) (const char sdcdev[]);
- void* (*fp_PP_close) (void* sdcd);
-
void* (*fp_serdisp_init) (void* sdcd, const char dispname[], const char extra[]);
void (*fp_serdisp_rewrite) (void* dd);
void (*fp_serdisp_update) (void* dd);
void (*fp_serdisp_clearbuffer) (void* dd);
- void (*fp_serdisp_setpixcol) (void* dd, int x, int y, long colour); // serdisp_setpixel or serdisp_setcolour
+ void (*fp_serdisp_setcolour) (void* dd, int x, int y, long colour);
int (*fp_serdisp_feature) (void* dd, int feature, int value);
int (*fp_serdisp_isoption) (void* dd, const char* optionname);
void (*fp_serdisp_setoption) (void* dd, const char* optionname, long value);
long (*fp_serdisp_getoption) (void* dd, const char* optionname, int* typesize);
int (*fp_serdisp_getwidth) (void* dd);
int (*fp_serdisp_getheight) (void* dd);
+ int (*fp_serdisp_getcolours) (void* dd);
+ int (*fp_serdisp_getdepth) (void* dd);
void (*fp_serdisp_quit) (void* dd);
void (*fp_serdisp_close) (void* dd);
+ uint8_t (*fp_SDGPI_search) (void* dd, const char* gpname);
+ int (*fp_SDGPI_isenabled) (void* dd, uint8_t gpid);
+ int (*fp_SDGPI_enable) (void* dd, uint8_t gpid, int enable);
+ int (*fp_SDEVLP_add_listener) (void* dd, uint8_t gpid, fp_eventlistener_t eventlistener );
+ const char*
+ (*fp_serdisp_defaultdevice) (const char* dispname);
int CheckSetup();
+ void eventListener (void* dd, SDGP_event_t* recycle);
+
+ tTouchEvent* touchEvent;
+
+protected:
+ virtual bool GetDriverFeature (const std::string & Feature, int & value);
+ virtual uint32_t GetDefaultBackgroundColor(void);
+
public:
cDriverSerDisp(cDriverConfig * config);
- virtual ~cDriverSerDisp();
virtual int Init();
virtual int DeInit();
virtual void Clear();
- virtual void Set8Pixels(int x, int y, unsigned char data);
+ virtual void SetPixel(int x, int y, uint32_t data);
+
virtual void Refresh(bool refreshAll = false);
virtual void SetBrightness(unsigned int percent);
+
+ virtual bool SetFeature (const std::string & Feature, int value);
+
+ virtual cGLCDEvent * GetEvent(void);
+
};
+} // end of namespace
#endif
-} // end of namespace
diff --git a/glcddrivers/simlcd.c b/glcddrivers/simlcd.c
index 6dc1dfe..d1da90f 100644
--- a/glcddrivers/simlcd.c
+++ b/glcddrivers/simlcd.c
@@ -9,6 +9,8 @@
* to the COPYING file distributed with this package.
*
* (c) 2001-2004 Carsten Siebholz <c.siebholz AT t-online.de>
+ * (c) 2011 Dirk Heiser
+ * (c) 2011 Wolfgang Astleitner <mrwastl AT users.sourceforge.net>
*/
#include <stdio.h>
@@ -19,22 +21,22 @@
#include "config.h"
#include "simlcd.h"
+#define DISPLAY_REFRESH_FILE "/tmp/simlcd.sem"
+#define DISPLAY_DATA_FILE "/tmp/simlcd.dat"
+#define TOUCH_REFRESH_FILE "/tmp/simtouch.sem"
+#define TOUCH_DATA_FILE "/tmp/simtouch.dat"
-namespace GLCD
-{
+#define FG_CHAR "#"
+#define BG_CHAR "."
-cDriverSimLCD::cDriverSimLCD(cDriverConfig * config)
-: config(config)
+namespace GLCD
{
- oldConfig = new cDriverConfig(*config);
-}
-cDriverSimLCD::~cDriverSimLCD()
+cDriverSimLCD::cDriverSimLCD(cDriverConfig * config) : cDriver(config)
{
- delete oldConfig;
}
-int cDriverSimLCD::Init()
+int cDriverSimLCD::Init(void)
{
width = config->width;
if (width <= 0)
@@ -51,13 +53,13 @@ int cDriverSimLCD::Init()
}
// setup lcd array
- LCD = new unsigned char *[(width + 7) / 8];
+ LCD = new uint32_t *[width];
if (LCD)
{
- for (int x = 0; x < (width + 7) / 8; x++)
+ for (int x = 0; x < width; x++)
{
- LCD[x] = new unsigned char[height];
- memset(LCD[x], 0, height);
+ LCD[x] = new uint32_t[height];
+ //memset(LCD[x], 0, height);
}
}
@@ -70,12 +72,12 @@ int cDriverSimLCD::Init()
return 0;
}
-int cDriverSimLCD::DeInit()
+int cDriverSimLCD::DeInit(void)
{
// free lcd array
if (LCD)
{
- for (int x = 0; x < (width + 7) / 8; x++)
+ for (int x = 0; x < width; x++)
{
delete[] LCD[x];
}
@@ -85,7 +87,7 @@ int cDriverSimLCD::DeInit()
return 0;
}
-int cDriverSimLCD::CheckSetup()
+int cDriverSimLCD::CheckSetup(void)
{
if (config->width != oldConfig->width ||
config->height != oldConfig->height)
@@ -105,29 +107,29 @@ int cDriverSimLCD::CheckSetup()
return 0;
}
-void cDriverSimLCD::Clear()
+void cDriverSimLCD::Clear(void)
{
- for (int x = 0; x < (width + 7) / 8; x++)
- memset(LCD[x], 0, height);
+ for (int y = 0; y < height; y++)
+ {
+ for (int x = 0; x < width; x++)
+ {
+ LCD[x][y] = GRAPHLCD_White;
+ }
+ }
}
-void cDriverSimLCD::Set8Pixels(int x, int y, unsigned char data)
+void cDriverSimLCD::SetPixel(int x, int y, uint32_t data)
{
if (x >= width || y >= height)
return;
- if (!config->upsideDown)
- {
- // normal orientation
- LCD[x / 8][y] = LCD[x / 8][y] | data;
- }
- else
+ if (config->upsideDown)
{
// upside down orientation
x = width - 1 - x;
y = height - 1 - y;
- LCD[x / 8][y] = LCD[x / 8][y] | ReverseBits(data);
}
+ LCD[x][y] = data;
}
void cDriverSimLCD::Refresh(bool refreshAll)
@@ -135,36 +137,41 @@ void cDriverSimLCD::Refresh(bool refreshAll)
FILE * fp = NULL;
int x;
int y;
- int i;
- unsigned char c;
if (CheckSetup() > 0)
refreshAll = true;
- fp = fopen("/tmp/simlcd.sem", "r");
+ fp = fopen(DISPLAY_REFRESH_FILE, "r");
if (!fp || refreshAll)
{
if (fp)
fclose(fp);
- fp = fopen("/tmp/simlcd.dat", "w");
+ fp = fopen(DISPLAY_DATA_FILE, "w");
if (fp)
{
for (y = 0; y < height; y++)
{
- for (x = 0; x < (width + 7) / 8; x++)
+ for (x = 0; x < width; x++)
{
- c = LCD[x][y] ^ (config->invert ? 0xff : 0x00);
- for (i = 0; i < 8; i++)
+ if (LCD[x][y] == GRAPHLCD_Black)
{
- if (c & 0x80)
+ if (!config->invert)
{
- fprintf(fp,"#");
+ fprintf(fp,FG_CHAR);
+ } else
+ {
+ fprintf(fp,BG_CHAR);
}
- else
+ }
+ else
+ {
+ if (!config->invert)
{
- fprintf(fp,".");
+ fprintf(fp,BG_CHAR);
+ } else
+ {
+ fprintf(fp,FG_CHAR);
}
- c = c << 1;
}
}
fprintf(fp,"\n");
@@ -172,7 +179,7 @@ void cDriverSimLCD::Refresh(bool refreshAll)
fclose(fp);
}
- fp = fopen("/tmp/simlcd.sem", "w");
+ fp = fopen(DISPLAY_REFRESH_FILE, "w");
fclose(fp);
}
else
@@ -181,4 +188,31 @@ void cDriverSimLCD::Refresh(bool refreshAll)
}
}
+uint32_t cDriverSimLCD::GetBackgroundColor(void)
+{
+ return GRAPHLCD_White;
+}
+
+bool cDriverSimLCD::GetDriverFeature(const std::string & Feature, int & value)
+{
+ if (strcasecmp(Feature.c_str(), "depth") == 0) {
+ value = 1;
+ return true;
+ } else if (strcasecmp(Feature.c_str(), "ismonochrome") == 0) {
+ value = true;
+ return true;
+ } else if (strcasecmp(Feature.c_str(), "isgreyscale") == 0 || strcasecmp(Feature.c_str(), "isgrayscale") == 0) {
+ value = false;
+ return true;
+ } else if (strcasecmp(Feature.c_str(), "iscolour") == 0 || strcasecmp(Feature.c_str(), "iscolor") == 0) {
+ value = false;
+ return true;
+ } else if (strcasecmp(Feature.c_str(), "touch") == 0 || strcasecmp(Feature.c_str(), "touchscreen") == 0) {
+ value = false;
+ return true;
+ }
+ value = 0;
+ return false;
+}
+
} // end of namespace
diff --git a/glcddrivers/simlcd.h b/glcddrivers/simlcd.h
index 8b2aca8..12f819c 100644
--- a/glcddrivers/simlcd.h
+++ b/glcddrivers/simlcd.h
@@ -9,6 +9,8 @@
* to the COPYING file distributed with this package.
*
* (c) 2001-2004 Carsten Siebholz <c.siebholz AT t-online.de>
+ * (c) 2011 Dirk Heiser
+ * (c) 2011 Wolfgang Astleitner <mrwastl AT users.sourceforge.net>
*/
#ifndef _GLCDDRIVERS_SIMLCD_H_
@@ -25,22 +27,20 @@ class cDriverConfig;
class cDriverSimLCD : public cDriver
{
private:
- unsigned char ** LCD;
- cDriverConfig * config;
- cDriverConfig * oldConfig;
-
+ uint32_t ** LCD;
int CheckSetup();
public:
cDriverSimLCD(cDriverConfig * config);
- virtual ~cDriverSimLCD();
virtual int Init();
virtual int DeInit();
virtual void Clear();
- virtual void Set8Pixels(int x, int y, unsigned char data);
+ virtual void SetPixel(int x, int y, uint32_t data);
virtual void Refresh(bool refreshAll = false);
+ virtual uint32_t GetBackgroundColor(void);
+ virtual bool GetDriverFeature (const std::string & Feature, int & value);
};
} // end of namespace
diff --git a/glcddrivers/ssd1306.c b/glcddrivers/ssd1306.c
new file mode 100644
index 0000000..852ea13
--- /dev/null
+++ b/glcddrivers/ssd1306.c
@@ -0,0 +1,340 @@
+/*
+ * GraphLCD driver library
+ *
+ * ssd1306.c - SSD1306 OLED driver class
+ *
+ * This file is released under the GNU General Public License. Refer
+ * to the COPYING file distributed with this package.
+ *
+ * (c) 2014 Andreas Regel <andreas.regel AT powarman.de>
+ */
+
+#include <stdint.h>
+#include <syslog.h>
+#include <unistd.h>
+#include <cstring>
+
+#include <wiringPi.h>
+#include <wiringPiSPI.h>
+
+#include "common.h"
+#include "config.h"
+#include "ssd1306.h"
+
+
+namespace GLCD
+{
+
+const int kLcdWidth = 128;
+const int kLcdHeight = 64;
+
+const int kSpiBus = 0;
+
+const int kGpioReset = 15;
+const int kGpioDC = 16;
+
+const uint8_t kCmdSetLowerColumn = 0x00;
+const uint8_t kCmdSetHigherColumn = 0x10;
+const uint8_t kCmdSetMemoryAddressingMode = 0x20;
+const uint8_t kCmdSetColumnAddress = 0x21;
+const uint8_t kCmdSetPageAddress = 0x22;
+const uint8_t kCmdSetDisplayStartLine = 0x40;
+const uint8_t kCmdSetContrast = 0x81;
+const uint8_t kCmdSetChargePump = 0x8D;
+const uint8_t kCmdSetSegmentReMap = 0xA0;
+const uint8_t kCmdEntireDisplayOnResume = 0xA4;
+const uint8_t kCmdEntireDisplayOn = 0xA5;
+const uint8_t kCmdSetNormalDisplay = 0xA6;
+const uint8_t kCmdSetInverseDisplay = 0xA7;
+const uint8_t kCmdSetMultiplexRatio = 0xA8;
+const uint8_t kCmdSetDisplayOff = 0xAE;
+const uint8_t kCmdSetDisplayOn = 0xAF;
+const uint8_t kCmdSetPageStart = 0xB0;
+const uint8_t kCmdSetComScanInc = 0xC0;
+const uint8_t kCmdSetComScanDec = 0xC8;
+const uint8_t kCmdSetDisplayOffset = 0xD3;
+const uint8_t kCmdSetDisplayClockDiv = 0xD5;
+const uint8_t kCmdSetPreChargePeriod = 0xD9;
+const uint8_t kCmdSetComPins = 0xDA;
+const uint8_t kCmdSetVComDeselectLevel = 0xDB;
+
+
+cDriverSSD1306::cDriverSSD1306(cDriverConfig * config)
+: cDriver(config)
+{
+ refreshCounter = 0;
+
+ wiringPiSetup();
+}
+
+cDriverSSD1306::~cDriverSSD1306()
+{
+ //delete port;
+}
+
+int cDriverSSD1306::Init()
+{
+ int x;
+
+ width = config->width;
+ if (width <= 0)
+ width = kLcdWidth;
+ height = config->height;
+ if (height <= 0)
+ height = kLcdHeight;
+
+ for (unsigned int i = 0; i < config->options.size(); i++)
+ {
+ if (config->options[i].name == "")
+ {
+ }
+ }
+
+ // setup lcd array (wanted state)
+ newLCD = new unsigned char*[width];
+ if (newLCD)
+ {
+ for (x = 0; x < width; x++)
+ {
+ newLCD[x] = new unsigned char[(height + 7) / 8];
+ memset(newLCD[x], 0, (height + 7) / 8);
+ }
+ }
+ // setup lcd array (current state)
+ oldLCD = new unsigned char*[width];
+ if (oldLCD)
+ {
+ for (x = 0; x < width; x++)
+ {
+ oldLCD[x] = new unsigned char[(height + 7) / 8];
+ memset(oldLCD[x], 0, (height + 7) / 8);
+ }
+ }
+
+ if (config->device == "")
+ {
+ return -1;
+ }
+
+ pinMode(kGpioReset, OUTPUT);
+ pinMode(kGpioDC, OUTPUT);
+
+ digitalWrite(kGpioReset, HIGH);
+ digitalWrite(kGpioDC, LOW);
+
+ wiringPiSPISetup(kSpiBus, 1000000);
+
+ /* reset display */
+ Reset();
+ usleep(1000);
+
+ WriteCommand(kCmdSetDisplayOff);
+
+ if (height == 64)
+ {
+ WriteCommand(kCmdSetMultiplexRatio, 0x3F);
+ WriteCommand(kCmdSetComPins, 0x12);
+ }
+ else if (height == 32)
+ {
+ WriteCommand(kCmdSetMultiplexRatio, 0x1F);
+ WriteCommand(kCmdSetComPins, 0x02);
+ }
+
+ WriteCommand(kCmdSetDisplayOffset, 0x00);
+ WriteCommand(kCmdSetDisplayStartLine | 0x00);
+ WriteCommand(kCmdSetMemoryAddressingMode, 0x01);
+ WriteCommand(kCmdSetSegmentReMap | 0x01);
+ WriteCommand(kCmdSetComScanDec);
+ WriteCommand(kCmdSetContrast, config->brightness * 255 / 100);
+ WriteCommand(kCmdEntireDisplayOnResume);
+ WriteCommand(kCmdSetNormalDisplay);
+ WriteCommand(kCmdSetDisplayClockDiv, 0x80);
+ WriteCommand(kCmdSetChargePump, 0x14);
+ WriteCommand(kCmdSetDisplayOn);
+
+ *oldConfig = *config;
+
+ // clear display
+ Clear();
+
+ syslog(LOG_INFO, "%s: SSD1306 initialized.\n", config->name.c_str());
+ return 0;
+}
+
+int cDriverSSD1306::DeInit()
+{
+ int x;
+ // free lcd array (wanted state)
+ if (newLCD)
+ {
+ for (x = 0; x < width; x++)
+ {
+ delete[] newLCD[x];
+ }
+ delete[] newLCD;
+ }
+ // free lcd array (current state)
+ if (oldLCD)
+ {
+ for (x = 0; x < width; x++)
+ {
+ delete[] oldLCD[x];
+ }
+ delete[] oldLCD;
+ }
+
+ return 0;
+}
+
+int cDriverSSD1306::CheckSetup()
+{
+ if (config->device != oldConfig->device ||
+ config->width != oldConfig->width ||
+ config->height != oldConfig->height)
+ {
+ DeInit();
+ Init();
+ return 0;
+ }
+
+ if (config->upsideDown != oldConfig->upsideDown ||
+ config->invert != oldConfig->invert)
+ {
+ oldConfig->upsideDown = config->upsideDown;
+ oldConfig->invert = config->invert;
+ return 1;
+ }
+ return 0;
+}
+
+void cDriverSSD1306::Clear()
+{
+ for (int x = 0; x < width; x++)
+ memset(newLCD[x], 0, (height + 7) / 8);
+}
+
+
+void cDriverSSD1306::SetPixel(int x, int y, uint32_t data)
+{
+ if (x >= width || y >= height)
+ return;
+
+ if (config->upsideDown)
+ {
+ x = width - 1 - x;
+ y = height - 1 - y;
+ }
+
+ int offset = (y % 8);
+ if (data == GRAPHLCD_White)
+ newLCD[x][y / 8] |= (1 << offset);
+ else
+ newLCD[x][y / 8] &= ( 0xFF ^ (1 << offset) );
+}
+
+
+#if 0
+void cDriverSSD1306::Set8Pixels(int x, int y, unsigned char data)
+{
+ if (x >= width || y >= height)
+ return;
+
+ if (!config->upsideDown)
+ {
+ int offset = 7 - (y % 8);
+ for (int i = 0; i < 8; i++)
+ {
+ newLCD[x + i][y / 8] |= ((data >> (7 - i)) << offset) & (1 << offset);
+ }
+ }
+ else
+ {
+ x = width - 1 - x;
+ y = height - 1 - y;
+ int offset = 7 - (y % 8);
+ for (int i = 0; i < 8; i++)
+ {
+ newLCD[x - i][y / 8] |= ((data >> (7 - i)) << offset) & (1 << offset);
+ }
+ }
+}
+#endif
+
+void cDriverSSD1306::Refresh(bool refreshAll)
+{
+ int x;
+ int y;
+ uint8_t numPages = (height + 7) / 8;
+ unsigned char data[16];
+
+ if (CheckSetup() == 1)
+ refreshAll = true;
+
+ if (config->refreshDisplay > 0)
+ {
+ refreshCounter = (refreshCounter + 1) % config->refreshDisplay;
+ if (!refreshAll && !refreshCounter)
+ refreshAll = true;
+ }
+
+ refreshAll = true;
+ if (refreshAll)
+ {
+ WriteCommand(kCmdSetColumnAddress, 0, width - 1);
+ WriteCommand(kCmdSetPageAddress, 0, numPages - 1);
+ for (x = 0; x < width; x++)
+ {
+ for (y = 0; y < numPages; y++)
+ {
+ data[y] = (newLCD[x][y]) ^ (config->invert ? 0xff : 0x00);
+ }
+ WriteData(data, numPages);
+ memcpy(oldLCD[x], newLCD[x], numPages);
+ }
+ // and reset RefreshCounter
+ refreshCounter = 0;
+ }
+ else
+ {
+ // draw only the changed bytes
+ }
+}
+
+void cDriverSSD1306::SetBrightness(unsigned int percent)
+{
+ WriteCommand(kCmdSetContrast, percent * 255 / 100);
+}
+
+void cDriverSSD1306::Reset()
+{
+ digitalWrite(kGpioReset, LOW);
+ usleep(1000);
+ digitalWrite(kGpioReset, HIGH);
+}
+
+void cDriverSSD1306::WriteCommand(uint8_t command)
+{
+ wiringPiSPIDataRW(kSpiBus, &command, 1);
+}
+
+void cDriverSSD1306::WriteCommand(uint8_t command, uint8_t argument)
+{
+ uint8_t buffer[2] = {command, argument};
+ wiringPiSPIDataRW(kSpiBus, buffer, 2);
+}
+
+void cDriverSSD1306::WriteCommand(uint8_t command, uint8_t argument1, uint8_t argument2)
+{
+ uint8_t buffer[3] = {command, argument1, argument2};
+ wiringPiSPIDataRW(kSpiBus, buffer, 3);
+}
+
+void cDriverSSD1306::WriteData(uint8_t * buffer, uint32_t length)
+{
+ digitalWrite(kGpioDC, HIGH);
+ wiringPiSPIDataRW(kSpiBus, buffer, length);
+ digitalWrite(kGpioDC, LOW);
+}
+
+} // end of namespace
diff --git a/glcddrivers/ssd1306.h b/glcddrivers/ssd1306.h
new file mode 100644
index 0000000..5d06b4c
--- /dev/null
+++ b/glcddrivers/ssd1306.h
@@ -0,0 +1,53 @@
+/*
+ * GraphLCD driver library
+ *
+ * ssd1306.h - SSD1306 OLED driver class
+ *
+ * This file is released under the GNU General Public License. Refer
+ * to the COPYING file distributed with this package.
+ *
+ * (c) 2014 Andreas Regel <andreas.regel AT powarman.de>
+ */
+
+#ifndef _GLCDDRIVERS_SSD1306_H_
+#define _GLCDDRIVERS_SSD1306_H_
+
+#include "driver.h"
+
+namespace GLCD
+{
+
+class cDriverConfig;
+
+class cDriverSSD1306 : public cDriver
+{
+private:
+ unsigned char ** newLCD; // wanted state
+ unsigned char ** oldLCD; // current state
+ int refreshCounter;
+
+ int CheckSetup();
+
+ void Reset();
+ void WriteCommand(uint8_t command);
+ void WriteCommand(uint8_t command, uint8_t argument);
+ void WriteCommand(uint8_t command, uint8_t argument1, uint8_t argument2);
+ void WriteData(uint8_t * buffer, uint32_t length);
+
+public:
+ cDriverSSD1306(cDriverConfig * config);
+ virtual ~cDriverSSD1306();
+
+ virtual int Init();
+ virtual int DeInit();
+
+ virtual void Clear();
+ virtual void SetPixel(int x, int y, uint32_t data);
+ //virtual void Set8Pixels(int x, int y, unsigned char data);
+ virtual void Refresh(bool refreshAll = false);
+ virtual void SetBrightness(unsigned int percent);
+};
+
+} // end of namespace
+
+#endif
diff --git a/glcddrivers/t6963c.c b/glcddrivers/t6963c.c
index d42da35..aec2585 100644
--- a/glcddrivers/t6963c.c
+++ b/glcddrivers/t6963c.c
@@ -8,7 +8,8 @@
* This file is released under the GNU General Public License. Refer
* to the COPYING file distributed with this package.
*
- * (c) 2003, 2004 Andreas Regel <andreas.regel AT powarman.de>
+ * (c) 2003-2004 Andreas Regel <andreas.regel AT powarman.de>
+ * (c) 2011 Wolfgang Astleitner <mrwastl AT users.sourceforge.net>
*/
#include <syslog.h>
@@ -107,10 +108,8 @@ const unsigned char kSerialCDLO = 0x04; //
cDriverT6963C::cDriverT6963C(cDriverConfig * config)
-: config(config)
+: cDriver(config)
{
- oldConfig = new cDriverConfig(*config);
-
port = new cParallelPort();
//width = config->width;
@@ -125,7 +124,6 @@ cDriverT6963C::cDriverT6963C(cDriverConfig * config)
cDriverT6963C::~cDriverT6963C()
{
delete port;
- delete oldConfig;
}
int cDriverT6963C::Init()
@@ -376,6 +374,52 @@ void cDriverT6963C::Clear()
memset(newLCD[x], 0, height);
}
+
+void cDriverT6963C::SetPixel(int x, int y, uint32_t data)
+{
+ if (x >= width || y >= height)
+ return;
+
+ if (FS == 6)
+ {
+ int pos = x % 6;
+ if (config->upsideDown)
+ {
+ x = width - 1 - x;
+ y = height - 1 - y;
+ } else {
+ pos = 5 - pos; // reverse bit position
+ }
+
+ // columns_per_line = (width + FS6-1) / FS6 (FS6 == 6 bits per byte used)
+ //int cols = (width + 6 - 1 ) / 6;
+ int col = x / 6;
+
+ if (data == GRAPHLCD_White)
+ newLCD[col][y] |= (1 << pos);
+ else
+ newLCD[col][y] &= ( 0x3F ^ (1 << pos) );
+ }
+ else
+ {
+ int pos = x % 8;
+ if (config->upsideDown)
+ {
+ x = width - 1 - x;
+ y = height - 1 - y;
+ } else {
+ pos = 7 - pos; // reverse bit position
+ }
+
+ if (data == GRAPHLCD_White)
+ newLCD[x / 8][y] |= (1 << pos);
+ else
+ newLCD[x / 8][y] &= ( 0xFF ^ (1 << pos) );
+ }
+}
+
+
+#if 0
void cDriverT6963C::Set8Pixels(int x, int y, unsigned char data)
{
if (x >= width || y >= height)
@@ -446,6 +490,7 @@ void cDriverT6963C::Set8Pixels(int x, int y, unsigned char data)
}
}
}
+#endif
void cDriverT6963C::Refresh(bool refreshAll)
{
diff --git a/glcddrivers/t6963c.h b/glcddrivers/t6963c.h
index 88be16b..a9388b4 100644
--- a/glcddrivers/t6963c.h
+++ b/glcddrivers/t6963c.h
@@ -8,7 +8,8 @@
* This file is released under the GNU General Public License. Refer
* to the COPYING file distributed with this package.
*
- * (c) 2003, 2004 Andreas Regel <andreas.regel AT powarman.de>
+ * (c) 2003-2004 Andreas Regel <andreas.regel AT powarman.de>
+ * (c) 2011 Wolfgang Astleitner <mrwastl AT users.sourceforge.net>
*/
#ifndef _GLCDDRIVERS_T6963C_H_
@@ -28,8 +29,6 @@ private:
cParallelPort * port;
unsigned char ** newLCD; // wanted state
unsigned char ** oldLCD; // current state
- cDriverConfig * config;
- cDriverConfig * oldConfig;
int refreshCounter;
int bidirectLPT;
int displayMode;
@@ -67,7 +66,8 @@ public:
virtual int DeInit();
virtual void Clear();
- virtual void Set8Pixels(int x, int y, unsigned char data);
+ virtual void SetPixel(int x, int y, uint32_t data);
+ //virtual void Set8Pixels(int x, int y, unsigned char data);
virtual void Refresh(bool refreshAll = false);
};
diff --git a/glcddrivers/vncserver.c b/glcddrivers/vncserver.c
new file mode 100644
index 0000000..8461548
--- /dev/null
+++ b/glcddrivers/vncserver.c
@@ -0,0 +1,211 @@
+/*
+ * GraphLCD driver library
+ *
+ * vncserver.h - vncserver device
+ * Output goes to a vncserver device
+ *
+ * This file is released under the GNU General Public License. Refer
+ * to the COPYING file distributed with this package.
+ *
+ * (c) 2013 Michael Heyer
+ */
+
+#include <fcntl.h>
+#include <stdio.h>
+#include <syslog.h>
+#include <unistd.h>
+#include <sys/mman.h>
+#include <sys/ioctl.h>
+#include <cstdlib>
+#include <cstring>
+#include <iostream>
+
+#include "common.h"
+#include "config.h"
+#include "vncserver.h"
+
+
+namespace GLCD
+{
+
+cDriverVncServer::cDriverVncServer(cDriverConfig * config)
+: cDriver(config),
+ offbuff(0)
+{
+}
+
+int cDriverVncServer::Init()
+{
+ printf(" init.\n");
+
+ width = config->width;
+ height = config->height;
+
+ // Figure out the size of the screen in bytes
+ screensize = width * height * 4;
+ depth = 24;
+ server = rfbGetScreen(NULL,NULL,width,height,8,3,4);
+ if (!server)
+ {
+ syslog(LOG_ERR, "failed to creat vncserver device.\n");
+ return -1;
+ }
+
+ for (unsigned int i = 0; i < config->options.size(); i++)
+ {
+ if (config->options[i].name == "HttpDir")
+ {
+ server->httpDir = (char *)config->options[i].value.c_str();
+ }
+ }
+
+ // init bounding box
+ bbox[0] = width - 1; // x top
+ bbox[1] = height - 1; // y top
+ bbox[2] = 0; // x bottom
+ bbox[3] = 0; // y bottom
+
+ // reserve another memory to draw into
+ offbuff = new char[screensize];
+ if (!offbuff)
+ {
+ syslog(LOG_ERR, "%s: failed to alloc memory for vncserver device.\n", config->name.c_str());
+ return -1;
+ }
+
+ server->frameBuffer=offbuff;
+ rfbInitServer(server);
+
+ *oldConfig = *config;
+
+ // clear display
+ Refresh(true);
+
+ rfbRunEventLoop(server, 5000, true);
+
+ syslog(LOG_INFO, "%s: VncServer initialized.\n", config->name.c_str());
+ return 0;
+}
+
+int cDriverVncServer::DeInit()
+{
+ if (offbuff)
+ delete[] offbuff;
+ return 0;
+}
+
+int cDriverVncServer::CheckSetup()
+{
+ if (config->device != oldConfig->device ||
+ config->port != oldConfig->port ||
+ 32 != oldConfig->width ||
+ config->height != oldConfig->height)
+ {
+ DeInit();
+ Init();
+ return 0;
+ }
+
+ if (config->upsideDown != oldConfig->upsideDown ||
+ config->invert != oldConfig->invert)
+ {
+ oldConfig->upsideDown = config->upsideDown;
+ oldConfig->invert = config->invert;
+ return 1;
+ }
+ return 0;
+}
+
+void cDriverVncServer::SetPixel(int x, int y, uint32_t data)
+{
+ int location;
+
+ if (x >= width || y >= height)
+ return;
+
+ if (config->upsideDown)
+ {
+ x = width - 1 - x;
+ y = height - 1 - y;
+ }
+
+ location = (x + y * width) * 4;
+ unsigned char r,g,b;
+ r = (data & 0x00FF0000) >> 16;
+ g = (data & 0x0000FF00) >> 8;
+ b = (data & 0x000000FF) >> 0;
+ if (config->invert) {
+ r = 255 - r;
+ g = 255 - g;
+ b = 255 - b;
+ }
+ *(offbuff + location + 0) = r;
+ *(offbuff + location + 1) = g;
+ *(offbuff + location + 2) = b;
+
+ if (x < bbox[0]) bbox[0] = x;
+ if (y < bbox[1]) bbox[1] = y;
+ if (x > bbox[2]) bbox[2] = x;
+ if (y > bbox[3]) bbox[3] = y;
+}
+
+void cDriverVncServer::Clear()
+{
+ memset(offbuff, 0, screensize);
+ processDamage();
+}
+
+void cDriverVncServer::Refresh(bool refreshAll)
+{
+ if (refreshAll) {
+ bbox[0] = 0;
+ bbox[1] = 0;
+ bbox[2] = width - 1;
+ bbox[3] = height - 1;
+ }
+ processDamage();
+}
+
+bool cDriverVncServer::GetDriverFeature (const std::string & Feature, int & value) {
+ if (offbuff) {
+ if (strcasecmp(Feature.c_str(), "depth") == 0) {
+ value = depth;
+ return true;
+ } else if (strcasecmp(Feature.c_str(), "ismonochrome") == 0) {
+ value = 0;
+ return true;
+ } else if (strcasecmp(Feature.c_str(), "isgreyscale") == 0 || strcasecmp(Feature.c_str(), "isgrayscale") == 0) {
+ value = 0;
+ return true;
+ } else if (strcasecmp(Feature.c_str(), "iscolour") == 0 || strcasecmp(Feature.c_str(), "iscolor") == 0) {
+ value = 1;
+ return true;
+#if 0
+ } else if (strcasecmp(Feature.c_str(), "touch") == 0 || strcasecmp(Feature.c_str(), "touchscreen") == 0) {
+ if (...) {
+ value = (...) ? 1 : 0;
+ }
+ return true;
+#endif
+ }
+ }
+ value = 0;
+ return false;
+}
+
+
+/* defines for different damage processing calls needed by _update() */
+void cDriverVncServer::processDamage (void) {
+
+ if (!((bbox[0] == (width - 1)) && (bbox[1] == (height - 1)) && (bbox[2] == 0) && (bbox[3] == 0))) {
+ rfbMarkRectAsModified(server,bbox[0],bbox[1],bbox[2],bbox[3]);
+ }
+
+ /* reset bounding box */
+ bbox[0] = width - 1;
+ bbox[1] = height - 1;
+ bbox[2] = 0;
+ bbox[3] = 0;
+}
+
+} // end of namespace
diff --git a/glcddrivers/vncserver.h b/glcddrivers/vncserver.h
new file mode 100644
index 0000000..e1d155d
--- /dev/null
+++ b/glcddrivers/vncserver.h
@@ -0,0 +1,50 @@
+/*
+ * GraphLCD driver library
+ *
+ * vncserver.h - vncserver device
+ * Output goes to a vncserver device
+ *
+ * This file is released under the GNU General Public License. Refer
+ * to the COPYING file distributed with this package.
+ *
+ * (c) 2013 Michael Heyer
+ */
+
+#ifndef _GLCDDRIVERS_VNCSERVER_H_
+#define _GLCDDRIVERS_VNCSERVER_H_
+
+#include "driver.h"
+#include <rfb/rfb.h>
+
+namespace GLCD
+{
+
+class cDriverConfig;
+
+class cDriverVncServer : public cDriver
+{
+private:
+ char *offbuff;
+ rfbScreenInfoPtr server;
+ long int screensize;
+ int bbox[4];
+ int depth;
+
+ int CheckSetup();
+ void processDamage (void);
+protected:
+ virtual bool GetDriverFeature (const std::string & Feature, int & value);
+public:
+ cDriverVncServer(cDriverConfig * config);
+
+ virtual int Init();
+ virtual int DeInit();
+
+ virtual void Clear();
+ virtual void SetPixel(int x, int y, uint32_t data);
+ virtual void Refresh(bool refreshAll = false);
+};
+
+} // end of namespace
+
+#endif