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
29 ** 8 bits sync byte (0xAA for sent commands, 0x55 for received commands)
31 ** 16 bits command length (excluding header)
33 const unsigned char CMD_HDR_SYNC = 0;
34 const unsigned char CMD_HDR_COMMAND = 1;
35 const unsigned char CMD_HDR_LENGTH = 2;
36 const unsigned char CMD_DATA_START = 4;
38 const unsigned char CMD_SYNC_SEND = 0xAA;
39 const unsigned char CMD_SYNC_RECV = 0x55;
40 const unsigned char CMD_ESCAPE_BYTE = 0x42;
43 const unsigned char CMD_SYS_SYNC = 0x00;
44 const unsigned char CMD_SYS_ACK = 0x01;
45 const unsigned char CMD_SYS_NACK = 0x02;
46 const unsigned char CMD_SYS_NIMP = 0xFF;
47 const unsigned char CMD_SYS_IR = 0x10;
49 const unsigned char CMD_DISP_CLEAR_SCREEN = 0x10;
50 const unsigned char CMD_DISP_SET_ROW_DATA = 0x14;
51 const unsigned char CMD_DISP_SET_ADDRESS = 0x16;
53 const unsigned char CMD_READ_CLOCK = 0x40;
54 const unsigned char CMD_WRITE_CLOCK = 0x41;
55 const unsigned char CMD_SET_PWM1 = 0x45;
56 const unsigned char CMD_SET_PWM2 = 0x46;
58 const unsigned char CMD_SET_MODE_MANAGED = 0x70;
59 const unsigned char CMD_SET_MODE_UNMANAGED = 0x71;
61 const unsigned char CMD_BOOT = 0x80;
64 cDriverPICCtl::cDriverPICCtl(cDriverConfig * config)
67 oldConfig = new cDriverConfig(*config);
69 port = new cSerialPort();
71 width = config->width;
72 height = config->height;
79 buf_flag_escape = false;
85 cDriverPICCtl::~cDriverPICCtl()
93 bool cDriverPICCtl::HasKeys()
98 int cDriverPICCtl::GetKey()
102 if (keys_pos != keys_pos_)
104 keys_pos_ = keys_pos;
105 return(keys[keys_pos-1]);
114 void cDriverPICCtl::InputHandler()
116 // read all available data (always get single bytes...)
117 while (port->ReadData(&buf[buf_pos]) > 0)
119 // search for SYNC byte
120 if ((buf[buf_pos] == CMD_SYNC_RECV) && (!buf_flag_escape))
122 if (buf_cmd_start != 255)
126 printf("Damaged Packet: ");
127 for (i=buf_cmd_start; i<buf_pos; i++)
129 printf("0x%02x ",buf[i]);
131 printf("; buf_pos = %d, buf_cmd_start = %d\n",buf_pos,buf_cmd_start);
134 syslog(LOG_INFO, "PICCtl received a malformed packet. Scrapped %d bytes\n",(buf_pos - buf_cmd_start));
136 buf[buf_pos] = CMD_SYNC_RECV;
138 buf_cmd_start = buf_pos;
142 // escaping is not used so far...
143 /* if ((buf[buf_pos] == CMD_ESCAPE_BYTE) && (!buf_flag_escape))
145 // this byte was for masking only.. ignore it!
146 buf_flag_escape = true;
149 buf_flag_escape = false;*/
153 // we need to check for a valid packet...
154 if ((buf_pos - buf_cmd_start) >= CMD_DATA_START)
156 // if we recieved a valid packet: start decoding
157 if (buf[buf_cmd_start + CMD_HDR_LENGTH+1] == (buf_pos - buf_cmd_start - CMD_DATA_START))
159 DecodeCmd(&buf[buf_cmd_start],buf_pos);
168 void cDriverPICCtl::DecodeCmd(uint8_t * cmd, uint8_t len)
172 printf("cmd(%2d): ",len);
173 for (i=0; i<len; i++) { printf("0x%02x ",cmd[i]);}
177 switch (cmd[CMD_HDR_COMMAND])
179 case CMD_SYS_ACK: ack_flag = true;
182 case CMD_SYS_IR: keys[keys_pos] = 256 * cmd[CMD_DATA_START] + cmd[CMD_DATA_START+1];
185 printf(" %s: recieved IR Command 0x%x \n",config->name.c_str(), cmd[CMD_DATA_START+1]);
189 default: syslog(LOG_INFO," %s: recieved Message 0x%x \n",config->name.c_str(), cmd[CMD_HDR_COMMAND]);
195 int cDriverPICCtl::Init()
199 // fixed values so far...
203 for (unsigned int i = 0; i < config->options.size(); i++)
205 if (config->options[i].name == "")
210 // setup lcd array (wanted state)
211 newLCD = new unsigned char*[height];
214 for (y = 0; y < height; y++)
216 newLCD[y] = new unsigned char[width/8];
217 memset(newLCD[y], 0, (width/8));
220 // setup lcd array (current state)
221 oldLCD = new unsigned char*[height];
224 for (y = 0; y < height; y++)
226 oldLCD[y] = new unsigned char[width/8];
227 memset(oldLCD[y], 0, (width/8));
231 if (config->device == "")
235 if (port->Open(config->device.c_str()) != 0)
238 *oldConfig = *config;
242 CmdDispClearScreen();
245 syslog(LOG_INFO, "%s: PICCtl initialized.\n", config->name.c_str());
249 int cDriverPICCtl::DeInit()
253 CmdDispSetUnManaged();
254 CmdDispClearScreen();
256 // free lcd array (wanted state)
259 for (y = 0; y < height; y++)
265 // free lcd array (current state)
268 for (y = 0; y < height; y++)
276 if (port->Close() != 0)
282 int cDriverPICCtl::CheckSetup()
284 if (config->device != oldConfig->device ||
285 config->width != oldConfig->width ||
286 config->height != oldConfig->height)
293 if (config->upsideDown != oldConfig->upsideDown ||
294 config->invert != oldConfig->invert)
296 oldConfig->upsideDown = config->upsideDown;
297 oldConfig->invert = config->invert;
303 void cDriverPICCtl::Clear()
305 for (int y = 0; y < height; y++)
306 memset(newLCD[y], 0, (width/8));
309 void cDriverPICCtl::Set8Pixels(int x, int y, unsigned char data)
311 if (x >= width || y >= height)
314 if (!config->upsideDown)
316 newLCD[y][x/8] = data;
322 newLCD[y][x / 8] |= ReverseBits(data);
326 void cDriverPICCtl::Refresh(bool refreshAll)
330 if (CheckSetup() == 1)
333 if (config->refreshDisplay > 0)
335 refreshCounter = (refreshCounter + 1) % config->refreshDisplay;
336 if (!refreshAll && !refreshCounter)
344 // always draw a complete row! (30 bytes!)
345 for (y = 0; y < height; y++)
347 CmdDispSetColData(y, 0, (width/8), newLCD[y]);
348 memcpy(oldLCD[y], newLCD[y], (width/8));
350 // and reset RefreshCounter
356 for (y = 0; y< height; y++)
358 // did anysthing change? -> draw new line
359 if (memcmp(newLCD[y],oldLCD[y],(width/8)) != 0)
361 CmdDispSetColData(y, 0, (width/8), newLCD[y]);
362 memcpy(oldLCD[y], newLCD[y], (width/8));
368 void cDriverPICCtl::SetBrightness(unsigned int percent)
370 CmdDispSetBrightness(percent);
373 int cDriverPICCtl::WaitForAck(void)
377 for (timeout=0; timeout<1000; timeout++)
381 if (ack_flag) return 0;
383 syslog(LOG_INFO, "%s: PICCtl missed a ACK packet!\n", config->name.c_str());
388 printf("%s: PICCtl missed a ACK packet!\n", config->name.c_str());
389 for (i=0; i<buf_pos; i++)
391 printf("0x%02x ",buf[i]);
393 printf("; buf_pos = %d, buf_cmd_start = %d\n",buf_pos,buf_cmd_start);
399 void cDriverPICCtl::CmdDispClearScreen(void)
403 cmd[CMD_HDR_SYNC] = CMD_SYNC_SEND;
404 cmd[CMD_HDR_COMMAND] = CMD_DISP_CLEAR_SCREEN;
405 cmd[CMD_HDR_LENGTH] = 0;
406 cmd[CMD_HDR_LENGTH+1] = 0;
409 port->WriteData(cmd, 4);
413 void cDriverPICCtl::CmdDispSetBrightness(uint8_t percent)
417 cmd[CMD_HDR_SYNC] = CMD_SYNC_SEND;
418 cmd[CMD_HDR_COMMAND] = CMD_SET_PWM1;
419 cmd[CMD_HDR_LENGTH] = 0;
420 cmd[CMD_HDR_LENGTH+1] = 1;
421 cmd[CMD_DATA_START] = (uint8_t) round(percent * 2.55);
424 port->WriteData(cmd, 5);
428 void cDriverPICCtl::CmdDispSetColData(uint8_t yoffset, uint8_t xoffset, uint8_t length, uint8_t * data)
433 address = 0x1E * yoffset + xoffset;
435 cmd[CMD_HDR_SYNC] = CMD_SYNC_SEND;
436 cmd[CMD_HDR_COMMAND] = CMD_DISP_SET_ROW_DATA;
437 cmd[CMD_HDR_LENGTH] = 0;
438 cmd[CMD_HDR_LENGTH+1] = (length + 2);
439 cmd[CMD_DATA_START] = (uint8_t)(address % 256); // lower address
440 cmd[CMD_DATA_START+1] = (uint8_t)(address / 256); // upper address
441 memcpy(&cmd[CMD_DATA_START+2], data, length);
444 port->WriteData(cmd, length + 6);
447 // for (address = 0; address < length+6; address ++) printf("0x%02x ",cmd[address]);
448 // printf("address=0x%x upper=0x%x lower=0x%x \n", address, (uint8_t)(address / 256), (uint8_t)(address % 256));
452 void cDriverPICCtl::CmdDispSetManaged(void)
456 cmd[CMD_HDR_SYNC] = CMD_SYNC_SEND;
457 cmd[CMD_HDR_COMMAND] = CMD_SET_MODE_MANAGED;
458 cmd[CMD_HDR_LENGTH] = 0;
459 cmd[CMD_HDR_LENGTH+1] = 0;
462 port->WriteData(cmd,4);
466 void cDriverPICCtl::CmdDispSetUnManaged(void)
470 cmd[CMD_HDR_SYNC] = CMD_SYNC_SEND;
471 cmd[CMD_HDR_COMMAND] = CMD_SET_MODE_UNMANAGED;
472 cmd[CMD_HDR_LENGTH] = 0;
473 cmd[CMD_HDR_LENGTH+1] = 0;
475 port->WriteData(cmd,4);