[Lcdproc] [patch] hd44780 FTDI USB support

Thomas Jarosch thomas.jarosch@intra2net.com
Wed Oct 31 17:59:01 2007


--Boundary-00=_BJMKH3C72dBYa1f
Content-Type: text/plain;
  charset="us-ascii"
Content-Transfer-Encoding: 7bit
Content-Disposition: inline

Hello together,

attached patch adds generic hd44780 FTDI USB support in 8 bit mode
using a dual channel FT2232C/D FTDI chip. Please have a look.

Documentation will be written once the code is ok. The patch needs
the configure-cleanup-v3 and report() patch I sent earlier.

Cheers,
Thomas

--Boundary-00=_BJMKH3C72dBYa1f
Content-Type: text/x-diff;
  charset="us-ascii";
  name="lcdproc-hd44780-ftdi.patch"
Content-Transfer-Encoding: 7bit
Content-Disposition: attachment;
	filename="lcdproc-hd44780-ftdi.patch"

diff -u -r -p --new-file lcdproc-CVS-current-20071031/acinclude.m4 lcdproc.ftdi/acinclude.m4
--- lcdproc-CVS-current-20071031/acinclude.m4	2007-10-31 18:30:29.000000000 +0100
+++ lcdproc.ftdi/acinclude.m4	2007-10-31 18:17:23.000000000 +0100
@@ -192,6 +192,9 @@ dnl			else
 			if test "$enable_libusb" = yes ; then
 				HD44780_DRIVERS="$HD44780_DRIVERS hd44780-hd44780-bwct-usb.o hd44780-hd44780-lcd2usb.o"
 			fi
+			if test "$enable_libftdi" = yes ; then
+				HD44780_DRIVERS="$HD44780_DRIVERS hd44780-ftdi.o"
+			fi
 			AC_CHECK_HEADER(linux/i2c-dev.h,
 				HD44780_DRIVERS="$HD44780_DRIVERS hd44780-i2c.o"
 				AC_DEFINE(HAVE_I2C,[1],[Define to 1 if you have the i2c headers])
diff -u -r -p --new-file lcdproc-CVS-current-20071031/server/drivers/hd44780-drivers.h lcdproc.ftdi/server/drivers/hd44780-drivers.h
--- lcdproc-CVS-current-20071031/server/drivers/hd44780-drivers.h	2007-10-14 14:02:53.000000000 +0200
+++ lcdproc.ftdi/server/drivers/hd44780-drivers.h	2007-10-31 18:12:00.000000000 +0100
@@ -23,6 +23,9 @@
 # include "hd44780-bwct-usb.h"
 # include "hd44780-lcd2usb.h"
 #endif
+#ifdef HAVE_LIBFTDI
+# include "hd44780-ftdi.h"
+#endif
 #ifdef HAVE_I2C
 # include "hd44780-i2c.h"
 #endif
@@ -55,6 +58,9 @@ static const ConnectionMapping connectio
 	{ "bwctusb",       HD44780_CT_BWCTUSB,       IF_TYPE_USB,     hd_init_bwct_usb  },
 	{ "lcd2usb",       HD44780_CT_I2C,           IF_TYPE_USB,     hd_init_lcd2usb   },
 #endif
+#ifdef HAVE_LIBFTDI
+	{ "ftdi",          HD44780_CT_FTDI,          IF_TYPE_USB,     hd_init_ftdi      },
+#endif
 #ifdef HAVE_I2C
 	{ "i2c",           HD44780_CT_I2C,           IF_TYPE_I2C,     hd_init_i2c       },
 #endif
diff -u -r -p --new-file lcdproc-CVS-current-20071031/server/drivers/hd44780-ftdi.c lcdproc.ftdi/server/drivers/hd44780-ftdi.c
--- lcdproc-CVS-current-20071031/server/drivers/hd44780-ftdi.c	1970-01-01 01:00:00.000000000 +0100
+++ lcdproc.ftdi/server/drivers/hd44780-ftdi.c	2007-10-31 17:35:55.000000000 +0100
@@ -0,0 +1,158 @@
+/*
+ * FTDI/USB driver module for Hitachi HD44780 based LCD displays
+ * connected to a FT2232C/D chip in 8 bit mode.
+ *
+ * Copyright (c) 2007, Intra2net AG <opensource@intra2net.com>
+ *
+ * This file is released under the GNU General Public License. Refer to the
+ * COPYING file distributed with this package.
+ *
+ */
+
+#include "hd44780-ftdi.h"
+
+#include "report.h"
+
+#include <stdlib.h>
+#include <unistd.h>
+#include <string.h>
+#include <usb.h>
+
+#include <stdio.h>
+#include <sys/types.h>
+#include <fcntl.h>
+
+#include <errno.h>
+
+#ifdef HAVE_CONFIG_H
+# include "config.h"
+#endif
+
+// initialize the driver
+int
+hd_init_ftdi(Driver *drvthis)
+{
+    int vendor_id, product_id;
+    int f;
+
+    PrivateData *p = (PrivateData*) drvthis->private_data;
+
+    p->hd44780_functions->senddata = ftdi_HD44780_senddata;
+    p->hd44780_functions->backlight = ftdi_HD44780_backlight;
+    p->hd44780_functions->scankeypad = ftdi_HD44780_scankeypad;
+    p->hd44780_functions->close = ftdi_HD44780_close;
+
+    // Load config
+    vendor_id = drvthis->config_get_int(drvthis->name, "vendor_id", 0, 0x0403);
+    product_id = drvthis->config_get_int(drvthis->name, "product_id", 0, 0x6001);
+
+    p->ftdi_line_RS = drvthis->config_get_int(drvthis->name, "ftdi_line_RS", 0, 0x01);
+    p->ftdi_line_RW = drvthis->config_get_int(drvthis->name, "ftdi_line_RW", 0, 0x02);
+    p->ftdi_line_E = drvthis->config_get_int(drvthis->name, "ftdi_line_E", 0, 0x04);
+    p->ftdi_line_backlight = drvthis->config_get_int(drvthis->name, "ftdi_line_backlight", 0, 0x08);
+
+    // Init 1. channel: data
+    ftdi_init(&p->ftdic);
+    ftdi_set_interface(&p->ftdic, INTERFACE_A);
+    f = ftdi_usb_open(&p->ftdic, vendor_id, product_id);
+    if(f < 0 && f != -5) {
+        report(RPT_ERR, "unable to open ftdi device: %d (%s)", f, ftdi_get_error_string(&p->ftdic));
+        return -1;
+    }
+    debug(RPT_DEBUG, "ftdi open succeeded(channel 1): %d", f);
+
+    debug(RPT_DEBUG, "enabling bitbang mode(channel 1)\n");
+    ftdi_enable_bitbang(&p->ftdic, 0xFF);
+
+    // Init 2. channel: control
+    ftdi_init(&p->ftdic2);
+    ftdi_set_interface(&p->ftdic2, INTERFACE_B);
+    f = ftdi_usb_open(&p->ftdic2, vendor_id, product_id);
+    if(f < 0 && f != -5) {
+        report(RPT_ERR, "unable to open second ftdi device: %d (%s)", f, ftdi_get_error_string(&p->ftdic2));
+        return -2;
+    }
+    debug(RPT_DEBUG, "ftdi open succeeded(channel 2): %d", f);
+
+    debug(RPT_DEBUG, "enabling bitbang mode (channel 2)");
+    ftdi_enable_bitbang(&p->ftdic2, 0xFF);
+
+    // FTDI bug: Sometimes first write gets lost on kernel 2.6, needs investigation.
+    ftdi_HD44780_senddata (p, 0, RS_INSTR, FUNCSET | IF_8BIT);
+    usleep (4100);
+
+    common_init(p, IF_8BIT);
+
+    return 0;
+}
+
+// ftdi_HD44780_senddata
+void
+ftdi_HD44780_senddata(PrivateData *p, unsigned char displayID, unsigned char flags, unsigned char ch)
+{
+    // Output data on first channel
+    int f = ftdi_write_data(&p->ftdic, &ch, 1);
+    if (f < 0) {
+        p->hd44780_functions->drv_report(RPT_ERR, "failed to write: %d (%s). Exiting", f, ftdi_get_error_string(&p->ftdic));
+        exit (-1);
+    }
+
+    // Setup RS and R/W and E
+    ch = p->ftdi_line_E | p->backlight_bit;
+    if (flags == RS_DATA) {
+        ch |= p->ftdi_line_RS;
+    }
+    f = ftdi_write_data(&p->ftdic2, &ch, 1);
+    if (f < 0) {
+        p->hd44780_functions->drv_report(RPT_ERR, "failed to write: %d (%s). Exiting", f, ftdi_get_error_string(&p->ftdic2));
+        exit(-1);
+    }
+
+    // Disable E
+    ch = 0x00 | p->backlight_bit;
+    if (flags == RS_DATA) {
+        ch |= p->ftdi_line_RS;
+    }
+    f = ftdi_write_data(&p->ftdic2, &ch, 1);
+    if (f < 0) {
+        p->hd44780_functions->drv_report(RPT_ERR, "failed to write: %d (%s). Exiting", f, ftdi_get_error_string(&p->ftdic2));
+        exit(-1);
+    }
+}
+
+
+void
+ftdi_HD44780_backlight(PrivateData *p, unsigned char state)
+{
+    int f;
+
+    p->backlight_bit = state ? p->ftdi_line_backlight : 0;
+
+    f = ftdi_write_data(&p->ftdic2, &state, 1);
+    if (f < 0) {
+        p->hd44780_functions->drv_report(RPT_ERR, "failed to write: %d (%s). Exiting", f, ftdi_get_error_string(&p->ftdic2));
+        exit(-1);
+    }
+}
+
+
+unsigned char
+ftdi_HD44780_scankeypad(PrivateData *p)
+{
+    return 0;
+}
+
+
+void
+ftdi_HD44780_close(PrivateData *p)
+{
+    ftdi_disable_bitbang(&p->ftdic);
+    ftdi_usb_close(&p->ftdic);
+    ftdi_deinit(&p->ftdic);
+
+    ftdi_disable_bitbang(&p->ftdic2);
+    ftdi_usb_close(&p->ftdic2);
+    ftdi_deinit(&p->ftdic2);
+}
+
+/* EOF */
diff -u -r -p --new-file lcdproc-CVS-current-20071031/server/drivers/hd44780-ftdi.h lcdproc.ftdi/server/drivers/hd44780-ftdi.h
--- lcdproc-CVS-current-20071031/server/drivers/hd44780-ftdi.h	1970-01-01 01:00:00.000000000 +0100
+++ lcdproc.ftdi/server/drivers/hd44780-ftdi.h	2007-10-30 11:45:53.000000000 +0100
@@ -0,0 +1,15 @@
+#ifndef HD_FTDI_H
+#define HD_FTDI_H
+
+#include "lcd.h"		/* for Driver */
+#include "hd44780-low.h"
+
+// initialise this particular driver
+int hd_init_ftdi(Driver *drvthis);
+
+void ftdi_HD44780_senddata(PrivateData *p, unsigned char displayID, unsigned char flags, unsigned char ch);
+void ftdi_HD44780_backlight(PrivateData *p, unsigned char state);
+unsigned char ftdi_HD44780_scankeypad(PrivateData *p);
+void ftdi_HD44780_close(PrivateData *p);
+
+#endif
diff -u -r -p --new-file lcdproc-CVS-current-20071031/server/drivers/hd44780-low.h lcdproc.ftdi/server/drivers/hd44780-low.h
--- lcdproc-CVS-current-20071031/server/drivers/hd44780-low.h	2007-10-31 18:30:33.000000000 +0100
+++ lcdproc.ftdi/server/drivers/hd44780-low.h	2007-10-31 18:27:47.000000000 +0100
@@ -21,6 +21,9 @@
 #  endif
 # endif
 
+#ifdef HAVE_LIBFTDI
+# include <ftdi.h>
+#endif
 
 // symbolic names for connection types
 #define HD44780_CT_UNKNOWN		0
@@ -38,7 +41,8 @@
 #define HD44780_CT_MPLAY		12
 #define HD44780_CT_BWCTUSB		13
 #define HD44780_CT_LCDUSB		14
-#define HD44780_CT_I2C			15
+#define HD44780_CT_FTDI		15
+#define HD44780_CT_I2C			16
 
 // symbolic names for interface types
 #define IF_TYPE_UNKNOWN		0
@@ -163,6 +167,15 @@ typedef struct driver_private_data {
 	int contrast;		// Contrast setting (range 0 - 1000)
 	int brightness;		// Brightness when backlight is "on" (range 0 - 1000)
 	int offbrightness;	// Brightness when backlight is "off" (range 0 - 1000)
+
+#ifdef HAVE_LIBFTDI
+	struct ftdi_context ftdic, ftdic2;
+
+	int ftdi_line_RS;
+	int ftdi_line_RW;
+	int ftdi_line_E;
+	int ftdi_line_backlight;
+#endif
 } PrivateData;
 
 
diff -u -r -p --new-file lcdproc-CVS-current-20071031/server/drivers/Makefile.am lcdproc.ftdi/server/drivers/Makefile.am
--- lcdproc-CVS-current-20071031/server/drivers/Makefile.am	2007-10-31 18:30:29.000000000 +0100
+++ lcdproc.ftdi/server/drivers/Makefile.am	2007-10-31 18:16:38.000000000 +0100
@@ -23,7 +23,7 @@ EXTRA_PROGRAMS = bayrad CFontz CFontz633
 noinst_LIBRARIES = libLCD.a libbignum.a
 
 IOWarrior_CFLAGS =   @LIBUSB_CFLAGS@ $(AM_CFLAGS)
-hd44780_CFLAGS =     @LIBUSB_CFLAGS@ $(AM_CFLAGS)
+hd44780_CFLAGS =     @LIBUSB_CFLAGS@ @LIBFTDI_CFLAGS@ $(AM_CFLAGS)
 g15_CFLAGS =         @LIBUSB_CFLAGS@ $(AM_CFLAGS)
 picolcd_CFLAGS =     @LIBUSB_CFLAGS@ $(AM_CFLAGS)	
 shuttleVFD_CFLAGS =  @LIBUSB_CFLAGS@ $(AM_CFLAGS)
@@ -35,7 +35,7 @@ curses_LDADD =       @LIBCURSES@
 CwLnx_LDADD =        libLCD.a libbignum.a
 g15_LDADD =          libLCD.a @LIBG15@
 glcdlib_LDADD =      libLCD.a @LIBGLCD@
-hd44780_LDADD =      libLCD.a @HD44780_DRIVERS@ @LIBUSB_LIBS@ libbignum.a
+hd44780_LDADD =      libLCD.a @HD44780_DRIVERS@ @LIBUSB_LIBS@ @LIBFTDI_LIBS@ libbignum.a
 hd44780_DEPENDENCIES = @HD44780_DRIVERS@
 icp_a106_LDADD =     libLCD.a
 imon_LDADD =         libLCD.a
@@ -75,7 +75,7 @@ g15_SOURCES = 	     lcd.h lcd_lib.h g15.
 glcdlib_SOURCES =    lcd.h lcd_lib.h glcdlib.h glcdlib.c report.h
 glk_SOURCES =        lcd.h glk.c glk.h glkproto.c glkproto.h report.h
 hd44780_SOURCES =    lcd.h lcd_lib.h hd44780.h hd44780.c hd44780-drivers.h hd44780-low.h hd44780-charmap.h report.h adv_bignum.h
-EXTRA_hd44780_SOURCES = hd44780-4bit.c hd44780-4bit.h hd44780-ext8bit.c hd44780-ext8bit.h lcd_sem.c lcd_sem.h hd44780-serialLpt.c hd44780-serialLpt.h hd44780-serial.c hd44780-serial.h hd44780-winamp.c hd44780-winamp.h hd44780-bwct-usb.c hd44780-bwct-usb.h hd44780-lcd2usb.c hd44780-lcd2usb.h hd44780-lis2.c hd44780-lis2.h hd44780-i2c.c hd44780-i2c.h port.h lpt-port.h timing.h
+EXTRA_hd44780_SOURCES = hd44780-4bit.c hd44780-4bit.h hd44780-ext8bit.c hd44780-ext8bit.h lcd_sem.c lcd_sem.h hd44780-serialLpt.c hd44780-serialLpt.h hd44780-serial.c hd44780-serial.h hd44780-winamp.c hd44780-winamp.h hd44780-bwct-usb.c hd44780-bwct-usb.h hd44780-lcd2usb.c hd44780-lcd2usb.h hd44780-lis2.c hd44780-lis2.h hd44780-i2c.c hd44780-i2c.h hd44780-ftdi.c hd44780-ftdi.h port.h lpt-port.h timing.h
 
 icp_a106_SOURCES =   lcd.h lcd_lib.h icp_a106.c icp_a106.h report.h
 imon_SOURCES =       lcd.h lcd_lib.h imon.h imon.c report.h

--Boundary-00=_BJMKH3C72dBYa1f--