diff --git a/LCDd.conf b/LCDd.conf index b2590f6..b3b6962 100644 --- a/LCDd.conf +++ b/LCDd.conf @@ -401,6 +401,21 @@ ConnectionType=t6963 # legal: yes, no] #delayBus=no +# serdisplib: Name of the underlying serdisplib driver, e.g. ctinclud. See +# serdisplib documentation for details. +serdisp_name=t6963 + +# serdisplib: The display device to use, e.g. serraw:/dev/ttyS0, +# parport:/dev/parport0 or USB:07c0/1501. +serdisp_device=/dev/ppi0 + +# serdisplib: Options string to pass to serdisplib during initialization. Use +# this to set any display related options (e.g. wiring). The display size is +# always set based on the Size configured above! By default, no options are +# set. +# Important: The value must be quoted as it contains equal signs! +#serdisp_options="INVERT=1" + ## glcdlib meta driver for graphical LCDs ## diff --git a/acinclude.m4 b/acinclude.m4 index fb2b393..03d79cc 100644 --- a/acinclude.m4 +++ b/acinclude.m4 @@ -173,6 +173,16 @@ dnl else if test "$enable_libpng" = yes ; then GLCD_DRIVERS="$GLCD_DRIVERS glcd-glcd-png.o" fi + AC_CHECK_HEADERS([serdisplib/serdisp.h],[ + AC_CHECK_LIB(serdisp, serdisp_nextdisplaydescription,[ + AC_DEFINE(HAVE_SERDISPLIB,[1],[Define to 1 if you have working serdisplib]) + LIBSERDISP="-lserdisp" + GLCD_DRIVERS="$GLCD_DRIVERS glcd-glcd-serdisp.o" + ],[ + AC_MSG_WARN([serdisp library not working]) + ]) + ]) + AC_SUBST(LIBSERDISP) DRIVERS="$DRIVERS glcd${SO}" actdrivers=["$actdrivers glcd"] ;; diff --git a/server/drivers/Makefile.am b/server/drivers/Makefile.am index a695916..d3ae447 100644 --- a/server/drivers/Makefile.am +++ b/server/drivers/Makefile.am @@ -43,7 +43,7 @@ CFontzPacket_LDADD = libLCD.a libbignum.a curses_LDADD = @LIBCURSES@ CwLnx_LDADD = libLCD.a libbignum.a g15_LDADD = @LIBG15@ -glcd_LDADD = libLCD.a @GLCD_DRIVERS@ @FT2_LIBS@ @LIBPNG_LIBS@ +glcd_LDADD = libLCD.a @GLCD_DRIVERS@ @FT2_LIBS@ @LIBPNG_LIBS@ @LIBSERDISP@ glcd_DEPENDENCIES = @GLCD_DRIVERS@ glcd-glcd-render.o glcdlib_LDADD = @LIBGLCD@ glk_LDADD = libbignum.a @@ -89,7 +89,7 @@ ea65_SOURCES = lcd.h ea65.h ea65.c report.h EyeboxOne_SOURCES = lcd.h lcd_lib.h EyeboxOne.c EyeboxOne.h report.h g15_SOURCES = lcd.h lcd_lib.h g15.h g15-num.c g15.c report.h glcd_SOURCES = lcd.h report.h glcd_drv.c glcd_drv.h glcd-low.h glcd-drivers.h glcd-render.c glcd-render.h -EXTRA_glcd_SOURCES = glcd-t6963.c glcd-t6963.h t6963_low.c t6963_low.h glcd-png.c glcd-png.h +EXTRA_glcd_SOURCES = glcd-t6963.c t6963_low.c t6963_low.h glcd-png.c glcd-serdisp.c glcdlib_SOURCES = lcd.h lcd_lib.h glcdlib.h glcdlib.c report.h glk_SOURCES = lcd.h glk.c glk.h glkproto.c glkproto.h report.h hd44780_SOURCES = lcd.h lcd_lib.h hd44780.h hd44780.c hd44780-drivers.h hd44780-low.h hd44780-charmap.h report.h adv_bignum.h diff --git a/server/drivers/glcd-drivers.h b/server/drivers/glcd-drivers.h index affb708..871d6a7 100644 --- a/server/drivers/glcd-drivers.h +++ b/server/drivers/glcd-drivers.h @@ -1,7 +1,7 @@ /** \file server/drivers/glcd-drivers.h * Connection type registry for glcd driver. * - * File file contains includes and pointers to the connection type's init() + * File file contains prototypes and pointers to the connection type's init() * function. */ @@ -12,18 +12,22 @@ # include "config.h" #endif -/* Include connection type header below */ +/* Include prototypes for initialization functions below */ #ifdef HAVE_PCSTYLE_LPT_CONTROL -# include "glcd-t6963.h" +int glcd_t6963_init(Driver *drvthis); #endif #ifdef HAVE_LIBPNG -# include "glcd-png.h" +int glcd_png_init(Driver *drvthis); +#endif +#ifdef HAVE_SERDISPLIB +int glcd_serdisp_init(Driver *drvthis); #endif /* symbolic names for connection types */ #define GLCD_CT_UNKNOWN 0 #define GLCD_CT_T6963 1 #define GLCD_CT_PNG 2 +#define GLCD_CT_SERDISP 3 /** Structure linking symbolic names to initialization routines */ typedef struct ConnectionMapping { @@ -44,6 +48,9 @@ static const ConnectionMapping connectionMapping[] = { #endif #ifdef HAVE_LIBPNG {"png", GLCD_CT_PNG, glcd_png_init}, +#endif +#ifdef HAVE_SERDISPLIB + {"serdisplib", GLCD_CT_SERDISP, glcd_serdisp_init}, #endif /* default, end of structure element (do not delete) */ {NULL, GLCD_CT_UNKNOWN, NULL} diff --git a/server/drivers/glcd-low.h b/server/drivers/glcd-low.h index 2013ebd..c333074 100644 --- a/server/drivers/glcd-low.h +++ b/server/drivers/glcd-low.h @@ -17,11 +17,17 @@ #define GLCD_DEFAULT_BRIGHTNESS 800 #define GLCD_DEFAULT_OFFBRIGHTNESS 100 +/** The framebuffer and its properties */ +struct glcd_framebuf { + unsigned char *data; /**< frame buffer */ + int px_width; /**< display width in dots */ + int px_height; /**< display height in dots */ + int bytesPerLine; /**< number of bytes per pixel row */ +}; + /** private data for the \c glcd driver */ typedef struct glcd_private_data { - unsigned char *framebuf; /**< frame buffer */ - int px_width; /**< display width in dots */ - int px_height; /**< display height in dots */ + struct glcd_framebuf framebuf; /**< the main framebuffer */ int cellwidth; /**< character cell width */ int cellheight; /**< character cell height */ int width; /**< display width in characters */ @@ -61,8 +67,10 @@ typedef struct hwDependentFns { /* ================== Framebuffer functions and macros =================== */ -#define BYTES_PER_LINE (p->px_width / 8) -#define FB_BYTES_TOTAL (p->px_height * BYTES_PER_LINE) +#define BYTES_PER_LINE (p->framebuf.bytesPerLine) +#define FB_BYTES_TOTAL (p->framebuf.px_height * BYTES_PER_LINE) +#define FB_BLACK 1 +#define FB_WHITE 0 /** * Draw one pixel into the framebuffer using 1bpp (black and white). This @@ -75,21 +83,47 @@ typedef struct hwDependentFns { * \param color Pixel color: 1 = set (black), 0 = not set (blank/white) */ static inline void -fb_draw_pixel(PrivateData *p, int x, int y, int color) +fb_draw_pixel(struct glcd_framebuf *fb, int x, int y, int color) { unsigned int pos; /* Byte within the framebuffer */ unsigned char bit; /* Bit within the framebuffer byte */ - if (x < 0 || x >= p->px_width || y < 0 || y >= p->px_height) + if (x < 0 || x >= fb->px_width || y < 0 || y >= fb->px_height) return; - pos = y * BYTES_PER_LINE + (x / 8); + pos = y * fb->bytesPerLine + (x / 8); bit = 0x80 >> (x % 8); - if (color == 1) - p->framebuf[pos] |= bit; + if (color == FB_BLACK) + fb->data[pos] |= bit; else - p->framebuf[pos] &= ~bit; + fb->data[pos] &= ~bit; } + +/** + * Get color value of one pixel from the framebuffer. + * + * \param p Pointer to driver's private data. + * \param x X-position + * \param y Y-position + * \return Pixel color: 1 = set (black), 0 = not set (blank/white) + */ +static inline int +fb_get_pixel(struct glcd_framebuf *fb, int x, int y) +{ + unsigned int pos; + unsigned char bit; + + if (x < 0 || x >= fb->px_width || y < 0 || y >= fb->px_height) + return FB_WHITE; + + pos = y * fb->bytesPerLine + (x / 8); + bit = 0x80 >> (x % 8); + + if (fb->data[pos] & bit) + return FB_BLACK; + else + return FB_WHITE; +} #endif diff --git a/server/drivers/glcd-png.c b/server/drivers/glcd-png.c index c1730e1..35edab3 100644 --- a/server/drivers/glcd-png.c +++ b/server/drivers/glcd-png.c @@ -27,7 +27,10 @@ #include "lcd.h" #include "report.h" #include "glcd-low.h" -#include "glcd-png.h" + +/* Prototypes */ +void glcd_png_blit(PrivateData *p); +void glcd_png_close(PrivateData *p); /** Private data for the PNG connection type */ typedef struct glcd_png_data { @@ -89,7 +92,7 @@ glcd_png_blit(PrivateData *p) png_bytep row_pointer; /* Check if framebufer has changed. If not there's nothing to do */ - if (memcmp(p->framebuf, ct_data->backingstore, FB_BYTES_TOTAL) == 0) + if (memcmp(p->framebuf.data, ct_data->backingstore, FB_BYTES_TOTAL) == 0) return; snprintf(filename, sizeof(filename), "/tmp/lcdproc%06d.png", num++); @@ -120,7 +123,7 @@ glcd_png_blit(PrivateData *p) png_init_io(png_ptr, fp); - png_set_IHDR(png_ptr, info_ptr, p->px_width, p->px_height, + png_set_IHDR(png_ptr, info_ptr, p->framebuf.px_width, p->framebuf.px_height, 1, PNG_COLOR_TYPE_GRAY, PNG_INTERLACE_NONE, PNG_COMPRESSION_TYPE_BASE, PNG_FILTER_TYPE_BASE); png_set_invert_mono(png_ptr); @@ -128,8 +131,8 @@ glcd_png_blit(PrivateData *p) png_write_info(png_ptr, info_ptr); /* Write the image row by row */ - row_pointer = p->framebuf; - for (row = 0; row < p->px_height; row++) { + row_pointer = p->framebuf.data; + for (row = 0; row < p->framebuf.px_height; row++) { png_write_row(png_ptr, row_pointer); row_pointer += BYTES_PER_LINE; } @@ -139,7 +142,7 @@ glcd_png_blit(PrivateData *p) fp = NULL; png_destroy_write_struct(&png_ptr, &info_ptr); - memcpy(ct_data->backingstore, p->framebuf, FB_BYTES_TOTAL); + memcpy(ct_data->backingstore, p->framebuf.data, FB_BYTES_TOTAL); return; diff --git a/server/drivers/glcd-png.h b/server/drivers/glcd-png.h deleted file mode 100644 index 9cbea5e..0000000 --- a/server/drivers/glcd-png.h +++ /dev/null @@ -1,8 +0,0 @@ -#ifndef GLCD_PNG_H -#define GLCD_PNG_H - -int glcd_png_init(Driver *drvthis); -void glcd_png_blit(PrivateData *p); -void glcd_png_close(PrivateData *p); - -#endif diff --git a/server/drivers/glcd-render.c b/server/drivers/glcd-render.c index fa119c7..46045d4 100644 --- a/server/drivers/glcd-render.c +++ b/server/drivers/glcd-render.c @@ -64,7 +64,7 @@ glcd_render_init(Driver *drvthis) RenderConfig *rconf; int w, h; - debug(RPT_INFO, "%s(): Freetype", __FUNCTION__); + debug(RPT_INFO, "%s: render_init: Freetype", drvthis->name); /* Allocate memory structures */ rconf = (RenderConfig *) calloc(1, sizeof(RenderConfig)); @@ -117,11 +117,10 @@ glcd_render_init(Driver *drvthis) } p->cellwidth = w; p->cellheight = h; - debug(RPT_INFO, "%s: using cellsize %dx%d", drvthis->name, p->cellwidth, p->cellheight); } #endif + debug(RPT_INFO, "%s: using cellsize %dx%d", drvthis->name, p->cellwidth, p->cellheight); - debug(RPT_INFO, "%s() successful", __FUNCTION__); return 0; #ifdef HAVE_FT2 @@ -233,7 +232,7 @@ glcd_render_char_unicode(Driver *drvthis, int x, int y, int c, int yscale, int x for (row = 0; row < r_height; row++, py++) { px = x * p->cellwidth; for (col = 0; col < r_width; col++, px++) { - fb_draw_pixel(p, px, py, 0); + fb_draw_pixel(&(p->framebuf), px, py, 0); } } @@ -255,7 +254,7 @@ glcd_render_char_unicode(Driver *drvthis, int x, int y, int c, int yscale, int x px += (r_width - bitmap->width)/2; for (col = 0; (col < bitmap->width) && (col < r_width); col++) { - fb_draw_pixel(p, px, py, bitmap_buf[col / 8] >> (7 - (col % 8)) & 1); + fb_draw_pixel(&(p->framebuf), px, py, bitmap_buf[col / 8] >> (7 - (col % 8)) & 1); px++; } bitmap_buf += bitmap->pitch; @@ -303,9 +302,9 @@ glcd_render_char(Driver *drvthis, int x, int y, unsigned char c) */ for (font_x = GLCD_FONT_WIDTH; font_x >= 0; font_x--) { if (glcd_iso8859_1[c][font_y] & (1 << font_x)) - fb_draw_pixel(p, px, py, 1); + fb_draw_pixel(&(p->framebuf), px, py, 1); else - fb_draw_pixel(p, px, py, 0); + fb_draw_pixel(&(p->framebuf), px, py, 0); px++; } py++; @@ -409,7 +408,7 @@ glcd_render_bignum(Driver *drvthis, int x, int num) int c, z; /* Column and byte within font definition */ int px, py; /* Pixel coordinates within the frame buffer */ - if (p->px_height < chr_hgt_NUM) + if (p->framebuf.px_height < chr_hgt_NUM) return; x--; @@ -417,13 +416,13 @@ glcd_render_bignum(Driver *drvthis, int x, int num) px = x * p->cellwidth; for (c = 0; c < widtbl_NUM[num]; c++) { /* center vertically */ - py = (p->px_height - chr_hgt_NUM) / 2; + py = (p->framebuf.px_height - chr_hgt_NUM) / 2; for (z = 0; z < chr_hgt_NUM; z++) { /* Test if pixel bit is set and draw it */ if (chrtbl_NUM[num][c * 3 + z / 8] & (1 << (z % 8))) - fb_draw_pixel(p, px, py, 1); + fb_draw_pixel(&(p->framebuf), px, py, 1); else - fb_draw_pixel(p, px, py, 0); + fb_draw_pixel(&(p->framebuf), px, py, 0); py++; } px++; diff --git a/server/drivers/glcd-serdisp.c b/server/drivers/glcd-serdisp.c new file mode 100644 index 0000000..a90cb90 --- /dev/null +++ b/server/drivers/glcd-serdisp.c @@ -0,0 +1,217 @@ +/** \file server/drivers/glcd-serdisp.c + * Connection type using serdisplib for output (bridge driver). + */ + +/*- + * Copyright (c) 2010 Bernhard Walle + * 2011 Markus Dolze + * + * This file is released under the GNU General Public License. Refer to the + * COPYING file distributed with this package. + */ + +#ifdef HAVE_CONFIG_H +# include "config.h" +#endif + +#include +#include +#include +#include +#include + +#include "lcd.h" +#include "report.h" +#include "glcd-low.h" + +#define SERDISPLIB_MAX_DISPLAYNAME 32 +#define SERDISPLIB_MAX_DEVICENAME PATH_MAX + +/* Prototypes */ +void glcd_serdisp_blit(PrivateData *p); +void glcd_serdisp_close(PrivateData *p); +void glcd_serdisp_backlight(PrivateData *p, int state); + +/** Private data for the serdisplib connection type */ +typedef struct glcd_serdisp_data { + /** the name of the display driver in serdisplib, e.g. 'ctinclud' */ + char display_name[SERDISPLIB_MAX_DISPLAYNAME]; + + /** the name of the device in serdisplib, e.g. /dev/parport0 */ + char display_device[SERDISPLIB_MAX_DEVICENAME]; + + /** the serdisplib connection handle */ + serdisp_CONN_t *serdisplib_conn; + + /** the serdisplib handle */ + serdisp_t *disp; + + /** framebuffer for incremental updates */ + struct glcd_framebuf bsbuf; +} CT_serdisp_data; + +/** + * API: Initialize the connection type driver. + * \param drvthis Pointer to driver structure. + * \retval 0 Success. + * \retval <0 Error. + */ +int +glcd_serdisp_init(Driver *drvthis) +{ + PrivateData *p = (PrivateData *)drvthis->private_data; + CT_serdisp_data *ct_data; + const char *s; + + report(RPT_INFO, "glcd/serdisplib: intializing..."); + + /* Set up connection type low-level functions */ + p->glcd_functions->blit = glcd_serdisp_blit; + p->glcd_functions->close = glcd_serdisp_close; + p->glcd_functions->set_backlight = glcd_serdisp_backlight; + + /* Allocate memory structures */ + ct_data = (CT_serdisp_data *) calloc(1, sizeof(CT_serdisp_data)); + if (ct_data == NULL) { + report(RPT_ERR, "%s: error allocating connection data", + drvthis->name); + return -1; + } + p->ct_data = ct_data; + + /* get the display name */ + s = drvthis->config_get_string(drvthis->name, "serdisp_name", 0, NULL); + if (s == NULL) { + report(RPT_ERR, "%s: \'serdisp_name\' missing in configuration", + drvthis->name); + goto err_out; + } + strncpy(ct_data->display_name, s, SERDISPLIB_MAX_DISPLAYNAME); + ct_data->display_name[SERDISPLIB_MAX_DISPLAYNAME - 1] = '\0'; + + /* get the display device */ + s = drvthis->config_get_string(drvthis->name, "serdisp_device", 0, NULL); + if (s == NULL) { + report(RPT_ERR, "%s: \'serdisp_device\' missing in configuration", + drvthis->name); + goto err_out; + } + strncpy(ct_data->display_device, s, SERDISPLIB_MAX_DEVICENAME); + ct_data->display_device[SERDISPLIB_MAX_DEVICENAME - 1] = '\0'; + + /* open the output device */ + ct_data->serdisplib_conn = SDCONN_open(ct_data->display_device); + if (ct_data->serdisplib_conn == NULL) { + report(RPT_ERR, "Could not open %s: %s", ct_data->display_device, + sd_geterrormsg()); + goto err_out; + } + + /* open and initialize the display with options */ + s = drvthis->config_get_string(drvthis->name, "serdisp_options", 0, ""); + debug(RPT_INFO, "%s: Using serdisp options: %s", drvthis->name, s); + ct_data->disp = serdisp_init(ct_data->serdisplib_conn, ct_data->display_name, s); + if (ct_data->disp == NULL) { + report(RPT_ERR, "Error opening display %s: %s\n", + ct_data->display_name, sd_geterrormsg()); + goto err_out; + } + + /* set size overriding anything set in serdisp_options */ + serdisp_setoption(ct_data->disp, "WIDTH", p->framebuf.px_width); + serdisp_setoption(ct_data->disp, "HEIGHT", p->framebuf.px_height); + + /* allocate backing store based on frame buffer */ + ct_data->bsbuf.px_width = p->framebuf.px_width; + ct_data->bsbuf.px_height = p->framebuf.px_height; + ct_data->bsbuf.bytesPerLine = p->framebuf.bytesPerLine; + ct_data->bsbuf.data = malloc(ct_data->bsbuf.px_height * ct_data->bsbuf.bytesPerLine); + if (ct_data->bsbuf.data == NULL) { + report(RPT_ERR, "%s: error allocating backing store", + drvthis->name); + } + memset(ct_data->bsbuf.data, 0x00, ct_data->bsbuf.px_height * ct_data->bsbuf.bytesPerLine); + + serdisp_clearbuffer(ct_data->disp); + + debug(RPT_INFO, "glcd/serdisplib: finished"); + return 0; + +err_out: + glcd_serdisp_close(p); + return -1; +} + + +/** + * API: Release low-level resources. + * \param p Pointer to glcd driver's private date structure. + */ +void +glcd_serdisp_close(PrivateData *p) +{ + if (p->ct_data != NULL) { + CT_serdisp_data *ct_data = (CT_serdisp_data *) p->ct_data; + + if (ct_data->serdisplib_conn && !ct_data->disp) + SDCONN_close(ct_data->serdisplib_conn); + if (ct_data->disp) + serdisp_quit(ct_data->disp); + if (ct_data->bsbuf.data) { + free(ct_data->bsbuf.data); + ct_data->bsbuf.data = NULL; + } + + free(p->ct_data); + p->ct_data = NULL; + } +} + + +/** + * API: Write the framebuffer to the display + * \param p Pointer to glcd driver's private date structure. + */ +void +glcd_serdisp_blit(PrivateData *p) +{ + CT_serdisp_data *ct_data = (CT_serdisp_data *) p->ct_data; + int px, py; + int pixel_new, pixel_old; + + /* + * Update method: go through the whole framebuffer line by line and + * compare each pixel with the one in the backing store. If different + * draw to serdisplib. + */ + for (py = 0; py < p->framebuf.px_height; py++) { + for (px = 0; px < p->framebuf.px_width; px++) { + pixel_old = fb_get_pixel(&(ct_data->bsbuf), px, py); + pixel_new = fb_get_pixel(&(p->framebuf), px, py); + if (pixel_old != pixel_new) { + serdisp_setcolour(ct_data->disp, px, py, + (pixel_new == FB_BLACK) ? SD_COL_BLACK : SD_COL_WHITE); + fb_draw_pixel(&(ct_data->bsbuf), px, py, pixel_new); + } + } + } + serdisp_update(ct_data->disp); +} + + +/** + * API: Turn the backlight on or off. The serdisp library does not support + * backlight levels. Any level set in glcd driver is ignored. + * \param p + * \param state + */ +void +glcd_serdisp_backlight(PrivateData *p, int state) +{ + CT_serdisp_data *ct_data = (CT_serdisp_data *) p->ct_data; + + if (state == BACKLIGHT_ON) + serdisp_setoption(ct_data->disp, "BACKLIGHT", SD_OPTION_YES); + else + serdisp_setoption(ct_data->disp, "BACKLIGHT", SD_OPTION_NO); +} diff --git a/server/drivers/glcd-t6963.c b/server/drivers/glcd-t6963.c index 573d197..94519a3 100644 --- a/server/drivers/glcd-t6963.c +++ b/server/drivers/glcd-t6963.c @@ -26,12 +26,13 @@ #include "lcd.h" #include "report.h" #include "glcd-low.h" -#include "glcd-t6963.h" #include "t6963_low.h" #define DEFAULT_PORT 0x378 static void t6963_graphic_clear(PrivateData *p); +void glcd_t6963_blit(PrivateData *p); +void glcd_t6963_close(PrivateData *p); typedef struct glcd_t6963_data { unsigned char *backingstore; /**< backing buffer */ @@ -54,9 +55,9 @@ glcd_t6963_init(Driver *drvthis) report(RPT_INFO, "GLCD/T6963: intializing"); /* Check the size before doing anything else! */ - if ((p->px_width > T6963_MAX_WIDTH) || (p->px_height > T6963_MAX_HEIGHT)) { + if ((p->framebuf.px_width > T6963_MAX_WIDTH) || (p->framebuf.px_height > T6963_MAX_HEIGHT)) { report(RPT_ERR, "GLCD/T6963: Size %dx%d not supported by connection type", - p->px_width, p->px_height); + p->framebuf.px_width, p->framebuf.px_height); return -1; } @@ -136,9 +137,9 @@ glcd_t6963_blit(PrivateData *p) CT_t6963_data *ct_data = (CT_t6963_data *) p->ct_data; int x, y; - for (y = 0; y < p->px_height; y++) { + for (y = 0; y < p->framebuf.px_height; y++) { /* set pointers to start of the line */ - unsigned char *sp = p->framebuf + (y * BYTES_PER_LINE); + unsigned char *sp = p->framebuf.data + (y * BYTES_PER_LINE); unsigned char *sq = ct_data->backingstore + (y * BYTES_PER_LINE); /* set pointers to end of the line */ diff --git a/server/drivers/glcd-t6963.h b/server/drivers/glcd-t6963.h deleted file mode 100644 index 70c6513..0000000 --- a/server/drivers/glcd-t6963.h +++ /dev/null @@ -1,8 +0,0 @@ -#ifndef GLCD_T6963_H -#define GLCD_T6963_H - -int glcd_t6963_init(Driver *drvthis); -void glcd_t6963_blit(PrivateData *p); -void glcd_t6963_close(PrivateData *p); - -#endif diff --git a/server/drivers/glcd_drv.c b/server/drivers/glcd_drv.c index be063bf..0a4970c 100644 --- a/server/drivers/glcd_drv.c +++ b/server/drivers/glcd_drv.c @@ -124,8 +124,10 @@ glcd_init(Driver *drvthis) drvthis->name, size, GLCD_DEFAULT_SIZE); sscanf(GLCD_DEFAULT_SIZE, "%dx%d", &w, &h); } - p->px_width = w; - p->px_height = h; + p->framebuf.px_width = w; + p->framebuf.px_height = h; + p->framebuf.bytesPerLine = (p->framebuf.px_width + 7) / 8; + debug(RPT_INFO, "%s: bytesPerLine (first) = %d", drvthis->name, BYTES_PER_LINE); /* Set contrast */ tmp = drvthis->config_get_int(drvthis->name, "Contrast", 0, GLCD_DEFAULT_CONTRAST); @@ -170,39 +172,33 @@ glcd_init(Driver *drvthis) } /* - * Currently this driver supports only display which width is a multiple - * of 8! + * Check these values AFTER driver initialization, as the driver may + * update them. */ - if ((p->px_width % 8) != 0) { - report(RPT_ERR, "%s: Pixel width must be mutiple of 8", drvthis->name); - return -1; - } - - /* - * Calculate these values AFTER driver initialization, as the driver - * may update them. - */ - if ((p->px_width > GLCD_MAX_WIDTH) || (p->px_height > GLCD_MAX_HEIGHT)) { + if ((p->framebuf.px_width > GLCD_MAX_WIDTH) || (p->framebuf.px_height > GLCD_MAX_HEIGHT)) { report(RPT_ERR, "%s: Size %dx%d set by ConnectionType is not supported", - drvthis->name, p->px_width, p->px_height); + drvthis->name, p->framebuf.px_width, p->framebuf.px_height); return -1; } - /* Allocate framebuffer */ - p->framebuf = malloc(FB_BYTES_TOTAL); - if (p->framebuf == NULL) { + /* Allocate framebuffer (re-calculate bytesPerLine before) */ + p->framebuf.bytesPerLine = (p->framebuf.px_width + 7) / 8; + debug(RPT_INFO, "%s: bytesPerLine (final) = %d", drvthis->name, BYTES_PER_LINE); + p->framebuf.data = malloc(FB_BYTES_TOTAL); + if (p->framebuf.data == NULL) { report(RPT_ERR, "%s: unable to allocate framebuffer", drvthis->name); return -1; } - memset(p->framebuf, 0x00, FB_BYTES_TOTAL); + memset(p->framebuf.data, 0x00, FB_BYTES_TOTAL); /* Initialize renderer */ if (glcd_render_init(drvthis) != 0) return -1; /* Cellwidth / height are set by the renderer */ - p->width = p->px_width / p->cellwidth; - p->height = p->px_height / p->cellheight; + p->width = p->framebuf.px_width / p->cellwidth; + p->height = p->framebuf.px_height / p->cellheight; + debug(RPT_INFO, "%s: Screen size (final) = %dx%d", drvthis->name, p->width, p->height); glcd_clear(drvthis); @@ -224,9 +220,9 @@ glcd_close(Driver *drvthis) if (p != NULL) { if (p->glcd_functions->close != NULL) p->glcd_functions->close(p); - if (p->framebuf != NULL) - free(p->framebuf); - p->framebuf = NULL; + if (p->framebuf.data != NULL) + free(p->framebuf.data); + p->framebuf.data = NULL; glcd_render_close(drvthis); free(p); @@ -310,7 +306,7 @@ glcd_clear(Driver *drvthis) debug(RPT_DEBUG, "%s()", __FUNCTION__); - memset(p->framebuf, 0x00, FB_BYTES_TOTAL); + memset(p->framebuf.data, 0x00, FB_BYTES_TOTAL); } @@ -327,7 +323,6 @@ glcd_flush(Driver *drvthis) debug(RPT_DEBUG, "%s()", __FUNCTION__); p->glcd_functions->blit(p); - } @@ -425,7 +420,7 @@ glcd_vbar(Driver *drvthis, int x, int y, int len, int promille, int options) for (col = xstart; col < xend; col++) { for (row = ystart; row > yend; row--) { - fb_draw_pixel(p, col, row, 1); + fb_draw_pixel(&(p->framebuf), col, row, 1); } } } @@ -451,7 +446,7 @@ glcd_hbar(Driver *drvthis, int x, int y, int len, int promille, int options) for (row = ystart; row < yend; row++) { for (col = xstart; col < xend; col++) { - fb_draw_pixel(p, col, row, 1); + fb_draw_pixel(&(p->framebuf), col, row, 1); } }