overhauled CwLnx driver (Dave Pratt)

This commit is contained in:
marschap
2007-04-30 13:47:35 +00:00
parent 8331b37fa3
commit 34e8d1e1ae
4 changed files with 145 additions and 38 deletions
+3
View File
@@ -224,6 +224,9 @@ Karsten Festag
Gatewood Green
- picolcd driver
Dave Pratt
- overhauled CwLnx driver
Further developers in the sourceforge lcdproc team:
Mindaugas Idzelis aim4min
+1
View File
@@ -14,6 +14,7 @@ v.0.5dev (ongoing development)
- server core: cleanup - remove unnecessary cruft
* server core: refactor renderin code
+ LCDd: config options TitleSpeed= and Heartbeat=
* overhauled CwLnx driver (Dave Pratt)
v.0.5.2
* fix switching on/off the Load screen in lcdproc client using the menu
+140 -37
View File
@@ -122,6 +122,7 @@ MODULE_EXPORT char *symbol_prefix = "CwLnx_";
static void CwLnx_linewrap(int fd, int on);
static void CwLnx_autoscroll(int fd, int on);
static void CwLnx_hidecursor(int fd);
static void CwLnx_set_char_unrestricted(Driver *drvthis, int n, unsigned char *dat);
#define LCD_CMD 254
@@ -140,31 +141,37 @@ static void CwLnx_hidecursor(int fd);
#define LCD_SETCHAR 78
#define LCD_ENABLE_SCROLL 81
#define LCD_DISABLE_SCROLL 82
#define LCD_SOFT_RESET 86
#define LCD_OFF_CURSOR 72
#define LCD_PUT_PIXEL 112
#define LCD_CLEAR_PIXEL 113
#define DELAY 2000 /* 2 milli sec */
#define UPDATE_DELAY 0 /* 1 imicro sec */
#define SETUP_DELAY 1 /* 2 micro sec */
#define UPDATE_DELAY 20000 /* 20 milliseconds */
#define SETUP_DELAY 20000 /* 20 milliseconds */
#define MOVE_COST 5 /* # bytes for most move-to ops */
static int Write_LCD(int fd, char *c, int size)
{
int rc;
int rc, wrote = 0;
int retries = 30;
do {
rc = write(fd, c, size);
if (rc == size)
if (rc > 0) {
c += rc;
size -= rc;
wrote += rc;
} else if (rc == 0 || (rc < 0 && errno == EAGAIN)) { /* would have blocked */
usleep(DELAY);
} else {
break;
usleep(DELAY);
}
} while (size > 0 && --retries > 0);
} while (--retries > 0);
return rc;
return wrote;
}
@@ -392,7 +399,20 @@ CwLnx_autoscroll(int fd, int on)
static void
CwLnx_hidecursor(int fd)
{
Disable_Cursor(fd);
Disable_Cursor(fd);
}
/********************************************************************
* Reset the display bios
*/
static void CwLnx_reboot(int fd)
{
char cmd[] = { LCD_CMD, LCD_SOFT_RESET, LCD_CMD_END };
Write_LCD(fd, cmd, 3);
usleep(SETUP_DELAY);
return;
}
@@ -410,8 +430,6 @@ CwLnx_hidecursor(int fd)
MODULE_EXPORT int
CwLnx_init(Driver *drvthis)
{
struct termios portset_save;
char device[200] = DEFAULT_DEVICE;
int speed = DEFAULT_SPEED;
char size[200] = DEFAULT_SIZE;
@@ -576,23 +594,26 @@ CwLnx_init(Driver *drvthis)
}
report(RPT_INFO, "%s: opened display on %s", drvthis->name, device);
/*
Since we don't know what speed the display is using when
we first connect to it, configure the port for the speed
we don't want to use, send a command to switch the display
to the speed we want to use, and flush the command.
*/
Init_Port(p->fd);
tcgetattr(p->fd, &portset_save);
speed = B19200;
Setup_Port(p->fd, speed);
if (speed == B9600) {
Setup_Port(p->fd, B19200);
Set_9600(p->fd);
close(p->fd);
p->fd = open(device, O_RDWR | O_NOCTTY | O_NDELAY);
if (p->fd == -1) {
report(RPT_ERR, "%s: open(%s) failed (%s)", drvthis->name, device, strerror(errno));
return -1;
} else {
Setup_Port(p->fd, B9600);
Set_19200(p->fd);
}
report(RPT_INFO, "%s: opened display on %s", drvthis->name, device);
tcdrain(p->fd);
usleep(SETUP_DELAY);
Init_Port(p->fd);
speed = B9600;
Setup_Port(p->fd, speed);
CwLnx_hidecursor(p->fd);
CwLnx_linewrap(p->fd, 1);
CwLnx_autoscroll(p->fd, 0);
@@ -712,7 +733,8 @@ CwLnx_flush(Driver *drvthis)
PrivateData *p = drvthis->private_data;
int i, j;
int move = 1;
int iUpdate = 0, jUpdate = 0;
unsigned char *firstUpdate = NULL, *lastUpdate = NULL;
unsigned char *q = p->framebuf;
unsigned char *r = p->backingstore;
@@ -720,25 +742,43 @@ CwLnx_flush(Driver *drvthis)
for (i = 0; i < p->height; i++) {
for (j = 0; j < p->width; j++) {
if ((*q == *r) && !((0 < *q) && (*q < 16))) {
move = 1;
}
else {
/* Draw characters that have changed, as well
* as custom characters. We know not if a custom
* character has changed. */
if (move == 1) {
Set_Insert(p->fd, i, j);
move = 0;
if (firstUpdate && q - lastUpdate > MOVE_COST) {
Set_Insert(p->fd, iUpdate, jUpdate);
Write_LCD(p->fd, (char *) firstUpdate,
lastUpdate - firstUpdate + 1);
firstUpdate = lastUpdate = NULL;
}
} else {
lastUpdate = q;
if (!firstUpdate) {
firstUpdate = q;
iUpdate = i;
jUpdate = j;
}
Write_LCD(p->fd, (char *) q, 1);
}
q++;
r++;
}
}
memcpy(p->backingstore, p->framebuf, p->width * p->height);
}
if (firstUpdate) {
Set_Insert(p->fd, iUpdate, jUpdate);
Write_LCD(p->fd, (char *) firstUpdate,
lastUpdate - firstUpdate + 1);
}
memcpy(p->backingstore, p->framebuf, p->width * p->height);
if (p->backlight != p->saved_backlight ||
p->brightness != p->saved_brightness) {
if (!p->backlight) {
Backlight_Brightness(p->fd, 1);
} else {
Backlight_Brightness(p->fd, 1 + p->brightness * 6 / 900); /* 90% and up is full brightness */
}
p->saved_backlight = p->backlight;
p->saved_brightness = p->brightness;
}
}
/**
* Print a character on the screen at position (x,y).
@@ -904,7 +944,11 @@ CwLnx_hbar(Driver *drvthis, int x, int y, int len, int promille, int options)
for (i = 1; i <= p->cellwidth; i++) {
// fill pixel columns from left to right.
memset(hBar, 0xFF & ~((1 << (p->cellwidth - i)) - 1), sizeof(hBar));
#if defined(SEAMLESS_HBARS)
CwLnx_set_char_unrestricted(drvthis, i+1, hBar);
#else
CwLnx_set_char(drvthis, i+1, hBar);
#endif
}
}
@@ -1020,6 +1064,65 @@ CwLnx_set_char(Driver *drvthis, int n, unsigned char *dat)
}
/*
* Identical to CwLnx_set_char, but it doesn't restrict the 12232 to
* using only 5 of its 6 columns. Full 6-column mode is required
* for seamless H-bars.
*/
#if defined(SEAMLESS_HBARS)
static void
CwLnx_set_char_unrestricted(Driver *drvthis, int n, unsigned char *dat)
{
PrivateData *p = drvthis->private_data;
char c;
int rc;
if ((n <= 0) || (n > CwLnx_get_free_chars(drvthis)))
return;
if (!dat)
return;
c = LCD_CMD;
rc = Write_LCD(p->fd, &c, 1);
c = LCD_SETCHAR;
rc = Write_LCD(p->fd, &c, 1);
c = (char) n;
rc = Write_LCD(p->fd, &c, 1);
if (p->model == 1602) { // the character model
unsigned char mask = (1 << p->cellwidth) - 1;
int row;
for (row = 0; row < p->cellheight; row++) {
c = dat[row] & mask;
Write_LCD(p->fd, &c, 1);
}
} else if (p->model == 12232) { // the graphical model
int col;
for (col = p->cellwidth - 1; col >= 0; col--) {
int letter = 0;
int row;
for (row = p->cellheight - 1; row >= 0; row--) {
letter <<= 1;
letter |= ((dat[row] >> col) & 1);
}
c = letter;
Write_LCD(p->fd, &c, 1);
}
}
c = LCD_CMD_END;
rc = Write_LCD(p->fd, &c, 1);
}
#endif
/**
* Place an icon on the screen.
* \param drvthis Pointer to driver structure.
+1 -1
View File
@@ -31,7 +31,7 @@
#define DEFAULT_DEVICE "/dev/lcd"
#define DEFAULT_BACKLIGHT 1
#define DEFAULT_BRIGHTNESS 200
#define DEFAULT_BRIGHTNESS 700
#define DEFAULT_CELL_WIDTH_1602 5
#define DEFAULT_CELL_WIDTH_12232 6