summaryrefslogtreecommitdiff
path: root/glcddrivers
diff options
context:
space:
mode:
authorManuel Reimer <manuel.reimer@gmx.de>2018-02-03 16:43:53 +0100
committerManuel Reimer <manuel.reimer@gmx.de>2018-02-03 16:43:53 +0100
commit3bbe763488aa84fdf29047b6b38acd11f8274862 (patch)
treec515987004f20f07fe38e96ad4ddc17ba40366ca /glcddrivers
parentf5528fefca614b8a134a1b6ba9e7cc476a8a537e (diff)
downloadgraphlcd-base-3bbe763488aa84fdf29047b6b38acd11f8274862.tar.gz
graphlcd-base-3bbe763488aa84fdf29047b6b38acd11f8274862.tar.bz2
Add usbserlcd driver
Diffstat (limited to 'glcddrivers')
-rw-r--r--glcddrivers/Makefile2
-rw-r--r--glcddrivers/drivers.c4
-rw-r--r--glcddrivers/drivers.h1
-rw-r--r--glcddrivers/port.c25
-rw-r--r--glcddrivers/port.h5
-rw-r--r--glcddrivers/usbserlcd.c273
-rw-r--r--glcddrivers/usbserlcd.h61
7 files changed, 369 insertions, 2 deletions
diff --git a/glcddrivers/Makefile b/glcddrivers/Makefile
index 8c2b3d6..2e5b64c 100644
--- a/glcddrivers/Makefile
+++ b/glcddrivers/Makefile
@@ -14,7 +14,7 @@ BASENAME = libglcddrivers.so
LIBNAME = $(BASENAME).$(VERMAJOR).$(VERMINOR).$(VERMICRO)
-OBJS = common.o config.o driver.o drivers.o port.o simlcd.o framebuffer.o gu140x32f.o gu256x64-372.o gu256x64-3900.o hd61830.o ks0108.o image.o sed1330.o sed1520.o t6963c.o noritake800.o serdisp.o avrctl.o g15daemon.o network.o gu126x64D-K610A4.o dm140gink.o
+OBJS = common.o config.o driver.o drivers.o port.o simlcd.o framebuffer.o gu140x32f.o gu256x64-372.o gu256x64-3900.o hd61830.o ks0108.o image.o sed1330.o sed1520.o t6963c.o noritake800.o serdisp.o avrctl.o g15daemon.o network.o gu126x64D-K610A4.o dm140gink.o usbserlcd.o
HEADERS = config.h driver.h drivers.h
diff --git a/glcddrivers/drivers.c b/glcddrivers/drivers.c
index 4c7e67a..ca1c30b 100644
--- a/glcddrivers/drivers.c
+++ b/glcddrivers/drivers.c
@@ -30,6 +30,7 @@
#include "dm140gink.h"
#include "serdisp.h"
#include "g15daemon.h"
+#include "usbserlcd.h"
#ifdef HAVE_LIBHID
#include "futabaMDM166A.h"
#endif
@@ -70,6 +71,7 @@ tDriver drivers[] =
{"network", kDriverNetwork},
{"gu126x64D-K610A4", kDriverGU126X64D_K610A4},
{"dm140gink", kDriverDM140GINK},
+ {"usbserlcd", kDriverUSBserLCD},
#ifdef HAVE_LIBHID
{"futabaMDM166A", kDriverFutabaMDM166A},
#endif
@@ -144,6 +146,8 @@ cDriver * CreateDriver(int driverID, cDriverConfig * config)
return new cDriverGU126X64D_K610A4(config);
case kDriverDM140GINK:
return new cDriverDM140GINK(config);
+ case kDriverUSBserLCD:
+ return new cDriverUSBserLCD(config);
#ifdef HAVE_LIBHID
case kDriverFutabaMDM166A:
return new cDriverFutabaMDM166A(config);
diff --git a/glcddrivers/drivers.h b/glcddrivers/drivers.h
index 970b01e..99d9f82 100644
--- a/glcddrivers/drivers.h
+++ b/glcddrivers/drivers.h
@@ -56,6 +56,7 @@ enum eDriver
#ifdef HAVE_DRIVER_ILI9341
kDriverILI9341 = 22,
#endif
+ kDriverUSBserLCD = 23,
kDriverSerDisp = 100,
kDriverG15daemon = 200
};
diff --git a/glcddrivers/port.c b/glcddrivers/port.c
index cfb4156..26592c4 100644
--- a/glcddrivers/port.c
+++ b/glcddrivers/port.c
@@ -16,7 +16,6 @@
#include <string.h>
#include <syslog.h>
#include <unistd.h>
-#include <termios.h>
#include <pthread.h>
#include <sys/io.h>
#include <sys/ioctl.h>
@@ -335,19 +334,30 @@ int cSerialPort::Open(const char * device)
cfsetispeed(&options, B921600);
cfsetospeed(&options, B921600);
+ // 8 bits, no parity, no stop bits
options.c_cflag &= ~PARENB;
options.c_cflag &= ~CSTOPB;
options.c_cflag &= ~CSIZE;
options.c_cflag |= CS8;
+ // No "hangup" (prevents Arduino firmware reboots)
+ options.c_cflag &= ~HUPCL;
+
+ // No hardware flow control
options.c_cflag &= ~CRTSCTS;
+ // Enable receiver, ignore status lines
options.c_cflag |= (CLOCAL | CREAD);
+ // disable canonical input, disable echo,
+ // disable visually erase chars
+ // disable terminal-generated signals
options.c_lflag &= ~(ICANON | ECHO | ECHOE | ISIG);
+ // disable input/output flow control, disable restart chars
options.c_iflag &= ~(IXON | IXOFF | IXANY);
+ // disable output processing
options.c_oflag &= ~OPOST;
tcsetattr(fd, TCSANOW, &options);
@@ -363,6 +373,15 @@ int cSerialPort::Close()
return 0;
}
+void cSerialPort::SetBaudRate(speed_t speed)
+{
+ struct termios options;
+ tcgetattr(fd, &options);
+ cfsetispeed(&options, speed);
+ cfsetospeed(&options, speed);
+ tcsetattr(fd, TCSANOW, &options);
+}
+
int cSerialPort::ReadData(unsigned char * data)
{
if (fd == -1)
@@ -382,4 +401,8 @@ void cSerialPort::WriteData(unsigned char * data, unsigned short length)
write(fd, data, length);
}
+void cSerialPort::WriteData(std::string data) {
+ WriteData((unsigned char*)data.c_str(), data.length());
+}
+
} // end of namespace
diff --git a/glcddrivers/port.h b/glcddrivers/port.h
index 6fcd635..ee851c8 100644
--- a/glcddrivers/port.h
+++ b/glcddrivers/port.h
@@ -12,6 +12,9 @@
#ifndef _GLCDDRIVERS_PORT_H_
#define _GLCDDRIVERS_PORT_H_
+#include <string>
+#include <termios.h>
+
namespace GLCD
{
@@ -69,10 +72,12 @@ public:
int Open(const char * device);
int Close();
+ void SetBaudRate(speed_t speed);
int ReadData(unsigned char * data);
void WriteData(unsigned char data);
void WriteData(unsigned char * data, unsigned short length);
+ void WriteData(std::string data);
};
} // end of namespace
diff --git a/glcddrivers/usbserlcd.c b/glcddrivers/usbserlcd.c
new file mode 100644
index 0000000..680a035
--- /dev/null
+++ b/glcddrivers/usbserlcd.c
@@ -0,0 +1,273 @@
+/*
+ * GraphLCD driver library
+ *
+ * usbserlcd.c - USBserLCD driver class
+ *
+ * This file is released under the GNU General Public License. Refer
+ * to the COPYING file distributed with this package.
+ *
+ * (c) 2017 Manuel Reimer <manuel.reimer@gmx.de>
+ */
+
+#include <syslog.h>
+#include <cstring>
+#include <cstdlib>
+
+#include "common.h"
+#include "config.h"
+#include "port.h"
+#include "usbserlcd.h"
+#include "stdint.h"
+
+
+namespace GLCD
+{
+
+cDriverUSBserLCD::cDriverUSBserLCD(cDriverConfig * config)
+: cDriver(config)
+{
+ port = new cSerialPort();
+ refreshCounter = 0;
+ FS = 8;
+ brightness = 255;
+}
+
+cDriverUSBserLCD::~cDriverUSBserLCD()
+{
+ delete port;
+}
+
+int cDriverUSBserLCD::Init()
+{
+ width = config->width;
+ if (width <= 0)
+ width = 240;
+ height = config->height;
+ if (height <= 0)
+ height = 128;
+
+ // setup lcd array (wanted state)
+ newLCD = new unsigned char*[(width + (FS - 1)) / FS];
+ if (newLCD)
+ {
+ for (int x = 0; x < (width + (FS - 1)) / FS; x++)
+ {
+ newLCD[x] = new unsigned char[height];
+ memset(newLCD[x], 0, height);
+ }
+ }
+ // setup lcd array (current state)
+ oldLCD = new unsigned char*[(width + (FS - 1)) / FS];
+ if (oldLCD)
+ {
+ for (int x = 0; x < (width + (FS - 1)) / FS; x++)
+ {
+ oldLCD[x] = new unsigned char[height];
+ memset(oldLCD[x], 0, height);
+ }
+ }
+
+ if (config->device == "")
+ return -1;
+
+ if (port->Open(config->device.c_str()) != 0)
+ return -1;
+
+ port->SetBaudRate(B115200);
+
+ *oldConfig = *config;
+
+ // clear display
+ Clear();
+
+ syslog(LOG_INFO, "%s: USBserLCD initialized.\n", config->name.c_str());
+ return 0;
+}
+
+int cDriverUSBserLCD::DeInit()
+{
+ int x;
+ // free lcd array (wanted state)
+ if (newLCD)
+ {
+ for (x = 0; x < (width + (FS - 1)) / FS; x++)
+ {
+ delete[] newLCD[x];
+ }
+ delete[] newLCD;
+ }
+ // free lcd array (current state)
+ if (oldLCD)
+ {
+ for (x = 0; x < (width + (FS - 1)) / FS; x++)
+ {
+ delete[] oldLCD[x];
+ }
+ delete[] oldLCD;
+ }
+
+ if (port->Close() != 0)
+ return -1;
+ return 0;
+}
+
+int cDriverUSBserLCD::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 cDriverUSBserLCD::Clear()
+{
+ for (int x = 0; x < (width + (FS - 1)) / FS; x++)
+ memset(newLCD[x], 0, height);
+}
+
+
+void cDriverUSBserLCD::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) );
+}
+
+void cDriverUSBserLCD::Refresh(bool refreshAll)
+{
+ int x,y;
+ uint16_t addr = 0;
+ uint16_t len = 0;
+
+ if (CheckSetup() == 1)
+ refreshAll = true;
+
+ if (config->refreshDisplay > 0)
+ {
+ refreshCounter = (refreshCounter + 1) % config->refreshDisplay;
+ if (!refreshAll && !refreshCounter)
+ refreshAll = true;
+ }
+
+ // draw all
+ std::string full_seq = "GLCD";
+ full_seq.reserve(8500);
+ full_seq += PKGTYPE_DATA; // Have to do it this way to get the NULL added
+ full_seq.append((char*)&addr, 2);
+
+ std::string bytes = "";
+ for (y = 0; y < height; y++)
+ {
+ for (x = 0; x < (width + (FS - 1)) / FS; x++)
+ {
+ char byte = (newLCD[x][y]) ^ (config->invert ? 0xff : 0x00);
+ bytes.append(&byte, 1);
+ if (refreshAll)
+ oldLCD[x][y] = newLCD[x][y];
+ }
+ }
+ len = bytes.length();
+ full_seq.append((char*)&len, 2);
+ full_seq.append(bytes);
+ // and reset RefreshCounter
+ refreshCounter = 0;
+
+ if (refreshAll) {
+ port->WriteData(full_seq);
+ return;
+ }
+
+ // draw only the changed bytes
+ std::string part_seq = "";
+ part_seq.reserve(8500);
+ std::string block_seq = "GLCD";
+ block_seq.reserve(8500);
+ block_seq += PKGTYPE_DATA;
+ bool cs = false;
+ bytes = "";
+ for (y = 0; y < height; y++)
+ {
+ for (x = 0; x < (width + (FS - 1)) / FS; x++)
+ {
+ if (oldLCD[x][y] != newLCD[x][y])
+ {
+ if (!cs)
+ {
+ if (width % FS == 0)
+ addr = (y * (width / FS)) + x;
+ else
+ addr = (y * (width / FS + 1)) + x;
+ block_seq = "GLCD";
+ block_seq += PKGTYPE_DATA;
+ block_seq.append((char*)&addr, 2);
+ bytes = "";
+ len = 0;
+ cs = true;
+ }
+ char byte = (newLCD[x][y]) ^ (config->invert ? 0xff : 0x00);
+ bytes.append(&byte, 1);
+ oldLCD[x][y] = newLCD[x][y];
+ }
+ else if (bytes != "")
+ {
+ part_seq.append(block_seq);
+ len = bytes.length();
+ part_seq.append((char*)&len, 2);
+ part_seq.append(bytes);
+ cs = false;
+ bytes = "";
+ block_seq = "";
+ }
+ }
+ }
+
+ if (bytes != "")
+ {
+ part_seq.append(block_seq);
+ len = bytes.length();
+ part_seq.append((char*)&len, 2);
+ part_seq.append(bytes);
+ }
+
+ // Send the smaller data block.
+ if (part_seq.length() < full_seq.length())
+ port->WriteData(part_seq);
+ else
+ port->WriteData(full_seq);
+}
+
+void cDriverUSBserLCD::SetBrightness(unsigned int percent)
+{
+ return;
+ unsigned char brightness = 255 * percent / 100;
+ std::string pkg = "GLCD" + PKGTYPE_BRIGHTNESS + brightness;
+ port->WriteData(pkg);
+}
+
+}
diff --git a/glcddrivers/usbserlcd.h b/glcddrivers/usbserlcd.h
new file mode 100644
index 0000000..698e90c
--- /dev/null
+++ b/glcddrivers/usbserlcd.h
@@ -0,0 +1,61 @@
+/*
+ * GraphLCD driver library
+ *
+ * t6963c.h - T6963C driver class
+ *
+ * low level routines based on lcdproc 0.5 driver, (c) 2001 Manuel Stahl
+ *
+ * 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) 2011 Wolfgang Astleitner <mrwastl AT users.sourceforge.net>
+ */
+
+#ifndef _GLCDDRIVERS_USBSERLED_H_
+#define _GLCDDRIVERS_USBSERLED_H_
+
+#include "driver.h"
+
+namespace GLCD
+{
+
+class cDriverConfig;
+class cSerialPort;
+
+// Possible serial package types
+enum glcd_pkgtype: char {
+ PKGTYPE_DATA,
+ PKGTYPE_BRIGHTNESS
+};
+
+class cDriverUSBserLCD : public cDriver
+{
+private:
+ cSerialPort * port;
+ unsigned char ** newLCD; // wanted state
+ unsigned char ** oldLCD; // current state
+ int refreshCounter;
+ int displayMode;
+
+ int FS;
+ char brightness;
+
+ int CheckSetup();
+
+public:
+ cDriverUSBserLCD(cDriverConfig * config);
+ virtual ~cDriverUSBserLCD();
+
+ 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 void SetBrightness(unsigned int percent);
+};
+
+} // end of namespace
+
+#endif