2 * GraphLCD driver library
4 * serdisp.h - include support for displays supported by serdisplib (if library is installed)
5 * http://serdisplib.sourceforge.net
7 * This file is released under the GNU General Public License. Refer
8 * to the COPYING file distributed with this package.
10 * (c) 2003-2005 Wolfgang Astleitner <mrwastl AT users.sourceforge.net>
22 #define SERDISP_VERSION(a,b) ((long)(((a) << 8) + (b)))
23 #define SERDISP_VERSION_GET_MAJOR(_c) ((int)( (_c) >> 8 ))
24 #define SERDISP_VERSION_GET_MINOR(_c) ((int)( (_c) & 0xFF ))
26 // taken from serdisp_control.h
27 #define FEATURE_CONTRAST 0x01
28 #define FEATURE_REVERSE 0x02
29 #define FEATURE_BACKLIGHT 0x03
30 #define FEATURE_ROTATE 0x04
32 #define SD_COL_BLACK 0xFF000000
37 cDriverSerDisp::cDriverSerDisp(cDriverConfig * config)
40 oldConfig = new cDriverConfig(*config);
45 cDriverSerDisp::~cDriverSerDisp(void)
50 int cDriverSerDisp::Init(void)
52 char* errmsg; // error message returned by dlerror()
54 std::string controller;
55 std::string optionstring = "";
56 std::string wiringstring;
59 // dynamically load serdisplib using dlopen() & co.
61 sdhnd = dlopen("libserdisp.so", RTLD_LAZY);
62 if (!sdhnd) { // try /usr/local/lib
63 sdhnd = dlopen("/usr/local/lib/libserdisp.so", RTLD_LAZY);
66 if (!sdhnd) { // serdisplib seems not to be installed
67 syslog(LOG_ERR, "%s: error: unable to dynamically load library '%s'. Err: %s (cDriver::Init)\n",
68 config->name.c_str(), "libserdisp.so", "not found");
72 dlerror(); // clear error code
74 /* pre-init some flags, function pointers, ... */
79 // get serdisp version
80 fp_serdisp_getversioncode = (long int (*)()) dlsym(sdhnd, "serdisp_getversioncode");
82 if (dlerror()) { // no serdisp_getversioncode() -> version of serdisplib is < 1.95
83 syslog(LOG_DEBUG, "%s: INFO: symbol serdisp_getversioncode unknown: autodetecting pre 1.95 serdisplib version (cDriver::Init)\n",
84 config->name.c_str());
86 fp_SDCONN_open = (void*(*)(const char*)) dlsym(sdhnd, "SDCONN_open");
87 if (dlerror()) { // no SDCONN_open() -> version of serdisplib is < 1.93
88 serdisp_version = SERDISP_VERSION(1,92);
89 syslog(LOG_DEBUG, "%s: INFO: detected serdisplib version <= 1.92 (cDriver::Init)\n", config->name.c_str());
91 fp_PP_open = (void*(*)(const char*))dlsym(sdhnd, "PP_open");
92 if ( (errmsg = dlerror()) != NULL ) { // should not happen
93 syslog(LOG_ERR, "%s: error: cannot load symbol %s. Err:%s (cDriver::Init)\n",
94 config->name.c_str(), "PP_open", errmsg);
97 fp_PP_close = (void*(*)(void*))dlsym(sdhnd, "PP_close");
98 if ( (errmsg = dlerror()) != NULL ) { // should not happen
99 syslog(LOG_ERR, "%s: error: cannot load symbol %s. Err:%s (cDriver::Init)\n",
100 config->name.c_str(), "PP_close", errmsg);
104 serdisp_version = SERDISP_VERSION(1,94); // no serdisp_getversioncode, but SDCONN_open: 1.93 or 1.94
105 syslog(LOG_DEBUG, "%s: INFO: detected serdisplib version 1.93 or 1.94 (cDriver::Init)\n", config->name.c_str());
107 fp_serdisp_quit = (void (*)(void*)) dlsym(sdhnd, "serdisp_quit");
108 if ( (errmsg = dlerror()) != NULL ) { // should not happen
109 syslog(LOG_ERR, "%s: error: cannot load symbol %s. Err:%s (cDriver::Init)\n",
110 config->name.c_str(), "serdisp_quit", errmsg);
115 fp_serdisp_setpixcol = (void (*)(void*, int, int, long int)) dlsym(sdhnd, "serdisp_setpixel");
116 if ( (errmsg = dlerror()) != NULL ) { // should not happen
117 syslog(LOG_ERR, "%s: error: cannot load symbol %s. Err:%s (cDriver::Init)\n",
118 config->name.c_str(), "serdisp_setpixel", errmsg);
121 fg_colour = 1; /* set foreground to 'pixel on' */
123 } else { // serdisp version >= 1.95
124 serdisp_version = fp_serdisp_getversioncode();
125 syslog(LOG_DEBUG, "%s: INFO: detected serdisplib version %d.%d (cDriver::Init)\n",
126 config->name.c_str(), SERDISP_VERSION_GET_MAJOR(serdisp_version), SERDISP_VERSION_GET_MINOR(serdisp_version));
129 fp_SDCONN_open = (void*(*)(const char*)) dlsym(sdhnd, "SDCONN_open");
130 if ( (errmsg = dlerror()) != NULL ) { // should not happen
131 syslog(LOG_ERR, "%s: error: cannot load symbol %s. Err:%s (cDriver::Init)\n",
132 config->name.c_str(), "SDCONN_open", errmsg);
135 fp_serdisp_quit = (void (*)(void*)) dlsym(sdhnd, "serdisp_quit");
136 if ( (errmsg = dlerror()) != NULL ) { // should not happen
137 syslog(LOG_ERR, "%s: error: cannot load symbol %s. Err:%s (cDriver::Init)\n",
138 config->name.c_str(), "serdisp_quit", errmsg);
141 fp_serdisp_setpixcol = (void (*)(void*, int, int, long int)) dlsym(sdhnd, "serdisp_setcolour");
142 if ( (errmsg = dlerror()) != NULL ) { // should not happen
143 syslog(LOG_ERR, "%s: error: cannot load symbol %s. Err:%s (cDriver::Init)\n",
144 config->name.c_str(), "serdisp_setcolour", errmsg);
147 fg_colour = SD_COL_BLACK; /* set foreground colour to black */
149 if (serdisp_version >= SERDISP_VERSION(1,96) ) {
150 supports_options = 1;
152 fp_serdisp_isoption = (int (*)(void*, const char*)) dlsym(sdhnd, "serdisp_isoption");
153 if ( (errmsg = dlerror()) != NULL ) { // should not happen
154 syslog(LOG_ERR, "%s: error: cannot load symbol %s. Err:%s (cDriver::Init)\n",
155 config->name.c_str(), "serdisp_isoption", errmsg);
158 fp_serdisp_setoption = (void (*)(void*, const char*, long int)) dlsym(sdhnd, "serdisp_setoption");
159 if ( (errmsg = dlerror()) != NULL ) { // should not happen
160 syslog(LOG_ERR, "%s: error: cannot load symbol %s. Err:%s (cDriver::Init)\n",
161 config->name.c_str(), "serdisp_setoption", errmsg);
167 // load other symbols that will be required
168 fp_serdisp_init = (void*(*)(void*, const char*, const char*)) dlsym(sdhnd, "serdisp_init");
169 if ( (errmsg = dlerror()) != NULL ) { // should not happen
170 syslog(LOG_ERR, "%s: error: cannot load symbol %s. Err:%s (cDriver::Init)\n",
171 config->name.c_str(), "serdisp_init", errmsg);
175 fp_serdisp_rewrite = (void (*)(void*)) dlsym(sdhnd, "serdisp_rewrite");
176 if ( (errmsg = dlerror()) != NULL ) { // should not happen
177 syslog(LOG_ERR, "%s: error: cannot load symbol %s. Err:%s (cDriver::Init)\n",
178 config->name.c_str(), "serdisp_rewrite", errmsg);
182 fp_serdisp_update = (void (*)(void*)) dlsym(sdhnd, "serdisp_update");
183 if ( (errmsg = dlerror()) != NULL ) { // should not happen
184 syslog(LOG_ERR, "%s: error: cannot load symbol %s. Err:%s (cDriver::Init)\n",
185 config->name.c_str(), "serdisp_update", errmsg);
189 fp_serdisp_clearbuffer = (void (*)(void*)) dlsym(sdhnd, "serdisp_clearbuffer");
190 if ( (errmsg = dlerror()) != NULL ) { // should not happen
191 syslog(LOG_ERR, "%s: error: cannot load symbol %s. Err:%s (cDriver::Init)\n",
192 config->name.c_str(), "serdisp_clearbuffer", errmsg);
196 fp_serdisp_feature = (int (*)(void*, int, int)) dlsym(sdhnd, "serdisp_feature");
197 if ( (errmsg = dlerror()) != NULL ) { // should not happen
198 syslog(LOG_ERR, "%s: error: cannot load symbol %s. Err:%s (cDriver::Init)\n",
199 config->name.c_str(), "serdisp_feature", errmsg);
203 fp_serdisp_close = (void (*)(void*))dlsym(sdhnd, "serdisp_close");
204 if ( (errmsg = dlerror()) != NULL ) { // should not happen
205 syslog(LOG_ERR, "%s: error: cannot load symbol %s. Err:%s (cDriver::Init)\n",
206 config->name.c_str(), "serdisp_close", errmsg);
210 fp_serdisp_getwidth = (int (*)(void*)) dlsym(sdhnd, "serdisp_getwidth");
211 if ( (errmsg = dlerror()) != NULL ) { // should not happen
212 syslog(LOG_ERR, "%s: error: cannot load symbol %s. Err:%s (cDriver::Init)\n",
213 config->name.c_str(), "serdisp_getwidth", errmsg);
217 fp_serdisp_getheight = (int (*)(void*)) dlsym(sdhnd, "serdisp_getheight");
218 if ( (errmsg = dlerror()) != NULL ) { // should not happen
219 syslog(LOG_ERR, "%s: error: cannot load symbol %s. Err:%s (cDriver::Init)\n",
220 config->name.c_str(), "serdisp_getheight", errmsg);
224 // done loading all required symbols
227 // setting up the display
231 for (unsigned int i = 0; i < config->options.size(); i++)
233 if (config->options[i].name == "Controller") {
234 controller = config->options[i].value;
235 } else if (config->options[i].name == "Options") {
236 optionstring = config->options[i].value;
237 } else if (config->options[i].name == "Wiring") {
238 wiringstring = config->options[i].value;
239 } else if (config->options[i].name == "FGColour") {
240 fg_colour = strtoul(config->options[i].value.c_str(), (char **)NULL, 0);
241 fg_colour |= 0xFF000000L; /* force alpha to 0xFF */
242 } else if (config->options[i].name == "BGColour") {
243 bg_colour = strtoul(config->options[i].value.c_str(), (char **)NULL, 0);
244 bg_colour |= 0xFF000000L; /* force alpha to 0xFF */
248 if (wiringstring.length()) {
249 optionstring = "WIRING=" + wiringstring + ((optionstring != "") ? ";" + optionstring : "");
252 if (controller == "")
254 syslog(LOG_ERR, "%s error: no controller given!\n", config->name.c_str());
259 if (config->device == "")
263 // neither device nor port is set
264 if (config->port == 0)
268 snprintf(temp, 8, "0x%x", config->port);
270 if (serdisp_version < SERDISP_VERSION(1,93) ) {
271 sdcd = fp_PP_open(temp);
273 sdcd = fp_SDCONN_open(temp);
277 syslog(LOG_ERR, "%s: error: unable to open port 0x%x for display %s. (cDriver::Init)\n",
278 config->name.c_str(), config->port, controller.c_str());
287 if (serdisp_version < SERDISP_VERSION(1,93) ) {
288 sdcd = fp_PP_open(config->device.c_str());
290 sdcd = fp_SDCONN_open(config->device.c_str());
294 syslog(LOG_ERR, "%s: error: unable to open device %s for display %s. (cDriver::Init)\n",
295 config->name.c_str(), config->device.c_str(), controller.c_str());
300 if (serdisp_version < SERDISP_VERSION(1,95) )
301 dd = fp_serdisp_init(sdcd, controller.c_str(), "");
303 dd = fp_serdisp_init(sdcd, controller.c_str(), optionstring.c_str());
307 syslog(LOG_ERR, "%s: error: cannot open display %s. Err:%s (cDriver::Init)\n",
308 config->name.c_str(), controller.c_str(), "no handle");
312 width = config->width;
314 width = fp_serdisp_getwidth(dd);
315 height = config->height;
317 height = fp_serdisp_getheight(dd);
319 if (serdisp_version < SERDISP_VERSION(1,96) ) {
320 fp_serdisp_feature(dd, FEATURE_ROTATE, config->upsideDown);
321 fp_serdisp_feature(dd, FEATURE_CONTRAST, config->contrast);
322 fp_serdisp_feature(dd, FEATURE_BACKLIGHT, config->backlight);
323 fp_serdisp_feature(dd, FEATURE_REVERSE, config->invert);
325 /* standard options */
326 fp_serdisp_setoption(dd, "ROTATE", config->upsideDown);
327 fp_serdisp_setoption(dd, "CONTRAST", config->contrast);
328 fp_serdisp_setoption(dd, "BACKLIGHT", config->backlight);
329 fp_serdisp_setoption(dd, "INVERT", config->invert);
331 /* driver dependend options */
332 for (unsigned int i = 0; i < config->options.size(); i++) {
333 std::string optionname = config->options[i].name;
334 if (optionname != "UpsideDown" && optionname != "Contrast" &&
335 optionname != "Backlight" && optionname != "Invert") {
337 if ( fp_serdisp_isoption(dd, optionname.c_str()) == 1 ) /* if == 1: option is existing AND r/w */
338 fp_serdisp_setoption(dd, optionname.c_str(), strtol(config->options[i].value.c_str(), NULL, 0));
344 *oldConfig = *config;
349 syslog(LOG_INFO, "%s: SerDisp with %s initialized.\n", config->name.c_str(), controller.c_str());
353 int cDriverSerDisp::DeInit(void)
355 if (serdisp_version < SERDISP_VERSION(1,93) ) {
356 fp_serdisp_close(dd);
360 //fp_serdisp_quit(dd);
361 /* use serdisp_close instead of serdisp_quit so that showpic and showtext are usable together with serdisplib */
362 fp_serdisp_close(dd);
364 (int) dlclose(sdhnd);
370 int cDriverSerDisp::CheckSetup()
374 if (config->device != oldConfig->device ||
375 config->port != oldConfig->port ||
376 config->width != oldConfig->width ||
377 config->height != oldConfig->height)
384 if (config->contrast != oldConfig->contrast)
386 fp_serdisp_feature(dd, FEATURE_CONTRAST, config->contrast);
387 oldConfig->contrast = config->contrast;
390 if (config->backlight != oldConfig->backlight)
392 fp_serdisp_feature(dd, FEATURE_BACKLIGHT, config->backlight);
393 oldConfig->backlight = config->backlight;
396 if (config->upsideDown != oldConfig->upsideDown)
398 fp_serdisp_feature(dd, FEATURE_ROTATE, config->upsideDown);
399 oldConfig->upsideDown = config->upsideDown;
402 if (config->invert != oldConfig->invert)
404 fp_serdisp_feature(dd, FEATURE_REVERSE, config->invert);
405 oldConfig->invert = config->invert;
409 /* driver dependend options */
410 for (unsigned int i = 0; i < config->options.size(); i++) {
411 std::string optionname = config->options[i].name;
412 if (optionname != "UpsideDown" && optionname != "Contrast" &&
413 optionname != "Backlight" && optionname != "Invert") {
415 if ( fp_serdisp_isoption(dd, optionname.c_str()) == 1 ) /* if == 1: option is existing AND r/w */
416 fp_serdisp_setoption(dd, optionname.c_str(), strtol(config->options[i].value.c_str(), NULL, 0));
417 oldConfig->options[i] = config->options[i];
428 void cDriverSerDisp::Clear(void)
431 fp_serdisp_clearbuffer(dd);
432 else { /* if bg_colour is set, draw background 'by hand' */
434 for (y = 0; y < fp_serdisp_getheight(dd); y++)
435 for (x = 0; x < fp_serdisp_getwidth(dd); x++)
436 fp_serdisp_setpixcol(dd, x, y, bg_colour); /* >= 1.95: serdisp_setcolour(), < 1.95: serdisp_setpixel() */
440 void cDriverSerDisp::Set8Pixels(int x, int y, unsigned char data) {
443 data = ReverseBits(data);
445 start = (x >> 3) << 3;
447 for (i = 0; i < 8; i++) {
448 pixel = data & (1 << i);
450 fp_serdisp_setpixcol(dd, start + i, y, fg_colour); /* >= 1.95: serdisp_setcolour(), < 1.95: serdisp_setpixel() */
451 else if (!pixel && bg_colour != -1) /* if bg_colour is set: use it if pixel is not set */
452 fp_serdisp_setpixcol(dd, start + i, y, bg_colour); /* >= 1.95: serdisp_setcolour(), < 1.95: serdisp_setpixel() */
456 void cDriverSerDisp::Refresh(bool refreshAll)
458 if (CheckSetup() == 1)
462 fp_serdisp_rewrite(dd);
464 fp_serdisp_update(dd);
467 } // end of namespace