overhauled CwLnx driver (Dave Pratt)
This commit is contained in:
@@ -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
|
||||
|
||||
@@ -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
@@ -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.
|
||||
|
||||
@@ -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
|
||||
|
||||
Reference in New Issue
Block a user