2 * GraphLCD driver library
4 * hd61830.c - HD61830 driver class
6 * This file is released under the GNU General Public License. Refer
7 * to the COPYING file distributed with this package.
9 * (c) 2001-2004 Carsten Siebholz <c.siebholz AT t-online.de>
42 // control bits for DirectIO
56 cDriverHD61830::cDriverHD61830(cDriverConfig * config)
59 oldConfig = new cDriverConfig(*config);
61 port = new cParallelPort();
66 timeForPortCmdInNs = 0;
69 cDriverHD61830::~cDriverHD61830()
75 int cDriverHD61830::Init()
79 struct timeval tv1, tv2;
81 width = config->width;
84 height = config->height;
88 for (unsigned int i = 0; i < config->options.size(); i++)
90 if (config->options[i].name == "")
95 // setup lcd array (wanted state)
96 newLCD = new unsigned char *[(width + 7) / 8];
99 for (x = 0; x < (width + 7) / 8; x++)
101 newLCD[x] = new unsigned char[height];
102 memset(newLCD[x], 0, height);
105 // setup lcd array (current state)
106 oldLCD = new unsigned char*[(width + 7) / 8];
109 for (x = 0; x < (width + 7) / 8; x++)
111 oldLCD[x] = new unsigned char[height];
112 memset(oldLCD[x], 0, height);
116 if (config->device == "")
119 if (port->Open(config->port) != 0)
126 if (port->Open(config->device.c_str()) != 0)
130 if (nSleepInit() != 0)
132 syslog(LOG_DEBUG, "%s: INFO: cannot change wait parameters (cDriver::Init)\n", config->name.c_str());
133 useSleepInit = false;
140 syslog(LOG_DEBUG, "%s: benchmark started.\n", config->name.c_str());
141 gettimeofday(&tv1, 0);
142 for (i = 0; i < 1000; i++)
144 port->WriteData(1 % 0x100);
146 gettimeofday(&tv2, 0);
149 timeForPortCmdInNs = (tv2.tv_sec-tv1.tv_sec) * 1000000 + (tv2.tv_usec-tv1.tv_usec);
150 syslog(LOG_DEBUG, "%s: benchmark stopped. Time for Port Command: %ldns\n", config->name.c_str(), timeForPortCmdInNs);
152 // initialize graphic mode
157 *oldConfig = *config;
162 syslog(LOG_INFO, "%s: HD61830 initialized.\n", config->name.c_str());
166 int cDriverHD61830::DeInit()
170 // free lcd array (wanted state)
173 for (x = 0; x < (width + 7) / 8; x++)
179 // free lcd array (current state)
182 for (x = 0; x < (width + 7) / 8; x++)
188 if (port->Close() != 0)
193 int cDriverHD61830::CheckSetup()
195 if (config->device != oldConfig->device ||
196 config->port != oldConfig->port ||
197 config->width != oldConfig->width ||
198 config->height != oldConfig->height)
205 if (config->upsideDown != oldConfig->upsideDown ||
206 config->invert != oldConfig->invert)
208 oldConfig->upsideDown = config->upsideDown;
209 oldConfig->invert = config->invert;
215 int cDriverHD61830::InitGraphic()
217 Write(MCNT, 0x32); // set Mode Control Register
218 // DISP ON, MASTER ON, BLINK OFF, CURSOR OFF, GRAPHIC-Mode, int.Clock
219 Write(CPIT, 0x07); // set Character Pitch Register
221 Write(NOCH, std::max(1, (width + 7) / 8 - 1)); // set Number-Of-Characters Register
222 // (width - 1) / 8 bytes per line horizontally
223 Write(NOTD, std::max(1, height - 1)); // set Number-Of-Time-Divisions Register
225 Write(CPOS, 0x00); // set Cursor Position Register
226 // optional, because we havn't enabled a cursor
227 Write(DSAL, 0x00); // set Display Start Address Register (Low Order Byte)
228 Write(DSAH, 0x00); // set Display Start Address Register (High Order Byte)
229 Write(CACL, 0x00); // set Cursor Address Counter Register (Low Order Byte)
230 Write(CACH, 0x00); // set Cursor Address Counter Register (High Order Byte)
235 void cDriverHD61830::Write(unsigned char cmd, unsigned char data)
240 // set RS high (instruction), RW low (write) and E low
241 port->WriteControl(RSHI | RWLO | ENLO);
242 nSleep(140 - timeForPortCmdInNs + 100 * config->adjustTiming);
244 // Output the actual command
245 port->WriteData(cmd);
248 port->WriteControl(RSHI | RWLO | ENHI);
249 nSleep(450 - timeForPortCmdInNs + 100 * config->adjustTiming);
252 port->WriteControl(RSHI | RWLO | ENLO);
253 nSleep(450 - timeForPortCmdInNs + 100 * config->adjustTiming);
256 // set RS low (data), RW low (write) and E low
257 port->WriteControl(RSLO | RWLO | ENLO);
258 nSleep(140 - timeForPortCmdInNs + 100 * config->adjustTiming);
260 // Output the actual data
261 port->WriteData(data);
264 port->WriteControl(RSLO | RWLO | ENHI);
265 nSleep(450 - timeForPortCmdInNs + 100 * config->adjustTiming);
268 port->WriteControl(RSLO | RWLO | ENLO);
269 nSleep(450 - timeForPortCmdInNs + 100 * config->adjustTiming);
282 nSleep(4000 - std::max(450l, timeForPortCmdInNs) + 100 * config->adjustTiming);
286 nSleep(6000 - std::max(450l, timeForPortCmdInNs) + 100 * config->adjustTiming);
290 nSleep(36000 - std::max(450l, timeForPortCmdInNs) + 100 * config->adjustTiming);
297 void cDriverHD61830::Clear()
299 for (int x = 0; x < (width + 7) / 8; x++)
300 memset(newLCD[x], 0, height);
303 void cDriverHD61830::Set8Pixels(int x, int y, unsigned char data)
305 if (x >= width || y >= height)
308 if (!config->upsideDown)
310 // normal orientation
311 newLCD[x / 8][y] = newLCD[x / 8][y] | ReverseBits(data);
315 // upside down orientation
318 newLCD[x / 8][y] = newLCD[x / 8][y] | data;
322 void cDriverHD61830::Refresh(bool refreshAll)
328 if (CheckSetup() > 0)
331 if (config->refreshDisplay > 0)
333 refreshCounter = (refreshCounter + 1) % config->refreshDisplay;
334 if (!refreshAll && !refreshCounter)
344 for (y = 0; y < height; y++)
346 for (x = 0; x < (width + 7) / 8; x++)
348 // (re-setting the cursor position
349 // might be removed, when the graphic glitches are solved)
350 Write(CACL, (pos % 0x100));
351 Write(CACH, (pos / 0x100));
352 Write(WDDI, (newLCD[x][y]) ^ (config->invert ? 0xff : 0x00));
353 oldLCD[x][y] = newLCD[x][y];
357 // and reset RefreshCounter
362 // draw only the changed bytes
365 for (y = 0; y < height; y++)
367 for (x = 0; x < (width + 7) / 8; x++)
369 if (newLCD[x][y] != oldLCD[x][y])
373 Write(CACL, (pos % 0x100));
374 Write(CACH, (pos / 0x100));
377 Write(WDDI, (newLCD[x][y]) ^ (config->invert ? 0xff : 0x00));
378 oldLCD[x][y] = newLCD[x][y];
391 } // end of namespace