diff options
author | mrwastl <mrwastl@users.sourceforge.net> | 2011-08-23 16:11:09 +0200 |
---|---|---|
committer | mrwastl <mrwastl@users.sourceforge.net> | 2011-08-23 16:11:09 +0200 |
commit | 4eac37eb258bb9c119b9133cd102767f2dc7dbad (patch) | |
tree | ce10b5e7a786ee96b282adf83089053202877783 | |
parent | 0269409fd3fdc8f0831270582cd27e425b29a2dd (diff) | |
download | graphlcd-base-4eac37eb258bb9c119b9133cd102767f2dc7dbad.tar.gz graphlcd-base-4eac37eb258bb9c119b9133cd102767f2dc7dbad.tar.bz2 |
enhancements for AX206dpf support (contr. by Lutz Neumann)
-rw-r--r-- | docs/DRIVER.ax206dpf | 59 | ||||
-rw-r--r-- | glcddrivers/ax206dpf.c | 474 | ||||
-rw-r--r-- | glcddrivers/ax206dpf.h | 34 | ||||
-rw-r--r-- | graphlcd.conf | 35 |
4 files changed, 498 insertions, 104 deletions
diff --git a/docs/DRIVER.ax206dpf b/docs/DRIVER.ax206dpf index 45c3d40..d8faf4b 100644 --- a/docs/DRIVER.ax206dpf +++ b/docs/DRIVER.ax206dpf @@ -24,6 +24,17 @@ If your DPF is already hacked, there is no need to install the "dpf-ax" package described in "Hacking your DPF". All necessary routines to access a hacked DPF are included in this driver. +Multi-display setups +-------------------- +This driver supports up to 4 displays. The displays can be aligned horizontal, +vertical or tiled (See "Example multi-display setups"). + +Hot plugging +------------ +Hot plugging of displays is supported. The driver will add/remove displays automatically +as they are plugged in or removed. For multi-display setups the scan for new displays will +continue until all needed displays are detected. + Non-root users -------------- The driver needs write access to /dev/proc/usb. So the calling user @@ -57,9 +68,14 @@ Height UpsideDown Rotates the display output by 180 degrees. This might be useful, if - the LCD is mounted upside-down. + the display is mounted upside-down. Possible values: 'yes', 'no' Default value: 'no' + +Brightness + Sets the brightness of the display's backlight. + Possible values: 0 <= x <= 100) + Default value: 100 Portrait Select portrait or landscape mode. @@ -73,6 +89,45 @@ Zoom Possible values: 1, 2, 3, 4 Default value: 1 +The following parameters are for multi-display setups only (see "Example multi-display setups"). + +Horizontal +Sets the number of displays in horizontal direction. + Possible values if Vertical=1: 1, 2, 3, 4 + if Vertical=2: 1, 2 + Default value: 1 + +Vertical + Sets the number of displays in vertical direction. + Possible values if Horizontal=1: 1, 2, 3, 4 + if Horizontal=2: 1, 2 + Default value: 1 + +Flip + Rotates a single displays output by 180 degrees. This might be useful, if + some displays are mounted upside-down. + Possible values for every display : 'y', 'n' + Default value: 'nnnn' + + +Example multi-display setups +---------------------------- +'#' = position of USB-connector + +Portrait=y Portrait=n Portrait=n Portrait=n +Horizontal=2 Horizontal=2 Horizontal=1 Horizontal=2 +Vertical=1 Vertical=1 Vertical=3 Vertical=2 +Flip=nn Flip=ny Flip=nyn Flip=nyny + ++-+ +-+ +---+ +---+ +---+ +---+ +---+ +| | | | # +---+ +---+# #+---+ #+---+ +---+# ++-+ +-+ 1 2 1 1 2 + # # +---+ +---+ +---+ + 1 2 +---+# #+---+ +---+# + 2 3 4 + +---+ + #+---+ + 3 Hacking your DPF ---------------- @@ -97,7 +152,7 @@ http://geekparadise.de/2011/04/digitaler-bilderrahmen-von-pearl-als-statusdispla [/quote] So if you are not sure if you have the right DPF or something goes wrong: -don't ask me ether - I'm like you only a user and not involved in the +don't ask me either - I'm like you only a user and not involved in the development of the hack! A guide how to hack the Pearl display can be found here (in german): diff --git a/glcddrivers/ax206dpf.c b/glcddrivers/ax206dpf.c index 708622a..ce5b15d 100644 --- a/glcddrivers/ax206dpf.c +++ b/glcddrivers/ax206dpf.c @@ -24,17 +24,25 @@ * This file is released under the GNU General Public License. Refer * to the COPYING file distributed with this package. * - * (c) 2011 Lutz Neumann <superelchi AT wolke7.de> + * (c) 2011 Lutz Neumann <superelchi AT wolke7.net> * * HISTORY * * v0.1 - 10 Aug 2011 - Inital release + * V0.2 - 20 Aug 2011 - Optimized display data transfer + * SetBrightness() implemented + * Multi-display support + * * */ #include <stdio.h> #include <syslog.h> #include <cstring> +#include <algorithm> +#include <pthread.h> +#include <time.h> +#include <usb.h> #include "common.h" #include "config.h" @@ -44,7 +52,24 @@ namespace GLCD { -static LIBDPF::DPFContext *dpfh; +typedef struct display_handle { + bool attached; + char address[8]; + bool isPortrait; + bool rotate90; + bool flip; + int minx, maxx; + int miny, maxy; + LIBDPF::DPFContext *dpfh; + unsigned char * LCD; +} DISPLAYHANDLE; + +static DISPLAYHANDLE *dh[MAX_DPFS]; +static pthread_mutex_t libax_mutex; +static std::string flips = ""; +static time_t lastscan; +static int lastbrightness; + cDriverAX206DPF::cDriverAX206DPF(cDriverConfig * config) : config(config) @@ -60,11 +85,25 @@ cDriverAX206DPF::~cDriverAX206DPF() int cDriverAX206DPF::Init(void) { zoom = 1; - bool forcePortrait = false; + portrait = false; + numxdisplays = numydisplays = 1; + sizex = sizey = bpp = 0; + + for (unsigned int i = 0; i < MAX_DPFS; i++) + { + dh[i] = (DISPLAYHANDLE *) malloc(sizeof(DISPLAYHANDLE)); + dh[i]->attached = false; + dh[i]->address[0] = 0; + dh[i]->dpfh = NULL; + dh[i]->LCD = NULL; + } + + lastbrightness = config->brightness ? config->brightness : 100; + for (unsigned int i = 0; i < config->options.size(); i++) { if (config->options[i].name == "Portrait") { - forcePortrait = config->options[i].value == "yes"; + portrait = config->options[i].value == "yes"; } else if (config->options[i].name == "Zoom") { int z = strtol(config->options[i].value.c_str(), (char **) NULL, 0); @@ -72,77 +111,236 @@ int cDriverAX206DPF::Init(void) zoom = z; else syslog(LOG_ERR, "%s error: zoom %d not supported, using default (%d)!\n",config->name.c_str(), z, zoom); + } + else if (config->options[i].name == "Horizontal") { + int h = strtol(config->options[i].value.c_str(), (char **) NULL, 0); + if (h > 0 && h <= 4) + numxdisplays = h; + else + syslog(LOG_ERR, "%s error: Horizontal=%d not supported, using default (%d)!\n",config->name.c_str(), h, numxdisplays); + } + else if (config->options[i].name == "Vertical") { + int v = strtol(config->options[i].value.c_str(), (char **) NULL, 0); + if (v > 0 && v <= 4) + numydisplays = v; + else + syslog(LOG_ERR, "%s error: Vertical=%d not supported, using default (%d)!\n",config->name.c_str(), v, numydisplays); + } + else if (config->options[i].name == "Flip") { + flips = config->options[i].value; + for (unsigned int j = 0; j < flips.size(); j++) + { + if (flips[j] != 'y' && flips[j] != 'n') + { + syslog(LOG_ERR, "%s error: flips=%s - illegal character, only 'y' and 'n' supported, using default!\n",config->name.c_str(), flips.c_str()); + flips = ""; + break; + } + } + } + } + + // See if we have too many displays + if (numxdisplays * numydisplays > MAX_DPFS) + syslog(LOG_ERR, "%s: too many displays (%dx%d). Max is %d!\n",config->name.c_str(), numxdisplays, numydisplays, MAX_DPFS); + + // Init all displays + numdisplays = 0; + int error = 0; + for (unsigned int i = 0; i < numxdisplays * numydisplays; i++) + { + error = InitSingleDisplay(i); + if (error < 0) + return -1; + numdisplays++; + } + + if (sizex == 0) + { + // no displays detected + sizex = (portrait) ? DEFAULT_HEIGHT : DEFAULT_WIDTH; + sizey = (portrait) ? DEFAULT_WIDTH : DEFAULT_HEIGHT; + bpp = DEFAULT_BPP; + } + + // setup temp transfer LCD array + tempLCD = (unsigned char *) malloc(sizex * sizey * bpp); + + width = sizex * numxdisplays; + height = sizey * numydisplays; + + if (zoom > 1) + { + height /= zoom; + width /= zoom; + } + ResetMinMax(); + + *oldConfig = *config; + + if (numdisplays == 1) + syslog(LOG_INFO, "%s: AX206DPF initialized (%dx%d).\n", config->name.c_str(), width, height); + else + { + unsigned n = 0; + for (unsigned int i = 0; i < numdisplays; i++) + if (dh[i]->attached) n++; + syslog(LOG_INFO, "%s: using %d display(s) (%d online, %d offline).\n", config->name.c_str(), numdisplays, n, numdisplays - n); + } + + lastscan = time(NULL); + + return 0; +} + +bool cDriverAX206DPF::RescanUSB() +{ + bool ret = false; + usb_find_busses(); + if (usb_find_devices() > 0) + { + unsigned int a = 0, b = 0; + for (unsigned int i = 0; i < numdisplays; i++) + { + if (dh[i]->attached) a |= 0x01 << i; + DeInitSingleDisplay(i); + } + for (unsigned int i = 0; i < numdisplays; i++) + { + InitSingleDisplay(i); + if (dh[i]->attached) b |= 0x01 << i; } + ret = a != b; } + return ret; +} - // Init display - - int error; +int cDriverAX206DPF::InitSingleDisplay(unsigned int di) +{ char index; - + if (config->device.length() != 4 || config->device.compare(0, 3, "dpf")) index = '0'; else index = config->device.at(3); - char usb_device[5]; - sprintf(usb_device, "usb%c", index); - - error = dpf_open(usb_device, &dpfh); - if (error < 0) { - syslog(LOG_INFO, "%s: can not open dpf device number '%c' (error %d).\n", config->name.c_str(), index, error); - return -1; - } - + char device[5]; + sprintf(device, "usb%c", index + di); + int error = dpf_open(device, &dh[di]->dpfh); + if (error < 0) + { + dh[di]->dpfh = NULL; + dh[di]->attached = false; + return 0; + } + dh[di]->attached = true; + struct usb_device *dev = usb_device(dh[di]->dpfh->dev.udev); + char *s1 = dev->bus->dirname; + char *s2 = dev->filename; + if (strlen(s1) > 3) s1 = (char *) "???"; + if (strlen(s2) > 3) s2 = (char *) "???"; + sprintf(dh[di]->address, "%s:%s", s1, s2); + // See, if we have to rotate the display - isPortrait = dpfh->width < dpfh->height; - rotate90 = isPortrait != forcePortrait; - - // Set width / height from display - unsigned int vwidth = (!rotate90) ? dpfh->width : dpfh->height; - unsigned int vheight = (!rotate90) ? dpfh->height : dpfh->width; - width = config->width; - if (width <= 0 || width > (int) vwidth) - width = (int) vwidth; - height = config->height; - if (height <= 0 || height > (int) vheight) - height = (int) vheight; - if (zoom > 1) + dh[di]->isPortrait = dh[di]->dpfh->width < dh[di]->dpfh->height; + dh[di]->rotate90 = dh[di]->isPortrait != portrait; + dh[di]->flip = (!dh[di]->isPortrait && dh[di]->rotate90); // adjust to make rotate por/land = physical por/land + if (flips.size() >= di + 1 && flips[di] == 'y') + dh[di]->flip = !dh[di]->flip; + + if (sizex == 0) { - height /= zoom; - width /= zoom; + // this is the first display found + // Get width / height from this display (all displays have same geometry) + sizex = ((!dh[di]->rotate90) ? dh[di]->dpfh->width : dh[di]->dpfh->height); + sizey = ((!dh[di]->rotate90) ? dh[di]->dpfh->height : dh[di]->dpfh->width); + bpp = dh[di]->dpfh->bpp; + } + else + { + // make sure alle displays have the same geometry + if ((!(sizex == dh[di]->dpfh->width && sizey == dh[di]->dpfh->height) && + !(sizex == dh[di]->dpfh->height && sizey == dh[di]->dpfh->width)) || + bpp != (unsigned int) dh[di]->dpfh->bpp) + { + syslog(LOG_INFO, "%s: all displays must have same geometry. Display %d has not. Giving up.\n", config->name.c_str(), di); + return -1; + } } + // setup physical lcd arrays + dh[di]->LCD = (unsigned char *) malloc(dh[di]->dpfh->height * dh[di]->dpfh->width * dh[di]->dpfh->bpp); + ClearSingleDisplay(di); - // setup lcd array - LCD = (unsigned char *) malloc(dpfh->height * dpfh->width * dpfh->bpp); - ResetMinMax(); + // Set Display Brightness + SetSingleDisplayBrightness(di, lastbrightness); - *oldConfig = *config; + + // Reorder displays + bool changed = false; + for (unsigned int i = 0; i < MAX_DPFS - 1; i++) + { + for (unsigned int j = i + 1; j < MAX_DPFS; j++) + { + if (strcmp(dh[i]->address, dh[j]->address) < 0) + { + DISPLAYHANDLE *h = dh[i]; + dh[i] = dh[j]; + dh[j] = h; + changed = true; + } + } + } + + //for (unsigned int i = 0; i < MAX_DPFS; i++) + // fprintf(stderr, "Display %d at %s\n", i, (dh[i]->attached) ? dh[i]->address : "-none-"); + //fprintf(stderr, "\n"); + + //fprintf(stderr, "Display %d at %s attached.\n", di, dh[di]->address); + //syslog(LOG_INFO, "%s: display %d at %s attached\n", config->name.c_str(), di, dh[di]->address); - // Set Display Brightness -- NOT WORKING! - //SetBrightness(config->brightness ? config->brightness : 100); - syslog(LOG_INFO, "%s: AX206DPF initialized (%dx%d).\n", config->name.c_str(), width, height); return 0; } +void cDriverAX206DPF::DeInitSingleDisplay(unsigned int di) +{ + if (dh[di]->dpfh != NULL) + dpf_close(dh[di]->dpfh); + dh[di]->dpfh = NULL; + + if (dh[di]->LCD != NULL) + free(dh[di]->LCD); + dh[di]->LCD = NULL; + + dh[di]->attached = false; + dh[di]->address[0] = 0; +} + int cDriverAX206DPF::DeInit(void) { - dpf_close(dpfh); + // close displays & free lcd arrays + for (unsigned int i = 0; i< numdisplays; i++) + DeInitSingleDisplay(i); - // free lcd array - if (LCD) - { - free(LCD); - } + if (tempLCD) + free(tempLCD); return 0; } + void cDriverAX206DPF::ResetMinMax(void) { - miny = dpfh->height - 1; - maxy = 0; + for (unsigned int i = 0; i < numydisplays; i++) + { + if (dh[i]->attached) + { + dh[i]->minx = dh[i]->dpfh->width - 1; + dh[i]->maxx = 0; + dh[i]->miny = dh[i]->dpfh->height - 1; + dh[i]->maxy = 0; + } + } } int cDriverAX206DPF::CheckSetup(void) @@ -171,11 +369,22 @@ int cDriverAX206DPF::CheckSetup(void) return 0; } +void cDriverAX206DPF::ClearSingleDisplay(unsigned int di) +{ + if (dh[di]->attached) + { + memset(dh[di]->LCD, 0, dh[di]->dpfh->width * dh[di]->dpfh->height * dh[di]->dpfh->bpp); //Black + dh[di]->minx = 0; + dh[di]->maxx = dh[di]->dpfh->width - 1; + dh[di]->miny = 0; + dh[di]->maxy = dh[di]->dpfh->height - 1; + } +} + void cDriverAX206DPF::Clear(void) { - memset(LCD, 0, dpfh->height * dpfh->width * dpfh->bpp); //Black - miny = 0; - maxy = dpfh->height - 1; + for (unsigned int i = 0; i < numdisplays; i++) + ClearSingleDisplay(i); } #define _RGB565_0(p) \ @@ -185,76 +394,142 @@ void cDriverAX206DPF::Clear(void) void cDriverAX206DPF::SetPixel(int x, int y, uint32_t data) { - bool flip = config->upsideDown; - if (!isPortrait && rotate90) - flip = !flip; + bool changed = false; - if (flip) + if (config->upsideDown) { - // upside down orientation + // global upside down orientation x = width - 1 - x; - y = height - 1 - y; + y = height - 1 -y; } - - unsigned int i; - if (rotate90) + + int sx = sizex / zoom; + int sy = sizey / zoom; + int di = (y / sy) * numxdisplays + (x / sx); + int lx = (x % sx) * zoom; + int ly = (y % sy) * zoom; + + if (!dh[di]->attached) + return; + + if (dh[di]->flip) + { + // local upside down orientation + lx = sizex - 1 - lx; + ly = sizey - 1 - ly; + } + + if (dh[di]->rotate90) { // wrong Orientation, rotate - int xn = y; - y = dpfh->height - 1 - x; - x = xn; + int i = ly; + ly = (dh[di]->dpfh->height) - 1 - lx; + lx = i; } - if (x >= ((int) dpfh->width / zoom) || y >= ((int) dpfh->height / zoom)) + if (lx < 0 || lx >= (int) dh[di]->dpfh->width || ly < 0 || ly >= (int) dh[di]->dpfh->height) + { + syslog(LOG_INFO, "x/y out of bounds (x=%d, y=%d, di=%d, rot=%d, flip=%d, lx=%d, ly=%d)\n", x, y, di, dh[di]->rotate90, dh[di]->flip, lx, ly); return; + } - y *= zoom; + unsigned char c1 = _RGB565_0(data); + unsigned char c2 = _RGB565_1(data); + if (zoom == 1) { - i = (y * dpfh->width + x) * dpfh->bpp; - LCD[i] = _RGB565_0(data); - LCD[i+1] = _RGB565_1(data); + unsigned int i = (ly * dh[di]->dpfh->width + lx) * dh[di]->dpfh->bpp; + if (dh[di]->LCD[i] != c1 || dh[di]->LCD[i+1] != c2) + { + dh[di]->LCD[i] = c1; + dh[di]->LCD[i+1] = c2; + changed = true; + } } else { for (int dy = 0; dy < zoom; dy++) { - i = ((y + dy) * dpfh->width + (x * zoom)) * dpfh->bpp; - for (int dx = 0; dx < zoom * dpfh->bpp; dx += dpfh->bpp) + unsigned int i = ((ly + dy) * dh[di]->dpfh->width + lx) * dh[di]->dpfh->bpp; + for (int dx = 0; dx < zoom * dh[di]->dpfh->bpp; dx += dh[di]->dpfh->bpp) { - LCD[i+dx] = _RGB565_0(data); - LCD[i+dx+1] = _RGB565_1(data); + if (dh[di]->LCD[i+dx] != c1 || dh[di]->LCD[i+dx+1] != c2) + { + dh[di]->LCD[i+dx] = c1; + dh[di]->LCD[i+dx+1] = c2; + changed = true; + } } } } - if (y * zoom < miny) miny = y; - if (y * zoom > maxy) maxy = y; + + if (changed) + { + if (lx < dh[di]->minx) dh[di]->minx = lx; + if (lx > dh[di]->maxx) dh[di]->maxx = lx; + if (ly < dh[di]->miny) dh[di]->miny = ly; + if (ly > dh[di]->maxy) dh[di]->maxy = ly; + } } void cDriverAX206DPF::Refresh(bool refreshAll) { + short rect[4]; if (CheckSetup() > 0) refreshAll = true; - - short rect[4]; - if (!refreshAll) + for (unsigned int di = 0; di < numdisplays; di++) { - rect[0] = 0; rect[1] = miny; - rect[2] = dpfh-> width; rect[3] = maxy + 1; - } - else - { - rect[0] = 0; rect[1] = 0; - rect[2] = dpfh->width; rect[3] = dpfh->height; + if (!dh[di]->attached) + { + time_t current = time(NULL); + if (current - lastscan >= USB_SCAN_INTERVALL) + { + lastscan = current; + if (RescanUSB()) + ; //return; // something changed, wait for next refresh + } + } + + if (!dh[di]->attached) + continue; + + if (refreshAll) + { + dh[di]->minx = 0; dh[di]->miny = 0; + dh[di]->maxx = dh[di]->dpfh->width - 1; dh[di]->maxy = dh[di]->dpfh->height - 1; + } + //fprintf(stderr, "%d: (%d,%d)-(%d,%d) ", di, dh[di]->minx, dh[di]->miny, dh[di]->maxx, dh[di]->maxy); + if (dh[di]->minx > dh[di]->maxx || dh[di]->miny > dh[di]->maxy) + continue; + + unsigned int cpylength = (dh[di]->maxx - dh[di]->minx + 1) * dh[di]->dpfh->bpp; + unsigned char *ps = dh[di]->LCD + (dh[di]->miny * dh[di]->dpfh->width + dh[di]->minx) * dh[di]->dpfh->bpp; + unsigned char *pd = tempLCD; + for (int y = dh[di]->miny; y <= dh[di]->maxy; y++) + { + memcpy(pd, ps, cpylength); + ps += dh[di]->dpfh->width * dh[di]->dpfh->bpp; + pd += cpylength; + } + + rect[0] = dh[di]->minx; rect[1] = dh[di]->miny; rect[2] = dh[di]->maxx + 1; rect[3] = dh[di]->maxy + 1; + pthread_mutex_lock(&libax_mutex); + int err = dpf_screen_blit(dh[di]->dpfh, tempLCD, rect); + pthread_mutex_unlock(&libax_mutex); + if (err < 0) + { + //fprintf(stderr, "Display %d detached (err=%d).\n", di, err); + syslog(LOG_INFO, "%s: display %d communication error (%d). Display detached\n", config->name.c_str(), di, err); + DeInitSingleDisplay(di); + RescanUSB(); + lastscan = time(NULL); + } } - if (rect[1] > rect[3]) - return; - - dpf_screen_blit(dpfh, &LCD[rect[1] * dpfh->width * dpfh->bpp], rect); ResetMinMax(); + //fprintf(stderr, "\n"); } GLCD::cColor cDriverAX206DPF::GetBackgroundColor(void) @@ -262,9 +537,11 @@ GLCD::cColor cDriverAX206DPF::GetBackgroundColor(void) return GLCD::cColor::Black; } -/* NOT WORKING - WILL FREEZE THE DISPLAY FROM TIME TO TIME! -void cDriverAX206DPF::SetBrightness(unsigned int percent) +void cDriverAX206DPF::SetSingleDisplayBrightness(unsigned int di, unsigned int percent) { + if (!dh[di]->attached) + return; + LIBDPF::DPFValue val; val.type = LIBDPF::TYPE_INTEGER; @@ -275,9 +552,20 @@ void cDriverAX206DPF::SetBrightness(unsigned int percent) val.value.integer = 7; else val.value.integer = (((percent * 10) + 167) * 6) / 1000; - dpf_setproperty(dpfh, PROPERTY_BRIGHTNESS, &val); + pthread_mutex_lock(&libax_mutex); + dpf_setproperty(dh[di]->dpfh, PROPERTY_BRIGHTNESS, &val); + pthread_mutex_unlock(&libax_mutex); +} + +void cDriverAX206DPF::SetBrightness(unsigned int percent) +{ + lastbrightness = percent; + + for (unsigned int i = 0; i < numdisplays; i++) + { + SetSingleDisplayBrightness(i, percent); + } } -*/ bool cDriverAX206DPF::GetDriverFeature(const std::string & Feature, int & value) { @@ -438,7 +726,7 @@ int dpf_open(const char *dev, DPFHANDLE *h) //if (dpf->mode == MODE_USB) { dpf->dev.udev = u; error = probe(dpf); - fprintf(stderr, "Got LCD dimensions: %dx%d\n", dpf->width, dpf->height); + //fprintf(stderr, "Got LCD dimensions: %dx%d\n", dpf->width, dpf->height); //} else { // dpf->dev.fd = fd; //} @@ -586,7 +874,7 @@ int check_known_device(struct usb_device *d) while (dev->desc) { if ((d->descriptor.idVendor == dev->vid) && (d->descriptor.idProduct == dev->pid)) { - fprintf(stderr, "Found %s\n", dev->desc); + //fprintf(stderr, "Found %s at %s:%s\n", dev->desc, d->bus->dirname, d->filename); return 1; } dev++; diff --git a/glcddrivers/ax206dpf.h b/glcddrivers/ax206dpf.h index 1446924..dc94873 100644 --- a/glcddrivers/ax206dpf.h +++ b/glcddrivers/ax206dpf.h @@ -23,7 +23,7 @@ * This file is released under the GNU General Public License. Refer * to the COPYING file distributed with this package. * - * (c) 2011 Lutz Neumann <superelchi AT wolke7.de> + * (c) 2011 Lutz Neumann <superelchi AT wolke7.net> * * HISTORY * @@ -35,26 +35,42 @@ #include "driver.h" - namespace GLCD { +#define MAX_DPFS 4 + +#define DEFAULT_WIDTH 320 +#define DEFAULT_HEIGHT 240 +#define DEFAULT_BPP 2 + +#define USB_SCAN_INTERVALL 10 // seconds between usb scans for missing displays class cDriverConfig; class cDriverAX206DPF : public cDriver { private: - unsigned char * LCD; cDriverConfig * config; cDriverConfig * oldConfig; - int zoom; - bool isPortrait; - bool rotate90; - int miny, maxy; - + unsigned char * tempLCD; // temp transfer buffer + + bool portrait; // portrait or landscape mode + int zoom; // pixel zoom factor + unsigned int numdisplays; // number of detected displays + unsigned int numxdisplays; // number of displays (horizontal) + unsigned int numydisplays; // number of displays (vertical) + unsigned int sizex; // logical horizontal size of one display + unsigned int sizey; // logical vertical size of one display + unsigned int bpp; // bits per pixel + int CheckSetup(); void ResetMinMax(); + bool RescanUSB(); + int InitSingleDisplay(unsigned int); + void DeInitSingleDisplay(unsigned int); + void ClearSingleDisplay(unsigned int); + void SetSingleDisplayBrightness(unsigned int, unsigned int); public: cDriverAX206DPF(cDriverConfig * config); @@ -67,7 +83,7 @@ public: virtual void SetPixel(int x, int y, uint32_t data); virtual void Refresh(bool refreshAll = false); virtual GLCD::cColor GetBackgroundColor(void); - //virtual void SetBrightness(unsigned int); + virtual void SetBrightness(unsigned int); virtual bool GetDriverFeature (const std::string & Feature, int & value); }; diff --git a/graphlcd.conf b/graphlcd.conf index 027e6f4..bb5a0f5 100644 --- a/graphlcd.conf +++ b/graphlcd.conf @@ -575,8 +575,19 @@ Driver=dm140gink Driver=ax206dpf #Width=320 #Height=240 +# +# UpsideDown +# Rotates the display output by 180 degrees. This might be useful, if +# the LCD is mounted upside-down. +# Possible values: 'yes', 'no' +# Default value: 'no' #UpsideDown=no # +# Brightness +# Sets the brightness of the display's backlight +# Possible values: 0 <= x <= 100) +# Default value: 100 +#Brightness=100 # # Device # Selects a specific display @@ -597,3 +608,27 @@ Driver=ax206dpf # Possible values: 1, 2, 3, 4 # Default value: 1 #Zoom=1 +# +# The following parameters are for multi-display setups only! +# +# Horizontal +# Sets the number of displays in horizontal direction. +# Possible values if Vertical=1: 1, 2, 3, 4 +# if Vertical=2: 1, 2 +# Default value: 1 +#Horizontal=1 +# +# Vertical +# Sets the number of displays in vertical direction. +# Possible values if Horizontal=1: 1, 2, 3, 4 +# if Horizontal=2: 1, 2 +# Default value: 1 +#Vertical=1 +# +# Flip +# Rotates a single displays output by 180 degrees. This might be useful, if +# some LCDs are mounted upside-down. +# Possible values for every display : 'y', 'n' +# Default value: 'nnnn' +#Flip=nnnn +# |