# HG changeset patch # User root@rika # Date 1202319470 0 # Node ID 37602e25a04aef2e0bbffea9d4baf10af2f4d6b7 # Parent df6a40031aa5e39e04edbf852f18c0213255dea0 added picctl code diff -r df6a40031aa5 -r 37602e25a04a graphlcd-base/glcddrivers/Makefile --- a/graphlcd-base/glcddrivers/Makefile Wed Feb 06 17:32:55 2008 +0000 +++ b/graphlcd-base/glcddrivers/Makefile Wed Feb 06 17:37:50 2008 +0000 @@ -14,7 +14,7 @@ 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 +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 picctl.o HEADERS = config.h driver.h drivers.h diff -r df6a40031aa5 -r 37602e25a04a graphlcd-base/glcddrivers/drivers.c --- a/graphlcd-base/glcddrivers/drivers.c Wed Feb 06 17:32:55 2008 +0000 +++ b/graphlcd-base/glcddrivers/drivers.c Wed Feb 06 17:37:50 2008 +0000 @@ -12,6 +12,7 @@ #include #include "drivers.h" +#include "picctl.h" #include "simlcd.h" #include "gu140x32f.h" #include "gu256x64-372.h" @@ -48,6 +49,7 @@ {"image", kDriverImage}, {"noritake800", kDriverNoritake800}, {"avrctl", kDriverAvrCtl}, + {"picctl", kDriverPICCtl}, {"network", kDriverNetwork}, {"gu126x64D-K610A4", kDriverGU126X64D_K610A4}, {"serdisp", kDriverSerDisp}, @@ -100,6 +102,8 @@ return new cDriverNoritake800(config); case kDriverAvrCtl: return new cDriverAvrCtl(config); + case kDriverPICCtl: + return cDriverPICCtl::getInstance(config); case kDriverNetwork: return new cDriverNetwork(config); case kDriverGU126X64D_K610A4: diff -r df6a40031aa5 -r 37602e25a04a graphlcd-base/glcddrivers/picctl.c --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/graphlcd-base/glcddrivers/picctl.c Wed Feb 06 17:37:50 2008 +0000 @@ -0,0 +1,398 @@ +/* + * GraphLCD driver library + * + * picctl.c - PIC controlled LCD driver class + * + * This file is released under the GNU General Public License. Refer + * to the COPYING file distributed with this package. + * + * Codebase by Andreas Regel + * (c) 2007 Carsten Presser + */ + +#include +#include +#include + +#include "common.h" +#include "config.h" +#include "port.h" +#include "picctl.h" + + + +namespace GLCD +{ + +/* command header: +** 8 bits sync byte (0xAA for sent commands, 0x55 for received commands) +** 8 bits command id +** 16 bits command length (excluding header) +*/ +const unsigned char CMD_HDR_SYNC = 0; +const unsigned char CMD_HDR_COMMAND = 1; +const unsigned char CMD_HDR_LENGTH = 2; +const unsigned char CMD_DATA_START = 4; + +const unsigned char CMD_SYNC_SEND = 0xAA; +const unsigned char CMD_SYNC_RECV = 0x55; + + +const unsigned char CMD_SYS_SYNC = 0x00; +const unsigned char CMD_SYS_ACK = 0x01; +const unsigned char CMD_SYS_NACK = 0x02; +const unsigned char CMD_SYS_NIMP = 0xFF; +const unsigned char CMD_SYS_IR = 0x10; + +const unsigned char CMD_DISP_CLEAR_SCREEN = 0x10; +const unsigned char CMD_DISP_SET_ROW_DATA = 0x14; +const unsigned char CMD_DISP_SET_ADDRESS = 0x16; + +const unsigned char CMD_READ_CLOCK = 0x40; +const unsigned char CMD_WRITE_CLOCK = 0x41; +const unsigned char CMD_SET_PWM1 = 0x45; +const unsigned char CMD_SET_PWM2 = 0x46; + +const unsigned char CMD_SET_MODE_MANAGED = 0x70; +const unsigned char CMD_SET_MODE_UNMANAGED = 0x71; + +const unsigned char CMD_BOOT = 0x80; +// singleton +cDriverPICCtl* cDriverPICCtl::instance = 0; + +cDriverPICCtl* cDriverPICCtl::getInstance(cDriverConfig * config) +{ + if (!instance) + instance = new cDriverPICCtl(config); + return instance; +} +// end singleton-pattern + + + +cDriverPICCtl::cDriverPICCtl(cDriverConfig * config) +: config(config) +{ + oldConfig = new cDriverConfig(*config); + + port = new cSerialPort(); + + //width = config->width; + //height = config->height; + refreshCounter = 0; + ack_flag = false; +} + +cDriverPICCtl::~cDriverPICCtl() +{ + delete port; + delete oldConfig; +} + +void cDriverPICCtl::SignalHandler(int signal) +{ + unsigned char buf[255]; + int numbytes,i; + + numbytes = instance->port->ReadData(buf,255); + + + if ((buf[CMD_HDR_SYNC] == CMD_SYNC_RECV) && (buf[CMD_HDR_LENGTH+1] == (numbytes - CMD_DATA_START))) + { + switch (buf[CMD_HDR_COMMAND]) + { + case CMD_SYS_ACK: instance->ack_flag = true; + break; + + case CMD_SYS_IR: printf(" Incoming Key-Event 0x%02x (Source 0x%02x)\n",buf[CMD_DATA_START+1],buf[CMD_DATA_START]); + break; + + default: printf(" recieved Message 0x%x \n",buf[CMD_HDR_COMMAND]); + } + } + else + { + syslog(LOG_INFO, "PICCtl received a malformed packet.\n"); + for (i=0; ioptions.size(); i++) + { + if (config->options[i].name == "") + { + } + } + + // setup lcd array (wanted state) + newLCD = new unsigned char*[height]; + if (newLCD) + { + for (y = 0; y < height; y++) + { + newLCD[y] = new unsigned char[width/8]; + memset(newLCD[y], 0, (width/8)); + } + } + // setup lcd array (current state) + oldLCD = new unsigned char*[height]; + if (oldLCD) + { + for (y = 0; y < height; y++) + { + oldLCD[y] = new unsigned char[width/8]; + memset(oldLCD[y], 0, (width/8)); + } + } + + if (config->device == "") + { + return -1; + } + if (port->Open(config->device.c_str(), SignalHandler) != 0) + return -1; + + *oldConfig = *config; + + // clear display + Clear(); + CmdDispClearScreen(); + CmdDispSetManaged(); + CmdDispSetBrightness(100); + + syslog(LOG_INFO, "%s: PICCtl initialized.\n", config->name.c_str()); + return 0; +} + +int cDriverPICCtl::DeInit() +{ + int y; + // free lcd array (wanted state) + if (newLCD) + { + for (y = 0; y < height; y++) + { + delete[] newLCD[y]; + } + delete[] newLCD; + } + // free lcd array (current state) + if (oldLCD) + { + for (y = 0; y < height; y++) + { + delete[] oldLCD[y]; + } + delete[] oldLCD; + } + + CmdDispSetUnManaged(); + + delete instance; + instance = 0; + + if (port->Close() != 0) + return -1; + return 0; +} + +int cDriverPICCtl::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 cDriverPICCtl::Clear() +{ + for (int y = 0; y < height; y++) + memset(newLCD[y], 0, (width/8)); +} + +void cDriverPICCtl::Set8Pixels(int x, int y, unsigned char data) +{ + if (x >= width || y >= height) + return; + + if (!config->upsideDown) + { + newLCD[y][x/8] = data; + } + else + { + x = width - 1 - x; + y = height - 1 - y; + newLCD[y][x / 8] |= ReverseBits(data); + } +} + +void cDriverPICCtl::Refresh(bool refreshAll) +{ + int y; + + if (CheckSetup() == 1) + refreshAll = true; + + if (config->refreshDisplay > 0) + { + refreshCounter = (refreshCounter + 1) % config->refreshDisplay; + if (!refreshAll && !refreshCounter) + refreshAll = true; + } + + + if (refreshAll) + { + // draw all + // always draw a complete row! (30 bytes!) + for (y = 0; y < height; y++) + { + CmdDispSetColData(y, 0, (width/8), newLCD[y]); + memcpy(oldLCD[y], newLCD[y], (width/8)); + } + // and reset RefreshCounter + refreshCounter = 0; + } + else + { + // for every line + for (y = 0; y< height; y++) + { + // did anysthing change? -> draw new line + if (memcmp(newLCD[y],oldLCD[y],(width/8)) != 0) + { + CmdDispSetColData(y, 0, (width/8), newLCD[y]); + memcpy(oldLCD[y], newLCD[y], (width/8)); + } + } + } +} + +void cDriverPICCtl::SetBrightness(unsigned int percent) +{ + CmdDispSetBrightness(percent); +} + +void cDriverPICCtl::SetClock(unsigned int percent) +{ + CmdDispSetBrightness(percent); +} + +int cDriverPICCtl::WaitForAck(void) +{ + int timeout; + + for (timeout=0; timeout<10000; timeout++) + { + usleep(10); + if (ack_flag) return 1; + } + syslog(LOG_INFO, "PICCtl: missed a ACK packet!.\n"); + return 0; +} + +void cDriverPICCtl::CmdDispClearScreen(void) +{ + uint8_t cmd[4]; + + cmd[CMD_HDR_SYNC] = CMD_SYNC_SEND; + cmd[CMD_HDR_COMMAND] = CMD_DISP_CLEAR_SCREEN; + cmd[CMD_HDR_LENGTH] = 0; + cmd[CMD_HDR_LENGTH+1] = 0; + + port->WriteData(cmd, 4); + WaitForAck(); +} + +void cDriverPICCtl::CmdDispSetBrightness(uint8_t percent) +{ + uint8_t cmd[5]; + + cmd[CMD_HDR_SYNC] = CMD_SYNC_SEND; + cmd[CMD_HDR_COMMAND] = CMD_SET_PWM1; + cmd[CMD_HDR_LENGTH] = 0; + cmd[CMD_HDR_LENGTH+1] = 1; + cmd[CMD_DATA_START] = (uint8_t) round(percent * 2.55); + + port->WriteData(cmd, 5); + WaitForAck(); +} + +void cDriverPICCtl::CmdDispSetColData(uint8_t yoffset, uint8_t xoffset, uint8_t length, uint8_t * data) +{ + uint8_t cmd[64]; + uint16_t address; + + address = 0x1E * yoffset + xoffset; + + cmd[CMD_HDR_SYNC] = CMD_SYNC_SEND; + cmd[CMD_HDR_COMMAND] = CMD_DISP_SET_ROW_DATA; + cmd[CMD_HDR_LENGTH] = 0; + cmd[CMD_HDR_LENGTH+1] = (length + 2); + cmd[CMD_DATA_START] = (uint8_t)(address % 256); // lower address + cmd[CMD_DATA_START+1] = (uint8_t)(address / 256); // upper address + memcpy(&cmd[CMD_DATA_START+2], data, length); + + port->WriteData(cmd, length + 6); + WaitForAck(); + +// for (address = 0; address < length+6; address ++) printf("0x%02x ",cmd[address]); +// printf("address=0x%x upper=0x%x lower=0x%x \n", address, (uint8_t)(address / 256), (uint8_t)(address % 256)); +// printf("\n"); +} + +void cDriverPICCtl::CmdDispSetManaged(void) +{ + uint8_t cmd[4]; + + cmd[CMD_HDR_SYNC] = CMD_SYNC_SEND; + cmd[CMD_HDR_COMMAND] = CMD_SET_MODE_MANAGED; + cmd[CMD_HDR_LENGTH] = 0; + cmd[CMD_HDR_LENGTH+1] = 0; + + port->WriteData(cmd,4); + WaitForAck(); +} + +void cDriverPICCtl::CmdDispSetUnManaged(void) +{ + uint8_t cmd[4]; + + cmd[CMD_HDR_SYNC] = CMD_SYNC_SEND; + cmd[CMD_HDR_COMMAND] = CMD_SET_MODE_UNMANAGED; + cmd[CMD_HDR_LENGTH] = 0; + cmd[CMD_HDR_LENGTH+1] = 0; + + port->WriteData(cmd,4); + WaitForAck(); +} + + +} // end NameSpace diff -r df6a40031aa5 -r 37602e25a04a graphlcd-base/glcddrivers/picctl.h --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/graphlcd-base/glcddrivers/picctl.h Wed Feb 06 17:37:50 2008 +0000 @@ -0,0 +1,68 @@ +/* + * GraphLCD driver library + * + * picctl.c - PIC controlled LCD driver class + * + * This file is released under the GNU General Public License. Refer + * to the COPYING file distributed with this package. + * + * Codebase by Andreas Regel + * (c) 2007 Carsten Presser + */ + +#ifndef _GLCDDRIVERS_PICCTL_H_ +#define _GLCDDRIVERS_PICCTL_H_ + +#include "driver.h" + +namespace GLCD +{ + +class cDriverConfig; +class cSerialPort; + +class cDriverPICCtl : public cDriver +{ +private: + cSerialPort * port; + unsigned char ** newLCD; // wanted state + unsigned char ** oldLCD; // current state + cDriverConfig * config; + cDriverConfig * oldConfig; + int refreshCounter; + bool ack_flag; + + int WaitForAck(void); + void CmdDispClearScreen(void); + void CmdSetMode(uint8_t mode); + void CmdDispSetManaged(void); + void CmdDispSetUnManaged(void); + void CmdDispSetBrightness(uint8_t percent); + void CmdDispSetColData(uint8_t yoffset, uint8_t xoffset, uint8_t length, uint8_t * data); + + int CheckSetup(); + + static void SignalHandler(int signal); + +// singleton + static cDriverPICCtl* instance; // die EINE instant + cDriverPICCtl(cDriverConfig * config); // Konstruktor + +public: + virtual int Init(); + virtual int DeInit(); + + virtual void Clear(); + virtual void Set8Pixels(int x, int y, unsigned char data); + virtual void Refresh(bool refreshAll = false); + virtual void SetBrightness(unsigned int percent); + virtual void SetClock(unsigned int percent); + +// singleton + virtual ~cDriverPICCtl(); // Destruktor + static cDriverPICCtl* getInstance(cDriverConfig * config); +}; + +} // end of namespace + +#endif diff -r df6a40031aa5 -r 37602e25a04a graphlcd-base/glcddrivers/port.c --- a/graphlcd-base/glcddrivers/port.c Wed Feb 06 17:32:55 2008 +0000 +++ b/graphlcd-base/glcddrivers/port.c Wed Feb 06 17:37:50 2008 +0000 @@ -16,6 +16,7 @@ #include #include #include +#include #include #include #include @@ -25,6 +26,9 @@ #include "port.h" + + + namespace GLCD { @@ -282,9 +286,10 @@ { } -int cSerialPort::Open(const char * device) +int cSerialPort::Open(const char * device, void (*FP)(int)) { struct termios options; + struct sigaction saio; fd = open(device, O_RDWR | O_NOCTTY | O_NDELAY); if (fd == -1) @@ -292,8 +297,19 @@ printf("error opening port\n"); return -1; } - //fcntl(fd, F_SETFL, FNDELAY); - fcntl(fd, F_SETFL, 0); + + + // install the signal handler before making the device asynchronous/ + saio.sa_handler = FP; + sigemptyset (&saio.sa_mask); + saio.sa_flags = 0; + saio.sa_restorer = NULL; + sigaction(SIGIO,&saio,NULL); + + // allow the process to receive SIGIO + fcntl(fd, F_SETOWN, getpid()); + // Make the file descriptor asynchronous + fcntl(fd, F_SETFL, FASYNC); tcgetattr(fd, &options); @@ -328,11 +344,11 @@ return 0; } -int cSerialPort::ReadData(unsigned char * data) +int cSerialPort::ReadData(unsigned char * data, int num) { if (fd == -1) return 0; - return read(fd, data, 1); + return read(fd, data, num); } void cSerialPort::WriteData(unsigned char data) @@ -347,4 +363,6 @@ write(fd, data, length); } + } // end of namespace + diff -r df6a40031aa5 -r 37602e25a04a graphlcd-base/glcddrivers/port.h --- a/graphlcd-base/glcddrivers/port.h Wed Feb 06 17:32:55 2008 +0000 +++ b/graphlcd-base/glcddrivers/port.h Wed Feb 06 17:37:50 2008 +0000 @@ -65,10 +65,10 @@ cSerialPort(); ~cSerialPort(); - int Open(const char * device); + int Open(const char * device, void (*FP)(int)); int Close(); - int ReadData(unsigned char * data); + int ReadData(unsigned char * data, int num); void WriteData(unsigned char data); void WriteData(unsigned char * data, unsigned short length); };