diff options
author | Manuel Reimer <manuel.reimer@gmx.de> | 2018-02-03 16:43:53 +0100 |
---|---|---|
committer | Manuel Reimer <manuel.reimer@gmx.de> | 2018-02-03 16:43:53 +0100 |
commit | 3bbe763488aa84fdf29047b6b38acd11f8274862 (patch) | |
tree | c515987004f20f07fe38e96ad4ddc17ba40366ca /glcddrivers | |
parent | f5528fefca614b8a134a1b6ba9e7cc476a8a537e (diff) | |
download | graphlcd-base-3bbe763488aa84fdf29047b6b38acd11f8274862.tar.gz graphlcd-base-3bbe763488aa84fdf29047b6b38acd11f8274862.tar.bz2 |
Add usbserlcd driver
Diffstat (limited to 'glcddrivers')
-rw-r--r-- | glcddrivers/Makefile | 2 | ||||
-rw-r--r-- | glcddrivers/drivers.c | 4 | ||||
-rw-r--r-- | glcddrivers/drivers.h | 1 | ||||
-rw-r--r-- | glcddrivers/port.c | 25 | ||||
-rw-r--r-- | glcddrivers/port.h | 5 | ||||
-rw-r--r-- | glcddrivers/usbserlcd.c | 273 | ||||
-rw-r--r-- | glcddrivers/usbserlcd.h | 61 |
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 |