/* $Id$ * $URL$ * * new style X11 Driver for LCD4Linux * * Copyright (C) 2003 Michael Reinelt * Copyright (C) 2004, 2008 The LCD4Linux Team * * based on the old XWindow.c which is * Copyright (C) 2000 Herbert Rosmanith * * This file is part of LCD4Linux. * * LCD4Linux is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2, or (at your option) * any later version. * * LCD4Linux is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. * */ /* * * exported fuctions: * * struct DRIVER drv_X11 * */ #include "config.h" #include #include #include #include #include #include #include #include #include #include #include #include "debug.h" #include "cfg.h" #include "qprintf.h" #include "timer.h" #include "plugin.h" #include "rgb.h" #include "drv.h" #include "widget.h" #include "widget_keypad.h" #include "drv_generic_graphic.h" #include "drv_generic_keypad.h" #ifdef WITH_DMALLOC #include #endif static char Name[] = "X11"; static int pixel = -1; /* pointsize in pixel */ static int pgap = 0; /* gap between points */ static int rgap = 0; /* row gap between lines */ static int cgap = 0; /* column gap between characters */ static int border = 0; /* window border */ static int buttons = 0; /* number of keypad buttons */ static int btnwidth = 0; static int btnheight = 0; static int dimx, dimy; /* total window dimension in pixel */ static Atom wmDeleteMessage; static RGBA *drv_X11_FB = NULL; /* framebuffer */ static RGBA BP_COL = {.R = 0xff,.G = 0xff,.B = 0xff,.A = 0x00 }; /* pixel background color */ static RGBA BR_COL = {.R = 0xff,.G = 0xff,.B = 0xff,.A = 0x00 }; /* border color */ static Display *dp; static int sc, dd; static Window w, rw; static Visual *vi; static GC gc; static Colormap cm; static Pixmap pm; /****************************************/ /*** hardware dependant functions ***/ /****************************************/ static XColor drv_X11_color(RGBA c, int brightness) { static XColor col[64]; static unsigned char alloced[64] = { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }; XColor xc; int key; xc.red = brightness * c.R; xc.green = brightness * c.G; xc.blue = brightness * c.B; /* 16bits per color, compressed to 6 bits (2 each color) */ key = (xc.red & 0xc000) >> 10 | (xc.green & 0xc000) >> 12 | (xc.blue & 0xc000) >> 14; /* todo: support more than 64 colors: check if allocated color is exactly the requested */ if (alloced[key]) { xc = col[key]; } else { xc.flags = DoRed | DoGreen | DoBlue; if (XAllocColor(dp, cm, &xc) == False) { error("%s: XAllocColor(%02x%02x%02x) failed!", Name, c.R, c.G, c.B); } col[key] = xc; alloced[key] = 1; } XSetForeground(dp, gc, xc.pixel); return (xc); } static void drv_X11_blit(const int row, const int col, const int height, const int width) { int r, c; for (r = row; r < row + height; r++) { int y = border + (r / YRES) * rgap + r * (pixel + pgap); for (c = col; c < col + width; c++) { int x = border + (c / XRES) * cgap + c * (pixel + pgap); RGBA p1 = drv_X11_FB[r * DCOLS + c]; RGBA p2 = drv_generic_graphic_rgb(r, c); if (p1.R != p2.R || p1.G != p2.G || p1.B != p2.B) { XClearArea(dp, w, x, y, pixel, pixel, 1); drv_X11_FB[r * DCOLS + c] = p2; } } } } static int drv_X11_brightness(int brightness) { static int Brightness = 255; int i; /* -1 is used to query the current brightness */ if (brightness == -1) return Brightness; if (brightness < 0) brightness = 0; if (brightness > 255) brightness = 255; if (Brightness != brigh
#
# $Id: README.MatrixOrbital,v 1.2 2000/03/22 07:33:50 reinelt Exp $
#

This is the README file for the MatrixOrbital display driver for lcd4linux

This driver supports the serial interface alphanumeric display modules by
Matrix Orbital Corporation (http://www.matrixorbital.com).

I could only test it with the LCD2041 model, but I think every other (LCD) model 
should work. These displays are supported:

  LCD0821: 2 lines by  8 characters
  LCD1621: 2 lines by 16 characters
  LCD2021: 2 lines by 20 characters
  LCD2041: 4 lines by 20 characters (tested)
  LCD4021: 2 lines by 40 characters

I could not test the vacuum fluorescent display models, but I think they should work, too.
There are no entries for this models in the driver table (at the bottom of MatrixOrbital.c),
but they could be easily added.

The displays come with an RS-232 and an I2C interface. The driver supports the RS-232 interface
only (because I have no idea how to find the I2C bus on my motherboard). 

Power can be applied either via an external DC power supply, a modified floppy power connector
(be aware that you can destroy your display if you get the pins wrong!) or via the RI (ring) 
signal of the RS-232 port. I choosed the latter, and modified a serial card so that it supplies 
+5V from the ISA bus to this pin (again, be aware that this is dangerous if you connect any other 
serial device to this modified port).

The driver supports vertical, horizontal and split bars (two independent bars in one line),
all bar types can be used simultanously. As the displays only have 8 user-defined characters,
the needed characters to display all the bars must be reduced to 8. This is done by replacing
characters with similar ones. To reduce flicker, a character which is displayed at the moment,
will not be redefined, even if it's not used in this run. Only if the character compaction 
fails, this characters will be redefined, too.

The displays have a GPO (general purpose output), where you can connect a LED or something. 
The driver supports controlling this GPO, but this function is unused by now.


Configuration:

The driver needs/supports the following entries in lcd4linux.conf:

Display: a valid Matrix Orbital Display name (e.g. "LCD2041")
Port: serial device the display is attached to (e.g. /dev/ttyS2)
Speed: the baud rate from the display (configured via jumpers) must match 
       this value. Possible values are 1200, 2400, 9600 and 19200
Contrast: sets the LCD display contrast to a level between 0 (light) 
          and 256 (dark). Default value: 160
if (color2RGBA(s, &BP_COL) < 0) { error("%s: ignoring illegal color '%s'", Name, s); } free(s); BL_COL = BP_COL; BR_COL = BP_COL; if ((s = cfg_get(section, "bordercolor", NULL)) != NULL) { if (color2RGBA(s, &BR_COL) < 0) { error("%s: ignoring illegal color '%s'", Name, s); } free(s); } /* virtual keyboard: number of buttons (0..6) */ if (cfg_number(section, "buttons", 0, 0, 6, &buttons) < 0) return -1; drv_X11_FB = malloc(DCOLS * DROWS * sizeof(*drv_X11_FB)); if (drv_X11_FB == NULL) { error("%s: framebuffer could not be allocated: malloc() failed", Name); return -1; } for (i = 0; i < DCOLS * DROWS; i++) { drv_X11_FB[i] = NO_COL; } if ((dp = XOpenDisplay(NULL)) == NULL) { error("%s: can't open display", Name); return -1; } sc = DefaultScreen(dp); gc = DefaultGC(dp, sc); vi = DefaultVisual(dp, sc); dd = DefaultDepth(dp, sc); rw = DefaultRootWindow(dp); cm = DefaultColormap(dp, sc); dimx = DCOLS * pixel + (DCOLS - 1) * pgap + (DCOLS / XRES - 1) * cgap; dimy = DROWS * pixel + (DROWS - 1) * pgap + (DROWS / YRES - 1) * rgap; if (buttons != 0) { btnwidth = (DCOLS * pixel + (DCOLS - 1) * pgap) / 10; btnheight = (DROWS * pixel + (DROWS - 1) * pgap) / buttons; } wa.event_mask = ExposureMask | ButtonPressMask | ButtonReleaseMask; sh.min_width = sh.max_width = dimx + 2 * border + btnwidth; sh.min_height = sh.max_height = dimy + 2 * border; sh.flags = PPosition | PSize | PMinSize | PMaxSize; if (sh.min_width > DisplayWidth(dp, sc) || sh.min_height > DisplayHeight(dp, sc)) { error("%s: Warning: X11-Window with dimensions (%d,%d) is greater than display (%d,%d)!", Name, sh.min_width, sh.min_height, DisplayWidth(dp, sc), DisplayHeight(dp, sc)); if (sh.min_width > 32767 || sh.min_height > 32676) { /* XProtocol data size exceeded */ exit(1); } } w = XCreateWindow(dp, rw, 0, 0, sh.min_width, sh.min_height, 0, 0, InputOutput, vi, CWEventMask, &wa); pm = XCreatePixmap(dp, w, dimx, dimy, dd); XSetWMProperties(dp, w, NULL, NULL, NULL, 0, &sh, NULL, NULL); wmDeleteMessage = XInternAtom(dp, "WM_DELETE_WINDOW", False); XSetWMProtocols(dp, w, &wmDeleteMessage, 1); XSetWindowBackground(dp, w, drv_X11_color(BR_COL, 255).pixel); XClearWindow(dp, w); /* set brightness (after first background painting) */ if (cfg_number(section, "Brightness", 255, 0, 255, &i) > 0) { drv_X11_brightness(i); } XStoreName(dp, w, "LCD4Linux"); XMapWindow(dp, w); XFlush(dp); while (1) { XNextEvent(dp, &ev); if (ev.type == Expose && ev.xexpose.count == 0) break; } /* regularly process X events */ /* Fixme: make 20msec configurable */ timer_add(drv_X11_timer, NULL, 20, 0); return 0; } /****************************************/ /*** plugins ***/ /****************************************/ static void plugin_brightness(RESULT * result, const int argc, RESULT * argv[]) { double brightness; switch (argc) { case 0: brightness = drv_X11_brightness(-1); SetResult(&result, R_NUMBER, &brightness); break; case 1: brightness = drv_X11_brightness(R2N(argv[0])); SetResult(&result, R_NUMBER, &brightness); break; default: error("%s.brightness(): wrong number of parameters", Name); SetResult(&result, R_STRING, ""); } } /****************************************/ /*** exported functions ***/ /****************************************/ /* list models */ int drv_X11_list(void) { printf("any X11 server"); return 0; } /* initialize driver & display */ int drv_X11_init(const char *section, const int quiet) { RGBA bl_col; int ret; info("%s: %s", Name, "$Rev$"); /* start display */ if ((ret = drv_X11_start(section)) != 0) return ret; /* real worker functions */ drv_generic_graphic_real_blit = drv_X11_blit; drv_generic_keypad_real_press = drv_X11_keypad; /* initialize generic graphic driver */ /* save BL_COL which may already be dimmed */ bl_col = BL_COL; if ((ret = drv_generic_graphic_init(section, Name)) != 0) return ret; BL_COL = bl_col; /* initialize generic key pad driver */ if ((ret = drv_generic_keypad_init(section, Name)) != 0) return ret; drv_generic_graphic_clear(); /* initially expose window */ drv_X11_expose(0, 0, dimx + 2 * border, dimy + 2 * border); if (!quiet) { char buffer[40]; qprintf(buffer, sizeof(buffer), "%s %dx%d", Name, DCOLS, DROWS); if (drv_generic_graphic_greet(buffer, NULL)) { drv_X11_expose(0, 0, dimx + 2 * border, dimy + 2 * border); sleep(3); drv_generic_graphic_clear(); } } /* register plugins */ AddFunction("LCD::brightness", -1, plugin_brightness); return 0; } /* close driver & display */ int drv_X11_quit(const __attribute__ ((unused)) int quiet) { info("%s: shutting down.", Name); drv_generic_graphic_quit(); drv_generic_keypad_quit(); if (drv_X11_FB) { free(drv_X11_FB); drv_X11_FB = NULL; } return (0); } DRIVER drv_X11 = { .name = Name, .list = drv_X11_list, .init = drv_X11_init, .quit = drv_X11_quit, };