diff --git a/LCDd.conf b/LCDd.conf
index 41aa8dd..94194b3 100644
--- a/LCDd.conf
+++ b/LCDd.conf
@@ -46,10 +46,11 @@ DriverPath=server/drivers/
# The following drivers are supported:
# bayrad, CFontz, CFontzPacket, curses, CwLnx, ea65, EyeboxOne, g15, glcd,
# glcdlib, glk, hd44780, icp_a106, imon, imonlcd,, IOWarrior, irman, joy,
-# lb216, lcdm001, lcterm, linux_input, lirc, lis, MD8800, mdm166a, ms6931, mtc_s16209x,
-# MtxOrb, mx5000, NoritakeVFD, picolcd,, pyramid, rawserial, sdeclcd,
-# sed1330, sed1520, serialPOS, serialVFD, shuttleVFD, sli,, stv5730, svga,
-# t6963, text, tyan, ula200, vlsys_m428, xosd
+# lb216, lcdm001, lcterm, linux_input, lirc, lis, MD8800, mdm166a, ms6931,
+# mtc_s16209x, MtxOrb, mx5000, NoritakeVFD, Olimex_MOD_LCD1x9, picolcd,
+# pyramid, rawserial, sdeclcd, sed1330, sed1520, serialPOS, serialVFD,
+# shuttleVFD, sli, stv5730, svga, t6963, text, tyan, ula200, vlsys_m428,
+# xosd
Driver=curses
# Tells the driver to bind to the given interface. [default: 127.0.0.1]
@@ -986,6 +987,13 @@ Reboot=no
+## Olimex MOD-LCD1x9 driver ##
+[Olimex_MOD_LCD1x9]
+
+# device file of the i2c controler
+Device=/dev/i2c-0
+
+
## Mini-box.com picoLCD (usblcd) driver ##
[picolcd]
diff --git a/acinclude.m4 b/acinclude.m4
index 31929bc..23efa4c 100644
--- a/acinclude.m4
+++ b/acinclude.m4
@@ -13,16 +13,17 @@ AC_ARG_ENABLE(drivers,
[ icp_a106,imon,imonlcd,IOWarrior,irman,irtrans,]
[ joy,lb216,lcdm001,lcterm,linux_input,lirc,lis,MD8800,mdm166a,]
[ ms6931,mtc_s16209x,MtxOrb,mx5000,NoritakeVFD,]
- [ picolcd,pyramid,rawserial,sdeclcd,sed1330,sed1520,]
- [ serialPOS,serialVFD,shuttleVFD,sli,stv5730,SureElec,]
- [ svga,t6963,text,tyan,ula200,vlsys_m428,xosd]
+ [ Olimex_MOD_LCD1x9,picolcd,pyramid,rawserial,]
+ [ sdeclcd,sed1330,sed1520,serialPOS,serialVFD,]
+ [ shuttleVFD,sli,stv5730,SureElec,svga,t6963,text,]
+ [ tyan,ula200,vlsys_m428,xosd]
[ ]
[ 'all' compiles all drivers;]
[ 'all,!xxx,!yyy' de-selects previously selected drivers],
drivers="$enableval",
drivers=[bayrad,CFontz,CFontzPacket,curses,CwLnx,glk,lb216,lcdm001,MtxOrb,pyramid,text])
-allDrivers=[bayrad,CFontz,CFontzPacket,curses,CwLnx,ea65,EyeboxOne,g15,glcd,glcdlib,glk,hd44780,i2500vfd,icp_a106,imon,imonlcd,IOWarrior,irman,irtrans,joy,lb216,lcdm001,lcterm,linux_input,lirc,lis,MD8800,mdm166a,ms6931,mtc_s16209x,MtxOrb,mx5000,NoritakeVFD,picolcd,pyramid,sdeclcd,sed1330,sed1520,serialPOS,serialVFD,shuttleVFD,sli,stv5730,SureElec,svga,t6963,text,tyan,ula200,vlsys_m428,xosd,rawserial]
+allDrivers=[bayrad,CFontz,CFontzPacket,curses,CwLnx,ea65,EyeboxOne,g15,glcd,glcdlib,glk,hd44780,i2500vfd,icp_a106,imon,imonlcd,IOWarrior,irman,irtrans,joy,lb216,lcdm001,lcterm,linux_input,lirc,lis,MD8800,mdm166a,ms6931,mtc_s16209x,MtxOrb,mx5000,NoritakeVFD,Olimex_MOD_LCD1x9,picolcd,pyramid,sdeclcd,sed1330,sed1520,serialPOS,serialVFD,shuttleVFD,sli,stv5730,SureElec,svga,t6963,text,tyan,ula200,vlsys_m428,xosd,rawserial]
if test "$debug" = yes; then
allDrivers=["${allDrivers},debug"]
fi
@@ -404,6 +405,15 @@ dnl else
DRIVERS="$DRIVERS NoritakeVFD${SO}"
actdrivers=["$actdrivers NoritakeVFD"]
;;
+ Olimex_MOD_LCD1x9)
+ AC_CHECK_HEADERS([linux/i2c.h],[
+ DRIVERS="$DRIVERS Olimex_MOD_LCD1x9${SO}"
+ actdrivers=["$actdrivers Olimex_MOD_LCD1x9"]
+ ],[
+dnl else
+ AC_MSG_WARN([The Olimex MOD-LCD1x9 driver needs linux/i2c.h])
+ ])
+ ;;
rawserial)
DRIVERS="$DRIVERS rawserial${SO}"
actdrivers=["$actdrivers rawserial"]
diff --git a/docs/LCDd.8.in b/docs/LCDd.8.in
index 6028b91..34ea399 100644
--- a/docs/LCDd.8.in
+++ b/docs/LCDd.8.in
@@ -277,6 +277,9 @@ LCD display on the Logitech MX5000 keyboard
.B NoritakeVFD
Noritake VFD Device CU20045SCPB-T28A
.TP
+.B Olimex_MOD_LCD1x9
+Olimex MOD-LCD1x9 14 segment display
+.TP
.B rawserial
Dumps the entire framebuffer to the serial port at a configurable rate.
.TP
diff --git a/docs/lcdproc-user/drivers.docbook b/docs/lcdproc-user/drivers.docbook
index e9a83f7..b267438 100644
--- a/docs/lcdproc-user/drivers.docbook
+++ b/docs/lcdproc-user/drivers.docbook
@@ -40,6 +40,7 @@ well as the configuration of LCDd.
&MtxOrb;
&mx5000;
&NoritakeVFD;
+&Olimex_MOD_LCD1x9;
&rawserial;
&picolcd;
&pylcd;
diff --git a/docs/lcdproc-user/drivers/Makefile.am b/docs/lcdproc-user/drivers/Makefile.am
index 2efa0a9..9b29d5f 100644
--- a/docs/lcdproc-user/drivers/Makefile.am
+++ b/docs/lcdproc-user/drivers/Makefile.am
@@ -32,6 +32,7 @@ EXTRA_DIST = bayrad.docbook \
mtxorb.docbook \
mx5000.docbook \
NoritakeVFD.docbook \
+ Olimex_MOD_LCD1x9.docbook \
picolcd.docbook \
ppttrouble.docbook \
pylcd.docbook \
diff --git a/docs/lcdproc-user/drivers/Olimex_MOD_LCD1x9.docbook b/docs/lcdproc-user/drivers/Olimex_MOD_LCD1x9.docbook
new file mode 100644
index 0000000..a575f10
--- /dev/null
+++ b/docs/lcdproc-user/drivers/Olimex_MOD_LCD1x9.docbook
@@ -0,0 +1,32 @@
+
+The Olimex_MOD_LCD1x9 Driver
+
+
+The Olimex_MOD_LCD1x9 driver supports the popular MOD-LCD1x9 14 segment
+display on I2C lines. Currently this driver only supports Linux.
+
+
+
+
+Configuration in LCDd.conf
+
+
+[Olimex_MOD_LCD1x9]
+
+
+
+
+ Device =
+ DEVICE
+
+
+ Set the I2C device [default: /dev/i2c-0]
+
+
+
+
+
+
+
+
+
diff --git a/docs/lcdproc-user/lcdproc-user.docbook b/docs/lcdproc-user/lcdproc-user.docbook
index b3ec38d..16435bb 100644
--- a/docs/lcdproc-user/lcdproc-user.docbook
+++ b/docs/lcdproc-user/lcdproc-user.docbook
@@ -47,6 +47,7 @@
+
diff --git a/server/drivers/Makefile.am b/server/drivers/Makefile.am
index 8c5507e..d507e02 100644
--- a/server/drivers/Makefile.am
+++ b/server/drivers/Makefile.am
@@ -23,7 +23,7 @@ AM_LDFLAGS = @LDSHARED@
lcdexecbindir = $(pkglibdir)
lcdexecbin_PROGRAMS = @DRIVERS@
-EXTRA_PROGRAMS = bayrad CFontz CFontzPacket curses CwLnx debug ea65 EyeboxOne g15 glcd glcdlib glk hd44780 i2500vfd icp_a106 imon imonlcd IOWarrior irman irtrans joy lb216 lcdm001 lcterm linux_input lirc lis MD8800 mdm166a ms6931 mtc_s16209x MtxOrb mx5000 NoritakeVFD picolcd pyramid rawserial sdeclcd sed1330 sed1520 serialPOS serialVFD shuttleVFD sli stv5730 SureElec svga t6963 text tyan ula200 vlsys_m428 xosd
+EXTRA_PROGRAMS = bayrad CFontz CFontzPacket curses CwLnx debug ea65 EyeboxOne g15 glcd glcdlib glk hd44780 i2500vfd icp_a106 imon imonlcd IOWarrior irman irtrans joy lb216 lcdm001 lcterm linux_input lirc lis MD8800 mdm166a ms6931 mtc_s16209x MtxOrb mx5000 NoritakeVFD Olimex_MOD_LCD1x9 picolcd pyramid rawserial sdeclcd sed1330 sed1520 serialPOS serialVFD shuttleVFD sli stv5730 SureElec svga t6963 text tyan ula200 vlsys_m428 xosd
noinst_LIBRARIES = libLCD.a libbignum.a
g15_CFLAGS = @LIBUSB_CFLAGS@ $(AM_CFLAGS)
@@ -117,6 +117,7 @@ mtc_s16209x_SOURCES = lcd.h lcd_lib.h mtc_s16209x.c mtc_s16209x.h report.h
MtxOrb_SOURCES = lcd.h lcd_lib.h MtxOrb.c MtxOrb.h report.h adv_bignum.h
mx5000_SOURCES = lcd.h mx5000.c mx5000.h report.h
NoritakeVFD_SOURCES = lcd.h lcd_lib.h NoritakeVFD.c NoritakeVFD.h report.h adv_bignum.h
+Olimex_MOD_LCD1x9_SOURCES = lcd.h report.h i2c.h i2c.c Olimex_MOD_LCD1x9.h Olimex_MOD_LCD1x9.c Olimex_MOD_LCD1x9_font.h
rawserial_SOURCES = lcd.h rawserial.c rawserial.h
picolcd_SOURCES = lcd.h picolcd.h picolcd.c report.h
pyramid_SOURCES = lcd.h pylcd.c pylcd.h
diff --git a/server/drivers/Olimex_MOD_LCD1x9.c b/server/drivers/Olimex_MOD_LCD1x9.c
new file mode 100644
index 0000000..13a8371
--- /dev/null
+++ b/server/drivers/Olimex_MOD_LCD1x9.c
@@ -0,0 +1,227 @@
+/** \file server/drivers/Olimex_MOD_LCD1x9.c
+ * LCDd \c Olimex_MOD_LCD1x9 driver for MOD-LCD1x9 from Olimex.
+ * This display uses a PCF857DU style controller.
+ */
+
+/* Copyright (C) 2015 Harald Geyer
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301
+ */
+
+#ifdef HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#include "lcd.h"
+#include "report.h"
+
+#include
+#include
+#include
+#include
+#include
+
+#include "i2c.h"
+#include "Olimex_MOD_LCD1x9_font.h"
+
+#define BUS_ADDRESS 0x38
+#define LEN_INIT_SEQ 24
+
+/** private data for the \c Olimex_MOD_LCD1x9 driver */
+typedef struct olimex1x9_private_data {
+ I2CHandle *dev; /**< handle of the i2c device */
+ uint16_t buf[11]; /**< header + frame buffer */
+} PrivateData;
+
+/* Vars for the server core */
+MODULE_EXPORT char *api_version = API_VERSION;
+MODULE_EXPORT int stay_in_foreground = 0;
+MODULE_EXPORT int supports_multiple = 1;
+MODULE_EXPORT char *symbol_prefix = "olimex1x9_";
+
+/**
+ * Initialize the driver.
+ * \param drvthis Pointer to driver structure.
+ * \retval 0 Success.
+ * \retval <0 Error.
+ */
+MODULE_EXPORT int
+olimex1x9_init (Driver *drvthis)
+{
+ PrivateData *p;
+ const char *configvalue;
+ char buffer[LEN_INIT_SEQ];
+ uint8_t *preamble;
+ int i;
+
+ /* Allocate and store private data */
+ p = (PrivateData *) malloc(sizeof(PrivateData));
+ if (p == NULL)
+ return -1;
+ if (drvthis->store_private_ptr(drvthis, p))
+ return -1;
+
+ configvalue = drvthis->config_get_string(drvthis->name, "Device", 0, I2C_DEFAULT_DEVICE);
+ p->dev = i2c_open(configvalue, BUS_ADDRESS);
+ if (!p->dev) {
+ report(RPT_ERR, "open i2c device '%s' failed: %s", configvalue, strerror(errno));
+ return(-1);
+ }
+
+ buffer[0] = 0xC8; /* Mode register */
+ buffer[1] = 0xF0; /* Blink register */
+ buffer[2] = 0xE0; /* Device select register */
+ buffer[3] = 0x00; /* Point register */
+ for (i = 4; i < LEN_INIT_SEQ; ++i)
+ buffer[i] = 0xFF;
+
+ if (i2c_write(p->dev, buffer, LEN_INIT_SEQ) < 0) {
+ report(RPT_ERR, "I2C: %s: sending of initialization data failed: %s", configvalue, strerror(errno));
+ return (-1);
+ }
+
+ preamble = (uint8_t *) p->buf;
+ preamble[0] = 0xE0; /* Device select register */
+ preamble[1] = 0x00; /* Point register */
+
+ report(RPT_DEBUG, "%s: init() done", drvthis->name);
+
+ return 0;
+}
+
+
+/**
+ * Close the driver (do necessary clean-up).
+ * \param drvthis Pointer to driver structure.
+ */
+MODULE_EXPORT void
+olimex1x9_close (Driver *drvthis)
+{
+ PrivateData *p = drvthis->private_data;
+
+ if (p != NULL) {
+ i2c_close(p->dev);
+ free(p);
+ }
+ drvthis->store_private_ptr(drvthis, NULL);
+}
+
+
+/**
+ * Return the display width in characters.
+ * \param drvthis Pointer to driver structure.
+ * \return Number of characters the display is wide.
+ */
+MODULE_EXPORT int
+olimex1x9_width (Driver *drvthis)
+{
+ return 9;
+}
+
+
+/**
+ * Return the display height in characters.
+ * \param drvthis Pointer to driver structure.
+ * \return Number of characters the display is high.
+ */
+MODULE_EXPORT int
+olimex1x9_height (Driver *drvthis)
+{
+ return 1;
+}
+
+
+/**
+ * Clear the screen.
+ * \param drvthis Pointer to driver structure.
+ */
+MODULE_EXPORT void
+olimex1x9_clear (Driver *drvthis)
+{
+ PrivateData *p = drvthis->private_data;
+
+ /* Don't overwrite the preamble part of the buffer */
+ memset(&p->buf[1], 0, sizeof(p->buf) - sizeof(p->buf[0]));
+}
+
+
+/**
+ * Flush data on screen to the display.
+ * \param drvthis Pointer to driver structure.
+ */
+MODULE_EXPORT void
+olimex1x9_flush (Driver *drvthis)
+{
+ PrivateData *p = drvthis->private_data;
+
+ i2c_write(p->dev, p->buf, sizeof(p->buf));
+}
+
+
+/**
+ * Print a string on the screen at position (x,y).
+ * The upper-left corner is (1,1), the lower-right corner is (9, 1).
+ * \param drvthis Pointer to driver structure.
+ * \param x Horizontal character position (column).
+ * \param y Vertical character position (row).
+ * \param string String that gets written.
+ */
+MODULE_EXPORT void
+olimex1x9_string (Driver *drvthis, int x, int y, const unsigned char string[])
+{
+ PrivateData *p = drvthis->private_data;
+ int pos = 10 - x; /* The left side is on the upper end of the buffer */
+ int count = 0;
+
+ while (string[count]) {
+ switch (string[count]) {
+ case '\b': /* Allow composition of characters */
+ ++pos;
+ break;
+ case ':': /* We can't display a proper ':' */
+ case '.': /* Use the dot between characters if possible */
+ if (pos < 9 &&
+ !(p->buf[pos+1] & htons(olimex1x9_font['.'])))
+ ++pos;
+ /* fall through */
+ default:
+ if (pos >= 1 && pos <= 9) /* no buffer overflow */
+ p->buf[pos] |=
+ htons(olimex1x9_font[string[count]]);
+ --pos;
+ }
+ ++count;
+ }
+}
+
+
+/**
+ * Print a character on the screen at position (x,y).
+ * The upper-left corner is (1,1), the lower-right corner is (9, 1).
+ * \param drvthis Pointer to driver structure.
+ * \param x Horizontal character position (column).
+ * \param y Vertical character position (row).
+ * \param c Character that gets written.
+ */
+MODULE_EXPORT void
+olimex1x9_chr (Driver *drvthis, int x, int y, unsigned char c)
+{
+ PrivateData *p = drvthis->private_data;
+
+ if (x < 1 || x > 9)
+ return;
+
+ p->buf[10-x] |= olimex1x9_font[c];
+}
diff --git a/server/drivers/Olimex_MOD_LCD1x9.h b/server/drivers/Olimex_MOD_LCD1x9.h
new file mode 100644
index 0000000..87d5c66
--- /dev/null
+++ b/server/drivers/Olimex_MOD_LCD1x9.h
@@ -0,0 +1,13 @@
+#ifndef OLIMEX_LCD1x9_H
+#define OLIMEX_LCD1x9_H
+
+MODULE_EXPORT int olimex1x9_init (Driver *drvthis);
+MODULE_EXPORT void olimex1x9_close (Driver *drvthis);
+MODULE_EXPORT int olimex1x9_width (Driver *drvthis);
+MODULE_EXPORT int olimex1x9_height (Driver *drvthis);
+MODULE_EXPORT void olimex1x9_clear (Driver *drvthis);
+MODULE_EXPORT void olimex1x9_flush (Driver *drvthis);
+MODULE_EXPORT void olimex1x9_string (Driver *drvthis, int x, int y, const char string[]);
+MODULE_EXPORT void olimex1x9_chr (Driver *drvthis, int x, int y, char c);
+
+#endif
diff --git a/server/drivers/Olimex_MOD_LCD1x9_font.h b/server/drivers/Olimex_MOD_LCD1x9_font.h
new file mode 100644
index 0000000..aec1739
--- /dev/null
+++ b/server/drivers/Olimex_MOD_LCD1x9_font.h
@@ -0,0 +1,131 @@
+#ifndef OLIMEX_LCD1x9_FONT_H
+#define OLIMEX_LCD1x9_FONT_H
+
+uint16_t olimex1x9_font[256] = {
+ 0x0000,
+ 0x0000,
+ 0x0000,
+ 0x0000,
+ 0x0000,
+ 0x0000,
+ 0x0000,
+ 0x0000,
+ 0x0000,
+ 0x0000,
+ 0x0000,
+ 0x0000,
+ 0x0000,
+ 0x0000,
+ 0x0000,
+ 0x0000,
+ 0x0000,
+ 0x0000,
+ 0x0000,
+ 0x0000,
+ 0x0000,
+ 0x0000,
+ 0x0000,
+ 0x0000,
+ 0x0000,
+ 0x0000,
+ 0x0000,
+ 0x0000,
+ 0x0000,
+ 0x0000,
+ 0x0000,
+ 0x0000,
+ 0x0000, /* ' ' */
+ 0x9800, /* '!' */
+ 0x0101, /* '"' */
+ 0x5054, /* '#' -- use this for a degree sign */
+ 0x0000, /* '$' */
+ 0x0000, /* '%' */
+ 0x0000, /* '&' */
+ 0x0100, /* ''' */
+ 0x0096, /* '(' */
+ 0x9090, /* ')' */
+ 0x6761, /* '*' */
+ 0x4640, /* '+' */
+ 0x0020, /* ',' */
+ 0x4040, /* '-' */
+ 0x0800, /* '.' */
+ 0x0120, /* '/' */
+ 0x9096, /* '0' */
+ 0x9000, /* '1' */
+ 0x50d2, /* '2' */
+ 0xd0d0, /* '3' */
+ 0xd044, /* '4' */
+ 0xc0d4, /* '5' */
+ 0xc0d6, /* '6' */
+ 0x9010, /* '7' */
+ 0xd0d6, /* '8' */
+ 0xd0d4, /* '9' */
+ 0x0800, /* ':' same as '.' */
+ 0x0000, /* ';' */
+ 0x2100, /* '<' */
+ 0x0000, /* '=' */
+ 0x0021, /* '>' */
+ 0x0000, /* '?' */
+ 0xffff, /* '@' */
+ 0xd056, /* 'A' */
+ 0x21d6, /* 'B' */
+ 0x0096, /* 'C' */
+ 0x0027, /* 'D' */
+ 0x00d6, /* 'E' */
+ 0x4056, /* 'F' */
+ 0xc0d6, /* 'G' */
+ 0xd046, /* 'H' */
+ 0x0688, /* 'I' */
+ 0x9080, /* 'J' */
+ 0x2146, /* 'K' */
+ 0x0086, /* 'L' */
+ 0x9107, /* 'M' */
+ 0xb007, /* 'N' */
+ 0x9096, /* 'O' */
+ 0x5056, /* 'P' */
+ 0xb096, /* 'Q' */
+ 0x7056, /* 'R' */
+ 0xc0d4, /* 'S' */
+ 0x0610, /* 'T' */
+ 0x9086, /* 'U' */
+ 0x0126, /* 'V' */
+ 0xb026, /* 'W' */
+ 0x2121, /* 'X' */
+ 0xd0c4, /* 'Y' */
+ 0x01b0, /* 'Z' */
+ 0x0096, /* '[' */
+ 0x2001, /* '\' */
+ 0x9090, /* ']' */
+ 0x0010, /* '^' */
+ 0x0080, /* '_' */
+ 0x0400, /* '`' */
+ 0x02c2, /* 'a' */
+ 0xc0c6, /* 'b' */
+ 0x00c2, /* 'c' */
+ 0xd0c2, /* 'd' */
+ 0x00e2, /* 'e' */
+ 0x0056, /* 'f' */
+ 0xe080, /* 'g' */
+ 0xc046, /* 'h' */
+ 0x8000, /* 'i' */
+ 0x9080, /* 'j' */
+ 0x6046, /* 'k' */
+ 0x0026, /* 'l' */
+ 0xc242, /* 'm' */
+ 0xc042, /* 'n' */
+ 0xc0c2, /* 'o' */
+ 0x5056, /* 'p' */
+ 0xd054, /* 'q' */
+ 0x0042, /* 'r' */
+ 0x6080, /* 's' */
+ 0x00c6, /* 't' */
+ 0x8082, /* 'u' */
+ 0x0022, /* 'v' */
+ 0xa022, /* 'w' */
+ 0x2121, /* 'x' */
+ 0xa080, /* 'y' */
+ 0x00e0, /* 'z' */
+ 0x0000
+};
+
+#endif