New hd44780 subdriver: usb4all

Thomas Mohaupt <[email protected]> Tue, 7 Feb 2012 22:38:47 +0100
Newsgroups gmane.comp.sysutils.lcdproc
Message-ID <CABJvhemSWLxHSwawVJ=YzXJhB1BBvMeEZsoBMy7+nvyAs_HcFQ@mail.gmail.com>
Hi,

attached you will find a hd44780 subdriver for the usb4all
microcontroller board.
(http://sprut.de/electronic/pic/projekte/usb4all/usb4all.htm)

I have tried to fulfill all requirements for new driver/submission. So
I hope it can be included in the code base without/only small
modifications.

Regards,
ThoMo

_______________________________________________
LCDproc mailing list
[email protected]
http://lists.omnipotent.net/mailman/listinfo/lcdproc
hd44780-usb4all.patch (application/octet-stream, 12.8 KB)
? server/drivers/hd44780-usb4all.c
? server/drivers/hd44780-usb4all.h
Index: LCDd.conf
===================================================================
RCS file: /cvsroot/lcdproc/lcdproc/LCDd.conf,v
retrieving revision 1.162
diff -u -r1.162 LCDd.conf
--- LCDd.conf	1 Feb 2012 22:42:59 -0000	1.162
+++ LCDd.conf	7 Feb 2012 21:30:54 -0000
@@ -514,10 +514,10 @@
 # You may also need to configure the keypad layout further on in this file.
 Keypad=no
 
-# Set the initial contrast (bwctusb and lcd2usb) [default: 500; legal: 0 - 1000]
+# Set the initial contrast (bwctusb, lcd2usb and usb4all) [default: 500; legal: 0 - 1000]
 Contrast=0
 
-# Set brightness of the backlight (lcd2usb only) [default: 0; legal: 0 - 1000]
+# Set brightness of the backlight (lcd2usb and usb4all) [default: 0; legal: 0 - 1000]
 #Brightness=1000
 #OffBrightness=0
 
Index: acinclude.m4
===================================================================
RCS file: /cvsroot/lcdproc/lcdproc/acinclude.m4,v
retrieving revision 1.124
diff -u -r1.124 acinclude.m4
--- acinclude.m4	1 Feb 2012 22:42:59 -0000	1.124
+++ acinclude.m4	7 Feb 2012 21:30:55 -0000
@@ -216,7 +216,7 @@
 				HD44780_DRIVERS="$HD44780_DRIVERS hd44780-hd44780-4bit.o hd44780-hd44780-ext8bit.o hd44780-lcd_sem.o hd44780-hd44780-winamp.o hd44780-hd44780-serialLpt.o"
 			fi
 			if test "$enable_libusb" = yes ; then
-				HD44780_DRIVERS="$HD44780_DRIVERS hd44780-hd44780-bwct-usb.o hd44780-hd44780-lcd2usb.o hd44780-hd44780-uss720.o hd44780-hd44780-usbtiny.o"
+				HD44780_DRIVERS="$HD44780_DRIVERS hd44780-hd44780-bwct-usb.o hd44780-hd44780-lcd2usb.o hd44780-hd44780-uss720.o hd44780-hd44780-usbtiny.o hd44780-hd44780-usb4all.o"
 			fi
 			if test "$enable_libftdi" = yes ; then
 				HD44780_DRIVERS="$HD44780_DRIVERS hd44780-hd44780-ftdi.o"
Index: docs/LCDd.8.in
===================================================================
RCS file: /cvsroot/lcdproc/lcdproc/docs/LCDd.8.in,v
retrieving revision 1.37
diff -u -r1.37 LCDd.8.in
--- docs/LCDd.8.in	1 Feb 2012 22:42:59 -0000	1.37
+++ docs/LCDd.8.in	7 Feb 2012 21:30:55 -0000
@@ -193,6 +193,9 @@
 .TP
 .B usbtiny
 Devices based on Dick Streefland's USBtiny firmware
+.TP
+.B usb4all
+Sprut's open source/open hardware USB-4-all (http://www.sprut.de/electronic/pic/projekte/usb4all/usb4all.htm)
 .RE
 .TP
 .B i2500vfd
Index: docs/lcdproc-user/drivers/hd44780.docbook
===================================================================
RCS file: /cvsroot/lcdproc/lcdproc/docs/lcdproc-user/drivers/hd44780.docbook,v
retrieving revision 1.74
diff -u -r1.74 hd44780.docbook
--- docs/lcdproc-user/drivers/hd44780.docbook	2 Jan 2012 09:22:31 -0000	1.74
+++ docs/lcdproc-user/drivers/hd44780.docbook	7 Feb 2012 21:30:58 -0000
@@ -133,6 +133,12 @@
     <link linkend="hd44780-usblcd">usblcd</link>:
     USBLCD from Adams IT Services (<ulink url="http://www.usblcd.de/"></ulink>)
   </para></listitem>
+  
+  <listitem><para>
+    <link linkend="hd44780-usb4all">USB-4-all</link>:
+    Display connected to USB-4-all controller (<ulink url="http://www.sprut.de/"></ulink>)
+  </para></listitem>
+  
 </itemizedlist>
 
 <para>
@@ -2715,6 +2721,237 @@
 </note>
 </sect3>
 
+<sect3 id="hd44780-usb4all">
+<title>USB-4-all controller</title>
+
+<para>
+The USB-4-all controller board from Sprut (<ulink url="http://www.sprut.de/"></ulink>)
+is a small interface board which allows you to connect different hardware to the USB. 
+The subdriver for LCDproc supports dual HD44780 displays and a 4x4 keypad as well as 
+software adjustable contrast and brightness (backlight). 
+</para>
+
+<table id="hd44780-usb4all-display.mapping">
+<title>HD44780: USB-4-all - Display connection</title>
+<tgroup cols="4" align="left">
+<colspec colname="ctrl1" align="center"/>
+<colspec colname="ctrl2" align="center"/>
+<colspec colname="lcd1" align="center"/>
+<colspec colname="lcd2" align="center"/>
+  <thead>
+    <row>
+      <entry namest="ctrl1" nameend="ctrl2" align="center">USB-4-all</entry>
+      <entry align="center">LCD1</entry>
+      <entry align="center">LCD2</entry>
+    </row>
+    <row>
+      <entry>name</entry>
+      <entry>pin</entry>
+      <entry>name</entry>
+      <entry>name</entry>
+    </row>
+  </thead>
+  <tbody>
+    <row>
+      <entry>RB7</entry>
+      <entry>28</entry>
+      <entry>D7</entry>
+      <entry>D7</entry>
+    </row>
+    <row>
+      <entry>RB6</entry>
+      <entry>27</entry>
+      <entry>D6</entry>
+      <entry>D6</entry>
+    </row>
+    <row>
+      <entry>RB5</entry>
+      <entry>26</entry>
+      <entry>D5</entry>
+      <entry>D5</entry>
+    </row>
+    <row>
+      <entry>RB4</entry>
+      <entry>25</entry>
+      <entry>D4</entry>
+      <entry>D4</entry>
+    </row>
+    <row>
+      <entry>RB3</entry>
+      <entry>24</entry>
+      <entry>R/W</entry>
+      <entry>R/W</entry>
+    </row>
+    <row>
+      <entry>RB2</entry>
+      <entry>23</entry>
+      <entry>RS</entry>
+      <entry>RS</entry>
+    </row>
+    <row>
+      <entry>RB0</entry>
+      <entry>21</entry>
+      <entry>EN</entry>
+      <entry> </entry>
+    </row>
+    <row>
+      <entry>RC0</entry>
+      <entry>11</entry>
+      <entry> </entry>
+      <entry>EN</entry>
+    </row>
+  </tbody>
+</tgroup>
+</table>
+
+<table id="hd44780-usb4all-keypad.mapping">
+<title>HD44780: USB-4-all - Keypad connection</title>
+<tgroup cols="3" align="left">
+<colspec colname="ctrl1" align="center"/>
+<colspec colname="ctrl2" align="center"/>
+<colspec colname="keypad" align="center"/>
+  <thead>
+    <row>
+      <entry namest="ctrl1" nameend="ctrl2" align="center">USB-4-all</entry>
+      <entry align="center">keypad</entry>
+    </row>
+    <row>
+      <entry>name</entry>
+      <entry>pin</entry>
+      <entry>name</entry>
+    </row>
+  </thead>
+  <tbody>
+    <row>
+      <entry>RA0</entry>
+      <entry>2</entry>
+      <entry>X1</entry>
+    </row>
+    <row>
+      <entry>RA1</entry>
+      <entry>3</entry>
+      <entry>X2</entry>
+    </row>
+    <row>
+      <entry>RA2</entry>
+      <entry>4</entry>
+      <entry>X3</entry>
+    </row>
+    <row>
+      <entry>RA3</entry>
+      <entry>5</entry>
+      <entry>X4</entry>
+    </row>
+    <row>
+      <entry>RA4</entry>
+      <entry>6</entry>
+      <entry>Y1</entry>
+    </row>
+    <row>
+      <entry>RA5</entry>
+      <entry>7</entry>
+      <entry>Y2</entry>
+    </row>
+    <row>
+      <entry>RC6</entry>
+      <entry>17</entry>
+      <entry>Y3</entry>
+    </row>
+    <row>
+      <entry>RC7</entry>
+      <entry>18</entry>
+      <entry>Y4</entry>
+    </row>
+  </tbody>
+</tgroup>
+</table>
+
+<table id="hd44780-usb4all-analog.mapping">
+<title>HD44780: USB-4-all - Brightness and contrast connection</title>
+<tgroup cols="3" align="left">
+<colspec colname="ctrl1" align="center"/>
+<colspec colname="ctrl2" align="center"/>
+<colspec colname="analog" align="center"/>
+  <thead>
+    <row>
+      <entry namest="ctrl1" nameend="ctrl2" align="center">USB-4-all</entry>
+      <entry align="center">Desc</entry>
+    </row>
+    <row>
+      <entry>name</entry>
+      <entry>pin</entry>
+      <entry> </entry>
+    </row>
+  </thead>
+  <tbody>
+    <row>
+      <entry>RC1</entry>
+      <entry>12</entry>
+      <entry>brightness</entry>
+    </row>
+    <row>
+      <entry>RC2</entry>
+      <entry>13</entry>
+      <entry>contrast</entry>
+    </row>
+  </tbody>
+</tgroup>
+</table>
+
+
+<figure id="hd44780-usb4all-brightness.block-diagram">
+<title>HD44780: USB-4-all brightness control</title>
+<screen>
+<![CDATA[
+                          o 5V (PIC Pin 20)
+                          |
+                          |e
+               ___    b |/
+   RC1 o------|___|-----|    pnp 
+               10k      |\
+                          |c
+                          |
+                          -
+                         | | 10R
+                         | |
+                          -
+                          |
+                          +---> LCD 15 (+ Backlight)
+
+                          +---> LCD 16 (- Backlight)
+                          |
+                         === GND
+]]>                           
+</screen>
+</figure>
+
+<figure id="hd44780-usb4all-contrast.block-diagram">
+<title>HD44780: USB-4-all contrast control</title>
+<screen>
+<![CDATA[
+                           o 5V (PIC Pin 20)
+                           |
+                           -
+                          | |4,7k
+                          | |
+                           -
+                           |     ____
+                           +----|____|-----+----> LCD 3 (Contrast)
+                           |c    680R      |
+               ___     b |/                |+
+   RC2 o------|___|------|  npn           --- 10yF
+               22k       |\               ---
+                           |e              |
+                           |               |
+                           |               |
+                          ===             === GND
+]]>                           
+</screen>
+</figure>
+
+</sect3>
+
+
 </sect2>
 
 
Index: server/drivers/Makefile.am
===================================================================
RCS file: /cvsroot/lcdproc/lcdproc/server/drivers/Makefile.am,v
retrieving revision 1.107
diff -u -r1.107 Makefile.am
--- server/drivers/Makefile.am	1 Feb 2012 22:42:59 -0000	1.107
+++ server/drivers/Makefile.am	7 Feb 2012 21:30:59 -0000
@@ -94,7 +94,7 @@
 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-usbtiny.c hd44780-usbtiny.h hd44780-lis2.c hd44780-lis2.h hd44780-i2c.c hd44780-i2c.h hd44780-ftdi.c hd44780-ftdi.h hd44780-ethlcd.c hd44780-ethlcd.h hd44780-uss720.c hd44780-uss720.h hd44780-usblcd.c hd44780-usblcd.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-usbtiny.c hd44780-usbtiny.h hd44780-lis2.c hd44780-lis2.h hd44780-i2c.c hd44780-i2c.h hd44780-ftdi.c hd44780-ftdi.h hd44780-ethlcd.c hd44780-ethlcd.h hd44780-uss720.c hd44780-uss720.h hd44780-usblcd.c hd44780-usblcd.h hd44780-usb4all.c hd44780-usb4all.h port.h lpt-port.h timing.h
 i2500vfd_SOURCES =   lcd.h i2500vfd.c i2500vfd.h glcd_font5x8.h report.h
 icp_a106_SOURCES =   lcd.h lcd_lib.h icp_a106.c icp_a106.h report.h
 imon_SOURCES =       lcd.h lcd_lib.h hd44780-charmap.h imon.h imon.c report.h adv_bignum.h
Index: server/drivers/hd44780-drivers.h
===================================================================
RCS file: /cvsroot/lcdproc/lcdproc/server/drivers/hd44780-drivers.h,v
retrieving revision 1.29
diff -u -r1.29 hd44780-drivers.h
--- server/drivers/hd44780-drivers.h	15 Jan 2011 19:36:16 -0000	1.29
+++ server/drivers/hd44780-drivers.h	7 Feb 2012 21:30:59 -0000
@@ -24,6 +24,7 @@
 # include "hd44780-lcd2usb.h"
 # include "hd44780-usbtiny.h"
 # include "hd44780-uss720.h"
+# include "hd44780-usb4all.h"
 #endif
 #ifdef HAVE_LIBFTDI
 # include "hd44780-ftdi.h"
@@ -68,6 +69,7 @@
 	{ "lcd2usb",       HD44780_CT_LCD2USB,       IF_TYPE_USB,     hd_init_lcd2usb   },
 	{ "usbtiny",       HD44780_CT_USBTINY,       IF_TYPE_USB,     hd_init_usbtiny   },
 	{ "uss720",        HD44780_CT_USS720,        IF_TYPE_USB,     hd_init_uss720    },
+	{ "usb4all",       HD44780_CT_USB4ALL,       IF_TYPE_USB,     hd_init_usb4all   },
 #endif
 #ifdef HAVE_LIBFTDI
 	{ "ftdi",          HD44780_CT_FTDI,          IF_TYPE_USB,     hd_init_ftdi      },
Index: server/drivers/hd44780-low.h
===================================================================
RCS file: /cvsroot/lcdproc/lcdproc/server/drivers/hd44780-low.h,v
retrieving revision 1.50
diff -u -r1.50 hd44780-low.h
--- server/drivers/hd44780-low.h	30 Dec 2011 00:21:30 -0000	1.50
+++ server/drivers/hd44780-low.h	7 Feb 2012 21:30:59 -0000
@@ -52,6 +52,7 @@
 #define HD44780_CT_USS720		18
 #define HD44780_CT_USBLCD		19
 #define HD44780_CT_USBTINY		20
+#define HD44780_CT_USB4ALL              21
 /**@}*/
 
 /** \name Symbolic names for interface types
@@ -132,6 +133,10 @@
 	/* libusb-based connection types */
 	usb_dev_handle *usbHandle;	/**< USB device handle */
 	int usbIndex;		/**< USB interface index */
+	int usbMode;                /**< USB write mode (bulk or interrupt)*/
+	int usbEpOut;               /**< USB Endpoint Out */
+	int usbEpIn;                /**< USB Endpoint In */
+	tx_buffer rx_buf;           /**< Input buffer */
 #endif
 
 #ifdef HAVE_LIBFTDI
hd44780-usb4all.c (text/x-csrc, 13.2 KB)
/** \file server/drivers/hd44780-usb4all.c
 * USB-4-all connection type of hd44780 driver for
 * Hitachi HD44780 based LCD displays.
 *
 * USB-4-all is PIC based USB controller, see
 * http://www.sprut.de/electronic/pic/projekte/usb4all/usb4all.htm
 *
 * Some code parts are adapted from Roland Wundrig linux demo code
 * (part of usb4all package)
 *
 */

/*-
 * Copyright (C) 2012 Thomas Mohaupt <[email protected]>
 *               2010 Roland Wundrig <http://wundrig.de/>
 *
 * This file is released under the GNU General Public License version 2.
 * Refer to the COPYING file distributed with this package.
 */

#ifdef HAVE_CONFIG_H
# include "config.h"
#endif

#include <stdio.h>
#include <stdlib.h>
#include <usb.h>

#include "hd44780-usb4all.h"
#include "hd44780-low.h"
#include "report.h"

/* connection type specific functions to be exposed using pointers in init() */
void usb4all_HD44780_senddata(PrivateData *p,
                              unsigned char displayID,
                              unsigned char flags,
                              unsigned char ch);
void usb4all_HD44780_close(PrivateData *p);
void usb4all_HD44780_backlight(PrivateData *p, unsigned char state);
void usb4all_HD44780_set_contrast(PrivateData *p, unsigned char value);
unsigned char usb4all_HD44780_readkeypad(PrivateData *p, unsigned int Ydata);

/**
 * Send a command with data to usb4all controller and reads the answer.
 * Even if some inputs should be read a command to do this has to send before.
 * \param p            pointer to private data structure
 * \param data_out     pointer to data send to controller
 * \param data_in      pointer to buffer where read in data is stored
 * \return             number of bytes read in
 */
int
usb4all_data_io(PrivateData *p, tx_buffer *data_out, tx_buffer *data_in)
{
	int res;

	if (p->usbMode == MODE_BULK) {
		res = usb_bulk_write(p->usbHandle,
		                     p->usbEpOut,
		                     (char *) data_out->buffer,
		                     data_out->use_count,
		                     TIMEOUT_WRITE);
	}
	else {
		res = usb_interrupt_write(p->usbHandle,
		                          p->usbEpOut,
		                          (char *) data_out->buffer,
		                          data_out->use_count,
		                          TIMEOUT_WRITE);
	}

	if (res < 0) {
		p->hd44780_functions->drv_report(RPT_WARNING,
		    "usb4all_data_io: unable to send, result = %d ...", res);
		return -1;
	}

	// if a reset command is send the usb4all controller doesn't answer
	if (data_out->buffer[0] == USB4ALL_RESET) {
		return 0;
	}

	if (res != data_out->use_count) {
		p->hd44780_functions->drv_report(RPT_WARNING,
		    "usb4all_data_io: Want to send %d bytes but currently only %d bytes was send!?",
		    data_out->use_count, res);
		return -1;
	}

	if (p->usbMode == MODE_BULK) {
		res = usb_bulk_read(p->usbHandle,
		                    p->usbEpIn,
		                    (char *) data_in->buffer,
		                    USB4ALL_RX_MAX,
		                    TIMEOUT_READ);
	} else {
		res = usb_interrupt_read(p->usbHandle,
		                         p->usbEpIn,
		                         (char *) data_in->buffer,
		                         USB4ALL_RX_MAX,
		                         TIMEOUT_READ);
	}

	return res;
}

/**
 * Set the pwm value on the pwm channel
 * \param p            pointer to private date structure
 * \param pwm_channel  the pwm channel
 * \param value        the high-part of each pwm cylce
 */
void
usb4all_set_pwm_value(PrivateData *p, unsigned char pwm_channel, unsigned char value)
{
	p->tx_buf.buffer[0] = 0x56 + pwm_channel;
	p->tx_buf.buffer[1] = 0x02;
	p->tx_buf.buffer[2] = value;
	p->tx_buf.buffer[3] = 0x00;
	p->tx_buf.use_count = 4;
	usb4all_data_io(p, &p->tx_buf, &p->rx_buf);
}

/**
 * Init the usb-4-all controller part for PWM
 * The PWM outputs can be used to control bightness and contrast
 * \param p            pointer to private date structure
 * \param pwm_channel  channel to initialize (1 or 2)
 */
void
usb4all_init_pwm(PrivateData *p, unsigned char pwm_channel)
{
	p->hd44780_functions->drv_report(RPT_INFO,
	    "init usb4all controller for PWM channel %d ", pwm_channel);

	p->tx_buf.buffer[0] = 0x056 + pwm_channel;
	p->tx_buf.buffer[1] = 0x01;
	p->tx_buf.buffer[2] = 0x05;
	p->tx_buf.use_count = 3;
	usb4all_data_io(p, &p->tx_buf, &p->rx_buf);
}

/**
 * Init the usb-4-all controller part for digital I/O (keypad)
 * \param p          pointer to private date structure
 */
void
usb4all_init_keypad(PrivateData *p)
{
	p->hd44780_functions->drv_report(RPT_INFO, "init usb4all controller for keypad");

	/* Input  lines (X) RA0, RA1, RA2, RA3*/
	p->tx_buf.buffer[0] = 0x50;
	p->tx_buf.buffer[1] = 0x04;
	p->tx_buf.buffer[2] = 0x0F;
	p->tx_buf.buffer[3] = 0x00;
	p->tx_buf.buffer[4] = 0x00;
	p->tx_buf.use_count = 5;
	usb4all_data_io(p, &p->tx_buf, &p->rx_buf);

	/* Output lines (Y) RA4, RA5, RC6, RC7*/
	p->tx_buf.buffer[1] = 0x05;
	p->tx_buf.buffer[2] = 0x30;
	p->tx_buf.buffer[3] = 0x00;
	p->tx_buf.buffer[4] = 0xC0;
	usb4all_data_io(p, &p->tx_buf, &p->rx_buf);
}

/**
 * Init the usb-4-all controller part for LCD displays
 * \param p          pointer to private date structure
 * \param displayID  display to init
 * \param rows       number of lines
 * \param cols       number of characters
 */
void
usb4all_init_lcd(PrivateData *p, unsigned char displayID, unsigned char rows, unsigned char cols)
{
	p->hd44780_functions->drv_report(RPT_INFO,
	    "init usb4all controller for display %d ", displayID);

	p->tx_buf.buffer[0] = 0x054 + displayID;
	p->tx_buf.buffer[1] = 0x01;
	p->tx_buf.buffer[2] = rows;
	p->tx_buf.buffer[3] = cols;
	p->tx_buf.use_count = 4;
	usb4all_data_io(p, &p->tx_buf, &p->rx_buf);
}

/**
 * Init the usb-4-all controller
 * \param p          pointer to private date structure
 */
void
usb4all_init(PrivateData *p)
{
	usb4all_init_lcd(p, 1, p->dispVOffset[0], p->width);
	if (p->numDisplays == 2) {
		usb4all_init_lcd(p, 2, p->dispVOffset[1], p->width);
	}

	usb4all_init_pwm(p, USB4ALL_PWM_CONTRAST);
	if (p->have_backlight) {
		usb4all_init_pwm(p, USB4ALL_PWM_BRIGHTNESS);
	}

	if (p->have_keypad) {
		usb4all_init_keypad(p);
	}
}

/**
 * Identifies the usb transfer mode and endpoint addresses.
 * Values are stored in the corresponding private data
 * fields (usbMode, usbEpIn and usbEpOut).
 * \param p      Pointer to PrivateData structure
 * \param iface  Pointer to USB interface descriptor
 */
void
usb4all_determine_usb_params(PrivateData *p, struct usb_interface_descriptor *iface)
{
	p->usbMode = -1;

	if ((iface->endpoint[0].bmAttributes&USB_ENDPOINT_TYPE_MASK) == USB_ENDPOINT_TYPE_INTERRUPT &&
	    (iface->endpoint[1].bmAttributes&USB_ENDPOINT_TYPE_MASK) == USB_ENDPOINT_TYPE_INTERRUPT) {
		p->usbMode = MODE_INT;
	}
	if ((iface->endpoint[0].bmAttributes&USB_ENDPOINT_TYPE_MASK) == USB_ENDPOINT_TYPE_BULK &&
	    (iface->endpoint[1].bmAttributes&USB_ENDPOINT_TYPE_MASK) == USB_ENDPOINT_TYPE_BULK) {
		p->usbMode =  MODE_BULK;
	}

	if (p->usbMode == -1) {
		p->hd44780_functions->drv_report(RPT_ERR,
		    "Unsupported USB_ENDPOINT_TYPE = %d / %d",
		    iface->endpoint[0].bmAttributes&USB_ENDPOINT_TYPE_MASK,
		    iface->endpoint[1].bmAttributes&USB_ENDPOINT_TYPE_MASK);
		return;
	}

	if (iface->endpoint[0].bEndpointAddress & USB_ENDPOINT_DIR_MASK) {
		p->usbEpIn  = iface->endpoint[0].bEndpointAddress & USB_ENDPOINT_ADDRESS_MASK;
		p->usbEpOut = iface->endpoint[1].bEndpointAddress & USB_ENDPOINT_ADDRESS_MASK;
	}
	else {
		p->usbEpIn  = iface->endpoint[1].bEndpointAddress & USB_ENDPOINT_ADDRESS_MASK;
		p->usbEpOut = iface->endpoint[0].bEndpointAddress & USB_ENDPOINT_ADDRESS_MASK;
	}
}

/**
 * Pseudo (empty) uPause function.
 * Override the uPause function as a usb4all device takes care of timing itself.
 * \param p      Pointer to PrivateData structure (unused)
 * \param usecs  Number of micro-seconds to sleep (ignored)
 */
void
usb4all_HD44780_uPause(PrivateData *p, int usecs)
{
}


/**
 * Initialize the driver.
 * \param drvthis  Pointer to driver structure.
 * \retval 0       Success.
 * \retval -1      Error.
 */
int
hd_init_usb4all(Driver *drvthis)
{
	PrivateData *p = (PrivateData *) drvthis->private_data;

	struct usb_bus *bus;

	p->hd44780_functions->senddata = usb4all_HD44780_senddata;
	p->hd44780_functions->close = usb4all_HD44780_close;

	p->hd44780_functions->set_contrast = usb4all_HD44780_set_contrast;
	p->hd44780_functions->backlight = usb4all_HD44780_backlight;
	p->hd44780_functions->readkeypad = usb4all_HD44780_readkeypad;

	/* try to find USB device */
	usb_init();
	usb_find_busses();
	usb_find_devices();

	p->usbHandle = NULL;
	for (bus = usb_get_busses(); bus != NULL; bus = bus->next) {
		struct usb_device *dev;

		for (dev = bus->devices; dev != NULL; dev = dev->next) {

			/* Check if this device is a usb4all device */
			if ((dev->descriptor.idVendor == USB4ALL_VENDORID) &&
			    (dev->descriptor.idProduct == USB4ALL_PRODUCTID)) {

				/* USB-4-all device found; try to open it */
				p->usbHandle = usb_open(dev);
				if (p->usbHandle == NULL) {
					report(RPT_WARNING,
					  "hd_init_usb4all: unable to open device");
					/*
					 * Do not exit here because other
					 * (possibly working) devices may
					 * be connected.
					 */
				}
				else {
					report(RPT_INFO,
					  "hd_init_usb4all: USB-4-all device found");
					usb4all_determine_usb_params(p,
					  &dev->config[0].interface[0].altsetting[0]);
				}
			}
		}
	}

	/* No device found at all */
	if (p->usbHandle == NULL) {
		report(RPT_ERR, "hd_init_usb4all: no (matching) USB-4-all device found");
		return -1;
	}

	if (p->usbMode == -1) {
		report(RPT_ERR, "hd_init_usb4all: unknown usb mode");
		return -1;
	}

	/* allocate and initialize buffer */
	if ((p->tx_buf.buffer = malloc(USB4ALL_TX_MAX)) == NULL) {
		report(RPT_ERR, "hd_init_usb4all: could not allocate send buffer");
		usb4all_HD44780_close(p);
		return -1;
	}

	if ((p->rx_buf.buffer = malloc(USB4ALL_RX_MAX)) == NULL) {
		report(RPT_ERR, "hd_init_usb4all: could not allocate receive buffer");
		usb4all_HD44780_close(p);
		return -1;
	}

	common_init(p, IF_4BIT);

	/* replace uPause with empty one after initialization */
	p->hd44780_functions->uPause = usb4all_HD44780_uPause;

	// initialize usb-4-all controller
	usb4all_init(p);

	return 0;
}

/**
 * Send a single byte of data to the LCD.
 * \param p       pointer to private date structure
 * \param dispID  display to send data to (0 = all displays)
 * \param flags   data or instruction command (RS_DATA | RS_INSTR)
 * \param ch      character to display or instruction value
 */ 
void
usb4all_HD44780_senddata(PrivateData *p, unsigned char displayID, unsigned char flags, unsigned char ch)
{
	if (displayID == 0) {
		usb4all_HD44780_senddata(p, 1, flags, ch);
		if (p->numDisplays == 2) {
			usb4all_HD44780_senddata(p, 2, flags, ch);
		}
		return;
	}

	p->tx_buf.buffer[0] = 0x54 + displayID;
	p->tx_buf.buffer[1] = (flags == RS_DATA) ? 0x02 : 0x03;
	p->tx_buf.buffer[2] = ch;
	p->tx_buf.use_count = 3;
	usb4all_data_io(p, &p->tx_buf, &p->rx_buf);
}

/**
 * Turn display backlight on or off.
 * Backlight is turned on or off by toggeling between the brightness
 * and offbrightness values.
 * \param p      Pointer to driver's private data structure.
 * \param state  New backlight status.
 */
void
usb4all_HD44780_backlight(PrivateData *p, unsigned char state)
{
	/* get backlight brightness */
	int promille = (state == BACKLIGHT_ON) ? p->brightness : p->offbrightness;

	p->hd44780_functions->drv_debug(RPT_DEBUG,
	    "usb4all_HD44780_backlight: Setting backlight to %d", promille);

	/* and set it (converted from [0,1000] -> [255,0]) */
	usb4all_set_pwm_value(p, USB4ALL_PWM_BRIGHTNESS, ((1000 - promille) * 255) / 1000);
}

/**
 * Change display contrast.
 * \param p      Pointer to driver's private data structure.
 * \param value  New contrast value (one byte).
 */
void
usb4all_HD44780_set_contrast(PrivateData *p, unsigned char value)
{
	p->hd44780_functions->drv_debug(RPT_DEBUG,
	    "usb4all_HD44780_set_contrast: Setting contrast to %d", value);
	usb4all_set_pwm_value(p, USB4ALL_PWM_CONTRAST, value);
}

/**
 * Read the keypad
 * \param Ydata  the up to 4 bits that should be put on the Y side of the matrix
 * \return       the up to 4 bits that are read out on the X side of the matrix
 */
unsigned char
usb4all_HD44780_readkeypad(PrivateData *p, unsigned int Ydata)
{
	/* adjust and invert bits */
	Ydata = ((Ydata << 4) ^ 0xF0);

	/* Output lines (Y) are RA4, RA5, RC6, RC7 */
	p->tx_buf.buffer[0] = 0x50;
	p->tx_buf.buffer[1] = 0x02;
	p->tx_buf.buffer[2] = Ydata & 0x30;
	p->tx_buf.buffer[3] = 0x00;
	p->tx_buf.buffer[4] = Ydata & 0xC0;
	p->tx_buf.use_count = 5;

	usb4all_data_io(p, &p->tx_buf, &p->rx_buf);

	/* Read RA3 RA2 RA1 RA0 */
	p->tx_buf.buffer[0] = 0x50;
	p->tx_buf.buffer[1] = 0x03;
	p->tx_buf.use_count = 2;
	usb4all_data_io(p, &p->tx_buf, &p->rx_buf);

	/* filter and invert the result */
	return ((p->rx_buf.buffer[2] & 0x0F) | 0xF0) ^ 0xFF;
}

/**
 * Close the driver (do necessary clean-up).
 * \param p  Pointer to driver's private data structure.
 */
void
usb4all_HD44780_close(PrivateData *p)
{
	if (p->usbHandle != NULL) {
		if (p->have_backlight) {
			usb4all_HD44780_backlight(p, BACKLIGHT_OFF);
		}

		usb_close(p->usbHandle);
		p->usbHandle = NULL;
	}

	if (p->tx_buf.buffer != NULL) {
		free(p->tx_buf.buffer);
		p->tx_buf.buffer = NULL;
	}

	if (p->rx_buf.buffer != NULL) {
		free(p->rx_buf.buffer);
		p->rx_buf.buffer = NULL;
	}

}

/* EOF */
hd44780-usb4all.h (text/x-chdr, 1.7 KB)
/** \file server/drivers/hd44780-usb4all.h
 * USB-4-all connection type of hd44780 driver for
 * Hitachi HD44780 based LCD displays.
 *
 * USB-4-all is PIC based USB controller, see
 * http://www.sprut.de/electronic/pic/projekte/usb4all/usb4all.htm
 *
 * Some code parts are adapted from Roland Wundrig linux demo code
 * (part of usb4all package)
 *
 */

/*-
 * Copyright (C) 2012 Thomas Mohaupt <[email protected]>
 *               2010 Roland Wundrig <http://wundrig.de/>
 *
 * This file is released under the GNU General Public License version 2.
 * Refer to the COPYING file distributed with this package.
 *
 * This is a HD44780 subdriver for an USB-4-all controller with display.
 * It supports to
 * - 2 displays with each up to 2x40 or 4x20 lines/characters.
 * - contrast control (PWM1)
 * - brightness control (PWM2)
 * - 4x4 keypad (RA0 - RA3 - X lines, RA4, RA5, RC6, RC7 - Y lines)
 *
 * Only the MCD version is supported!
 *
 */

#ifndef HD_USB4ALL_H
#define HD_USB4ALL_H

#include "lcd.h"		/* for Driver */

/* vendor and product id */
#define USB4ALL_VENDORID   0x004D8
#define USB4ALL_PRODUCTID  0x0FF0B

/* USB read/write timeouts */
#define TIMEOUT_READ   1000
#define TIMEOUT_WRITE  1000

/* USB transfer modes */
#define MODE_INT   0x04    /* usb interface : interrup mode */
#define MODE_BULK  0x08    /* usb interface : bulk mode */

#define USB4ALL_TX_MAX  64  /* usb4all tx buffer size */
#define USB4ALL_RX_MAX  16  /* usb4all rx buffer size */

/* assignment of PWM channels*/
#define USB4ALL_PWM_CONTRAST    0x01  /* PWM channel used for contrast*/
#define USB4ALL_PWM_BRIGHTNESS  0x02  /* PWM channel used for brightness*/

#define USB4ALL_RESET   0xFF

/* initialise this particular driver */
int hd_init_usb4all(Driver *drvthis);

#endif