summaryrefslogtreecommitdiff
path: root/glcddrivers/gu126x64D-K610A4.c
diff options
context:
space:
mode:
authorandreas 'randy' weinberger <vdr@smue.org>2010-02-21 19:58:27 +0100
committerandreas 'randy' weinberger <vdr@smue.org>2010-02-21 19:58:27 +0100
commit10ab31fa86dbf9875b5f6baa6ac59fefaaf86be3 (patch)
tree60ad7c856565f03e145b2996d1bb5f9cd64c0532 /glcddrivers/gu126x64D-K610A4.c
downloadgraphlcd-base-10ab31fa86dbf9875b5f6baa6ac59fefaaf86be3.tar.gz
graphlcd-base-10ab31fa86dbf9875b5f6baa6ac59fefaaf86be3.tar.bz2
initial git upload, based on graphlcd-base-0.1.5
Diffstat (limited to 'glcddrivers/gu126x64D-K610A4.c')
-rw-r--r--glcddrivers/gu126x64D-K610A4.c967
1 files changed, 967 insertions, 0 deletions
diff --git a/glcddrivers/gu126x64D-K610A4.c b/glcddrivers/gu126x64D-K610A4.c
new file mode 100644
index 0000000..e927f49
--- /dev/null
+++ b/glcddrivers/gu126x64D-K610A4.c
@@ -0,0 +1,967 @@
+/*
+ * GraphLCD driver library
+ *
+ * gu126x64D-K610A4.c - 8-bit driver module for Noritake GU126x64D-K610A4 VFD
+ * displays. The VFD is operating in its 8 bit-mode
+ * connected to a single PC parallel port.
+ *
+ * based on:
+ * gu256x64-372 driver module for graphlcd
+ * (c) 2004 Andreas 'randy' Weinberger (randy AT smue.org)
+ * gu256x64-3900 driver module for graphlcd
+ * (c) 2004 Ralf Mueller (ralf AT bj-ig.de)
+ * gu140x32f driver module for graphlcd
+ * (c) 2003 Andreas Brachold <vdr04 AT deltab.de>
+ * ks0108 driver module for graphlcd
+ * (c) 2004 Andreas 'randy' Weinberger (randy AT smue.org)
+ *
+ * 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)
+ */
+
+#include <errno.h>
+#include <syslog.h>
+#include <unistd.h>
+#include <sys/time.h>
+
+#include "common.h"
+#include "config.h"
+#include "gu126x64D-K610A4.h"
+#include "port.h"
+
+namespace GLCD
+{
+//----- commands to the display -----------------------------------------------
+static const unsigned char CMD_RUN_MACRO_01 = 0x01; // run macro 1
+static const unsigned char CMD_RUN_MACRO_02 = 0x02; // run macro 2
+static const unsigned char CMD_RUN_MACRO_03 = 0x03; // run macro 3
+static const unsigned char CMD_RUN_MACRO_04 = 0x04; // run macro 4
+static const unsigned char CMD_RUN_MACRO_05 = 0x05; // run macro 5
+static const unsigned char CMD_RUN_MACRO_06 = 0x06; // run macro 6
+static const unsigned char CMD_RUN_MACRO_07 = 0x07; // run macro 7
+
+static const unsigned char CMD_CURSOR_POS = 0x10; // Set cursor position
+static const unsigned char CMD_BOX_SET = 0x11; // Set area
+static const unsigned char CMD_BOX_CLEAR = 0x12; // Clear area
+static const unsigned char CMD_BOX_INVERT = 0x13; // Invert area
+static const unsigned char CMD_RECT_SET = 0x14; // Set outline
+static const unsigned char CMD_RECT_CLEAR = 0x15; // Clear outline
+
+static const unsigned char CMD_PIXEL_SET = 0x16; // Set pixel at current pos
+static const unsigned char CMD_PIXEL_CLEAR = 0x17; // Clear pixel at current pos
+
+static const unsigned char CMD_GRAPHIC_WRITE = 0x18; // Write graphics data (args: len, data)
+static const unsigned char CMD_RESET = 0x19; // Reset display
+static const unsigned char CMD_WRITE_MODE = 0x1A; // Write mode
+static const unsigned char CMD_INTRO = 0x1B; // Intro for other commands (see CMA_*)
+static const unsigned char CMD_FONT_PROP_SML = 0x1C; // Select font: proportional mini
+static const unsigned char CMD_FONT_FIX_MED = 0x1D; // Select font: fixed spaced 5x7
+static const unsigned char CMD_FONT_FIX_BIG = 0x1E; // Select font: fixed spaced 10x14
+
+static const unsigned char CMA_MACROS_ERASE = 0x4D; // Erase Macros (usage: CMD_INTRO + this)
+static const unsigned char CMA_EPROM_LOCK = 0x4C; // Lock EEPROM (usage: CMD_INTRO + this)
+static const unsigned char CMA_EPROM_UNLOCK = 0x55; // Unlock EEPROM (usage: CMD_INTRO + this)
+
+static const unsigned char CMA_POWER_OFF = 0x46; // Power off (usage: CMD_INTRO + this)
+static const unsigned char CMA_POWER_ON = 0x50; // Power on (usage: CMD_INTRO + this)
+
+//----- signal lines ----------------------------------------------------------
+static const unsigned char OUT_EN_HI = kAutoLow ;
+static const unsigned char OUT_EN_LO = kAutoHigh;
+static const unsigned char OUT_EN_MASK = OUT_EN_HI;
+
+static const unsigned char IN_MB_HI = 0x40;
+static const unsigned char IN_MB_LO = 0x00;
+static const unsigned char IN_MB_MASK = IN_MB_HI;
+
+//----- log flags -------------------------------------------------------------
+static const unsigned int LL_REFRESH_START = 0x0001; // 1
+static const unsigned int LL_REFRESH_END = 0x0002; // 2
+static const unsigned int LL_REFRESH_MED = 0x0004; // 4
+static const unsigned int LL_VFD_CMD = 0x0008; // 8
+static const unsigned int LL_MAX_WAIT = 0x0010; // 16
+
+//----- mixed consts ----------------------------------------------------------
+static const long ADJUST_FACTOR = 100; // used to adjust timing
+
+//-----------------------------------------------------------------------------
+cDriverGU126X64D_K610A4::cDriverGU126X64D_K610A4(cDriverConfig * config)
+ : port (0)
+ , config (config)
+ , oldConfig (0)
+ , myNumRows (0)
+ , myDrawMem (0)
+ , myVFDMem (0)
+ , myUseSleepInit (false)
+ , myPortDelayNS (0)
+ , myDelay125NS (0)
+ , myRefreshCounter (0)
+ , myClaimCounter (0)
+ , 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()
+{
+ width = config->width;
+ if (width <= 0 || width > 256) // don't allow unreasonable big sizes from config
+ {
+ width = 126;
+ } // if
+
+ height = config->height;
+ if (height <= 0 || height > 256) // don't allow unreasonable big sizes from config
+ {
+ height = 64;
+ } // if
+
+ //----- parse config -----
+ for (unsigned int i = 0; i < config->options.size(); i++)
+ {
+ if (config->options[i].name == "Debug")
+ {
+ myLogFlags = atoi(config->options[i].value.c_str());
+ } // if
+ } // for
+
+ myNumRows = ((height + 7) / 8);
+ port = new cParallelPort();
+
+ // setup drawing memory
+ myDrawMem = new unsigned char *[width];
+ for (int x = 0; x < width; x++)
+ {
+ myDrawMem[x] = new unsigned char[myNumRows];
+ memset(myDrawMem[x], 0, myNumRows);
+ } // for
+
+ // setup vfd memory
+ myVFDMem = new unsigned char *[width];
+ for (int x = 0; x < width; x++)
+ {
+ myVFDMem[x] = new unsigned char[myNumRows];
+ memset(myVFDMem[x], 0, myNumRows);
+ } // for
+
+ if (initParallelPort() < 0)
+ {
+ return -1;
+ } // if
+
+ initDisplay();
+
+ *oldConfig = *config;
+
+ // Set Display SetBrightness
+ SetBrightness(config->brightness);
+
+ // clear display
+ Clear();
+ clearVFDMem();
+
+ syslog( LOG_INFO, "%s: initialized (width: %d height: %d)"
+ , config->name.c_str(), width, height
+ );
+
+ return 0;
+} // cDriverGU126X64D_K610A4::Init()
+
+//-----------------------------------------------------------------------------
+int cDriverGU126X64D_K610A4::DeInit()
+{
+ if (myVFDMem)
+ {
+ for (int x = 0; x < width; x++)
+ {
+ delete[] myVFDMem[x];
+ } // for
+ delete[] myVFDMem;
+ myVFDMem = 0;
+ } // if
+
+ if (myDrawMem)
+ {
+ for(int x = 0; x < width; x++)
+ {
+ delete[] myDrawMem[x];
+ } // for
+ delete[] myDrawMem;
+ myDrawMem = 0;
+ } // if
+
+ if (port)
+ {
+ // claim port to avoid msg when closing the port
+ port->Claim();
+ if (port->Close() != 0)
+ {
+ return -1;
+ } // if
+ delete port;
+ port = 0;
+ } // if
+
+ return 0;
+} // cDriverGU126X64D_K610A4::DeInit()
+
+//-----------------------------------------------------------------------------
+int cDriverGU126X64D_K610A4::checkSetup()
+{
+ if ( config->device != oldConfig->device
+ || config->port != oldConfig->port
+ || config->width != oldConfig->width
+ || config->height != oldConfig->height
+ )
+ {
+ DeInit();
+ Init();
+ return 0;
+ } // if
+
+ if (config->brightness != oldConfig->brightness)
+ {
+ oldConfig->brightness = config->brightness;
+ SetBrightness(config->brightness);
+ } // if
+
+ if ( config->upsideDown != oldConfig->upsideDown
+ || config->invert != oldConfig->invert
+ )
+ {
+ oldConfig->upsideDown = config->upsideDown;
+ oldConfig->invert = config->invert;
+
+ return 1;
+ } // if
+
+ return 0;
+} // cDriverGU126X64D_K610A4::checkSetup()
+
+//-----------------------------------------------------------------------------
+int cDriverGU126X64D_K610A4::initParallelPort()
+{
+ struct timeval tv1, tv2;
+
+ if (config->device == "")
+ {
+ // use DirectIO
+ if (port->Open(config->port) != 0)
+ {
+ syslog(LOG_ERR, "%s: unable to initialize gu256x64-3900!", config->name.c_str());
+ return -1;
+ } // if
+ syslog(LOG_INFO, "%s: using direct IO!", config->name.c_str());
+ uSleep(10);
+ }
+ else
+ {
+ // use ppdev
+ if (port->Open(config->device.c_str()) != 0)
+ {
+ syslog(LOG_ERR, "%s: unable to initialize gu256x64-3900!", config->name.c_str());
+ return -1;
+ } // if
+ syslog(LOG_INFO, "%s: using ppdev!", config->name.c_str());
+ } // if
+
+ if (nSleepInit() != 0)
+ {
+ syslog(LOG_ERR, "%s: INFO: cannot change wait parameters Err: %s (cDriver::Init)", config->name.c_str(), strerror(errno));
+ myUseSleepInit = false;
+ }
+ else
+ {
+ myUseSleepInit = true;
+ } // if
+
+ //----- measure the time to write to the port -----
+ syslog(LOG_DEBUG, "%s: benchmark started.", config->name.c_str());
+ gettimeofday(&tv1, 0);
+
+ const int aBenchCount = 1000; // don't change this!
+ for (int x = 0; x < aBenchCount; x++)
+ {
+ port->WriteData(x % 0x100);
+ } // for
+
+ gettimeofday(&tv2, 0);
+
+ // release the port, which was implicitely claimed by open
+ port->Release();
+
+ if (myUseSleepInit) nSleepDeInit();
+
+ myPortDelayNS = (tv2.tv_sec - tv1.tv_sec) * 1000000 + (tv2.tv_usec - tv1.tv_usec);
+
+ myDelay125NS = std::max(125 + (ADJUST_FACTOR * config->adjustTiming) - myPortDelayNS, 0L);
+
+ syslog( LOG_DEBUG, "%s: benchmark stopped. Time for Port Command: %ldns, delay: %ldns"
+ , config->name.c_str(), myPortDelayNS, myDelay125NS
+ );
+
+ return 0;
+} // cDriverGU126X64D_K610A4::initParallelPort()
+
+//-----------------------------------------------------------------------------
+void cDriverGU126X64D_K610A4::initDisplay()
+{
+ claimPort();
+ cmdReset();
+ releasePort();
+} // cDriverGU126X64D_K610A4::initDisplay()
+
+//-----------------------------------------------------------------------------
+void cDriverGU126X64D_K610A4::clearVFDMem()
+{
+ for (int x = 0; x < width; x++)
+ {
+ memset(myVFDMem[x], 0, myNumRows);
+ } // for
+} // cDriverGU126X64D_K610A4::clearVFDMem()
+
+//-----------------------------------------------------------------------------
+void cDriverGU126X64D_K610A4::Clear()
+{
+ for (int x = 0; x < width; x++)
+ {
+ memset(myDrawMem[x], 0, myNumRows);
+ } // for
+} // cDriverGU126X64D_K610A4::Clear()
+
+//-----------------------------------------------------------------------------
+void cDriverGU126X64D_K610A4::SetBrightness(unsigned int percent)
+{
+ claimPort();
+ cmdSetBrightness(percent);
+ releasePort();
+} // cDriverGU126X64D_K610A4::SetBrightness()
+
+//-----------------------------------------------------------------------------
+bool cDriverGU126X64D_K610A4::waitForStatus(unsigned char theMask, unsigned char theValue, int theMaxWait)
+{
+ theValue = theValue & theMask;
+
+ int status = port->ReadStatus();
+
+ if ((status & theMask) != theValue)
+ {
+ // wait some time for MB go HI/LO but not forever
+ int i = 0;
+ for(i = 0; ((status & theMask) != theValue) && i < theMaxWait; i++)
+ {
+ status = port->ReadStatus();
+ } // for
+
+ if (isLogEnabled(LL_MAX_WAIT) && i >= theMaxWait)
+ {
+ syslog( LOG_INFO, "%s: slept for %5d times while waiting for MB = %d"
+ , config->name.c_str(), i, ((theMask & theValue) == 0 ? 0 : 1)
+ );
+ } //
+ } // if
+
+ return ((status & theMask) == theValue);
+} // cDriverGU126X64D_K610A4::waitForStatus()
+
+//-----------------------------------------------------------------------------
+void cDriverGU126X64D_K610A4::writeParallel(unsigned char data)
+{
+ if (myUseSleepInit) nSleepInit();
+
+ waitForStatus(IN_MB_MASK, IN_MB_LO, 500); // wait for MB == LO
+
+ port->WriteData(data); // write data
+ nSleep(myDelay125NS); // - sleep
+
+ port->WriteControl(OUT_EN_LO & OUT_EN_MASK); // set ENABLE to LO
+ nSleep(myDelay125NS); // - sleep
+
+ port->WriteControl(OUT_EN_HI & OUT_EN_MASK); // set ENABLE to HI
+
+ waitForStatus(IN_MB_MASK, IN_MB_HI, 50); // wait for MB == HI
+
+// the other drivers don't do this neither
+// if (myUseSleepInit) nSleepDeInit();
+} // cDriverGU126X64D_K610A4::writeParallel()
+
+//-----------------------------------------------------------------------------
+int cDriverGU126X64D_K610A4::write(unsigned char data)
+{
+ int b = 0;
+
+ writeParallel(data);
+ ++b;
+
+ // if data == 0x60 -> send 0x60 twice
+ // (0x60 switches to hex-mode)
+ if (data == 0x60)
+ {
+ writeParallel(data);
+ ++b;
+ } // if
+
+ return b;
+} // cDriverGU126X64D_K610A4::write()
+
+//-----------------------------------------------------------------------------
+void cDriverGU126X64D_K610A4::setPixel(int x, int y)
+{
+ if (!myDrawMem ) return;
+ if (x >= width || x < 0) return;
+ if (y >= height || y < 0) return;
+
+ if (config->upsideDown)
+ {
+ x = width - 1 - x;
+ y = height - 1 - y;
+ } // if
+
+ unsigned char c = 0x80 >> (y % 8);
+
+ myDrawMem[x][y/8] = myDrawMem[x][y/8] | c;
+} // cDriverGU126X64D_K610A4::setPixel()
+
+//-----------------------------------------------------------------------------
+void cDriverGU126X64D_K610A4::Set8Pixels(int x, int y, unsigned char data)
+{
+ // x - pos isn't maybe align to 8
+ x &= 0xFFF8;
+
+ for (int n = 0; n < 8; ++n)
+ {
+ if ((data & (0x80 >> n)) != 0) // if bit is set
+ {
+ setPixel(x + n, y);
+ } // if
+ } // for
+} // cDriverGU126X64D_K610A4::Set8Pixels()
+
+//-----------------------------------------------------------------------------
+void cDriverGU126X64D_K610A4::Refresh(bool refreshAll)
+{
+ // no mem present -> return
+ if (!myVFDMem || !myDrawMem)
+ {
+ return;
+ } // if
+
+ // create log
+ if (isLogEnabled(LL_REFRESH_START))
+ {
+ syslog( LOG_INFO, "%s: > Refresh() all = %d RefreshDisplay = %d RefreshCtr = %d Delay = %ld"
+ , config->name.c_str()
+ , refreshAll
+ , config->refreshDisplay
+ , myRefreshCounter
+ , myDelay125NS
+ );
+ } // if
+
+ // setup changed -> refresh all
+ if (checkSetup() > 0)
+ {
+ syslog(LOG_DEBUG, "%s: Refresh() checkSetup() returned != 0 -> refreshAll = true", config->name.c_str());
+ refreshAll = true;
+ } // if
+
+ // refresh-counter exceeded -> refresh all
+ if (!refreshAll && config->refreshDisplay != 0)
+ {
+ myRefreshCounter = (myRefreshCounter + 1) % config->refreshDisplay;
+ refreshAll = myRefreshCounter == 0;
+
+ if (refreshAll && isLogEnabled(LL_REFRESH_START))
+ {
+ syslog(LOG_DEBUG, "%s: Refresh() refresh-count reached -> refreshAll = true", config->name.c_str());
+ } // if
+ } // if
+
+ if (isLogEnabled(LL_REFRESH_START))
+ {
+ syslog( LOG_INFO, "%s: Refresh() all = %d RefreshDisplay = %d RefreshCtr = %d Delay = %ld"
+ , config->name.c_str()
+ , refreshAll
+ , config->refreshDisplay
+ , myRefreshCounter
+ , myDelay125NS
+ );
+ } // if
+
+ // time for logs
+ struct timeval tv1, tv2;
+ gettimeofday(&tv1, 0);
+
+ claimPort();
+
+ int chunk = 128; // displays with more than 128 pixels width are written in chunks
+ // note: this driver isn't really prepared to handle displays
+ // with other dimensions than 126x64
+ int xb = 0;
+ int yb = 0;
+ long bc = 0;
+
+ for (yb = 0; yb < myNumRows; ++yb)
+ {
+ int minX = width;
+ int maxX = 0;
+
+ //----- if !refreshAll -> check modified bytes
+ if (!refreshAll)
+ {
+ for (xb = 0; xb < width; ++xb)
+ {
+ if (myVFDMem[xb][yb] != myDrawMem[xb][yb])
+ {
+ minX = std::min(minX, xb);
+ maxX = std::max(maxX, xb);
+ } // if
+ } // for
+ }
+ else
+ {
+ minX = 0;
+ maxX = width - 1;
+ } // if
+
+ // create log
+ if (isLogEnabled(LL_REFRESH_MED))
+ {
+ if (minX <= maxX)
+ {
+ syslog( LOG_INFO, "%s: Row[%d] %3d - %3d : %3d"
+ , config->name.c_str(), yb
+ , minX, maxX
+ , maxX - minX + 1
+ );
+ }
+ else
+ {
+ syslog( LOG_INFO, "%s: Row[%d] --- - --- : ---"
+ , config->name.c_str(), yb
+ );
+ } // if
+ } // if
+
+ // perform refresh
+ if (minX <= maxX)
+ {
+ bc += cmdSetCursorPos(minX, yb * 8);
+
+ for (xb = minX; xb <= maxX; ++xb)
+ {
+ if ((xb - minX) % chunk == 0)
+ {
+ bc += cmdGraphicWrite(std::min((maxX - xb + 1), chunk));
+ } // if
+
+ bc += cmdGraphicData(myDrawMem[xb][yb]);
+ myVFDMem[xb][yb] = myDrawMem[xb][yb];
+ } // for
+ } // if
+ } // for
+
+ releasePort();
+
+ // create log
+ if (isLogEnabled(LL_REFRESH_END))
+ {
+ gettimeofday(&tv2, 0);
+
+ long duration_ms = ((tv2.tv_sec - tv1.tv_sec) * 1000000 + (tv2.tv_usec - tv1.tv_usec))
+ / 1000 /* us -> ms */
+ ;
+
+ syslog( LOG_INFO, "%s: < Refresh() all = %d took %3ld ms %5ld bytes = %5ld bytes/sec = %5ld ns/byte"
+ , config->name.c_str()
+ , refreshAll
+ , duration_ms
+ , bc
+ , duration_ms == 0 ? -1 : bc * 1000 / duration_ms
+ , bc == 0 ? -1 : duration_ms * 1000000 / bc
+ );
+ } // if
+} // cDriverGU126X64D_K610A4::Refresh()
+
+//-----------------------------------------------------------------------------
+int cDriverGU126X64D_K610A4::cmdReset()
+{
+ ensureNotInGraphics();
+ int b = 0;
+
+ if (isLogEnabled(LL_VFD_CMD))
+ {
+ syslog(LOG_INFO, "- 1B: CMD_RESET : 0x%02X ", int(CMD_RESET));
+ } // if
+
+ b += write(CMD_RESET);
+
+ unsigned char aMode = 1 << 7 // data orientation : 0: horizontal, 1: vertical , default: 0
+ | 0 << 6 // cursor movement : 0: horizontal, 1: vertical , default: 0
+ | 0 << 5 // cursor direction : 0: forwards , 1: backwards, default: 0
+ | 0 << 4 // underscore cursor: 0: off , 1: on , default: 0
+ | 0 << 3 // underscore cursor: 0: static , 1: flash , default: 0
+ | 0 << 2 // not in documentation
+ | 0 << 0 // pen type: 0: overwrite, 1: AND, 2: OR, 3: XOR , default: 0
+ ;
+
+ if (isLogEnabled(LL_VFD_CMD))
+ {
+ syslog(LOG_INFO, "- 2B: CMD_WRITE_MODE : 0x%02X 0x%02X", int(CMD_RESET), int(aMode));
+ } // if
+
+ b += write(CMD_WRITE_MODE);
+ b += write(aMode);
+
+ return b;
+} // cDriverGU126X64D_K610A4::cmdReset()
+
+//-----------------------------------------------------------------------------
+int cDriverGU126X64D_K610A4::cmdPower(bool fOn)
+{
+ ensureNotInGraphics();
+ int b = 0;
+
+ if (isLogEnabled(LL_VFD_CMD))
+ {
+ syslog( LOG_INFO, "- 2B: CMD_POWER : 0x%02X 0x%02X"
+ , int(CMD_INTRO), int(fOn ? CMA_POWER_ON : CMA_POWER_OFF)
+ );
+ } // if
+
+ b += write(CMD_INTRO);
+ b += write(fOn ? CMA_POWER_ON : CMA_POWER_OFF);
+
+ return b;
+} // cDriverGU126X64D_K610A4::cmdPower()
+
+//-----------------------------------------------------------------------------
+int cDriverGU126X64D_K610A4::cmdLock(bool fLock)
+{
+ ensureNotInGraphics();
+ int b = 0;
+
+ if (isLogEnabled(LL_VFD_CMD))
+ {
+ syslog( LOG_INFO, "- 2B: CMD_LOCK : 0x%02X 0x%02X"
+ , int(CMD_INTRO), int(fLock ? CMA_EPROM_LOCK : CMA_EPROM_UNLOCK)
+ );
+ } // if
+
+ b += write(CMD_INTRO);
+ b += write(fLock ? CMA_EPROM_LOCK : CMA_EPROM_UNLOCK);
+
+ return b;
+} // cDriverGU126X64D_K610A4::cmdPower()
+
+//-----------------------------------------------------------------------------
+int cDriverGU126X64D_K610A4::cmdSetCursorPos(unsigned char x, unsigned char y)
+{
+ ensureNotInGraphics();
+ int b = 0;
+
+ if (isLogEnabled(LL_VFD_CMD))
+ {
+ syslog( LOG_INFO, "- 3B: CMD_CURSOR_POS : 0x%02X 0x%02X 0x%02X (x = %3d, y = %3d)"
+ , int(CMD_CURSOR_POS), int(x), int(y), int(x), int(y)
+ );
+ } // if
+
+ b += write(CMD_CURSOR_POS); // cmd
+ b += write(x ); // xpos
+ b += write(y ); // ypos
+
+ return b;
+} // cDriverGU126X64D_K610A4::cmdSetCursorPos();
+
+//-----------------------------------------------------------------------------
+int cDriverGU126X64D_K610A4::cmdGraphicWrite(unsigned char count)
+{
+ ensureNotInGraphics();
+ int b = 0;
+
+ if (isLogEnabled(LL_VFD_CMD))
+ {
+ syslog( LOG_INFO, "- 2B: CMD_GRAPHIC_WRITE: 0x%02X 0x%02X (%d bytes)"
+ , int(CMD_GRAPHIC_WRITE), int(count), int(count)
+ );
+ } // if
+
+ b += write(CMD_GRAPHIC_WRITE); // cmd
+ b += write(count ); // len
+
+ myDataPendingCounter = count;
+
+ return b;
+} // cDriverGU126X64D_K610A4::cmdGraphicWrite()
+
+//-----------------------------------------------------------------------------
+int cDriverGU126X64D_K610A4::cmdGraphicData(unsigned char data)
+{
+ int b = 0;
+
+ myDataPendingCounter--;
+ if (myDataPendingCounter < 0)
+ {
+ syslog( LOG_WARNING, "%s error: more graphic data written than announced -> ignored"
+ , config->name.c_str()
+ );
+ }
+ else
+ {
+ if (isLogEnabled(LL_VFD_CMD))
+ {
+ syslog( LOG_INFO, "- 1B: CMD_GRAPHIC_DATA : 0x%02X (expecting another %d bytes)"
+ , int(data), myDataPendingCounter
+ );
+ } // if
+
+ b += write(data ^ (config->invert ? 0xFF : 0x00));
+ } // if
+
+ return b;
+} // cDriverGU126X64D_K610A4::cmdGraphicData()
+
+//-----------------------------------------------------------------------------
+int cDriverGU126X64D_K610A4::cmdSetBrightness(unsigned int percent)
+{
+ ensureNotInGraphics();
+ int b = 0;
+
+ unsigned char bright = 0;
+ if (percent >= 85) bright = 0xFF;
+ else if (percent >= 71) bright = 0xFE;
+ else if (percent >= 57) bright = 0xFD;
+ else if (percent >= 43) bright = 0xFC;
+ else if (percent >= 29) bright = 0xFB;
+ else if (percent >= 15) bright = 0xFA;
+ else if (percent >= 1) bright = 0xF9;
+ else bright = 0xF8;
+
+ if (isLogEnabled(LL_VFD_CMD))
+ {
+ syslog( LOG_INFO, "- 2B: CMD_INTRO : 0x%02X 0x%02X = set brightness"
+ , int(CMD_INTRO), int(bright)
+ );
+ } // if
+
+ b += write(CMD_INTRO);
+ b += write(bright);
+
+ return b;
+} // cDriverGU126X64D_K610A4::cmdSetBrightness()
+
+//-----------------------------------------------------------------------------
+int cDriverGU126X64D_K610A4::cmdSetFont(FontType theFont)
+{
+ ensureNotInGraphics();
+ int b = 0;
+
+ unsigned char aCmd = 0;
+ switch (theFont)
+ {
+ case FONT_PROP_SML: aCmd = CMD_FONT_PROP_SML; break;
+ case FONT_FIX_BIG : aCmd = CMD_FONT_FIX_BIG ; break;
+ case FONT_FIX_MED :
+ default : aCmd = CMD_FONT_FIX_MED ; break;
+ } // switch
+
+ if (isLogEnabled(LL_VFD_CMD))
+ {
+ syslog(LOG_INFO, "- 1B: CMD_SET_FONT : 0x%02X", int(aCmd));
+ } // if
+
+ b += write(aCmd);
+
+ return b;
+} // cDriverGU126X64D_K610A4::cmdSetFont()
+
+//-----------------------------------------------------------------------------
+int cDriverGU126X64D_K610A4::cmdWriteText(const char *theText)
+{
+ ensureNotInGraphics();
+ int b = 0;
+
+ if (isLogEnabled(LL_VFD_CMD))
+ {
+ syslog(LOG_INFO, "-%2dB: WRITE_TEXT : '%s'", strlen(theText), theText);
+ } // if
+
+ for (const char *p = theText; *p != '\0'; ++p)
+ {
+ b += write(*p);
+ } // for
+
+ return b;
+} // cDriverGU126X64D_K610A4::cmdWriteText()
+
+//-----------------------------------------------------------------------------
+int cDriverGU126X64D_K610A4::cmdDrawRect(unsigned char x1, unsigned char y1, unsigned char x2, unsigned char y2)
+{
+ ensureNotInGraphics();
+ int b = 0;
+
+ if (isLogEnabled(LL_VFD_CMD))
+ {
+ syslog( LOG_INFO, "- 5B: CMD_SET_OUTLINE : 0x%02X 0x%02X 0x%02X 0x%02X 0x%02X (x1 = %3d, y1 = %3d, x2 = %3d, y2 = %3d)"
+ , int(CMD_CURSOR_POS)
+ , int(x1), int(y1), int(x2), int(y2)
+ , int(x1), int(y1), int(x2), int(y2)
+ );
+ } // if
+
+ b += write(CMD_RECT_SET );
+ b += write(x1 );
+ b += write(y1 );
+ b += write(x2 );
+ b += write(y2 );
+
+ return b;
+} // cDriverGU126X64D_K610A4::cmdDrawRect()
+
+//-----------------------------------------------------------------------------
+int cDriverGU126X64D_K610A4::cmdSetMacro(unsigned char theMacroNum, unsigned char theCountBytes)
+{
+ if (theMacroNum > 7)
+ {
+ return 0;
+ } // if
+
+ ensureNotInGraphics();
+ int b = 0;
+
+ if (isLogEnabled(LL_VFD_CMD))
+ {
+ syslog( LOG_INFO, "- 3B: CMD_INTRO : 0x%02X 0x%02X 0x%02X (define macro %d with length %d)"
+ , int(CMD_INTRO)
+ , int(theMacroNum), int(theCountBytes)
+ , int(theMacroNum), int(theCountBytes)
+ );
+ } // if
+
+ b += write(CMD_INTRO );
+ b += write(theMacroNum );
+ b += write(theCountBytes );
+
+ return b;
+} // cDriverGU126X64D_K610A4::cmdSetMacro()
+
+//-----------------------------------------------------------------------------
+int cDriverGU126X64D_K610A4::cmdSetPixel(bool fSet)
+{
+ int b = 0;
+
+ if (fSet)
+ {
+ ensureNotInGraphics();
+
+ if (isLogEnabled(LL_VFD_CMD))
+ {
+ syslog(LOG_INFO, "- 1B: SET_PIXEL : 0x%02X", 0x16);
+ } // if
+
+ b += write(CMD_PIXEL_SET);
+ }
+ else
+ {
+ b = cmdClrPixel();
+ } // if
+
+ return b;
+} // cDriverGU126X64D_K610A4::cmdSetPixel()
+
+//-----------------------------------------------------------------------------
+int cDriverGU126X64D_K610A4::cmdClrPixel()
+{
+ ensureNotInGraphics();
+ int b = 0;
+
+ if (isLogEnabled(LL_VFD_CMD))
+ {
+ syslog(LOG_INFO, "- 1B: CLR_PIXEL : 0x%02X", 0x17);
+ } // if
+
+ b += write(CMD_PIXEL_CLEAR);
+
+ return b;
+} // cDriverGU126X64D_K610A4::cmdClrPixel()
+
+//-----------------------------------------------------------------------------
+void cDriverGU126X64D_K610A4::ensureNotInGraphics()
+{
+ if (myClaimCounter <= 0)
+ {
+ syslog(LOG_ERR, "%s: ERROR: port not claimed (%d)", config->name.c_str(), myClaimCounter);
+ } // if
+
+ if (myDataPendingCounter > 0)
+ {
+ syslog( LOG_WARNING, "%s error: expected another %d bytes graphic data, filling with 0x00"
+ , config->name.c_str(), myDataPendingCounter
+ );
+ } // if
+ while (myDataPendingCounter > 0)
+ {
+ cmdGraphicData(0);
+ } // while
+} // cDriverGU126X64D_K610A4::ensureNotInGraphics()
+
+
+//-----------------------------------------------------------------------------
+void cDriverGU126X64D_K610A4::claimPort()
+{
+ if (myClaimCounter == 0)
+ {
+ port->Claim();
+ } // if
+
+ myClaimCounter++;
+
+ if (myClaimCounter > 1)
+ {
+ syslog( LOG_WARNING, "%s: port claimed more than once (%d)"
+ , config->name.c_str(), myClaimCounter
+ );
+ } // if
+
+} // cDriverGU126X64D_K610A4::claimPort()
+
+//-----------------------------------------------------------------------------
+void cDriverGU126X64D_K610A4::releasePort()
+{
+ if (myClaimCounter == 1)
+ {
+ port->Release();
+ } // if
+
+ myClaimCounter--;
+
+ if (myClaimCounter < 0)
+ {
+ syslog( LOG_WARNING, "%s: port released more often than claimed"
+ , config->name.c_str()
+ );
+ myClaimCounter = 0;
+ } // if
+
+} // cDriverGU126X64D_K610A4::releasePort()
+
+//-----------------------------------------------------------------------------
+bool cDriverGU126X64D_K610A4::isLogEnabled(int theLevel) const
+{
+ return (theLevel & myLogFlags) != 0;
+} // cDriverGU126X64D_K610A4::isLogEnabled()
+
+//-----------------------------------------------------------------------------
+} // end of namespace
+