LCDproc development and user support list

Text archives Help


Fwd: Re: [Lcdproc] Re: VLSYS L.I.S 2005 Driver written


Chronological Thread 
  • From: daryl AT rainyday.ca (Daryl F)
  • Subject: Fwd: Re: [Lcdproc] Re: VLSYS L.I.S 2005 Driver written
  • Date: Mon May 14 04:23:01 2007

Peter Marschall wrote:
> Hi Daryl,
>
> On Tuesday, 8. May 2007 02:01, Daryl F wrote:
>> Here's the patch for the VLSYS L.I.S driver. It is for lcdproc-0.5.1.
>> The code isn't really pretty. I had to do some guessing since VLSYS
>> won't reveal the inner workings. But it works.
>
> Thanks for the patch.
>
> I have had a quick look at it, which made me consider it as not
> yet ready for inclusion into the LCDproc CVS.
>
> Here are my reasons:
> - the patch is based against 0.5.1
> Please re-base it against LCDproc CVS available at
> http://lcdproc.sourceforge.net/nightly/lcdproc-CVS-current.tar.gz
> - it contains whole files (which are newer in CVS than in your version)
> Please reduce the patch to the changes only.
> - there are issues with it posted on the mailing list
> See paul_c's and Todd Luliak's posts.
> Please try to address the issues mentioned.
> It is not acceptable for a patch to break compilation of LCdproc
> (and pleae do not expect the maintainer [who does not have
> the hardware] why).
> - It lacks documentation completely
> Please add doxygen documentation to the source (see the
> IOWarrior or CFontzPacket drivers as an example) and
> add the other missing parts (see
> http://lcdproc.sourceforge.net/docs/current-dev.html#documentation
> what is expected)
> Once these issues are addressed, I'll happily commit the drivr to CVS.
>
> This may sound a bit harsh, but it is not ment that way.
> It is only meant as a remnider what is expected of an
> LCDproc driver: not only compile-able and working code,
> but also documentation accompanying it, so that users
> that obviously do not have such in-depth knowledge
> about the driver internals as you, the author,
> can get the driver to run easily.
>
> Thanks
> Peter
>
>

Hi Peter,

It didn't sound harsh at all. I completely missed updating the doxygen
documents. I followed the instruction on documenting at the Sourceforge
link you gave me.

I obtained the latest CVS tarball and retrofitted my changes to it as
you requested.

I addressed one of the issues from paul_c and Todd Luliak, namely I
added a test for the correct level of support in libftdi to acinclude.m4.

The other issue of 'configure: error: Unknown driver lis' will already
be handled when compiling from CVS due to the use of `sh autogen.sh` to
run aclocal, automake, and autoconf. That also reduces the size of my
patch greatly since I don't have to provide an update to the configure
script, just patch acinclude.m4.

If I need to make any more changes I look forward to your requests.

Thanks for bearing with me in my first attempt at contributing to open
source.

Thanks,
Daryl

diff -ruN lcdproc-CVS-current-20070513/LCDd.conf
lcdproc-CVS-current-20070513-lis/LCDd.conf
--- lcdproc-CVS-current-20070513/LCDd.conf 2007-05-06 02:00:13.000000000
-0500
+++ lcdproc-CVS-current-20070513-lis/LCDd.conf 2007-05-13 22:09:19.000000000
-0500
@@ -619,6 +619,11 @@
#prog=lcdd


+## LIS MCE 2005 driver ##
+[lis]
+Device=/dev/ttyUSB0
+Brightness=1000
+

##The driver for the VFD of the Medion MD8800 PC ##
[MD8800]
diff -ruN lcdproc-CVS-current-20070513/acinclude.m4
lcdproc-CVS-current-20070513-lis/acinclude.m4
--- lcdproc-CVS-current-20070513/acinclude.m4 2007-05-06 02:00:13.000000000
-0500
+++ lcdproc-CVS-current-20070513-lis/acinclude.m4 2007-05-13
17:24:44.000000000 -0500
@@ -7,7 +7,7 @@
[ Possible drivers are:]
[
bayrad,CFontz,CFontz633,CFontzPacket,curses,CwLnx,ea65,]
[
EyeboxOne,g15,glcdlib,glk,hd44780,icp_a106,imon,IOWarrior,]
- [
irman,joy,lb216,lcdm001,lcterm,lirc,MD8800,ms6931,]
+ [
irman,joy,lb216,lcdm001,lcterm,lirc,lis,MD8800,ms6931,]
[
mtc_s16209x,MtxOrb,NoritakeVFD,picolcd,pyramid,sed1330]
[
sed1520,serialPOS,serialVFD,sli,stv5730,svga,t6963,text,]
[ tyan,ula200,xosd]
@@ -16,7 +16,7 @@
drivers="$enableval",

drivers=[bayrad,CFontz,CFontz633,curses,CwLnx,glk,lb216,lcdm001,MtxOrb,pyramid,text])

-allDrivers=[bayrad,CFontz,CFontz633,CFontzPacket,curses,CwLnx,ea65,EyeboxOne,g15,glcdlib,glk,hd44780,icp_a106,imon,IOWarrior,irman,joy,lb216,lcdm001,lcterm,lirc,MD8800,ms6931,mtc_s16209x,MtxOrb,NoritakeVFD,picolcd,pyramid,sed1330,sed1520,serialPOS,serialVFD,sli,stv5730,svga,t6963,text,tyan,ula200,xosd]
+allDrivers=[bayrad,CFontz,CFontz633,CFontzPacket,curses,CwLnx,ea65,EyeboxOne,g15,glcdlib,glk,hd44780,icp_a106,imon,IOWarrior,irman,joy,lb216,lcdm001,lcterm,lirc,lis,MD8800,ms6931,mtc_s16209x,MtxOrb,NoritakeVFD,picolcd,pyramid,sed1330,sed1520,serialPOS,serialVFD,sli,stv5730,svga,t6963,text,tyan,ula200,xosd]

drivers=`echo $drivers | sed -e 's/,/ /g'`

@@ -256,6 +256,30 @@
AC_MSG_WARN([The lirc driver needs the lirc
client library])
])
;;
+ lis)
+ AC_CHECK_HEADERS([usb.h ftdi.h],[
+ AC_CHECK_LIB(ftdi, main,[
+ LIBFTDI="-lusb -lftdi"
+ DRIVERS="$DRIVERS lis${SO}"
+ actdrivers=["$actdrivers lis"]
+ ],[
+dnl else
+ AC_MSG_WARN([The lis driver needs the
ftdi library])
+ ])
+ ],[
+dnl else
+ AC_MSG_WARN([The lis driver needs ftdi.h and
usb.h])
+ ])
+ AC_CACHE_CHECK([for ftdi_setdtr() in libftdi],
ac_cv_ftdi_setdtr,
+ [oldlibs="$LIBS"
+ LIBS="$LIBS $LIBFTDI"
+ AC_TRY_LINK_FUNC(ftdi_setdtr, ac_cv_ftdi_setdtr=yes,
ac_cv_ftdi_setdtr=no)
+ LIBS="$oldlibs"
+ ])
+ if test "$ac_cv_ftdi_setdtrt" = no; then
+ AC_MSG_WARN([Upgrade to libftdi >= version
0.8])
+ fi
+ ;;
MD8800)
DRIVERS="$DRIVERS MD8800${SO}"
actdrivers=["$actdrivers MD8800"]
diff -ruN lcdproc-CVS-current-20070513/docs/LCDd.8.in
lcdproc-CVS-current-20070513-lis/docs/LCDd.8.in
--- lcdproc-CVS-current-20070513/docs/LCDd.8.in 2007-04-01 02:00:18.000000000
-0500
+++ lcdproc-CVS-current-20070513-lis/docs/LCDd.8.in 2007-05-13
22:10:59.000000000 -0500
@@ -189,6 +189,9 @@
.B lirc
Infrared (input)
.TP
+.B lis
+L.I.S MCE 2005 20x2 VFD (http://vlsys.co.kr)
+.TP
.B MD8800
VFD displays in Medion MD8800 PCs
.TP
diff -ruN lcdproc-CVS-current-20070513/docs/lcdproc-user/drivers/lis.docbook
lcdproc-CVS-current-20070513-lis/docs/lcdproc-user/drivers/lis.docbook
--- lcdproc-CVS-current-20070513/docs/lcdproc-user/drivers/lis.docbook
1969-12-31 18:00:00.000000000 -0600
+++ lcdproc-CVS-current-20070513-lis/docs/lcdproc-user/drivers/lis.docbook
2007-05-13 22:27:07.000000000 -0500
@@ -0,0 +1,50 @@
+<sect1 id="lis-howto">
+<title>The lis Driver</title>
+
+<para>
+ This section talks about using LCDproc with the VLSystem L.I.S
+ MCE 2005 Vacuum Flourescent Display based on the FTDI USB-to-serial
+ converter, the Microchip PIC-16F716 microcontroller, and
+ the NEC UPD16314 display driver that can be obtained at
+ <ulink url="http://www.vlsys.co.kr";>VLSys</ulink>.
+</para>
+
+<!-- ## VLSys lis driver ## -->
+<sect2 id="lis-config">
+<title>Configuration in LCDd.conf</title>
+
+<sect3 id="lis-config-section">
+<title>[lis]</title>
+
+<variablelist>
+<varlistentry>
+ <term>
+ <command>Brightness=</command>
+ <arg choice="plain"><replaceable>BRIGHTNESS</replaceable></arg>
+ </term>
+ <listitem><para>
+ Set the initial brightness [default: <literal>1000</literal>; legal:
<literal>0</literal> - <literal>1000</literal>]
+ </para></listitem>
+ </term>
+ <listitem><para>
+ Select the LCD size [default: <literal>20x4</literal>]
+ </para></listitem>
+</varlistentry>
+
+<varlistentry>
+ <term>
+ <command>Device=</command>
+ <arg choice="plain"><replaceable>DEVICE</replaceable></arg>
+ </term>
+ <listitem><para>
+ USB device to use. Usual values are <filename>/dev/ttyUSB0</filename>,
<filename>/dev/ttyUSB1</filename>, etc.
+ [default: <filename>/dev/ttyUSB0</filename>].
+ </para></listitem>
+</varlistentry>
+</variablelist>
+
+</sect3>
+
+</sect2>
+
+</sect1>
diff -ruN lcdproc-CVS-current-20070513/docs/lcdproc-user/drivers.docbook
lcdproc-CVS-current-20070513-lis/docs/lcdproc-user/drivers.docbook
--- lcdproc-CVS-current-20070513/docs/lcdproc-user/drivers.docbook
2007-03-19 02:00:24.000000000 -0500
+++ lcdproc-CVS-current-20070513-lis/docs/lcdproc-user/drivers.docbook
2007-05-13 22:30:37.000000000 -0500
@@ -28,6 +28,7 @@
&lcdm001;
&lcterm;
&lirc;
+&lis;
&MD8800;
&ms6931;
&mtc_s16209x;
diff -ruN lcdproc-CVS-current-20070513/docs/lcdproc-user/lcdproc-user.docbook
lcdproc-CVS-current-20070513-lis/docs/lcdproc-user/lcdproc-user.docbook
--- lcdproc-CVS-current-20070513/docs/lcdproc-user/lcdproc-user.docbook
2007-03-19 02:00:24.000000000 -0500
+++ lcdproc-CVS-current-20070513-lis/docs/lcdproc-user/lcdproc-user.docbook
2007-05-13 22:29:43.000000000 -0500
@@ -34,6 +34,7 @@
<!ENTITY lcdm001 SYSTEM "drivers/lcdm001.docbook">
<!ENTITY lcterm SYSTEM "drivers/lcterm.docbook">
<!ENTITY lirc SYSTEM "drivers/lircin.docbook">
+ <!ENTITY lis SYSTEM "drivers/lis.docbook">
<!ENTITY MD8800 SYSTEM "drivers/MD8800.docbook">
<!ENTITY ms6931 SYSTEM "drivers/ms6931.docbook">
<!ENTITY mtc_s16209x SYSTEM "drivers/mtc_s16209x.docbook">
diff -ruN lcdproc-CVS-current-20070513/server/drivers/Makefile.am
lcdproc-CVS-current-20070513-lis/server/drivers/Makefile.am
--- lcdproc-CVS-current-20070513/server/drivers/Makefile.am 2007-05-06
02:00:15.000000000 -0500
+++ lcdproc-CVS-current-20070513-lis/server/drivers/Makefile.am 2007-05-13
17:42:47.000000000 -0500
@@ -19,7 +19,7 @@
#LIBS =

pkglib_PROGRAMS = @DRIVERS@
-EXTRA_PROGRAMS = bayrad CFontz CFontz633 CFontzPacket curses CwLnx ea65
EyeboxOne g15 glcdlib glk hd44780 icp_a106 imon IOWarrior irman joy lb216
lcdm001 lcterm lirc MD8800 ms6931 mtc_s16209x MtxOrb NoritakeVFD picolcd
pyramid sed1330 sed1520 serialPOS serialVFD stv5730 svga t6963 text tyan sli
ula200 xosd
+EXTRA_PROGRAMS = bayrad CFontz CFontz633 CFontzPacket curses CwLnx ea65
EyeboxOne g15 glcdlib glk hd44780 icp_a106 imon IOWarrior irman joy lb216
lcdm001 lcterm lirc lis MD8800 ms6931 mtc_s16209x MtxOrb NoritakeVFD picolcd
pyramid sed1330 sed1520 serialPOS serialVFD stv5730 svga t6963 text tyan sli
ula200 xosd
noinst_LIBRARIES = libLCD.a libbignum.a

IOWarrior_CFLAGS = @libusb_cflags@ $(AM_CFLAGS)
@@ -42,6 +42,7 @@
irman_LDADD = @LIBIRMAN@
lcterm_LDADD = libLCD.a
lirc_LDADD = @LIBLIRC_CLIENT@
+lis_LDADD = libLCD.a @LIBFTDI@
MD8800_LDADD = libLCD.a
mtc_s16209x_LDADD = libLCD.a
MtxOrb_LDADD = libLCD.a libbignum.a
@@ -83,6 +84,7 @@
lcdm001_SOURCES = lcd.h lcdm001.c lcdm001.h report.h
lcterm_SOURCES = lcd.h lcd_lib.h lcterm.c lcterm.h report.h
lirc_SOURCES = lcd.h lircin.c lircin.h report.h
+lis_SOURCES = lcd.h lcd_lib.h lis.h lis.c report.h
MD8800_SOURCES = lcd.h lcd_lib.h MD8800.c MD8800.h report.h
ms6931_SOURCES = lcd.h lcd_lib.h ms6931.h ms6931.c report.h
mtc_s16209x_SOURCES = lcd.h lcd_lib.h mtc_s16209x.c mtc_s16209x.h report.h
diff -ruN lcdproc-CVS-current-20070513/server/drivers/lis.c
lcdproc-CVS-current-20070513-lis/server/drivers/lis.c
--- lcdproc-CVS-current-20070513/server/drivers/lis.c 1969-12-31
18:00:00.000000000 -0600
+++ lcdproc-CVS-current-20070513-lis/server/drivers/lis.c 2007-05-07
09:53:14.000000000 -0500
@@ -0,0 +1,1465 @@
+/*
+ * LIS driver for lcdproc
+ * For the L.I.S MCE vacuum fluorescent display from vlsys.co.kr
+ * 20x2 display using NEC UPD16314 driver and FTDI FT232RQ USB-to-serial
+ * converter.
+ *
+ * This driver uses the libftdi library to interface to the FTDI chip. Make
+ * sure kernel module ftdi_sio doesn't claim the device.
+ *
+ * Based on the ula200 driver Copyright (C) 2006, Bernhard Walle
+ * and the CrystalFontz 633 driver Copyright (C) 2002 David GLAUDE
+ *
+ * Copyright (c) 2007, Daryl Fonseca-Holt
<wyatt AT prairieturtle.ca>
+ *
+ * This file is released under the GNU General Public License. Refer to the
+ * COPYING file distributed with this package.
+ *
+ *
+ *
+ *
+ */
+
+/*
+ * Notes on this driver
+ *
+ * vlsys is unwilling to provide information about the protocol for this
+ * device. This driver was developed entirely by analyzing the USB data
+ * flowing between the host and the device on a WinXP machine. As such it
+ * probably isn't an optimal driver but it works.
+ *
+ * Using a dirty buffer/clean buffer approach was useless since I could
+ * not determine how to write to specific columns. The only thing selectable
+ * was which line would be written at column 1.
+ */
+
+#include <stdlib.h>
+#include <stdio.h>
+#include <unistd.h>
+#include <termios.h>
+#include <fcntl.h>
+#include <string.h>
+#include <errno.h>
+#include <syslog.h>
+
+#include <usb.h>
+#include <ftdi.h>
+
+#include <sys/syscall.h>
+
+#ifdef HAVE_CONFIG_H
+# include "config.h"
+#endif
+
+#include "lcd.h"
+#include "lis.h"
+#include "report.h"
+#include "lcd_lib.h"
+#include "timing.h"
+
+void lis_test(Driver *drvthis);
+
+/* 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 = "lis_";
+
+
+///////////////////////////////////////////////////////////////////////////////
+// constants
+//
+#define DISPLAY_VENDOR_ID 0x0403
+#define DISPLAY_PRODUCT_ID 0x6001
+
+#define CELLWIDTH 5
+#define CELLHEIGHT 8
+
+#define DEFAULT_BRIGHTNESS 750
+
+/*
+ * Charactar mapping for UPD16314 device by Daryl Fonseca-Holt
+ *
<wyatt AT prairieturtle.ca>
taken from Mark Haemmerling's HD44780 table.
+ * Character mapping for HD44780 devices by Mark Haemmerling
<mail AT markh.de>.
+ *
+ * Translates ISO 8859-1 to any HD44780 charset.
+ *
+ * Charmap selector (C) 2006 Pillon Matteo
<matteo.pillon AT email.it>
+ *
+ * This file is released under the GNU General Public License.
+ * Refer to the COPYING file distributed with this package.
+ */
+
+/*
+ * UPD16314 table
+ *
+ */
+
+const unsigned char UPD16314_charmap[] = {
+ /* #0 */
+ 0, 1, 2, 3, 4, 5, 6, 7,
+ 8, 9, 10, 11, 12, 13, 14, 15,
+ 16, 17, 18, 19, 20, 21, 22, 23,
+ 24, 25, 26, 27, 28, 29, 30, 31,
+ /* #32 */
+ 32, 33, 34, 35, 36, 37, 38, 39,
+ 40, 41, 42, 43, 44, 45, 46, 47,
+ 48, 49, 50, 51, 52, 53, 54, 55,
+ 56, 57, 58, 59, 60, 61, 62, 63,
+ /* #64 */
+ 64, 65, 66, 67, 68, 69, 70, 71,
+ 72, 73, 74, 75, 76, 77, 78, 79,
+ 80, 81, 82, 83, 84, 85, 86, 87,
+ 88, 89, 90, 91, 47, 93, 94, 95,
+ /* #96 */
+ 96, 97, 98, 99, 100, 101, 102, 103,
+ 104, 105, 106, 107, 108, 109, 110, 111,
+ 112, 113, 114, 115, 116, 117, 118, 119,
+ 120, 121, 122, 123, 124, 125, 126, 127,
+ /* #128 */
+ 128, 129, 130, 131, 132, 133, 134, 135,
+ 136, 137, 138, 139, 140, 141, 142, 143,
+ 144, 145, 146, 147, 148, 149, 150, 151,
+ 152, 153, 154, 155, 156, 157, 158, 159,
+ /* #160 */
+ 160, 33, 236, 237, 164, 92, 124, 167,
+ 168, 169, 170, 171, 172, 173, 174, 175,
+ 176, 177, 178, 179, 180, 181, 182, 183,
+ 184, 185, 186, 187, 188, 189, 190, 191,
+ /* #192 */
+ 192, 193, 194, 195, 196, 197, 198, 199,
+ 200, 201, 202, 203, 204, 205, 206, 207,
+ 208, 209, 210, 211, 212, 213, 214, 215,
+ 216, 217, 218, 219, 220, 221, 223, 224,
+ /* #224 */
+ 224, 225, 226, 227, 228, 229, 230, 231,
+ 232, 233, 234, 235, 237, 237, 238, 239,
+ 240, 241, 242, 243, 244, 245, 246, 247,
+ 248, 249, 250, 251, 252, 253, 254, 3
+};
+
+
+///////////////////////////////////////////////////////////////////////////////
+// private data types
+//
+typedef struct {
+
+ // the handle for the USB FTDI library
+ struct ftdi_context ftdic;
+
+ // the width and the height (in number of characters) of the library
+ int width, height;
+
+ // The framebuffer and the framebuffer for the last contents (incr.
update)
+ unsigned char *framebuf;
+
+ // dirty line flags
+ unsigned int *line_flags;
+
+ // child thread flag
+ int child_flag;
+
+ // parent thread flag
+ int parent_flag;
+
+ // display brightness 0-1000
+ int brightness;
+
+ // custom characters loaded
+ int cc_flag;
+
+} PrivateData;
+
+
+///////////////////////////////////////////////////////////////////////////////
+// Write a command to the display.
+//
+// @param p the private data
+// @param data the data bytes
+// @param length the number of bytes in @p data which are valid
+// @return 0 on success, negative value on error
+//
+static int
+lis_ftdi_write_command(Driver *drvthis, unsigned char *data, int length)
+{
+ PrivateData *p = (PrivateData *) drvthis->private_data;
+ int err;
+
+ err = ftdi_write_data(&p->ftdic, data, length);
+ if (err < 0) {
+ report(RPT_WARNING, "%s: ftdi_write_data failed with %d",
drvthis->name, err);
+ return -1;
+ }
+
+ timing_uPause(16000);
+
+ return 0;
+}
+
+//////////////////////////////////////////////////////////////////////////////
+// Displays a string at line n (n typically 1 or 2)
+//
+static int
+lis_ftdi_line_to_display(Driver *drvthis, int line, unsigned char *string,
int len)
+{
+ PrivateData *p = (PrivateData *) drvthis->private_data;
+ unsigned char buffer[128];
+ int err;
+ int i;
+
+ if (len > p->width || line < 1 || line > p->height) {
+ return -EINVAL;
+ }
+ buffer[0] = 160+line;
+ buffer[1] = 0;
+ buffer[2] = 167;
+
+ for (i=0; i < len; i++) {
+ buffer[i+3] = UPD16314_charmap[(unsigned char)string[i]];
+ }
+ buffer[i+3] = 0x00;
+
+ err = lis_ftdi_write_command(drvthis, buffer, len+4);
+ if (err < 0) {
+ report(RPT_WARNING, "%s: lis_ftdi_string: "
+ "lis_ftdi_write_command() failed",
drvthis->name);
+ }
+
+ return err;
+}
+
+
+///////////////////////////////////////////////////////////////////////////////
+// Flush the framebuffer to the display
+//
+MODULE_EXPORT void
+lis_flush(Driver *drvthis)
+{
+ PrivateData *p = (PrivateData *) drvthis->private_data;
+
+ int line;
+
+
+ for (line = 0; line < p->height; line++) {
+ if (p->line_flags[line]) {
+ lis_ftdi_line_to_display(drvthis, line+1, p->framebuf
+ (line * p->width), p->width);
+ p->line_flags[line] = 0; // clean
+ }
+ }
+}
+
+
+///////////////////////////////////////////////////////////////////////////////
+// Loads custom characters in the display
+//
+static int
+lis_load_custom_chars(Driver *drvthis)
+{
+ PrivateData *p = (PrivateData *) drvthis->private_data;
+ int i, col, row, err;
+ unsigned char buffer[65];
+ char custom_chars[8][CELLHEIGHT*CELLHEIGHT] = {
+ { 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0 },
+ { 1, 0, 0, 0, 0, /* 1-5 characters used by
hbar() */
+ 1, 0, 0, 0, 0,
+ 1, 0, 0, 0, 0,
+ 1, 0, 0, 0, 0,
+ 1, 0, 0, 0, 0,
+ 1, 0, 0, 0, 0,
+ 1, 0, 0, 0, 0,
+ 1, 0, 0, 0, 0 },
+ { 1, 1, 0, 0, 0,
+ 1, 1, 0, 0, 0,
+ 1, 1, 0, 0, 0,
+ 1, 1, 0, 0, 0,
+ 1, 1, 0, 0, 0,
+ 1, 1, 0, 0, 0,
+ 1, 1, 0, 0, 0,
+ 1, 1, 0, 0, 0 },
+ { 1, 1, 1, 0, 0,
+ 1, 1, 1, 0, 0,
+ 1, 1, 1, 0, 0,
+ 1, 1, 1, 0, 0,
+ 1, 1, 1, 0, 0,
+ 1, 1, 1, 0, 0,
+ 1, 1, 1, 0, 0,
+ 1, 1, 1, 0, 0 },
+ { 1, 1, 1, 1, 0,
+ 1, 1, 1, 1, 0,
+ 1, 1, 1, 1, 0,
+ 1, 1, 1, 1, 0,
+ 1, 1, 1, 1, 0,
+ 1, 1, 1, 1, 0,
+ 1, 1, 1, 1, 0,
+ 1, 1, 1, 1, 0 },
+ { 1, 1, 1, 1, 1,
+ 1, 1, 1, 1, 1,
+ 1, 1, 1, 1, 1,
+ 1, 1, 1, 1, 1,
+ 1, 1, 1, 1, 1,
+ 1, 1, 1, 1, 1,
+ 1, 1, 1, 1, 1,
+ 1, 1, 1, 1, 1 },
+ { 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0,
+ 1, 1, 1, 1, 1,
+ 1, 0, 0, 0, 1,
+ 1, 0, 0, 0, 1,
+ 1, 0, 0, 0, 1,
+ 1, 1, 1, 1, 1,
+ 0, 0, 0, 0, 0 },
+ { 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0,
+ 1, 1, 1, 1, 1,
+ 1, 0, 1, 0, 1,
+ 1, 1, 0, 1, 1,
+ 1, 0, 1, 0, 1,
+ 1, 1, 1, 1, 1,
+ 0, 0, 0, 0, 0 }};
+
+ buffer[0] = 0xad; // command to write CGRAM at 0
+
+ for (i = 0; i < 8; i++)
+ {
+
+ /* build the buffer */
+ for (row = 0; row < CELLHEIGHT; row++) {
+ unsigned char value = 0;
+
+ for (col = 0; col < CELLWIDTH; col++) {
+ value <<= 1;
+ value |= (custom_chars[i][(row * CELLWIDTH) +
col] > 0) ? 1 : 0;
+ }
+ buffer[(i*8)+row+1] = value;
+ }
+ }
+ err = lis_ftdi_write_command(drvthis, buffer, 65);
+ if (err < 0) {
+ report(RPT_WARNING, "%s: lis_load_custom_chars(): "
+ "lis_ftdi_write_command() failed",
drvthis->name);
+ }
+ else
+ p->cc_flag = 1;
+
+ return err;
+}
+
+//////////////////////////////////////////////////////////////////////////////
+// Seperate thread to keep a read up on the USB device at all times
+int
+lis_read_thread(void *arg)
+{
+ Driver *drvthis;
+ PrivateData *p;
+ char unsigned buffer[64];
+ int size;
+
+ drvthis = (Driver *)arg;
+ p = (PrivateData *) drvthis->private_data;
+
+ while(! p->child_flag) {
+ for (size = ftdi_read_data(&p->ftdic, buffer, 64); size > 0;
size = ftdi_read_data(&p->ftdic, buffer, 64))
+ ;
+ if (size < 0) {
+ return size;
+ p->parent_flag = 0;
+ }
+ }
+ p->parent_flag = 0;
+ return 0;
+
+}
+
+///////////////////////////////////////////////////////////////////////////////
+// Control the display brightness
+//
+MODULE_EXPORT int
+lis_set_brightness(Driver *drvthis, int state, int promille)
+{
+ unsigned char buffer[2];
+ int err;
+ PrivateData *p = (PrivateData *) drvthis->private_data;
+
+ if (promille < 0 || promille > 1000)
+ return -EINVAL;
+
+ buffer[0] = 0xa5;
+ if ( promille < 251 )
+ buffer[1] = 0x3; // 25%
+ else if ( promille < 501 )
+ buffer[1] = 0x2; // 50%
+ else if ( promille < 751 )
+ buffer[1] = 0x1; // 75%
+ else
+ buffer[1] = 0x0; // 100%
+
+ err = ftdi_write_data(&p->ftdic, buffer, 2);
+ if (err < 0) {
+ report(RPT_WARNING, "%s: lis_set_brightness(): ftdi_write_data
failed with %d", drvthis->name, err);
+ return err;
+ }
+ else
+ p->brightness = promille;
+ return 0;
+}
+
+///////////////////////////////////////////////////////////////////////////////
+// Get the brightness setting
+MODULE_EXPORT int
+lis_get_brightness(Driver *drvthis, int state)
+{
+ PrivateData *p = (PrivateData *) drvthis->private_data;
+
+ return p->brightness;
+}
+
+///////////////////////////////////////////////////////////////////////////////
+// Init the driver and display
+//
+MODULE_EXPORT int
+lis_init(Driver *drvthis)
+{
+ PrivateData *p;
+ int err;
+ const char *s;
+ unsigned char buffer[64], *thread_stack;
+ int count;
+
+ // Alocate and store private data
+ p = (PrivateData *) malloc( sizeof( PrivateData) );
+ if (p == NULL) {
+ return -1;
+ }
+ if (drvthis->store_private_ptr(drvthis, p)) {
+ return -1;
+ }
+
+ p->child_flag = 0;
+ p->parent_flag = 0;
+ p->cc_flag = 0;
+
+ // Get and parse size
+ s = drvthis->config_get_string( drvthis->name, "size", 0, "20x2");
+ if ((sscanf(s, "%dx%d", &(p->width), &(p->height)) != 2)
+ || (p->width <= 0) || (p->width > LCD_MAX_WIDTH)
+ || (p->height <= 0) || (p->height > LCD_MAX_HEIGHT)) {
+ report(RPT_ERR, "%s: cannot read Size %s", drvthis->name, s);
+ return -1;
+ }
+
+ // set up the dirty flags
+ if( ! (p->line_flags = (unsigned int *)malloc(sizeof(int) *
p->height))) {
+ report(RPT_ERR, "%s: cannot allocate line flags memory",
drvthis->name);
+ return -1;
+ }
+ for (count = 0; count < p->height; count++)
+ p->line_flags[count] = 1;
// dirty!
+
+ /* Which display brightness */
+ count = drvthis->config_get_int(drvthis->name, "Brightness", 0,
DEFAULT_BRIGHTNESS);
+ if ((count < 0) || (count > 1000)) {
+ report(RPT_WARNING, "%s: Brightness must be between 0 and
1000; using default %d",
+ drvthis->name, DEFAULT_BRIGHTNESS);
+ count = DEFAULT_BRIGHTNESS;
+ }
+ p->brightness = count;
+
+ /* End of config file parsing */
+
+
+ // initialise delay timing
+ if (timing_init()) {
+ report(RPT_ERR, "%s: cannot initialise delay timing",
drvthis->name);
+ return -1;
+ }
+ // Allocate framebuffer
+ p->framebuf = (unsigned char *) malloc(p->width * p->height);
+ if (p->framebuf == NULL) {
+ report(RPT_ERR, "%s: unable to allocate framebuffer",
drvthis->name);
+ goto err_begin;
+ }
+
+ // open the FTDI library
+ ftdi_init(&p->ftdic);
+// (&p->ftdic)->usb_write_timeout = 20;
+// (&p->ftdic)->usb_read_timeout = 20;
+
+ // open the device
+ err = ftdi_usb_open(&p->ftdic, DISPLAY_VENDOR_ID, DISPLAY_PRODUCT_ID);
+ if (err < 0) {
+ report(RPT_ERR, "%s: cannot open USB device", drvthis->name);
+ goto err_framebuf;
+ }
+
+ // set communication parameters
+ err = ftdi_set_line_property(&p->ftdic, BITS_7, STOP_BIT_1, EVEN);
+ if (err < 0) {
+ report(RPT_ERR, "%s: cannot set line properties",
drvthis->name);
+ goto err_ftdi;
+ }
+
+ // set DTR mask and high
+ err = ftdi_setdtr(&p->ftdic, SIO_SET_DTR_MASK | SIO_SET_DTR_HIGH);
+ if (err < 0) {
+ report(RPT_ERR, "%s: cannot set DTR mask", drvthis->name);
+ goto err_ftdi;
+ }
+
+ // set RTS mask and high
+ err = ftdi_setrts(&p->ftdic, SIO_SET_RTS_MASK | SIO_SET_RTS_HIGH);
+ if (err < 0) {
+ report(RPT_ERR, "%s: cannot set RTS mask", drvthis->name);
+ goto err_ftdi;
+ }
+
+ // set the baudrate
+ err = ftdi_set_baudrate(&p->ftdic, 1200);
+ if (err < 0) {
+ report(RPT_ERR, "%s: cannot set baudrate", drvthis->name);
+ goto err_ftdi;
+ }
+
+ // set RTS high
+ err = ftdi_setrts(&p->ftdic, SIO_SET_RTS_HIGH);
+ if (err < 0) {
+ report(RPT_ERR, "%s: cannot set RTS high", drvthis->name);
+ goto err_ftdi;
+ }
+
+ // set DTR high
+ err = ftdi_setdtr(&p->ftdic, SIO_SET_DTR_HIGH);
+ if (err < 0) {
+ report(RPT_ERR, "%s: cannot set DTR high", drvthis->name);
+ goto err_ftdi;
+ }
+
+ for (count = 0; count < 6; count++) {
+ // reset device
+ err = ftdi_usb_reset(&p->ftdic);
+ if (err < 0) {
+ report(RPT_ERR, "%s: cannot reset device",
drvthis->name);
+ goto err_ftdi;
+ }
+ }
+ // set latency timer
+ err = ftdi_set_latency_timer(&p->ftdic, 16);
+ if (err < 0) {
+ report(RPT_ERR, "%s: cannot set latency timer",
drvthis->name);
+ goto err_ftdi;
+ }
+
+ // clone a thread to keep a read up on the device
+ thread_stack = calloc(4096, 1);
+ if(! thread_stack) {
+ report(RPT_ERR, "%s: cannot create thread stack",
drvthis->name);
+ goto err_framebuf;
+ }
+
+ err = clone(lis_read_thread, thread_stack+4092, CLONE_VM |
CLONE_THREAD| CLONE_SIGHAND, drvthis);
+ if (err == -1) {
+ report(RPT_ERR, "%s: clone() - %s", drvthis->name,
strerror(errno));
+ goto err_framebuf;
+ }
+ p->parent_flag = 1; // show we're now a happy parent,
birth successful.
+
+ // set communication parameters
+ err = ftdi_set_line_property(&p->ftdic, BITS_7, STOP_BIT_1, EVEN);
+ if (err < 0) {
+ report(RPT_ERR, "%s: cannot set line properties",
drvthis->name);
+ goto err_ftdi;
+ }
+
+ // set DTR mask and high
+ err = ftdi_setdtr(&p->ftdic, SIO_SET_DTR_MASK | SIO_SET_DTR_HIGH);
+ if (err < 0) {
+ report(RPT_ERR, "%s: cannot set DTR mask", drvthis->name);
+ goto err_ftdi;
+ }
+
+ // set RTS mask and high
+ err = ftdi_setrts(&p->ftdic, SIO_SET_RTS_MASK | SIO_SET_RTS_HIGH);
+ if (err < 0) {
+ report(RPT_ERR, "%s: cannot set RTS mask", drvthis->name);
+ goto err_ftdi;
+ }
+
+ // disable flow control
+ err = ftdi_setflowctrl(&p->ftdic, SIO_DISABLE_FLOW_CTRL);
+ if (err < 0) {
+ report(RPT_ERR, "%s: cannot disable flow control",
drvthis->name);
+ goto err_ftdi;
+ }
+
+ // set the baudrate
+ err = ftdi_set_baudrate(&p->ftdic, 1200);
+ if (err < 0) {
+ report(RPT_ERR, "%s: cannot set baudrate", drvthis->name);
+ goto err_ftdi;
+ }
+
+ // set RTS mask and high
+ err = ftdi_setrts(&p->ftdic, SIO_SET_RTS_MASK | SIO_SET_RTS_HIGH);
+ if (err < 0) {
+ report(RPT_ERR, "%s: cannot set RTS mask", drvthis->name);
+ goto err_ftdi;
+ }
+
+ // set DTR mask and high
+ err = ftdi_setdtr(&p->ftdic, SIO_SET_DTR_MASK | SIO_SET_DTR_HIGH);
+ if (err < 0) {
+ report(RPT_ERR, "%s: cannot set DTR mask", drvthis->name);
+ goto err_ftdi;
+ }
+
+ // disable flow control
+ err = ftdi_setflowctrl(&p->ftdic, SIO_DISABLE_FLOW_CTRL);
+ if (err < 0) {
+ report(RPT_ERR, "%s: cannot disable flow control",
drvthis->name);
+ goto err_ftdi;
+ }
+
+ // set DTR mask and high
+ err = ftdi_setdtr(&p->ftdic, SIO_SET_DTR_MASK | SIO_SET_DTR_HIGH);
+ if (err < 0) {
+ report(RPT_ERR, "%s: cannot set DTR mask", drvthis->name);
+ goto err_ftdi;
+ }
+
+ // set RTS high
+ err = ftdi_setrts(&p->ftdic, SIO_SET_RTS_HIGH);
+ if (err < 0) {
+ report(RPT_ERR, "%s: cannot set RTS high", drvthis->name);
+ goto err_ftdi;
+ }
+
+ timing_uPause(192000);
+
+ // set the baudrate
+ err = ftdi_set_baudrate(&p->ftdic, 1200);
+ if (err < 0) {
+ report(RPT_ERR, "%s: cannot set baudrate", drvthis->name);
+ goto err_ftdi;
+ }
+
+ // set communication parameters
+ err = ftdi_set_line_property(&p->ftdic, BITS_7, STOP_BIT_1, NONE);
+ if (err < 0) {
+ report(RPT_ERR, "%s: cannot set line properties",
drvthis->name);
+ goto err_ftdi;
+ }
+
+ // set DTR high
+ err = ftdi_setdtr(&p->ftdic, SIO_SET_DTR_HIGH);
+ if (err < 0) {
+ report(RPT_ERR, "%s: cannot set DTR high", drvthis->name);
+ goto err_ftdi;
+ }
+
+ // set RTS high
+ err = ftdi_setrts(&p->ftdic, SIO_SET_RTS_HIGH);
+ if (err < 0) {
+ report(RPT_ERR, "%s: cannot set RTS high", drvthis->name);
+ goto err_ftdi;
+ }
+
+ timing_uPause(192000);
+
+ // set DTR mask and high
+ err = ftdi_setdtr(&p->ftdic, SIO_SET_DTR_MASK | SIO_SET_DTR_HIGH);
+ if (err < 0) {
+ report(RPT_ERR, "%s: cannot set DTR mask", drvthis->name);
+ goto err_ftdi;
+ }
+
+ timing_uPause(192000);
+
+ // set RTS mask and high
+ err = ftdi_setrts(&p->ftdic, SIO_SET_RTS_MASK | SIO_SET_RTS_HIGH);
+ if (err < 0) {
+ report(RPT_ERR, "%s: cannot set RTS mask", drvthis->name);
+ goto err_ftdi;
+ }
+
+ timing_uPause(236000);
+
+ // set DTR high
+ err = ftdi_setdtr(&p->ftdic, SIO_SET_DTR_HIGH);
+ if (err < 0) {
+ report(RPT_ERR, "%s: cannot set DTR high", drvthis->name);
+ goto err_ftdi;
+ }
+
+ // set RTS high
+ err = ftdi_setrts(&p->ftdic, SIO_SET_RTS_HIGH);
+ if (err < 0) {
+ report(RPT_ERR, "%s: cannot set RTS high", drvthis->name);
+ goto err_ftdi;
+ }
+
+ timing_uPause(192000);
+
+ // set DTR mask and high
+ err = ftdi_setdtr(&p->ftdic, SIO_SET_DTR_MASK | SIO_SET_DTR_HIGH);
+ if (err < 0) {
+ report(RPT_ERR, "%s: cannot set DTR mask", drvthis->name);
+ goto err_ftdi;
+ }
+
+ // set RTS mask and high
+ err = ftdi_setrts(&p->ftdic, SIO_SET_RTS_MASK | SIO_SET_RTS_HIGH);
+ if (err < 0) {
+ report(RPT_ERR, "%s: cannot set RTS mask", drvthis->name);
+ goto err_ftdi;
+ }
+
+ timing_uPause(236000);
+
+ // set DTR mask and high
+ err = ftdi_setdtr(&p->ftdic, SIO_SET_DTR_MASK | SIO_SET_DTR_HIGH);
+ if (err < 0) {
+ report(RPT_ERR, "%s: cannot set DTR mask", drvthis->name);
+ goto err_ftdi;
+ }
+
+ // set RTS high
+ err = ftdi_setrts(&p->ftdic, SIO_SET_RTS_HIGH);
+ if (err < 0) {
+ report(RPT_ERR, "%s: cannot set RTS high", drvthis->name);
+ goto err_ftdi;
+ }
+
+ timing_uPause(192000);
+
+ // set the baudrate
+ err = ftdi_set_baudrate(&p->ftdic, 1200);
+ if (err < 0) {
+ report(RPT_ERR, "%s: cannot set baudrate", drvthis->name);
+ goto err_ftdi;
+ }
+
+ // set communication parameters
+ err = ftdi_set_line_property(&p->ftdic, BITS_7, STOP_BIT_1, NONE);
+ if (err < 0) {
+ report(RPT_ERR, "%s: cannot set line properties",
drvthis->name);
+ goto err_ftdi;
+ }
+
+ // set DTR high
+ err = ftdi_setdtr(&p->ftdic, SIO_SET_DTR_HIGH);
+ if (err < 0) {
+ report(RPT_ERR, "%s: cannot set DTR high", drvthis->name);
+ goto err_ftdi;
+ }
+
+ // set RTS high
+ err = ftdi_setrts(&p->ftdic, SIO_SET_RTS_HIGH);
+ if (err < 0) {
+ report(RPT_ERR, "%s: cannot set RTS high", drvthis->name);
+ goto err_ftdi;
+ }
+
+ timing_uPause(192000);
+
+ // set DTR mask and high
+ err = ftdi_setdtr(&p->ftdic, SIO_SET_DTR_MASK | SIO_SET_DTR_HIGH);
+ if (err < 0) {
+ report(RPT_ERR, "%s: cannot set DTR mask", drvthis->name);
+ goto err_ftdi;
+ }
+
+ timing_uPause(192000);
+
+ // set RTS mask and high
+ err = ftdi_setrts(&p->ftdic, SIO_SET_RTS_MASK | SIO_SET_RTS_HIGH);
+ if (err < 0) {
+ report(RPT_ERR, "%s: cannot set RTS mask", drvthis->name);
+ goto err_ftdi;
+ }
+
+ timing_uPause(236000);
+
+ // set DTR high
+ err = ftdi_setdtr(&p->ftdic, SIO_SET_DTR_HIGH);
+ if (err < 0) {
+ report(RPT_ERR, "%s: cannot set DTR high", drvthis->name);
+ goto err_ftdi;
+ }
+
+ // set RTS high
+ err = ftdi_setrts(&p->ftdic, SIO_SET_RTS_HIGH);
+ if (err < 0) {
+ report(RPT_ERR, "%s: cannot set RTS high", drvthis->name);
+ goto err_ftdi;
+ }
+
+ timing_uPause(236000);
+
+ // set DTR mask and high
+ err = ftdi_setdtr(&p->ftdic, SIO_SET_DTR_MASK | SIO_SET_DTR_HIGH);
+ if (err < 0) {
+ report(RPT_ERR, "%s: cannot set DTR mask", drvthis->name);
+ goto err_ftdi;
+ }
+
+ // set RTS high
+ err = ftdi_setrts(&p->ftdic, SIO_SET_RTS_HIGH);
+ if (err < 0) {
+ report(RPT_ERR, "%s: cannot set RTS high", drvthis->name);
+ goto err_ftdi;
+ }
+
+ // set the baudrate
+ err = ftdi_set_baudrate(&p->ftdic, 1200);
+ if (err < 0) {
+ report(RPT_ERR, "%s: cannot set baudrate", drvthis->name);
+ goto err_ftdi;
+ }
+
+ // set communication parameters
+ err = ftdi_set_line_property(&p->ftdic, BITS_7, STOP_BIT_1, NONE);
+ if (err < 0) {
+ report(RPT_ERR, "%s: cannot set line properties",
drvthis->name);
+ goto err_ftdi;
+ }
+
+ // set DTR high
+ err = ftdi_setdtr(&p->ftdic, SIO_SET_DTR_HIGH);
+ if (err < 0) {
+ report(RPT_ERR, "%s: cannot set DTR high", drvthis->name);
+ goto err_ftdi;
+ }
+
+ // set RTS high
+ err = ftdi_setrts(&p->ftdic, SIO_SET_RTS_HIGH);
+ if (err < 0) {
+ report(RPT_ERR, "%s: cannot set RTS high", drvthis->name);
+ goto err_ftdi;
+ }
+
+ timing_uPause(13*16000);
+
+ // set DTR mask and high
+ err = ftdi_setdtr(&p->ftdic, SIO_SET_DTR_MASK | SIO_SET_DTR_HIGH);
+ if (err < 0) {
+ report(RPT_ERR, "%s: cannot set DTR mask", drvthis->name);
+ goto err_ftdi;
+ }
+
+ timing_uPause(13*16000);
+
+ // set RTS mask and high
+ err = ftdi_setrts(&p->ftdic, SIO_SET_RTS_MASK | SIO_SET_RTS_HIGH);
+ if (err < 0) {
+ report(RPT_ERR, "%s: cannot set RTS mask", drvthis->name);
+ goto err_ftdi;
+ }
+
+ timing_uPause(15*16000);
+
+ // set DTR high
+ err = ftdi_setdtr(&p->ftdic, SIO_SET_DTR_HIGH);
+ if (err < 0) {
+ report(RPT_ERR, "%s: cannot set DTR high", drvthis->name);
+ goto err_ftdi;
+ }
+
+ // set RTS high
+ err = ftdi_setrts(&p->ftdic, SIO_SET_RTS_HIGH);
+ if (err < 0) {
+ report(RPT_ERR, "%s: cannot set RTS high", drvthis->name);
+ goto err_ftdi;
+ }
+
+ timing_uPause(13*16000);
+
+ // set DTR mask and high
+ err = ftdi_setdtr(&p->ftdic, SIO_SET_DTR_MASK | SIO_SET_DTR_HIGH);
+ if (err < 0) {
+ report(RPT_ERR, "%s: cannot set DTR mask", drvthis->name);
+ goto err_ftdi;
+ }
+
+ // set RTS mask and high
+ err = ftdi_setrts(&p->ftdic, SIO_SET_RTS_MASK | SIO_SET_RTS_HIGH);
+ if (err < 0) {
+ report(RPT_ERR, "%s: cannot set RTS mask", drvthis->name);
+ goto err_ftdi;
+ }
+
+ timing_uPause(16*16000);
+
+ // set DTR mask and high
+ err = ftdi_setdtr(&p->ftdic, SIO_SET_DTR_MASK | SIO_SET_DTR_HIGH);
+ if (err < 0) {
+ report(RPT_ERR, "%s: cannot set DTR mask", drvthis->name);
+ goto err_ftdi;
+ }
+
+ // set RTS mask and high
+ err = ftdi_setrts(&p->ftdic, SIO_SET_RTS_MASK | SIO_SET_RTS_HIGH);
+ if (err < 0) {
+ report(RPT_ERR, "%s: cannot set RTS mask", drvthis->name);
+ goto err_ftdi;
+ }
+
+ // disable flow control
+ err = ftdi_setflowctrl(&p->ftdic, SIO_DISABLE_FLOW_CTRL);
+ if (err < 0) {
+ report(RPT_ERR, "%s: cannot disable flow control",
drvthis->name);
+ goto err_ftdi;
+ }
+
+ timing_uPause(16000);
+
+ // set DTR high
+ err = ftdi_setdtr(&p->ftdic, SIO_SET_DTR_HIGH);
+ if (err < 0) {
+ report(RPT_ERR, "%s: cannot set DTR high", drvthis->name);
+ goto err_ftdi;
+ }
+
+ // set RTS high
+ err = ftdi_setrts(&p->ftdic, SIO_SET_RTS_HIGH);
+ if (err < 0) {
+ report(RPT_ERR, "%s: cannot set RTS high", drvthis->name);
+ goto err_ftdi;
+ }
+
+ for (count = 0; count < 6; count++) {
+ // reset device
+ err = ftdi_usb_reset(&p->ftdic);
+ if (err < 0) {
+ report(RPT_ERR, "%s: cannot reset device",
drvthis->name);
+ goto err_ftdi;
+ }
+ }
+
+ // set latency timer
+ err = ftdi_set_latency_timer(&p->ftdic, 16);
+ if (err < 0) {
+ report(RPT_ERR, "%s: cannot set latency timer",
drvthis->name);
+ goto err_ftdi;
+ }
+
+ timing_uPause(16000);
+
+ // set communication parameters
+ err = ftdi_set_line_property(&p->ftdic, BITS_7, STOP_BIT_1, NONE);
+ if (err < 0) {
+ report(RPT_ERR, "%s: cannot set line properties",
drvthis->name);
+ goto err_ftdi;
+ }
+
+ // set DTR mask and high
+ err = ftdi_setdtr(&p->ftdic, SIO_SET_DTR_MASK | SIO_SET_DTR_HIGH);
+ if (err < 0) {
+ report(RPT_ERR, "%s: cannot set DTR mask", drvthis->name);
+ goto err_ftdi;
+ }
+
+ // set RTS mask and high
+ err = ftdi_setrts(&p->ftdic, SIO_SET_RTS_MASK | SIO_SET_RTS_HIGH);
+ if (err < 0) {
+ report(RPT_ERR, "%s: cannot set RTS mask", drvthis->name);
+ goto err_ftdi;
+ }
+
+ // disable flow control
+ err = ftdi_setflowctrl(&p->ftdic, SIO_DISABLE_FLOW_CTRL);
+ if (err < 0) {
+ report(RPT_ERR, "%s: cannot disable flow control",
drvthis->name);
+ goto err_ftdi;
+ }
+
+ // set the baudrate
+ err = ftdi_set_baudrate(&p->ftdic, 1200);
+ if (err < 0) {
+ report(RPT_ERR, "%s: cannot set baudrate", drvthis->name);
+ goto err_ftdi;
+ }
+
+ // set the baudrate
+ err = ftdi_set_baudrate(&p->ftdic, 38400);
+ if (err < 0) {
+ report(RPT_ERR, "%s: cannot set baudrate", drvthis->name);
+ goto err_ftdi;
+ }
+
+ // set RTS mask and high
+ err = ftdi_setrts(&p->ftdic, SIO_SET_RTS_MASK | SIO_SET_RTS_HIGH);
+ if (err < 0) {
+ report(RPT_ERR, "%s: cannot set RTS mask", drvthis->name);
+ goto err_ftdi;
+ }
+
+ // set DTR mask and high
+ err = ftdi_setdtr(&p->ftdic, SIO_SET_DTR_MASK | SIO_SET_DTR_HIGH);
+ if (err < 0) {
+ report(RPT_ERR, "%s: cannot set DTR mask", drvthis->name);
+ goto err_ftdi;
+ }
+
+ // set communication parameters N,8,1
+ err = ftdi_set_line_property(&p->ftdic, BITS_8, STOP_BIT_1, NONE);
+ if (err < 0) {
+ report(RPT_ERR, "%s: cannot set line properties N,8,1",
drvthis->name);
+ goto err_ftdi;
+ }
+
+ // disable flow control
+ err = ftdi_setflowctrl(&p->ftdic, SIO_DISABLE_FLOW_CTRL);
+ if (err < 0) {
+ report(RPT_ERR, "%s: cannot disable flow control",
drvthis->name);
+ goto err_ftdi;
+ }
+
+ // set DTR high
+ err = ftdi_setrts(&p->ftdic, SIO_SET_DTR_HIGH);
+ if (err < 0) {
+ report(RPT_ERR, "%s: cannot set DTR high", drvthis->name);
+ goto err_ftdi;
+ }
+
+#if 0
+ // uncomment this if using a patched version of ftdi
+ // set the event character to 0x00
+ err = ftdi_set_event_char(&p->ftdic, 0x100);
+ if (err < 0) {
+ report(RPT_ERR, "%s: cannot set event character ",
drvthis->name);
+ goto err_ftdi;
+ }
+
+ timing_uPause(16000);
+#endif
+
+ // don't know what this does exactly
+ buffer[0] = 0xa4;
+ buffer[1] = 0x7d;
+ err = ftdi_write_data(&p->ftdic, buffer, 2);
+ if (err < 0) {
+ report(RPT_WARNING, "%s: ftdi_write_data failed with %d",
drvthis->name, err);
+ goto err_ftdi;
+ }
+
+ timing_uPause(3*16000);
+
+ buffer[0] = 0xaa;
+ buffer[1] = 0xaa;
+ for(count = 0; count < 10; count++) {
+ err = ftdi_write_data(&p->ftdic, buffer, 2);
+ if (err < 0) {
+ report(RPT_WARNING, "%s: ftdi_write_data failed with
%d", drvthis->name, err);
+ goto err_ftdi;
+ }
+ timing_uPause(3*16000);
+ }
+
+ // set the event character to 0x00 (only works with patched libftdi)
+// err = ftdi_set_event_char(&p->ftdic, 0x00);
+// if (err < 0) {
+// report(RPT_ERR, "%s: cannot set event character ",
drvthis->name);
+// goto err_ftdi;
+// }
+//
+// timing_uPause(16000);
+
+ // set DTR high
+ err = ftdi_setdtr(&p->ftdic, SIO_SET_DTR_HIGH);
+ if (err < 0) {
+ report(RPT_ERR, "%s: cannot set DTR high", drvthis->name);
+ goto err_ftdi;
+ }
+
+ // set RTS high
+ err = ftdi_setrts(&p->ftdic, SIO_SET_RTS_HIGH);
+ if (err < 0) {
+ report(RPT_ERR, "%s: cannot set RTS high", drvthis->name);
+ goto err_ftdi;
+ }
+
+ for (count = 0; count < 6; count++) {
+ // reset device
+ err = ftdi_usb_reset(&p->ftdic);
+ if (err < 0) {
+ report(RPT_ERR, "%s: cannot reset device",
drvthis->name);
+ goto err_ftdi;
+ }
+ }
+
+ // set latency timer
+ err = ftdi_set_latency_timer(&p->ftdic, 16);
+ if (err < 0) {
+ report(RPT_ERR, "%s: cannot set latency timer",
drvthis->name);
+ goto err_ftdi;
+ }
+
+ timing_uPause(16000);
+
+ // set communication parameters N,8,1
+ err = ftdi_set_line_property(&p->ftdic, BITS_8, STOP_BIT_1, NONE);
+ if (err < 0) {
+ report(RPT_ERR, "%s: cannot set line properties N,8,1",
drvthis->name);
+ goto err_ftdi;
+ }
+
+ // set DTR mask and high
+ err = ftdi_setdtr(&p->ftdic, SIO_SET_DTR_MASK | SIO_SET_DTR_HIGH);
+ if (err < 0) {
+ report(RPT_ERR, "%s: cannot set DTR mask", drvthis->name);
+ goto err_ftdi;
+ }
+
+ // set RTS mask and high
+ err = ftdi_setrts(&p->ftdic, SIO_SET_RTS_MASK | SIO_SET_RTS_HIGH);
+ if (err < 0) {
+ report(RPT_ERR, "%s: cannot set RTS mask", drvthis->name);
+ goto err_ftdi;
+ }
+
+ // disable flow control
+ err = ftdi_setflowctrl(&p->ftdic, SIO_DISABLE_FLOW_CTRL);
+ if (err < 0) {
+ report(RPT_ERR, "%s: cannot disable flow control",
drvthis->name);
+ goto err_ftdi;
+ }
+
+ // set the baudrate
+ err = ftdi_set_baudrate(&p->ftdic, 38400);
+ if (err < 0) {
+ report(RPT_ERR, "%s: cannot set baudrate 38400",
drvthis->name);
+ goto err_ftdi;
+ }
+
+ // set the baudrate
+ err = ftdi_set_baudrate(&p->ftdic, 38400);
+ if (err < 0) {
+ report(RPT_ERR, "%s: cannot set baudrate 38400",
drvthis->name);
+ goto err_ftdi;
+ }
+
+ // set RTS mask and high
+ err = ftdi_setrts(&p->ftdic, SIO_SET_RTS_MASK | SIO_SET_RTS_HIGH);
+ if (err < 0) {
+ report(RPT_ERR, "%s: cannot set RTS mask", drvthis->name);
+ goto err_ftdi;
+ }
+
+ // set DTR mask and high
+ err = ftdi_setdtr(&p->ftdic, SIO_SET_DTR_MASK | SIO_SET_DTR_HIGH);
+ if (err < 0) {
+ report(RPT_ERR, "%s: cannot set DTR mask", drvthis->name);
+ goto err_ftdi;
+ }
+
+ // set communication parameters N,8,1
+ err = ftdi_set_line_property(&p->ftdic, BITS_8, STOP_BIT_1, NONE);
+ if (err < 0) {
+ report(RPT_ERR, "%s: cannot set line properties N,8,1",
drvthis->name);
+ goto err_ftdi;
+ }
+
+ // disable flow control
+ err = ftdi_setflowctrl(&p->ftdic, SIO_DISABLE_FLOW_CTRL);
+ if (err < 0) {
+ report(RPT_ERR, "%s: cannot disable flow control",
drvthis->name);
+ goto err_ftdi;
+ }
+
+ // turn off the event character (only works with patched libftdi)
+// err = ftdi_set_event_char(&p->ftdic, 0x00);
+// if (err < 0) {
+// report(RPT_ERR, "%s: cannot turn off event character ",
drvthis->name);
+// goto err_ftdi;
+// }
+//
+// timing_uPause(2*16000);
+
+ // not sure about this
+ buffer[0] = 0xa0;
+ err = lis_ftdi_write_command(drvthis, buffer, 1);
+ if (err < 0) {
+ report(RPT_WARNING, "%s: lis_ftdi_clear: "
+ "lis_ftdi_write_command failed", drvthis->name);
+ }
+
+ timing_uPause(10*16000);
+
+ lis_load_custom_chars(drvthis);
+
+ report(RPT_DEBUG, "%s: init() done", drvthis->name);
+
+// lis_test(drvthis); /*DEBUG*/
+
+ return 0;
+
+err_ftdi:
+ ftdi_usb_close(&p->ftdic);
+ ftdi_deinit(&p->ftdic);
+ if(p->line_flags)
+ free(p->line_flags);
+err_framebuf:
+ free(p->framebuf);
+err_begin:
+
+ if (p->parent_flag) { // terminate the child
+ p->child_flag = 1;
+ while(p->parent_flag)
+ timing_uPause(5*16000);
+ }
+ return -1;
+}
+
+///////////////////////////////////////////////////////////////////////////////
+// Clean-up
+//
+MODULE_EXPORT void
+lis_close(Driver *drvthis)
+{
+ PrivateData *p = (PrivateData *) drvthis->private_data;
+
+ if (p != NULL) {
+ if (p->parent_flag) { // terminate the child
+ p->child_flag = 1;
+ while(p->parent_flag)
+ timing_uPause(5*16000);
+ }
+ ftdi_usb_purge_buffers(&p->ftdic);
+ ftdi_usb_close(&p->ftdic);
+ ftdi_deinit(&p->ftdic);
+
+ if (p->framebuf != NULL)
+ free(p->framebuf);
+
+ free(p);
+ }
+ drvthis->store_private_ptr(drvthis, NULL);
+}
+
+///////////////////////////////////////////////////////////////////////////////
+// Returns the display width
+//
+MODULE_EXPORT int
+lis_width (Driver *drvthis)
+{
+ PrivateData *p = (PrivateData *) drvthis->private_data;
+
+ return p->width;
+}
+
+///////////////////////////////////////////////////////////////////////////////
+// Returns the display height
+//
+MODULE_EXPORT int
+lis_height (Driver *drvthis)
+{
+ PrivateData *p = (PrivateData *) drvthis->private_data;
+
+ return p->height;
+}
+
+///////////////////////////////////////////////////////////////////////////////
+// Clear the framebuffer
+//
+MODULE_EXPORT void
+lis_clear (Driver *drvthis)
+{
+ PrivateData *p = (PrivateData *) drvthis->private_data;
+ int line;
+
+ for (line = 0; line < p->height; line++) {
+ memset(p->framebuf + (line * p->width), ' ', p->width);
+ p->line_flags[line] = 1;
+ }
+}
+
+///////////////////////////////////////////////////////////////////////////////
+// Place a character in the framebuffer
+//
+MODULE_EXPORT void
+lis_chr (Driver *drvthis, int x, int y, char ch)
+{
+ PrivateData *p = (PrivateData *) drvthis->private_data;
+
+ // ignore out-of-range
+ if (y > p->height || x > p->width)
+ return;
+
+ y--;
+ x--;
+
+ if ( p->framebuf[ (y * p->width) + x] != ch) {
+ p->framebuf[ (y * p->width) + x] = ch;
+
+ p->line_flags[y] = 1;
+ }
+}
+
+///////////////////////////////////////////////////////////////////////////////
+// Place a string in the framebuffer
+//
+MODULE_EXPORT void
+lis_string (Driver *drvthis, int x, int y, char *s)
+{
+ PrivateData *p = (PrivateData *) drvthis->private_data;
+ int i;
+
+ x --; // Convert 1-based coords to 0-based
+ y --;
+
+ for (i = 0; s[i]; i++) {
+ // Check for buffer overflows...
+ if ((y * p->width) + x + i > (p->width * p->height))
+ break;
+
+ if ( p->framebuf[(y*p->width) + x + i] != s[i] ) {
+ p->framebuf[(y*p->width) + x + i] = s[i];
+ p->line_flags[((y*p->width) + x + i ) / p->width ] =
1; // dirty
+ }
+ }
+}
+
+
+///////////////////////////////////////////////////////////////////////////////
+// Set default icon into a userdef char
+//
+MODULE_EXPORT int
+lis_icon (Driver *drvthis, int x, int y, int icon)
+{
+ char ch;
+
+ switch (icon) {
+ case ICON_BLOCK_FILLED:
+ ch = 0xff;
+ break;
+ case ICON_HEART_FILLED:
+ ch = 0x9d;
+ break;
+ case ICON_HEART_OPEN:
+ ch = 0x9c;
+ break;
+ case ICON_ARROW_UP:
+ ch = 0x18;
+ break;
+ case ICON_ARROW_DOWN:
+ ch = 0x19;
+ break;
+ case ICON_ARROW_LEFT:
+ ch = 0x1b;
+ break;
+ case ICON_ARROW_RIGHT:
+ ch = 0x1a;
+ break;
+ case ICON_CHECKBOX_OFF:
+ ch = 0x6f;
+ break;
+ case ICON_CHECKBOX_ON:
+ ch = 0xc7;
+ break;
+ case ICON_CHECKBOX_GRAY:
+ ch = 7;
+ break;
+ case ICON_STOP:
+ ch = 0x16;
+ break;
+ case ICON_PAUSE:
+ ch = 0xa0;
+ break;
+ case ICON_PLAY:
+ ch = 0x10;
+ break;
+ case ICON_PLAYR:
+ ch = 0x11;
+ break;
+ case ICON_FF:
+ ch = 0xbb;
+ break;
+ case ICON_FR:
+ ch = 0xbc;
+ break;
+ case ICON_NEXT:
+ ch = 0x1d;
+ break;
+ case ICON_PREV:
+ ch = 0x1c;
+ break;
+ case ICON_REC:
+ ch = 0xae;
+ break;
+ default:
+ return -1; /* Let the core do other icons */
+
+ lis_chr(drvthis, x, y, ch);
+ }
+ return 0;
+}
+
+///////////////////////////////////////////////////////////////////////////////
+// Draw a horizontal bar
+//
+// options ignored
+// truncates to fit display if needed
+MODULE_EXPORT void
+lis_hbar(Driver *drvthis, int x, int y, int len, int promille, int options)
+{
+ PrivateData *p = (PrivateData *) drvthis->private_data;
+ char buf[p->width+1];
+ int per_pel;
+ char *bp;
+
+ if (! p->cc_flag)
+ lis_load_custom_chars(drvthis);
+
+ if (x + len > p->width)
+ len = p->width - x;
+
+ if (len < 1 || promille < 0 || promille > 1000 )
+ return;
+
+ // blank area for bar
+ memset(buf, ' ', len);
+
+ if( promille == 0)
+ return;
+
+ per_pel = 1000 / (len * CELLWIDTH);
+
+ bp = buf;
+
+ while(promille > per_pel) {
+ if( promille >= per_pel * CELLWIDTH) {
+ *bp = 0x05; // full width
+ promille -= CELLWIDTH*per_pel;
+ } else {
+ *bp = (promille / per_pel);
+ promille = 0;
+ }
+ bp++;
+ }
+ *bp = 0x00;
+
+ lis_string(drvthis, x, y, buf);
+}
+
+
+void
+lis_test(Driver *drvthis)
+{
+ int x, y, i;
+
+
+ x = 0;
+ y = 1;
+ lis_clear(drvthis);
+
+ for (i = 0; i < 1001; i++) {
+ lis_hbar(drvthis, 1, 1, 20, i, 0);
+ lis_flush(drvthis);
+ }
+}
diff -ruN lcdproc-CVS-current-20070513/server/drivers/lis.h
lcdproc-CVS-current-20070513-lis/server/drivers/lis.h
--- lcdproc-CVS-current-20070513/server/drivers/lis.h 1969-12-31
18:00:00.000000000 -0600
+++ lcdproc-CVS-current-20070513-lis/server/drivers/lis.h 2007-03-04
13:11:18.000000000 -0600
@@ -0,0 +1,44 @@
+
+/*
+ Based on the lis driver Copyright (C) 2006, Bernhard Walle
+ Copyright (c) 2007, Daryl Fonseca-Holt
<wyatt AT prairieturtle.ca>
+
+ 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
*/
+#ifndef LIS_H
+#define LIS_H
+
+#include "lcd.h"
+
+#ifndef bool
+# define bool short
+# define true 1
+# define false 0
+#endif
+
+MODULE_EXPORT int lis_init(Driver *drvthis);
+MODULE_EXPORT void lis_close (Driver *drvthis);
+MODULE_EXPORT int lis_width (Driver *drvthis);
+MODULE_EXPORT int lis_height (Driver *drvthis);
+MODULE_EXPORT void lis_clear (Driver * drvthis);
+MODULE_EXPORT void lis_string (Driver * drvthis, int x, int y, char
string[]);
+MODULE_EXPORT void lis_chr (Driver * drvthis, int x, int y, char c);
+MODULE_EXPORT void lis_set_char (Driver * drvthis, int n, char *dat);
+MODULE_EXPORT void lis_flush (Driver * drvthis);
+MODULE_EXPORT void lis_vbar (Driver * drvthis, int x, int y, int len, int
promille, int options);
+MODULE_EXPORT void lis_hbar (Driver * drvthis, int x, int y, int len, int
promille, int options);
+MODULE_EXPORT void lis_num (Driver * drvthis, int x, int num);
+MODULE_EXPORT int lis_icon(Driver * drvthis, int x, int y, int icon);
+
+#endif /* LIS_H */



Archive powered by MHonArc 2.6.18.

Top of page