diff options
Diffstat (limited to 'glcddrivers')
-rw-r--r-- | glcddrivers/Makefile | 6 | ||||
-rw-r--r-- | glcddrivers/futabaMDM166A.c | 476 | ||||
-rw-r--r-- | glcddrivers/futabaMDM166A.h | 78 | ||||
-rw-r--r-- | glcddrivers/image.c | 7 | ||||
-rw-r--r-- | glcddrivers/noritake800.c | 55 | ||||
-rw-r--r-- | glcddrivers/noritake800.h | 2 |
6 files changed, 596 insertions, 28 deletions
diff --git a/glcddrivers/Makefile b/glcddrivers/Makefile index 671c581..331c829 100644 --- a/glcddrivers/Makefile +++ b/glcddrivers/Makefile @@ -18,6 +18,12 @@ OBJS = common.o config.o driver.o drivers.o port.o simlcd.o framebuffer.o gu140x HEADERS = config.h driver.h drivers.h +ifeq ($(shell pkg-config --exists libhid && echo 1), 1) +OBJS += futabaMDM166A.o +INCLUDES += $(shell pkg-config --cflags libhid) +LIBS += $(shell pkg-config --libs libhid) +DEFINES += -DHAVE_LIBHID +endif ### Implicit rules: diff --git a/glcddrivers/futabaMDM166A.c b/glcddrivers/futabaMDM166A.c new file mode 100644 index 0000000..14b858d --- /dev/null +++ b/glcddrivers/futabaMDM166A.c @@ -0,0 +1,476 @@ +/* + * GraphLCD driver library + * + * 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> +#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 "futabaMDM166A.h" + +static const byte STATE_OFF = 0x00; //Symbol off +static const byte STATE_ON = 0x01; //Symbol on +static const byte STATE_ONHIGH = 0x02; //Symbol on, high intensity, can only be used with the volume symbols + +static const byte CMD_PREFIX = 0x1b; +static const byte CMD_SETCLOCK = 0x00; //Actualize the time of the display +static const byte CMD_SMALLCLOCK = 0x01; //Display small clock on display +static const byte CMD_BIGCLOCK = 0x02; //Display big clock on display +static const byte CMD_SETSYMBOL = 0x30; //Enable or disable symbol +static const byte CMD_SETDIMM = 0x40; //Set the dimming level of the display +static const byte CMD_RESET = 0x50; //Reset all configuration data to default and clear +static const byte CMD_SETRAM = 0x60; //Set the actual graphics RAM offset for next data write +static const byte CMD_SETPIXEL = 0x70; //Write pixel data to RAM of the display +static const byte CMD_TEST1 = 0xf0; //Show vertical test pattern +static const byte CMD_TEST2 = 0xf1; //Show horizontal test pattern + +static const byte TIME_12 = 0x00; //12 hours format +static const byte TIME_24 = 0x01; //24 hours format + +static const byte BRIGHT_OFF = 0x00; //Display off +static const byte BRIGHT_DIMM = 0x01; //Display dimmed +static const byte BRIGHT_FULL = 0x02; //Display full brightness + +namespace GLCD { + +cHIDQueue::cHIDQueue() { + hid = NULL; + bInit = false; +} + +cHIDQueue::~cHIDQueue() { + cHIDQueue::close(); +} + +bool cHIDQueue::open() +{ + HIDInterfaceMatcher matcher = { 0x19c2, 0x6a11, NULL, NULL, 0 }; + hid_return ret; + + /* see include/debug.h for possible values */ + hid_set_debug(HID_DEBUG_NONE); + hid_set_debug_stream(0); + /* passed directly to libusb */ + hid_set_usb_debug(0); + + ret = hid_init(); + if (ret != HID_RET_SUCCESS) { + syslog(LOG_ERR, "libhid: init - %s (%d)", hiderror(ret), ret); + return false; + } + bInit = true; + + hid = hid_new_HIDInterface(); + if (hid == 0) { + syslog(LOG_ERR, "libhid: hid_new_HIDInterface() failed, out of memory?\n"); + return false; + } + + ret = hid_force_open(hid, 0, &matcher, 3); + if (ret != HID_RET_SUCCESS) { + syslog(LOG_ERR, "libhid: open - %s (%d)", hiderror(ret), ret); + hid_close(hid); + hid_delete_HIDInterface(&hid); + hid = 0; + return false; + } + + while (!empty()) { + pop(); + } + //ret = hid_write_identification(stdout, hid); + //if (ret != HID_RET_SUCCESS) { + // syslog(LOG_INFO, "libhid: write_identification %s (%d)", hiderror(ret), ret); + // return false; + //} + return true; +} + +void cHIDQueue::close() { + hid_return ret; + if (hid != 0) { + ret = hid_close(hid); + if (ret != HID_RET_SUCCESS) { + syslog(LOG_ERR, "libhid: close - %s (%d)", hiderror(ret), ret); + } + + hid_delete_HIDInterface(&hid); + hid = 0; + } + if(bInit) { + ret = hid_cleanup(); + if (ret != HID_RET_SUCCESS) { + syslog(LOG_ERR, "libhid: cleanup - %s (%d)", hiderror(ret), ret); + } + bInit = false; + } +} + +void cHIDQueue::Cmd(const byte & cmd) { + this->push(CMD_PREFIX); + this->push(cmd); +} + +void cHIDQueue::Data(const byte & data) { + this->push(data); +} + +bool cHIDQueue::Flush() { + + if(empty()) + return true; + if(!isopen()) { + return false; + } + + int const PATH_OUT[1] = { 0xff7f0004 }; + char buf[64]; + hid_return ret; + + while (!empty()) { + buf[0] = (char) std::min((size_t)63,size()); + for(unsigned int i = 0;i < 63 && !empty();++i) { + buf[i+1] = (char) front(); //the first element in the queue + pop(); //remove the first element of the queue + } + ret = hid_set_output_report(hid, PATH_OUT, sizeof(PATH_OUT), buf, (buf[0] + 1)); + if (ret != HID_RET_SUCCESS) { + syslog(LOG_ERR, "libhid: set_output_report - %s (%d)", hiderror(ret), ret); + while (!empty()) { + pop(); + } + cHIDQueue::close(); + return false; + } + } + return true; +} + +const char *cHIDQueue::hiderror(hid_return ret) const +{ + switch(ret) { + case HID_RET_SUCCESS: + return "success"; + case HID_RET_INVALID_PARAMETER: + return "invalid parameter"; + case HID_RET_NOT_INITIALISED: + return "not initialized"; + case HID_RET_ALREADY_INITIALISED: + return "hid_init() already called"; + case HID_RET_FAIL_FIND_BUSSES: + return "failed to find any USB busses"; + case HID_RET_FAIL_FIND_DEVICES: + return "failed to find any USB devices"; + case HID_RET_FAIL_OPEN_DEVICE: + return "failed to open device"; + case HID_RET_DEVICE_NOT_FOUND: + return "device not found"; + case HID_RET_DEVICE_NOT_OPENED: + return "device not yet opened"; + case HID_RET_DEVICE_ALREADY_OPENED: + return "device already opened"; + case HID_RET_FAIL_CLOSE_DEVICE: + return "could not close device"; + case HID_RET_FAIL_CLAIM_IFACE: + return "failed to claim interface; is another driver using it?"; + case HID_RET_FAIL_DETACH_DRIVER: + return "failed to detach kernel driver"; + case HID_RET_NOT_HID_DEVICE: + return "not recognized as a HID device"; + case HID_RET_HID_DESC_SHORT: + return "HID interface descriptor too short"; + case HID_RET_REPORT_DESC_SHORT: + return "HID report descriptor too short"; + case HID_RET_REPORT_DESC_LONG: + return "HID report descriptor too long"; + case HID_RET_FAIL_ALLOC: + return "failed to allocate memory"; + case HID_RET_OUT_OF_SPACE: + return "no space left in buffer"; + case HID_RET_FAIL_SET_REPORT: + return "failed to set report"; + case HID_RET_FAIL_GET_REPORT: + return "failed to get report"; + case HID_RET_FAIL_INT_READ: + return "interrupt read failed"; + case HID_RET_NOT_FOUND: + return "not found"; +#ifdef HID_RET_TIMEOUT + case HID_RET_TIMEOUT: + return "timeout"; +#endif + default: + return "unknown error or timeout"; + } + return "unknown error"; +} + + +cDriverFutabaMDM166A::cDriverFutabaMDM166A(cDriverConfig * config) +: config(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 + width = config->width; + if (width <= 0 || width > 96) + width = 96; + height = config->height; + if (height <= 0 || height > 16) + height = 16; + m_iSizeYb = ((height + 7) / 8); + + + /*for (unsigned int i = 0; i < config->options.size(); i++) + { + if (config->options[i].name == "") + { + } + }*/ + + *oldConfig = *config; + + // setup the memory array for the drawing array + m_pDrawMem = new unsigned char[width * m_iSizeYb]; + // setup the memory array for the display array + m_pVFDMem = new unsigned char[width * m_iSizeYb]; + if(!m_pDrawMem || !m_pVFDMem) { + syslog(LOG_ERR, "FutabaMDM166A: malloc frame buffer failed, out of memory?\n"); + return -1; + } + + // clear display + ClearVFDMem(); + Clear(); + + + if(!cHIDQueue::open()) { + return -1; + } + lastIconState = 0; + + cHIDQueue::Cmd(CMD_RESET); + // Set Display SetBrightness + SetBrightness(config->brightness ? config->brightness : 50); + + if(cHIDQueue::Flush()) { + syslog(LOG_INFO, "%s: initialized.\n", config->name.c_str()); + return 0; + } + return -1; +} + +int cDriverFutabaMDM166A::DeInit() +{ + cHIDQueue::close(); + + if (m_pVFDMem) + delete[] m_pVFDMem; + if (m_pDrawMem) + delete[] m_pDrawMem; + + return 0; +} + +int cDriverFutabaMDM166A::CheckSetup() +{ + if (config->width != oldConfig->width || + config->height != oldConfig->height) + { + DeInit(); + return Init(); + } + + 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 cDriverFutabaMDM166A::ClearVFDMem() +{ + for (unsigned int n = 0; m_pVFDMem && n < (width * m_iSizeYb); n++) + m_pVFDMem[n] = 0x00; +} + +void cDriverFutabaMDM166A::Clear() +{ + for (unsigned int n = 0; m_pDrawMem && n < (width * m_iSizeYb); n++) + m_pDrawMem[n] = 0x00; +} + +void cDriverFutabaMDM166A::SetPixel(int x, int y, uint32_t data) +{ + byte c; + int n; + + if (!m_pDrawMem) + 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) * width); + c = 0x80 >> (y % 8); + + //m_pDrawMem[n] |= c; + if (data == GLCD::cColor::White) + m_pDrawMem[n] |= c; + else + m_pDrawMem[n] &= (0xFF ^ c); +} + +#if 0 +void cDriverFutabaMDM166A::Set8Pixels(int x, int y, byte data) +{ + int n; + + // x - pos is'nt mayby align to 8 + x &= 0xFFF8; + + for (n = 0; n < 8; ++n) + { + if (data & (0x80 >> n)) // if bit is set + SetPixel(x + n, y); + } +} +#endif + +void cDriverFutabaMDM166A::Refresh(bool refreshAll) +{ + unsigned int n, x, yb; + + if (!m_pVFDMem || !m_pDrawMem) + return; + + bool doRefresh = false; + unsigned int nWidth = width; + unsigned int minX = nWidth; + unsigned int maxX = 0; + + int s = CheckSetup(); + if(s < 0) + return; + if (s > 0) + refreshAll = true; + + for (yb = 0; yb < m_iSizeYb; ++yb) + for (x = 0; x < nWidth; ++x) + { + n = x + (yb * nWidth); + if (m_pVFDMem[n] != m_pDrawMem[n]) + { + m_pVFDMem[n] = m_pDrawMem[n]; + minX = std::min(minX, x); + maxX = std::max(maxX, x + 1); + doRefresh = true; + } + } + + m_nRefreshCounter = (m_nRefreshCounter + 1) % (config->refreshDisplay ? config->refreshDisplay : 50); + + if (!refreshAll && !m_nRefreshCounter) + refreshAll = true; + + if (refreshAll || doRefresh) + { + if (refreshAll) { + minX = 0; + maxX = nWidth; + // and reset RefreshCounter + m_nRefreshCounter = 0; + } + + maxX = std::min(maxX, nWidth); + + unsigned int nData = (maxX-minX) * m_iSizeYb; + if(nData) { + // send data to display, controller + cHIDQueue::Cmd(CMD_SETRAM); + cHIDQueue::Data(minX*m_iSizeYb); + cHIDQueue::Cmd(CMD_SETPIXEL); + cHIDQueue::Data(nData); + + for (x = minX; x < maxX; ++x) + for (yb = 0; yb < m_iSizeYb; ++yb) + { + n = x + (yb * nWidth); + cHIDQueue::Data((m_pVFDMem[n]) ^ (config->invert ? 0xff : 0x00)); + } + } + } + cHIDQueue::Flush(); +} + +/** + * Sets the brightness of the display. + * + * \param nBrightness The value the brightness (less 33% = off + * more then 66% = highest brightness,else half brightness ). + */ +void cDriverFutabaMDM166A::SetBrightness(unsigned int percent) +{ + byte nBrightness = 1; + if (percent < 33) { + nBrightness = 0; + } else if (nBrightness > 66) { + nBrightness = 2; + } + cHIDQueue::Cmd(CMD_SETDIMM); + cHIDQueue::Data(nBrightness); +} + +} + + + + diff --git a/glcddrivers/futabaMDM166A.h b/glcddrivers/futabaMDM166A.h new file mode 100644 index 0000000..c01a2e0 --- /dev/null +++ b/glcddrivers/futabaMDM166A.h @@ -0,0 +1,78 @@ +/* + * GraphLCD driver library + * + * 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_ +#define _GLCDDRIVERS_FutabaMDM166A_H_ + +#include "driver.h" + +#define HAVE_STDBOOL_H +#include <hid.h> +#include <queue> + +namespace GLCD +{ + class cDriverConfig; + + class cHIDQueue : public std::queue<byte> { + HIDInterface* hid; + bool bInit; + public: + cHIDQueue(); + virtual ~cHIDQueue(); + virtual bool open(); + virtual void close(); + virtual bool isopen() const { return hid != 0; } + void Cmd(const byte & cmd); + void Data(const byte & data); + bool Flush(); + private: + const char *hiderror(hid_return ret) const; + }; + + 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; + unsigned int m_nRefreshCounter; + unsigned int lastIconState; + int CheckSetup(); + protected: + void ClearVFDMem(); + 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 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); + }; +}; +#endif + + + diff --git a/glcddrivers/image.c b/glcddrivers/image.c index 4ca3937..6a67ddd 100644 --- a/glcddrivers/image.c +++ b/glcddrivers/image.c @@ -32,6 +32,7 @@ cDriverImage::cDriverImage(cDriverConfig * config) cDriverImage::~cDriverImage() { + DeInit(); delete oldConfig; } @@ -74,9 +75,15 @@ int cDriverImage::Init() int cDriverImage::DeInit() { if (newLCD) + { delete[] newLCD; + newLCD = 0; + } if (oldLCD) + { delete[] oldLCD; + oldLCD = 0; + } return 0; } diff --git a/glcddrivers/noritake800.c b/glcddrivers/noritake800.c index 5665ee3..bb0b43a 100644 --- a/glcddrivers/noritake800.c +++ b/glcddrivers/noritake800.c @@ -27,7 +27,7 @@ * This file is released under the GNU General Public License. Refer * to the COPYING file distributed with this package. * - * (c) 2004 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> */ @@ -172,13 +172,13 @@ cDriverNoritake800::~cDriverNoritake800() int x; if (m_pVFDMem) - for (x = 0; x < (width + 7) / 8; x++) + for (x = 0; x < width; x++) { delete[] m_pVFDMem[x]; } delete[] m_pVFDMem; if (m_pDrawMem) - for (x = 0; x < (width + 7) / 8; x++) + for (x = 0; x < width; x++) { delete[] m_pDrawMem[x]; } @@ -272,19 +272,18 @@ int cDriverNoritake800::Init() m_pport->Claim(); syslog(LOG_DEBUG, "%s: benchmark started.\n", m_Config->name.c_str()); gettimeofday(&tv1, 0); - int nBenchFactor = 100000; - for (x = 0; x < nBenchFactor; x++) + int nBenchIterations = 10000; + for (x = 0; x < nBenchIterations; x++) { m_pport->WriteData(x % 0x100); } gettimeofday(&tv2, 0); nSleepDeInit(); - //m_nTimingAdjustCmd = ((tv2.tv_sec - tv1.tv_sec) * 10000 + (tv2.tv_usec - tv1.tv_usec)) / 1000; - m_nTimingAdjustCmd = long(double((tv2.tv_sec - tv1.tv_sec) * 1000 + (tv2.tv_usec - tv1.tv_usec)) / double(nBenchFactor)); + // 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); m_pport->Release(); - // initialize display N800Cmd(Init800A); @@ -328,31 +327,34 @@ int cDriverNoritake800::Init() void cDriverNoritake800::Refresh(bool refreshAll) { - // - // for VFD displays, we can safely ignore refreshAll, as they are "sticky" - // int xb, yb; if (CheckSetup() > 0) - refreshAll = true; // we don't use it + refreshAll = true; if (!m_pVFDMem || !m_pDrawMem) return; -// // just refresh if the time needed between refreshes is up -// m_nRefreshCounter = (m_nRefreshCounter + 1) % m_Config->refreshDisplay; -// if(!m_nRefreshCounter) -// { + if (m_Config->refreshDisplay > 0) + { + m_nRefreshCounter = (m_nRefreshCounter + 1) % m_Config->refreshDisplay; + if (m_nRefreshCounter == 0) + refreshAll = true; + } + m_pport->Claim(); for (xb = 0; xb < width; ++xb) { for (yb = 0; yb < m_iSizeYb; ++yb) { - if (m_pVFDMem[xb][yb] != m_pDrawMem[xb][yb]) + // if differenet or explicitly refresh all + if ( m_pVFDMem[xb][yb] != m_pDrawMem[xb][yb] || + refreshAll ) { m_pVFDMem[xb][yb] = m_pDrawMem[xb][yb]; - // reset RefreshCounter - m_nRefreshCounter = 0; + // reset RefreshCounter if doing a full refresh + if (refreshAll) + m_nRefreshCounter = 0; // actually write to display N800WriteByte( (m_pVFDMem[xb][yb]) ^ ((m_Config->invert != 0) ? 0xff : 0x00), @@ -363,7 +365,6 @@ void cDriverNoritake800::Refresh(bool refreshAll) } } m_pport->Release(); -// } } void cDriverNoritake800::N800Cmd(unsigned char data) @@ -375,13 +376,13 @@ void cDriverNoritake800::N800Cmd(unsigned char data) m_pport->WriteControl(m_pWiringMaskCache[0x00]); // write to data port m_pport->WriteData(data); - //nSleep(100 + (100 * m_Config->adjustTiming) - m_nTimingAdjustCmd); + nSleep(100 + (100 * m_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 * m_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 * m_Config->adjustTiming) - m_nTimingAdjustCmd); // set direction to "port_input" m_pport->WriteControl(LPT_CTL_HI_DIR | m_pWiringMaskCache[0x00]); } @@ -395,13 +396,13 @@ void cDriverNoritake800::N800Data(unsigned char data) m_pport->WriteControl(m_pWiringMaskCache[VFDSGN_CD]); // write to data port m_pport->WriteData(data); - //nSleep(100 + (100 * m_Config->adjustTiming) - m_nTimingAdjustCmd); + nSleep(100 + (100 * m_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 * m_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 * m_Config->adjustTiming) - m_nTimingAdjustCmd); // set direction to "port_input" m_pport->WriteControl(LPT_CTL_HI_DIR | m_pWiringMaskCache[0x00]); } @@ -443,7 +444,7 @@ void cDriverNoritake800::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, GLCD::cColor::White); + SetPixel(x + n, y); } } #endif diff --git a/glcddrivers/noritake800.h b/glcddrivers/noritake800.h index a212e59..f41aa7a 100644 --- a/glcddrivers/noritake800.h +++ b/glcddrivers/noritake800.h @@ -27,7 +27,7 @@ * This file is released under the GNU General Public License. Refer * to the COPYING file distributed with this package. * - * (c) 2004 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> */ |