graphlcd-base/glcddrivers/serdisp.c
changeset 4 df6a40031aa5
equal deleted inserted replaced
3:d0e62fc47285 4:df6a40031aa5
       
     1 /*
       
     2  * GraphLCD driver library
       
     3  *
       
     4  * serdisp.h  -  include support for displays supported by serdisplib (if library is installed)
       
     5  *               http://serdisplib.sourceforge.net
       
     6  *
       
     7  * This file is released under the GNU General Public License. Refer
       
     8  * to the COPYING file distributed with this package.
       
     9  *
       
    10  * (c) 2003-2005 Wolfgang Astleitner <mrwastl AT users.sourceforge.net>
       
    11  */
       
    12 
       
    13 #include <stdio.h>
       
    14 #include <stdlib.h>
       
    15 #include <syslog.h>
       
    16 #include <dlfcn.h>
       
    17 
       
    18 #include "common.h"
       
    19 #include "config.h"
       
    20 #include "serdisp.h"
       
    21 
       
    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 ))
       
    25 
       
    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
       
    31 
       
    32 #define SD_COL_BLACK      0xFF000000
       
    33 
       
    34 namespace GLCD
       
    35 {
       
    36 
       
    37 cDriverSerDisp::cDriverSerDisp(cDriverConfig * config)
       
    38 :   config(config)
       
    39 {
       
    40     oldConfig = new cDriverConfig(*config);
       
    41 
       
    42     dd = (void *) NULL;
       
    43 }
       
    44 
       
    45 cDriverSerDisp::~cDriverSerDisp(void)
       
    46 {
       
    47     delete oldConfig;
       
    48 }
       
    49 
       
    50 int cDriverSerDisp::Init(void)
       
    51 {
       
    52     char* errmsg; // error message returned by dlerror()
       
    53 
       
    54     std::string controller;
       
    55     std::string optionstring = "";
       
    56     std::string wiringstring;
       
    57 
       
    58 
       
    59     // dynamically load serdisplib using dlopen() & co.
       
    60 
       
    61     sdhnd = dlopen("libserdisp.so", RTLD_LAZY);
       
    62     if (!sdhnd) { // try /usr/local/lib
       
    63         sdhnd = dlopen("/usr/local/lib/libserdisp.so", RTLD_LAZY);
       
    64     }
       
    65 
       
    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");
       
    69         return -1;
       
    70     }
       
    71 
       
    72     dlerror(); // clear error code
       
    73 
       
    74     /* pre-init some flags, function pointers, ... */
       
    75     supports_options = 0;
       
    76     fg_colour = 1;
       
    77     bg_colour = -1;
       
    78 
       
    79     // get serdisp version
       
    80     fp_serdisp_getversioncode = (long int (*)()) dlsym(sdhnd, "serdisp_getversioncode");
       
    81 
       
    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());
       
    85 
       
    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());
       
    90 
       
    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);
       
    95                 return -1;
       
    96             }
       
    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);
       
   101                 return -1;
       
   102             }
       
   103         } else {
       
   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());
       
   106 
       
   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);
       
   111                 return -1;
       
   112             }
       
   113         }
       
   114 
       
   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);
       
   119             return -1;
       
   120         }
       
   121         fg_colour = 1; /* set foreground to 'pixel on' */
       
   122 
       
   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));
       
   127 
       
   128 
       
   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);
       
   133             return -1;
       
   134         }
       
   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);
       
   139             return -1;
       
   140         }
       
   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);
       
   145             return -1;
       
   146         }
       
   147         fg_colour = SD_COL_BLACK; /* set foreground colour to black */
       
   148 
       
   149         if (serdisp_version >= SERDISP_VERSION(1,96) ) {
       
   150             supports_options = 1;
       
   151 
       
   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);
       
   156                 return -1;
       
   157             }
       
   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);
       
   162                 return -1;
       
   163             }
       
   164         } /* >= 1.96 */
       
   165     }
       
   166 
       
   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);
       
   172         return -1;
       
   173     }
       
   174 
       
   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);
       
   179         return -1;
       
   180     }
       
   181 
       
   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);
       
   186         return -1;
       
   187     }
       
   188 
       
   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);
       
   193         return -1;
       
   194     }
       
   195 
       
   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);
       
   200         return -1;
       
   201     }
       
   202 
       
   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);
       
   207         return -1;
       
   208     }
       
   209 
       
   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);
       
   214         return -1;
       
   215     }
       
   216 
       
   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);
       
   221         return -1;
       
   222     }
       
   223 
       
   224     // done loading all required symbols
       
   225 
       
   226 
       
   227     // setting up the display
       
   228     width = 0;
       
   229     height = 0;
       
   230 
       
   231     for (unsigned int i = 0; i < config->options.size(); i++)
       
   232     {
       
   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 */
       
   245         }
       
   246     }
       
   247 
       
   248     if (wiringstring.length()) {
       
   249         optionstring = "WIRING=" + wiringstring + ((optionstring != "") ? ";" + optionstring : "");
       
   250     }
       
   251 
       
   252     if (controller == "")
       
   253     {
       
   254         syslog(LOG_ERR, "%s error: no controller given!\n", config->name.c_str());
       
   255         return -1;
       
   256     }
       
   257 
       
   258 
       
   259     if (config->device == "")
       
   260     {
       
   261         // use DirectIO
       
   262 
       
   263         // neither device nor port is set
       
   264         if (config->port == 0)
       
   265             return -1;
       
   266 
       
   267         char temp[10];
       
   268         snprintf(temp, 8, "0x%x", config->port);
       
   269 
       
   270         if (serdisp_version < SERDISP_VERSION(1,93) ) {
       
   271             sdcd = fp_PP_open(temp);
       
   272         } else {
       
   273             sdcd = fp_SDCONN_open(temp);
       
   274         }
       
   275 
       
   276         if (sdcd == 0) {
       
   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());
       
   279             return -1;
       
   280         }
       
   281 
       
   282         uSleep(10);
       
   283     }
       
   284     else
       
   285     {
       
   286         // use ppdev
       
   287         if (serdisp_version < SERDISP_VERSION(1,93) ) {
       
   288             sdcd = fp_PP_open(config->device.c_str());
       
   289         } else {
       
   290             sdcd = fp_SDCONN_open(config->device.c_str());
       
   291         }
       
   292 
       
   293         if (sdcd == 0) {
       
   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());
       
   296             return -1;
       
   297         }
       
   298     }
       
   299 
       
   300     if (serdisp_version < SERDISP_VERSION(1,95) )
       
   301         dd = fp_serdisp_init(sdcd, controller.c_str(), "");
       
   302     else
       
   303         dd = fp_serdisp_init(sdcd, controller.c_str(), optionstring.c_str());
       
   304 
       
   305     if (!dd)
       
   306     {
       
   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");
       
   309         return -1;
       
   310     }
       
   311 
       
   312     width = config->width;
       
   313     if (width <= 0)
       
   314         width = fp_serdisp_getwidth(dd);
       
   315     height = config->height;
       
   316     if (height <= 0)
       
   317         height = fp_serdisp_getheight(dd);
       
   318 
       
   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);
       
   324     } else {
       
   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);
       
   330 
       
   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") {
       
   336 
       
   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));
       
   339             }
       
   340         }
       
   341 
       
   342     }
       
   343 
       
   344     *oldConfig = *config;
       
   345 
       
   346     // clear display
       
   347     Clear();
       
   348 
       
   349     syslog(LOG_INFO, "%s: SerDisp with %s initialized.\n", config->name.c_str(), controller.c_str());
       
   350     return 0;
       
   351 }
       
   352 
       
   353 int cDriverSerDisp::DeInit(void)
       
   354 {
       
   355     if (serdisp_version < SERDISP_VERSION(1,93) ) {
       
   356         fp_serdisp_close(dd);
       
   357         fp_PP_close(sdcd);
       
   358         sdcd = NULL;
       
   359     } else {
       
   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);
       
   363     }
       
   364     (int) dlclose(sdhnd);
       
   365     sdhnd = NULL;
       
   366 
       
   367     return 0;
       
   368 }
       
   369 
       
   370 int cDriverSerDisp::CheckSetup()
       
   371 {
       
   372     bool update = false;
       
   373 
       
   374     if (config->device != oldConfig->device ||
       
   375         config->port != oldConfig->port ||
       
   376         config->width != oldConfig->width ||
       
   377         config->height != oldConfig->height)
       
   378     {
       
   379         DeInit();
       
   380         Init();
       
   381         return 0;
       
   382     }
       
   383 
       
   384     if (config->contrast != oldConfig->contrast)
       
   385     {
       
   386         fp_serdisp_feature(dd, FEATURE_CONTRAST, config->contrast);
       
   387         oldConfig->contrast = config->contrast;
       
   388         update = true;
       
   389     }
       
   390     if (config->backlight != oldConfig->backlight)
       
   391     {
       
   392         fp_serdisp_feature(dd, FEATURE_BACKLIGHT, config->backlight);
       
   393         oldConfig->backlight = config->backlight;
       
   394         update = true;
       
   395     }
       
   396     if (config->upsideDown != oldConfig->upsideDown)
       
   397     {
       
   398         fp_serdisp_feature(dd, FEATURE_ROTATE, config->upsideDown);
       
   399         oldConfig->upsideDown = config->upsideDown;
       
   400         update = true;
       
   401     }
       
   402     if (config->invert != oldConfig->invert)
       
   403     {
       
   404         fp_serdisp_feature(dd, FEATURE_REVERSE, config->invert);
       
   405         oldConfig->invert = config->invert;
       
   406         update = true;
       
   407     }
       
   408 
       
   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") {
       
   414 
       
   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];
       
   418             update = true;
       
   419         }
       
   420     }
       
   421 
       
   422 
       
   423     if (update)
       
   424         return 1;
       
   425     return 0;
       
   426 }
       
   427 
       
   428 void cDriverSerDisp::Clear(void)
       
   429 {
       
   430     if (bg_colour == -1)
       
   431         fp_serdisp_clearbuffer(dd);
       
   432     else {  /* if bg_colour is set, draw background 'by hand' */
       
   433         int x,y;
       
   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() */
       
   437     }
       
   438 }
       
   439 
       
   440 void cDriverSerDisp::Set8Pixels(int x, int y, unsigned char data) {
       
   441     int i, start, pixel;
       
   442 
       
   443     data = ReverseBits(data);
       
   444 
       
   445     start = (x >> 3) << 3;
       
   446 
       
   447     for (i = 0; i < 8; i++) {
       
   448         pixel = data & (1 << i);
       
   449         if (pixel)
       
   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() */
       
   453     }
       
   454 }
       
   455 
       
   456 void cDriverSerDisp::Refresh(bool refreshAll)
       
   457 {
       
   458     if (CheckSetup() == 1)
       
   459         refreshAll = true;
       
   460 
       
   461     if (refreshAll)
       
   462         fp_serdisp_rewrite(dd);
       
   463     else
       
   464         fp_serdisp_update(dd);
       
   465 }
       
   466 
       
   467 } // end of namespace