2 * GraphLCD driver library
4 * picctl.c - PIC controlled LCD driver class
6 * This file is released under the GNU General Public License. Refer
7 * to the COPYING file distributed with this package.
9 * Codebase by Andreas Regel <andreas.regel AT powarman.de>
10 * (c) 2007 Carsten Presser
28 ** 8 bits sync byte (0xAA for sent commands, 0x55 for received commands)
30 ** 16 bits command length (excluding header)
32 const unsigned char CMD_HDR_SYNC = 0;
33 const unsigned char CMD_HDR_COMMAND = 1;
34 const unsigned char CMD_HDR_LENGTH = 2;
35 const unsigned char CMD_DATA_START = 4;
37 const unsigned char CMD_SYNC_SEND = 0xAA;
38 const unsigned char CMD_SYNC_RECV = 0x55;
39 const unsigned char CMD_ESCAPE_BYTE = 0x42;
42 const unsigned char CMD_SYS_SYNC = 0x00;
43 const unsigned char CMD_SYS_ACK = 0x01;
44 const unsigned char CMD_SYS_NACK = 0x02;
45 const unsigned char CMD_SYS_NIMP = 0xFF;
46 const unsigned char CMD_SYS_IR = 0x10;
48 const unsigned char CMD_DISP_CLEAR_SCREEN = 0x10;
49 const unsigned char CMD_DISP_SET_ROW_DATA = 0x14;
50 const unsigned char CMD_DISP_SET_ADDRESS = 0x16;
52 const unsigned char CMD_READ_CLOCK = 0x40;
53 const unsigned char CMD_WRITE_CLOCK = 0x41;
54 const unsigned char CMD_SET_PWM1 = 0x45;
55 const unsigned char CMD_SET_PWM2 = 0x46;
57 const unsigned char CMD_SET_MODE_MANAGED = 0x70;
58 const unsigned char CMD_SET_MODE_UNMANAGED = 0x71;
60 const unsigned char CMD_BOOT = 0x80;
64 uint8_t cDriverPICCtl::buf[255];
65 uint8_t cDriverPICCtl::buf_pos;
66 uint8_t cDriverPICCtl::buf_cmd_start;
67 bool cDriverPICCtl::buf_flag_escape;
70 cDriverPICCtl* cDriverPICCtl::instance = 0;
72 cDriverPICCtl* cDriverPICCtl::getInstance(cDriverConfig * config)
75 instance = new cDriverPICCtl(config);
78 // end singleton-pattern
82 cDriverPICCtl::cDriverPICCtl(cDriverConfig * config)
85 oldConfig = new cDriverConfig(*config);
87 port = new cSerialPort();
89 //width = config->width;
90 //height = config->height;
96 buf_flag_escape = false;
99 cDriverPICCtl::~cDriverPICCtl()
105 void cDriverPICCtl::SignalHandler(int signal)
109 // read all available data
110 while (instance->port->ReadData(&buf[buf_pos]) > 0)
112 // search for SYNC byte
113 if ((buf[buf_pos] == CMD_SYNC_RECV) && (!buf_flag_escape))
115 if (buf_cmd_start != 255)
117 /*printf("Damaged Packet: ");
118 for (i=buf_cmd_start; i<buf_pos; i++)
120 printf("0x%02x ",buf[i]);
122 printf("; buf_pos = %d, buf_cmd_start = %d\n",buf_pos,buf_cmd_start);*/
124 syslog(LOG_INFO, "PICCtl received a malformed packet. Scrapped %d bytes\n",(buf_pos - buf_cmd_start));
126 buf[buf_pos] = CMD_SYNC_RECV;
128 buf_cmd_start = buf_pos;
132 if ((buf[buf_pos] == CMD_ESCAPE_BYTE) && (!buf_flag_escape))
134 // this byte was for masking only.. ignore it!
135 buf_flag_escape = true;
138 buf_flag_escape = false;
141 for (i=1; i<=buf_pos; i++) { printf("0x%02x ",buf[i]);}
146 // we need to check for a valid packet...
147 if ((buf_pos - buf_cmd_start) >= CMD_DATA_START)
149 // if we recieved a valid packet: start decoding
150 if (buf[buf_cmd_start + CMD_HDR_LENGTH+1] == (buf_pos - buf_cmd_start - CMD_DATA_START))
152 instance->DecodeCmd(&buf[buf_cmd_start],buf_pos);
162 void cDriverPICCtl::DecodeCmd(uint8_t * cmd, uint8_t len)
165 printf("cmd(%2d): ",len);
166 for (i=0; i<len; i++) { printf("0x%02x ",cmd[i]);}
169 switch (cmd[CMD_HDR_COMMAND])
171 case CMD_SYS_ACK: ack_flag = true;
174 case CMD_SYS_IR: syslog(LOG_INFO," %s: incoming Key-Event 0x%02x (Source 0x%02x)\n",config->name.c_str(), cmd[CMD_DATA_START+1], cmd[CMD_DATA_START]);
175 printf(" %s: incoming Key-Event 0x%02x (Source 0x%02x)\n",config->name.c_str(), cmd[CMD_DATA_START+1], cmd[CMD_DATA_START]);
178 default: syslog(LOG_INFO," %s: recieved Message 0x%x \n",config->name.c_str(), cmd[CMD_HDR_COMMAND]);
184 int cDriverPICCtl::Init()
188 // fixed values so far...
192 for (unsigned int i = 0; i < config->options.size(); i++)
194 if (config->options[i].name == "")
199 // setup lcd array (wanted state)
200 newLCD = new unsigned char*[height];
203 for (y = 0; y < height; y++)
205 newLCD[y] = new unsigned char[width/8];
206 memset(newLCD[y], 0, (width/8));
209 // setup lcd array (current state)
210 oldLCD = new unsigned char*[height];
213 for (y = 0; y < height; y++)
215 oldLCD[y] = new unsigned char[width/8];
216 memset(oldLCD[y], 0, (width/8));
220 if (config->device == "")
224 if (port->Open(config->device.c_str(), SignalHandler) != 0)
227 *oldConfig = *config;
231 CmdDispClearScreen();
233 CmdDispSetBrightness(0);
235 syslog(LOG_INFO, "%s: PICCtl initialized.\n", config->name.c_str());
239 int cDriverPICCtl::DeInit()
242 // free lcd array (wanted state)
245 for (y = 0; y < height; y++)
251 // free lcd array (current state)
254 for (y = 0; y < height; y++)
261 CmdDispSetUnManaged();
266 if (port->Close() != 0)
271 int cDriverPICCtl::CheckSetup()
273 if (config->device != oldConfig->device ||
274 config->width != oldConfig->width ||
275 config->height != oldConfig->height)
282 if (config->upsideDown != oldConfig->upsideDown ||
283 config->invert != oldConfig->invert)
285 oldConfig->upsideDown = config->upsideDown;
286 oldConfig->invert = config->invert;
292 void cDriverPICCtl::Clear()
294 for (int y = 0; y < height; y++)
295 memset(newLCD[y], 0, (width/8));
298 void cDriverPICCtl::Set8Pixels(int x, int y, unsigned char data)
300 if (x >= width || y >= height)
303 if (!config->upsideDown)
305 newLCD[y][x/8] = data;
311 newLCD[y][x / 8] |= ReverseBits(data);
315 void cDriverPICCtl::Refresh(bool refreshAll)
319 if (CheckSetup() == 1)
322 if (config->refreshDisplay > 0)
324 refreshCounter = (refreshCounter + 1) % config->refreshDisplay;
325 if (!refreshAll && !refreshCounter)
333 // always draw a complete row! (30 bytes!)
334 for (y = 0; y < height; y++)
336 CmdDispSetColData(y, 0, (width/8), newLCD[y]);
337 memcpy(oldLCD[y], newLCD[y], (width/8));
339 // and reset RefreshCounter
345 for (y = 0; y< height; y++)
347 // did anysthing change? -> draw new line
348 if (memcmp(newLCD[y],oldLCD[y],(width/8)) != 0)
350 CmdDispSetColData(y, 0, (width/8), newLCD[y]);
351 memcpy(oldLCD[y], newLCD[y], (width/8));
357 void cDriverPICCtl::SetBrightness(unsigned int percent)
359 CmdDispSetBrightness(percent);
362 void cDriverPICCtl::SetClock(unsigned int percent)
364 CmdDispSetBrightness(percent);
367 int cDriverPICCtl::WaitForAck(void)
371 for (timeout=0; timeout<10000; timeout++)
374 if (ack_flag) return 1;
376 syslog(LOG_INFO, "PICCtl: missed a ACK packet!.\n");
380 void cDriverPICCtl::CmdDispClearScreen(void)
384 cmd[CMD_HDR_SYNC] = CMD_SYNC_SEND;
385 cmd[CMD_HDR_COMMAND] = CMD_DISP_CLEAR_SCREEN;
386 cmd[CMD_HDR_LENGTH] = 0;
387 cmd[CMD_HDR_LENGTH+1] = 0;
389 port->WriteData(cmd, 4);
393 void cDriverPICCtl::CmdDispSetBrightness(uint8_t percent)
397 cmd[CMD_HDR_SYNC] = CMD_SYNC_SEND;
398 cmd[CMD_HDR_COMMAND] = CMD_SET_PWM1;
399 cmd[CMD_HDR_LENGTH] = 0;
400 cmd[CMD_HDR_LENGTH+1] = 1;
401 cmd[CMD_DATA_START] = (uint8_t) round(percent * 2.55);
403 port->WriteData(cmd, 5);
407 void cDriverPICCtl::CmdDispSetColData(uint8_t yoffset, uint8_t xoffset, uint8_t length, uint8_t * data)
412 address = 0x1E * yoffset + xoffset;
414 cmd[CMD_HDR_SYNC] = CMD_SYNC_SEND;
415 cmd[CMD_HDR_COMMAND] = CMD_DISP_SET_ROW_DATA;
416 cmd[CMD_HDR_LENGTH] = 0;
417 cmd[CMD_HDR_LENGTH+1] = (length + 2);
418 cmd[CMD_DATA_START] = (uint8_t)(address % 256); // lower address
419 cmd[CMD_DATA_START+1] = (uint8_t)(address / 256); // upper address
420 memcpy(&cmd[CMD_DATA_START+2], data, length);
422 port->WriteData(cmd, length + 6);
425 // for (address = 0; address < length+6; address ++) printf("0x%02x ",cmd[address]);
426 // printf("address=0x%x upper=0x%x lower=0x%x \n", address, (uint8_t)(address / 256), (uint8_t)(address % 256));
430 void cDriverPICCtl::CmdDispSetManaged(void)
434 cmd[CMD_HDR_SYNC] = CMD_SYNC_SEND;
435 cmd[CMD_HDR_COMMAND] = CMD_SET_MODE_MANAGED;
436 cmd[CMD_HDR_LENGTH] = 0;
437 cmd[CMD_HDR_LENGTH+1] = 0;
439 port->WriteData(cmd,4);
443 void cDriverPICCtl::CmdDispSetUnManaged(void)
447 cmd[CMD_HDR_SYNC] = CMD_SYNC_SEND;
448 cmd[CMD_HDR_COMMAND] = CMD_SET_MODE_UNMANAGED;
449 cmd[CMD_HDR_LENGTH] = 0;
450 cmd[CMD_HDR_LENGTH+1] = 0;
452 port->WriteData(cmd,4);