overhauled CwLnx driver (Dave Pratt)
This commit is contained in:
@@ -224,6 +224,9 @@ Karsten Festag
|
|||||||
Gatewood Green
|
Gatewood Green
|
||||||
- picolcd driver
|
- picolcd driver
|
||||||
|
|
||||||
|
Dave Pratt
|
||||||
|
- overhauled CwLnx driver
|
||||||
|
|
||||||
|
|
||||||
Further developers in the sourceforge lcdproc team:
|
Further developers in the sourceforge lcdproc team:
|
||||||
Mindaugas Idzelis aim4min
|
Mindaugas Idzelis aim4min
|
||||||
|
|||||||
@@ -14,6 +14,7 @@ v.0.5dev (ongoing development)
|
|||||||
- server core: cleanup - remove unnecessary cruft
|
- server core: cleanup - remove unnecessary cruft
|
||||||
* server core: refactor renderin code
|
* server core: refactor renderin code
|
||||||
+ LCDd: config options TitleSpeed= and Heartbeat=
|
+ LCDd: config options TitleSpeed= and Heartbeat=
|
||||||
|
* overhauled CwLnx driver (Dave Pratt)
|
||||||
|
|
||||||
v.0.5.2
|
v.0.5.2
|
||||||
* fix switching on/off the Load screen in lcdproc client using the menu
|
* 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_linewrap(int fd, int on);
|
||||||
static void CwLnx_autoscroll(int fd, int on);
|
static void CwLnx_autoscroll(int fd, int on);
|
||||||
static void CwLnx_hidecursor(int fd);
|
static void CwLnx_hidecursor(int fd);
|
||||||
|
static void CwLnx_set_char_unrestricted(Driver *drvthis, int n, unsigned char *dat);
|
||||||
|
|
||||||
|
|
||||||
#define LCD_CMD 254
|
#define LCD_CMD 254
|
||||||
@@ -140,31 +141,37 @@ static void CwLnx_hidecursor(int fd);
|
|||||||
#define LCD_SETCHAR 78
|
#define LCD_SETCHAR 78
|
||||||
#define LCD_ENABLE_SCROLL 81
|
#define LCD_ENABLE_SCROLL 81
|
||||||
#define LCD_DISABLE_SCROLL 82
|
#define LCD_DISABLE_SCROLL 82
|
||||||
|
#define LCD_SOFT_RESET 86
|
||||||
#define LCD_OFF_CURSOR 72
|
#define LCD_OFF_CURSOR 72
|
||||||
|
|
||||||
#define LCD_PUT_PIXEL 112
|
#define LCD_PUT_PIXEL 112
|
||||||
#define LCD_CLEAR_PIXEL 113
|
#define LCD_CLEAR_PIXEL 113
|
||||||
|
|
||||||
#define DELAY 2000 /* 2 milli sec */
|
#define DELAY 2000 /* 2 milli sec */
|
||||||
#define UPDATE_DELAY 0 /* 1 imicro sec */
|
#define UPDATE_DELAY 20000 /* 20 milliseconds */
|
||||||
#define SETUP_DELAY 1 /* 2 micro sec */
|
#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)
|
static int Write_LCD(int fd, char *c, int size)
|
||||||
{
|
{
|
||||||
int rc;
|
int rc, wrote = 0;
|
||||||
int retries = 30;
|
int retries = 30;
|
||||||
|
|
||||||
do {
|
do {
|
||||||
rc = write(fd, c, size);
|
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;
|
break;
|
||||||
usleep(DELAY);
|
}
|
||||||
|
} while (size > 0 && --retries > 0);
|
||||||
|
|
||||||
} while (--retries > 0);
|
return wrote;
|
||||||
|
|
||||||
return rc;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@@ -392,7 +399,20 @@ CwLnx_autoscroll(int fd, int on)
|
|||||||
static void
|
static void
|
||||||
CwLnx_hidecursor(int fd)
|
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
|
MODULE_EXPORT int
|
||||||
CwLnx_init(Driver *drvthis)
|
CwLnx_init(Driver *drvthis)
|
||||||
{
|
{
|
||||||
struct termios portset_save;
|
|
||||||
|
|
||||||
char device[200] = DEFAULT_DEVICE;
|
char device[200] = DEFAULT_DEVICE;
|
||||||
int speed = DEFAULT_SPEED;
|
int speed = DEFAULT_SPEED;
|
||||||
char size[200] = DEFAULT_SIZE;
|
char size[200] = DEFAULT_SIZE;
|
||||||
@@ -576,23 +594,26 @@ CwLnx_init(Driver *drvthis)
|
|||||||
}
|
}
|
||||||
report(RPT_INFO, "%s: opened display on %s", drvthis->name, device);
|
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);
|
Init_Port(p->fd);
|
||||||
tcgetattr(p->fd, &portset_save);
|
if (speed == B9600) {
|
||||||
speed = B19200;
|
Setup_Port(p->fd, B19200);
|
||||||
Setup_Port(p->fd, speed);
|
|
||||||
Set_9600(p->fd);
|
Set_9600(p->fd);
|
||||||
close(p->fd);
|
} else {
|
||||||
|
Setup_Port(p->fd, B9600);
|
||||||
p->fd = open(device, O_RDWR | O_NOCTTY | O_NDELAY);
|
Set_19200(p->fd);
|
||||||
if (p->fd == -1) {
|
|
||||||
report(RPT_ERR, "%s: open(%s) failed (%s)", drvthis->name, device, strerror(errno));
|
|
||||||
return -1;
|
|
||||||
}
|
}
|
||||||
report(RPT_INFO, "%s: opened display on %s", drvthis->name, device);
|
tcdrain(p->fd);
|
||||||
|
usleep(SETUP_DELAY);
|
||||||
Init_Port(p->fd);
|
Init_Port(p->fd);
|
||||||
speed = B9600;
|
|
||||||
Setup_Port(p->fd, speed);
|
Setup_Port(p->fd, speed);
|
||||||
|
|
||||||
CwLnx_hidecursor(p->fd);
|
CwLnx_hidecursor(p->fd);
|
||||||
CwLnx_linewrap(p->fd, 1);
|
CwLnx_linewrap(p->fd, 1);
|
||||||
CwLnx_autoscroll(p->fd, 0);
|
CwLnx_autoscroll(p->fd, 0);
|
||||||
@@ -712,7 +733,8 @@ CwLnx_flush(Driver *drvthis)
|
|||||||
PrivateData *p = drvthis->private_data;
|
PrivateData *p = drvthis->private_data;
|
||||||
|
|
||||||
int i, j;
|
int i, j;
|
||||||
int move = 1;
|
int iUpdate = 0, jUpdate = 0;
|
||||||
|
unsigned char *firstUpdate = NULL, *lastUpdate = NULL;
|
||||||
|
|
||||||
unsigned char *q = p->framebuf;
|
unsigned char *q = p->framebuf;
|
||||||
unsigned char *r = p->backingstore;
|
unsigned char *r = p->backingstore;
|
||||||
@@ -720,25 +742,43 @@ CwLnx_flush(Driver *drvthis)
|
|||||||
for (i = 0; i < p->height; i++) {
|
for (i = 0; i < p->height; i++) {
|
||||||
for (j = 0; j < p->width; j++) {
|
for (j = 0; j < p->width; j++) {
|
||||||
if ((*q == *r) && !((0 < *q) && (*q < 16))) {
|
if ((*q == *r) && !((0 < *q) && (*q < 16))) {
|
||||||
move = 1;
|
if (firstUpdate && q - lastUpdate > MOVE_COST) {
|
||||||
}
|
Set_Insert(p->fd, iUpdate, jUpdate);
|
||||||
else {
|
Write_LCD(p->fd, (char *) firstUpdate,
|
||||||
/* Draw characters that have changed, as well
|
lastUpdate - firstUpdate + 1);
|
||||||
* as custom characters. We know not if a custom
|
firstUpdate = lastUpdate = NULL;
|
||||||
* character has changed. */
|
}
|
||||||
if (move == 1) {
|
} else {
|
||||||
Set_Insert(p->fd, i, j);
|
lastUpdate = q;
|
||||||
move = 0;
|
if (!firstUpdate) {
|
||||||
|
firstUpdate = q;
|
||||||
|
iUpdate = i;
|
||||||
|
jUpdate = j;
|
||||||
}
|
}
|
||||||
Write_LCD(p->fd, (char *) q, 1);
|
|
||||||
}
|
}
|
||||||
q++;
|
q++;
|
||||||
r++;
|
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).
|
* 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++) {
|
for (i = 1; i <= p->cellwidth; i++) {
|
||||||
// fill pixel columns from left to right.
|
// fill pixel columns from left to right.
|
||||||
memset(hBar, 0xFF & ~((1 << (p->cellwidth - i)) - 1), sizeof(hBar));
|
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);
|
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.
|
* Place an icon on the screen.
|
||||||
* \param drvthis Pointer to driver structure.
|
* \param drvthis Pointer to driver structure.
|
||||||
|
|||||||
@@ -31,7 +31,7 @@
|
|||||||
|
|
||||||
#define DEFAULT_DEVICE "/dev/lcd"
|
#define DEFAULT_DEVICE "/dev/lcd"
|
||||||
#define DEFAULT_BACKLIGHT 1
|
#define DEFAULT_BACKLIGHT 1
|
||||||
#define DEFAULT_BRIGHTNESS 200
|
#define DEFAULT_BRIGHTNESS 700
|
||||||
|
|
||||||
#define DEFAULT_CELL_WIDTH_1602 5
|
#define DEFAULT_CELL_WIDTH_1602 5
|
||||||
#define DEFAULT_CELL_WIDTH_12232 6
|
#define DEFAULT_CELL_WIDTH_12232 6
|
||||||
|
|||||||
Reference in New Issue
Block a user