glcd driver updates:

1. Remove connection type header files and put prototypes locally and in
   glcd-drivers.h. Don't fall into the pitfall of too many header files again.
2. Create a separate frame buffer structure (this allows easier re-use of
   the frame buffer functions).
3. Add a function to retrieve pixel values from framebuffer.
4. Add the 'serdisplib' connection type.
5. Support display width that are not a multiple of 8 (e.g. 122x32).
This commit is contained in:
mmdolze
2011-11-22 23:14:45 +00:00
parent 85241c253d
commit eac9d590a8
12 changed files with 348 additions and 83 deletions
+15
View File
@@ -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 ##
+10
View File
@@ -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"]
;;
+2 -2
View File
@@ -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
+11 -4
View File
@@ -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}
+45 -11
View File
@@ -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
+9 -6
View File
@@ -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;
-8
View File
@@ -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
+10 -11
View File
@@ -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++;
+217
View File
@@ -0,0 +1,217 @@
/** \file server/drivers/glcd-serdisp.c
* Connection type using serdisplib for output (bridge driver).
*/
/*-
* Copyright (c) 2010 Bernhard Walle <bernhard@bwalle.de>
* 2011 Markus Dolze <bsdfan@nurfuerspam.de>
*
* 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 <stdlib.h>
#include <strings.h>
#include <string.h>
#include <limits.h>
#include <serdisplib/serdisp.h>
#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);
}
+6 -5
View File
@@ -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 */
-8
View File
@@ -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
+23 -28
View File
@@ -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);
}
}