diff --git a/ChangeLog b/ChangeLog
index 1b5a12f..4adc342 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -71,6 +71,7 @@ v.0.5dev (ongoing development)
+ hd44780 driver: port usblcd connection type from 0.4.5 to 0.5 (M. Dolze)
* server: Fix interpretation of named screen priorities
+ new driver imonlcd for SoundGraph iMON LCD (Dean Harding, Jonathan Kyler)
+ * MtxOrb driver: Fix backlight for old firmware
v.0.5.2
* fix switching on/off the Load screen in lcdproc client using the menu
diff --git a/LCDd.conf b/LCDd.conf
index a59d2ec..8769190 100644
--- a/LCDd.conf
+++ b/LCDd.conf
@@ -759,6 +759,11 @@ Type=lkd
# is a vfd or vkd as they don't have this feature
Contrast=480
+# Some old displays do not have an adjustable backlight but only can
+# switch the backlight on/off. If you experience randomly appearing block
+# characters, try setting this to false. [default: yes; legal: yes, no]
+hasAdjustableBacklight=no
+
# Set the initial brightness [default: 1000; legal: 0 - 1000]
Brightness=1000
# Set the initial off-brightness [default: 0; legal: 0 - 1000]
diff --git a/docs/lcdproc-user/drivers/mtxorb.docbook b/docs/lcdproc-user/drivers/mtxorb.docbook
index 75f4866..6eea25c 100644
--- a/docs/lcdproc-user/drivers/mtxorb.docbook
+++ b/docs/lcdproc-user/drivers/mtxorb.docbook
@@ -292,6 +292,25 @@ Slightly modified in order to include it in this document March 2002, Rene Wagne
+
+
+ hasAdjustableBacklight =
+
+
+ yes
+ no
+
+
+
+
+ Some old firmware versions of Matrix Orbital modules do not support an
+ adjustable backlight but only can switch the backlight on/off. If you own
+ such a module and experience randomly appearing block characters and
+ backlight cannot be switched on or off, use this to no
+ [default: yes].
+
+
+
Brightness =
diff --git a/server/drivers/MtxOrb.c b/server/drivers/MtxOrb.c
index 752c474..aa6db19 100644
--- a/server/drivers/MtxOrb.c
+++ b/server/drivers/MtxOrb.c
@@ -136,6 +136,7 @@ typedef struct MtxOrb_private_data {
int contrast; /**< current contrast */
int brightness;
int offbrightness;
+ int adjustable_backlight;
MtxOrb_type_type MtxOrb_type;
@@ -147,6 +148,62 @@ typedef struct MtxOrb_private_data {
char info[255]; /**< info string contents */
} PrivateData;
+/** List of known Matrix Orbital modules */
+static const MtxOrbModuleEntry modulelist[] = {
+ /* model, name, flags */
+ { 0x01, "LCD0821", 0 },
+ { 0x03, "LCD2021", 0 },
+ { 0x04, "LCD1641", 0 },
+ { 0x05, "LCD2041", 0 }, /* VK202-25 ? */
+ { 0x06, "LCD4021", 0 },
+ { 0x07, "LCD4041", 0 },
+ { 0x08, "LK202-25", 0 },
+ { 0x09, "LK204-25", 0 },
+ { 0x0A, "LK404-55", 0 },
+ { 0x0B, "VFD2021", 0 },
+ { 0x0C, "VFD2041", 0 },
+ { 0x0D, "VFD4021", 0 },
+ { 0x0E, "VK202-25", 0 },
+ { 0x0F, "VK204-25", 0 },
+ { 0x10, "GLC12232", 0 },
+ { 0x11, "GLC12864", 0 },
+ { 0x12, "GLC128128", 0 }, /* ??? */
+ { 0x13, "GLC24064", 0 },
+ { 0x14, "GLK12864-25", 0 }, /* ??? */
+ { 0x15, "GLK24064-25", 0 },
+ { 0x21, "GLK128128-25", 0 }, /* ??? */
+ { 0x22, "GLK12232-25-WBL", 0 },
+ { 0x24, "GLK12232-25-SM", 0 },
+ { 0x31, "LK404-AT", 0 },
+ { 0x32, "VFD1621", 0 }, /* MOS-AV-162A ? */
+ { 0x33, "LK402-12", 0 },
+ { 0x34, "LK162-12", 0 },
+ { 0x35, "LK204-25PC", 0 },
+ { 0x36, "LK202-24-USB", 0 },
+ { 0x37, "VK202-24-USB", 0 },
+ { 0x38, "LK204-24-USB", 0 },
+ { 0x39, "VK204-24-USB", 0 },
+ { 0x3A, "PK162-12", 0 },
+ { 0x3B, "VK162-12", 0 },
+ { 0x3C, "MOS-AP-162A", 0 },
+ { 0x3D, "PK202-25", 0 },
+ { 0x3E, "MOS-AL-162A", 0 },
+ { 0x40, "MOS-AV-202A", 0 },
+ { 0x41, "MOS-AP-202A", 0 },
+ { 0x42, "PK202-24-USB", 0 },
+ { 0x43, "MOS-AL-082", 0 },
+ { 0x44, "MOS-AL-204", 0 },
+ { 0x45, "MOS-AV-204", 0 },
+ { 0x46, "MOS-AL-402", 0 },
+ { 0x47, "MOS-AV-402", 0 },
+ { 0x48, "LK082-12", 0 },
+ { 0x49, "VK402-12", 0 },
+ { 0x4A, "VK404-55", 0 },
+ { 0x4B, "LK402-25", 0 },
+ { 0x4C, "VK402-25", 0 },
+ { 0x00, NULL, 0 },
+};
+
/* Vars for the server core */
MODULE_EXPORT char *api_version = API_VERSION;
@@ -161,26 +218,6 @@ static void MtxOrb_cursorblink(Driver *drvthis, int on);
static void MtxOrb_cursor_goto(Driver *drvthis, int x, int y);
-/* Parse one key from the configfile */
-static char
-MtxOrb_parse_keypad_setting (Driver *drvthis, char *keyname, char default_value)
-{
- char return_val = 0;
- const char *s;
- char buf[255];
-
- s = drvthis->config_get_string(drvthis->name, keyname, 0, NULL);
- if (s != NULL) {
- strncpy(buf, s, sizeof(buf));
- buf[sizeof(buf)-1] = '\0';
- return_val = buf[0];
- } else {
- return_val = default_value;
- }
- return return_val;
-}
-
-
/**
* Initialize the driver.
* \param drvthis Pointer to driver structure.
@@ -253,6 +290,11 @@ MtxOrb_init (Driver *drvthis)
}
p->contrast = tmp;
+ /* Does it have an adjustable backlight */
+ tmp = drvthis->config_get_bool(drvthis->name, "hasAdjustableBacklight", 0, DEFAULT_ADJ_BACKLIGHT);
+ debug(RPT_INFO, "%s: hasAdjustableBacklight is '%d'", __FUNCTION__, tmp);
+ p->adjustable_backlight = tmp;
+
/* Which backlight brightness */
tmp = drvthis->config_get_int(drvthis->name, "Brightness", 0, DEFAULT_BRIGHTNESS);
debug(RPT_INFO, "%s: Brightness (in config) is '%d'", __FUNCTION__, tmp);
@@ -413,6 +455,8 @@ MtxOrb_init (Driver *drvthis)
MtxOrb_cursorblink(drvthis, DEFAULT_CURSORBLINK);
MtxOrb_set_contrast(drvthis, p->contrast);
MtxOrb_backlight(drvthis, DEFAULT_BACKLIGHT);
+ MtxOrb_get_info(drvthis);
+ report(RPT_INFO, "Display detected: %s", p->info);
report(RPT_DEBUG, "%s: init() done", drvthis->name);
@@ -748,28 +792,42 @@ MODULE_EXPORT void
MtxOrb_backlight (Driver *drvthis, int on)
{
PrivateData *p = drvthis->private_data;
- int promille = (on == BACKLIGHT_ON)
- ? p->brightness
- : p->offbrightness;
- if (IS_VKD_DISPLAY) {
- unsigned char out[5] = { '\xFE', 'Y', 0 };
+ if (p->adjustable_backlight) {
+
+ int promille = (on == BACKLIGHT_ON)
+ ? p->brightness
+ : p->offbrightness;
- /* map range [0, 1000] -> [0, 3] that the hardware understands */
- out[2] = (unsigned char) ((long) promille * 3 / 1000);
+ if (IS_VKD_DISPLAY) {
+ unsigned char out[5] = { '\xFE', 'Y', 0 };
- write(p->fd, out, 3);
+ /* map range [0, 1000] -> [0, 3] that the hardware understands */
+ out[2] = (unsigned char) ((long) promille * 3 / 1000);
+
+ write(p->fd, out, 3);
+ }
+ else {
+ unsigned char out[5] = { '\xFE', '\x99', 0 };
+
+ /* map range [0, 1000] -> [0, 255] that the hardware understands */
+ out[2] = (unsigned char) ((long) promille * 255 / 1000);
+
+ write(p->fd, out, 3);
+ }
+
+ debug(RPT_DEBUG, "MtxOrb: changed brightness to %d", promille);
}
else {
- unsigned char out[5] = { '\xFE', '\x99', 0 };
-
- /* map range [0, 1000] -> [0, 255] that the hardware understands */
- out[2] = (unsigned char) ((long) promille * 255 / 1000);
-
- write(p->fd, out, 3);
+ if (on == BACKLIGHT_ON) {
+ unsigned char out[4] = { '\xFE', 'B', '\0', 0};
+ write(p->fd, out, 3);
+ }
+ else {
+ unsigned char out[4] = { '\xFE', 'F', 0};
+ write(p->fd, out, 2);
+ }
}
-
- debug(RPT_DEBUG, "MtxOrb: changed brightness to %d", promille);
}
@@ -912,9 +970,9 @@ MtxOrb_cursor_goto(Driver *drvthis, int x, int y)
MODULE_EXPORT const char *
MtxOrb_get_info (Driver *drvthis)
{
- char in = 0;
- char tmp[255], buf[64];
- /* int i = 0; */
+ char tmp[10], buf[255];
+ int model = 0;
+ int i;
PrivateData *p = drvthis->private_data;
fd_set rfds;
@@ -925,115 +983,56 @@ MtxOrb_get_info (Driver *drvthis)
debug(RPT_DEBUG, "MtxOrb: get_info");
memset(p->info, '\0', sizeof(p->info));
- strcpy(p->info, "Matrix Orbital Driver ");
-
- /*
- * Read type of display
- */
-
- write(p->fd, "\x0FE" "7", 2);
+ strcat(p->info, "Matrix Orbital, ");
/* Watch fd to see when it has input. */
FD_ZERO(&rfds);
FD_SET(p->fd, &rfds);
+ /*
+ * Read type of display
+ * In query for its type, the display return a single byte value.
+ */
+ memset(tmp, '\0', sizeof(tmp));
+ write(p->fd, "\x0FE" "7", 2);
+
/* Wait the specified amount of time. */
tv.tv_sec = 0; /* seconds */
tv.tv_usec = 500; /* microseconds */
-/* retval = select(p->fd+1, &rfds, NULL, NULL, &tv); */
- retval = select(p->fd+1, &rfds, NULL, NULL, NULL);
+ retval = select(p->fd+1, &rfds, NULL, NULL, &tv);
if (retval) {
- if (read (p->fd, &in, 1) < 0) {
- syslog(LOG_WARNING, "MatrixOrbital driver: unable to read data");
- } else {
- switch (in) {
- case '\x01': strcat(p->info, "LCD0821 "); break;
- case '\x03': strcat(p->info, "LCD2021 "); break;
- case '\x04': strcat(p->info, "LCD1641 "); break;
- case '\x05': strcat(p->info, "LCD2041 "); break; /* VK202-25 ? */
- case '\x06': strcat(p->info, "LCD4021 "); break;
- case '\x07': strcat(p->info, "LCD4041 "); break;
- case '\x08': strcat(p->info, "LK202-25 "); break;
- case '\x09': strcat(p->info, "LK204-25 "); break;
- case '\x0A': strcat(p->info, "LK404-55 "); break;
- case '\x0B': strcat(p->info, "VFD2021 "); break;
- case '\x0C': strcat(p->info, "VFD2041 "); break;
- case '\x0D': strcat(p->info, "VFD4021 "); break;
- case '\x0E': strcat(p->info, "VK202-25 "); break;
- case '\x0F': strcat(p->info, "VK204-25 "); break;
- case '\x10': strcat(p->info, "GLC12232 "); break;
- case '\x11': strcat(p->info, "GLC12864 "); break;
- case '\x12': strcat(p->info, "GLC128128 "); break; /* ??? */
- case '\x13': strcat(p->info, "GLC24064 "); break;
- case '\x14': strcat(p->info, "GLK12864-25 "); break; /* ??? */
- case '\x15': strcat(p->info, "GLK24064-25 "); break;
- case '\x21': strcat(p->info, "GLK128128-25 "); break; /* ??? */
- case '\x22': strcat(p->info, "GLK12232-25-WBL "); break;
- case '\x24': strcat(p->info, "GLK12232-25-SM "); break;
- case '\x31': strcat(p->info, "LK404-AT "); break;
- case '\x32': strcat(p->info, "VFD1621 "); break; /* MOS-AV-162A ? */
- case '\x33': strcat(p->info, "LK402-12 "); break;
- case '\x34': strcat(p->info, "LK162-12 "); break;
- case '\x35': strcat(p->info, "LK204-25PC "); break;
- case '\x36': strcat(p->info, "LK202-24-USB "); break;
- case '\x37': strcat(p->info, "VK202-24-USB "); break;
- case '\x38': strcat(p->info, "LK204-24-USB "); break;
- case '\x39': strcat(p->info, "VK204-24-USB "); break;
- case '\x3A': strcat(p->info, "PK162-12 "); break;
- case '\x3B': strcat(p->info, "VK162-12 "); break;
- case '\x3C': strcat(p->info, "MOS-AP-162A "); break;
- case '\x3D': strcat(p->info, "PK202-25 "); break;
- case '\x3E': strcat(p->info, "MOS-AL-162A "); break;
- case '\x40': strcat(p->info, "MOS-AV-202A "); break;
- case '\x41': strcat(p->info, "MOS-AP-202A "); break;
- case '\x42': strcat(p->info, "PK202-24-USB "); break;
- case '\x43': strcat(p->info, "MOS-AL-082 "); break;
- case '\x44': strcat(p->info, "MOS-AL-204 "); break;
- case '\x45': strcat(p->info, "MOS-AV-204 "); break;
- case '\x46': strcat(p->info, "MOS-AL-402 "); break;
- case '\x47': strcat(p->info, "MOS-AV-402 "); break;
- case '\x48': strcat(p->info, "LK082-12 "); break;
- case '\x49': strcat(p->info, "VK402-12 "); break;
- case '\x4A': strcat(p->info, "VK404-55 "); break;
- case '\x4B': strcat(p->info, "LK402-25 "); break;
- case '\x4C': strcat(p->info, "VK402-25 "); break;
- default: /*snprintf(tmp, sizeof(tmp), "Unknown (%X) ", in); strcat(info, tmp); */
- break;
+ if (read(p->fd, &tmp, 1) < 0)
+ report(RPT_WARNING, "%s: unable to read data", drvthis->name);
+ else {
+ for (i = 0; modulelist[i].model != 0; i++) {
+ if (modulelist[i].model == tmp[0]) {
+ snprintf(buf, sizeof(buf), "Model: %s, ", modulelist[i].name);
+ strncat(p->info, buf, sizeof(p->info) - strlen(p->info) - 1);
+ model = (int) tmp[0];
+ break;
+ }
}
}
- } else
- syslog(LOG_WARNING, "MatrixOrbital driver: unable to read device type");
+ }
+ else
+ report(RPT_WARNING, "%s: unable to read device type", drvthis->name);
- /*
- * Read serial number of display
- */
-
- memset(tmp, '\0', sizeof(tmp));
- write(p->fd, "\x0FE" "5", 2);
-
- /* Wait the specified amount of time. */
- tv.tv_sec = 0; /* seconds */
- tv.tv_usec = 500; /* microseconds */
-
-/* retval = select(p->fd+1, &rfds, NULL, NULL, &tv); */
- retval = select(p->fd+1, &rfds, NULL, NULL, NULL);
-
- if (retval) {
- if (read(p->fd, &tmp, 2) < 0) {
- syslog(LOG_WARNING, "MatrixOrbital driver: unable to read data");
- } else {
- snprintf(buf, sizeof(buf), "Serial No: %ld ", (long int) tmp);
- strcat(p->info, buf);
- }
- } else
- syslog(LOG_WARNING, "MatrixOrbital driver: unable to read device serial number");
+ if (model == 0) {
+ snprintf(buf, sizeof(buf), "Unknown model (0x%02x), ", (int) tmp[0]);
+ strncat(p->info, buf, sizeof(p->info) - strlen(p->info) - 1);
+ }
/*
* Read firmware revision number
+ * TODO: check the format of a real display, because mine does not
+ * return anything.
+ * It is assumed that the display returns a two byte value giving
+ * the major/minor version number.
+ * NOTE: This is just a guess as the manual doesn't describe
+ * the returned format.
*/
-
memset(tmp, '\0', sizeof(tmp));
write(p->fd, "\x0FE" "6", 2);
@@ -1041,19 +1040,46 @@ MtxOrb_get_info (Driver *drvthis)
tv.tv_sec = 0; /* seconds */
tv.tv_usec = 500; /* microseconds */
-/* retval = select(p->fd+1, &rfds, NULL, NULL, &tv); */
- retval = select(p->fd+1, &rfds, NULL, NULL, NULL);
+ retval = select(p->fd+1, &rfds, NULL, NULL, &tv);
if (retval) {
- if (read(p->fd, &tmp, 2) < 0) {
- syslog(LOG_WARNING, "MatrixOrbital driver: unable to read data");
- } else {
- snprintf(buf, sizeof(buf), "Firmware Rev. %ld ", (long int) tmp);
- strcat(p->info, buf);
- }
- } else
- syslog(LOG_WARNING, "MatrixOrbital driver: unable to read device firmware revision");
+ if (read(p->fd, &tmp, 2) < 0)
+ report(RPT_WARNING, "%s: unable to read data", drvthis->name);
+
+ }
+ else
+ report(RPT_WARNING, "%s: unable to read device firmware revision", drvthis->name);
+ snprintf(buf, sizeof(buf), "Firmware Rev.: 0x%02x 0x%02x, ", tmp[0], tmp[1]);
+ strncat(p->info, buf, sizeof(p->info) - strlen(p->info) - 1);
+
+ /*
+ * Read serial number of display
+ * It is assumed that the display returns a two byte value giving
+ * the serial number.
+ * NOTE: This is just a guess as the manual doesn't describe
+ * the returned format, but for setting the serial number two bytes
+ * have to be supplied, so it is likely the display will return those.
+ */
+ memset(tmp, '\0', sizeof(tmp));
+ write(p->fd, "\x0FE" "5", 2);
+
+ /* Wait the specified amount of time. */
+ tv.tv_sec = 0; /* seconds */
+ tv.tv_usec = 500; /* microseconds */
+
+ retval = select(p->fd+1, &rfds, NULL, NULL, &tv);
+
+ if (retval) {
+ if (read(p->fd, &tmp, 2) < 0)
+ report(RPT_WARNING, "%s: unable to read data", drvthis->name);
+ }
+ else
+ report(RPT_WARNING, "%s: unable to read device serial number", drvthis->name);
+
+ snprintf(buf, sizeof(buf), "Serial No: 0x%02x 0x%02x", tmp[0], tmp[1]);
+ strncat(p->info, buf, sizeof(p->info) - strlen(p->info) - 1);
+
return p->info;
}
diff --git a/server/drivers/MtxOrb.h b/server/drivers/MtxOrb.h
index 32fadfa..1b8cf1d 100644
--- a/server/drivers/MtxOrb.h
+++ b/server/drivers/MtxOrb.h
@@ -4,6 +4,7 @@
#include "lcd.h"
#define DEFAULT_CONTRAST 480
+#define DEFAULT_ADJ_BACKLIGHT 1
#define DEFAULT_BRIGHTNESS 1000
#define DEFAULT_OFFBRIGHTNESS 0
#define DEFAULT_DEVICE "/dev/lcd"
@@ -15,6 +16,11 @@
#define DEFAULT_BACKLIGHT 1
#define DEFAULT_TYPE "lcd"
+typedef struct MtxOrbModule {
+ int model;
+ char *name;
+ int flags;
+} MtxOrbModuleEntry;
MODULE_EXPORT int MtxOrb_init (Driver *drvthis);
MODULE_EXPORT void MtxOrb_close (Driver *drvthis);