Re: Raspberry Pi as an inexpensive embedded LCDproc server
paul_c <[email protected]> Sun, 19 Aug 2012 14:28:31 +0100
| Newsgroups | gmane.comp.sysutils.lcdproc |
|---|---|
| Message-ID | <[email protected]> |
On Saturday 18 August 2012, Ethan Dicks wrote: > There would need to be some driver mods to use R-Pi GPIO Attached, first draft of a patch to drive a 44780 module using the gpio on a Raspberry Pi. Connected as a 4bit device to keep the wires down, it assumes only a single display is attached. Connections are: * header (gpio) LCD * P1-12 (18) D7 (14) * P1-16 (23) D6 (13) * P1-18 (24) D5 (12) * P1-22 (25) D4 (11) * P1-24 (8) EN (6) * P1-26 (7) RS (4) See: http://www.raspberrypi-spy.co.uk/2012/07/16x2-lcd-module-control-using-python/ for further details and a python test program. As the patch also touches on the configure & makefiles, autotools (aclocal, autoconf & automake) need to be installed - pkglib_PROGRAMS is now an invalid option, so a small tweak was required in server/drivers/Makefile.am to work round the problem. In use, the ConnectionType under [hd44780] is simply "rpi". Regards, Paul. _______________________________________________ LCDproc mailing list [email protected] http://lists.omnipotent.net/mailman/listinfo/lcdproc
RaspberryPi.patch
(text/x-diff, 12.1 KB)
diff -uprN /tmp/lcdproc-0.5.5/acinclude.m4 ./acinclude.m4
--- /tmp/lcdproc-0.5.5/acinclude.m4 2011-08-14 12:29:14.000000000 +0000
+++ ./acinclude.m4 2012-08-17 22:55:46.306836891 +0000
@@ -196,7 +196,7 @@ dnl else
actdrivers=["$actdrivers glk"]
;;
hd44780)
- HD44780_DRIVERS="hd44780-hd44780-serial.o hd44780-hd44780-lis2.o hd44780-hd44780-usblcd.o"
+ HD44780_DRIVERS="hd44780-hd44780-serial.o hd44780-hd44780-lis2.o hd44780-hd44780-usblcd.o hd44780-hd44780-rpi.o"
if test "$ac_cv_port_have_lpt" = yes ; then
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
diff -uprN /tmp/lcdproc-0.5.5/server/drivers/hd44780-drivers.h ./server/drivers/hd44780-drivers.h
--- /tmp/lcdproc-0.5.5/server/drivers/hd44780-drivers.h 2011-08-14 12:29:16.000000000 +0000
+++ ./server/drivers/hd44780-drivers.h 2012-08-19 11:42:49.499403978 +0000
@@ -34,6 +34,9 @@
#ifdef WITH_ETHLCD
# include "hd44780-ethlcd.h"
#endif
+#ifdef __ARMEL__
+# include "hd44780-rpi.h"
+#endif
# include "hd44780-usblcd.h"
/* add new connection type header files to the correct section above or here */
@@ -80,6 +83,9 @@ static const ConnectionMapping connectio
#ifdef WITH_ETHLCD
{ "ethlcd", HD44780_CT_ETHLCD, IF_TYPE_TCP, hd_init_ethlcd },
#endif
+#ifdef __ARMEL__
+ { "rpi", HD44780_CT_4BIT, IF_TYPE_PARPORT, hd_init_rpi },
+#endif
/* add new connection types in the correct section above or here */
/* default, end of structure element (do not delete) */
diff -uprN /tmp/lcdproc-0.5.5/server/drivers/hd44780-rpi.c ./server/drivers/hd44780-rpi.c
--- /tmp/lcdproc-0.5.5/server/drivers/hd44780-rpi.c 1970-01-01 00:00:00.000000000 +0000
+++ ./server/drivers/hd44780-rpi.c 2012-08-19 12:57:11.009325393 +0000
@@ -0,0 +1,258 @@
+/** \file server/drivers/hd44780-4bit.c
+ * \c 4bit connection type of \c hd44780 driver for Hitachi HD44780 based LCD displays.
+ *
+ * The LCD is operated in its 4 bit-mode to be connected to the gpio pins on the Raspberry Pi.
+ */
+
+/* Copyright (c) 2012 Paul Corner <[email protected]>
+ * 2000, 1999, 1995 Benjamin Tse <[email protected]>
+ * 2001 Joris Robijn <[email protected]>
+ * 1999 Andrew McMeikan <[email protected]>
+ * 1998 Richard Rognlie <[email protected]>
+ * 1997 Matthias Prinke <[email protected]>
+ *
+ * The connections are:
+ * header (gpio) LCD
+ * P1-12 (18) D7 (14)
+ * P1-16 (23) D6 (13)
+ * P1-18 (24) D5 (12)
+ * P1-22 (25) D4 (11)
+ * P1-24 (8) EN (6)
+ * P1-26 (7) RS (4)
+*/
+
+#define D7 18
+#define D6 23
+#define D5 24
+#define D4 25
+#define RS 7
+#define EN 8
+
+
+/*
+ *
+ * RW (5) MUST be hard wired low to prevent 5V logic appearing on
+ * the gpio pins.
+ *
+ * Only a single LCD is currently supported - That may change along with
+ * i2c connected devices.
+ *
+ *
+ * Based in part on the hd44780-4bit driver.
+ *
+ * This file is released under the GNU General Public License. Refer to the
+ * COPYING file distributed with this package.
+ */
+
+#include "hd44780-rpi.h"
+#include "hd44780-low.h"
+#include "port.h"
+#include "report.h"
+
+#include <stdio.h>
+#include <string.h>
+#include <stdlib.h>
+#include <errno.h>
+#include <dirent.h>
+#include <fcntl.h>
+#include <assert.h>
+#include <sys/mman.h>
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <unistd.h>
+
+// Generally, any function that accesses the LCD control lines needs to be
+// implemented separately for each HW design. This is typically (but not
+// restricted to):
+// HD44780_senddata
+// HD44780_readkeypad
+
+void lcdrpi_HD44780_senddata(PrivateData *p, unsigned char displayID, unsigned char flags, unsigned char ch);
+
+// To be implemented at some point if required..
+void lcdrpi_HD44780_backlight(PrivateData *p, unsigned char state);
+unsigned char lcdrpi_HD44780_readkeypad(PrivateData *p, unsigned int YData);
+
+static unsigned char *gpio_mem = NULL;
+static unsigned char *gpio_map = NULL;
+
+// I/O access
+static volatile unsigned int *gpio = NULL;
+
+// Set up a memory regions to access GPIO
+static int setup_io(Driver *drvthis)
+{
+ int mem_fd = 0;
+ /* open /dev/mem */
+ if (gpio != NULL) {
+ report(RPT_ERR, "IO already in use.");
+ return -1;
+ }
+ if ((mem_fd = open("/dev/mem", O_RDWR|O_SYNC) ) < 0) {
+ report(RPT_ERR, "can not open /dev/mem");
+ return -1;
+ }
+
+ if ((gpio_mem = malloc(BLOCK_SIZE + (PAGE_SIZE-1))) == NULL) {
+ report(RPT_ERR, "memory allocation error");
+ return -1;
+ }
+
+ if ((unsigned long)gpio_mem % PAGE_SIZE)
+ gpio_mem += PAGE_SIZE - ((unsigned long)gpio_mem % PAGE_SIZE);
+ gpio_map = (unsigned char *)mmap((caddr_t)gpio_mem,
+ BLOCK_SIZE, PROT_READ|PROT_WRITE,
+ MAP_SHARED|MAP_FIXED, mem_fd, GPIO_BASE);
+
+ if ((long)gpio_map < 0) {
+ report(RPT_ERR, "mmap error %d", (int)gpio_map);
+ return -1;
+ }
+ close(mem_fd); // Done with mem_fd and don't need to use it again.
+
+ // Always use volatile pointer!
+ gpio = (volatile unsigned *)gpio_map;
+ return 0;
+}
+
+
+/**
+ * Initialize the driver.
+ * \param drvthis Pointer to driver structure.
+ * \retval 0 Success.
+ * \retval -1 Error.
+ */
+int
+hd_init_rpi(Driver *drvthis)
+{
+ PrivateData *p = (PrivateData*) drvthis->private_data;
+
+ if (setup_io(drvthis) < 0) {
+ report(RPT_ERR, "Failed to set up gpio.");
+ return -1;
+ }
+ p->hd44780_functions->senddata = lcdrpi_HD44780_senddata;
+ // Next two are stubbed functions.
+ p->hd44780_functions->backlight = lcdrpi_HD44780_backlight;
+ p->hd44780_functions->readkeypad = lcdrpi_HD44780_readkeypad;
+
+ // Set up pins for output - INP_GPIO must be used before OUT_GPIO
+ // can be used.
+ INP_GPIO(D7);
+ OUT_GPIO(D7);
+ INP_GPIO(D6);
+ OUT_GPIO(D6);
+ INP_GPIO(D5);
+ OUT_GPIO(D5);
+ INP_GPIO(D4);
+ OUT_GPIO(D4);
+
+ INP_GPIO(RS);
+ OUT_GPIO(RS);
+ INP_GPIO(EN);
+ OUT_GPIO(EN);
+
+ // setup the lcd in 4 bit mode
+ p->hd44780_functions->senddata(p, 0, RS_INSTR, /*FUNCSET | IF_8BIT*/ 0x33);
+ p->hd44780_functions->uPause(p, 4100);
+ p->hd44780_functions->senddata(p, 0, RS_INSTR, /*FUNCSET | IF_4BIT*/ 0x32);
+ p->hd44780_functions->uPause(p, 150);
+
+ common_init(p, IF_4BIT);
+
+ return 0;
+}
+
+
+/**
+ * Send data or commands to the display.
+ * \param p Pointer to driver's private data structure.
+ * \param displayID ID of the display (or 0 for all) to send data to.
+ * \param flags Defines whether to end a command or data.
+ * \param ch The value to send.
+ */
+void
+lcdrpi_HD44780_senddata(PrivateData *p, unsigned char displayID, unsigned char flags, unsigned char ch)
+{
+
+ unsigned int set = 0x0000;
+
+ // Bit pattern to clear gpio pins
+ unsigned int clr = 0x01 << D7 | 0x01 << D6 | 0x01 << D5 | 0x01 << D4;
+
+ if (displayID != 0) {
+ return;
+ }
+
+ if (gpio == NULL) {
+ printf("gpio not set up.\n");
+ return;
+ }
+ // Set EN high while data lines are set up.
+ // Data is latched on the falling edge.
+ p->hd44780_functions->uPause(p, 1);
+ OUT_SET(EN);
+
+ if (flags == RS_INSTR) {
+ clr |= 0x01 << RS;
+ }
+ else { // flags == RS_DATA
+ set |= 0x01 << RS;
+ }
+
+ // Clear data lines ready for nibbles
+ GPIO_CLR = clr;
+
+ // Output upper nibble first
+ if (ch & 0x80) set |= 0x01 << D7;
+ if (ch & 0x40) set |= 0x01 << D6;
+ if (ch & 0x20) set |= 0x01 << D5;
+ if (ch & 0x10) set |= 0x01 << D4;
+ GPIO_SET = set;
+
+ // Data is clocked on the falling edge of EN
+ p->hd44780_functions->uPause(p, 50);
+ OUT_CLR(EN);
+ p->hd44780_functions->uPause(p, 50);
+
+ // Do same for lower nibble
+ p->hd44780_functions->uPause(p, 1);
+ OUT_SET(EN);
+
+ // Clear data lines ready for lower nibble
+ GPIO_CLR = clr;
+ if (ch & 0x08) set |= 0x01 << D7;
+ if (ch & 0x04) set |= 0x01 << D6;
+ if (ch & 0x02) set |= 0x01 << D5;
+ if (ch & 0x01) set |= 0x01 << D4;
+ GPIO_SET = set;
+
+ p->hd44780_functions->uPause(p, 50);
+ OUT_CLR(EN);
+ p->hd44780_functions->uPause(p, 50);
+
+ return;
+}
+
+
+/**
+ * Turn display backlight on or off.
+ * \param p Pointer to driver's private data structure.
+ * \param state New backlight status.
+ */
+void lcdrpi_HD44780_backlight(PrivateData *p, unsigned char state)
+{
+ return;
+}
+
+
+/**
+ * Read keypress.
+ * \param p Pointer to driver's private data structure.
+ * \param YData Bitmap of rows / lines to enable.
+ * \return Bitmap of the pressed keys.
+ */
+unsigned char lcdrpi_HD44780_readkeypad(PrivateData *p, unsigned int YData)
+{
+ return 0;
+}
diff -uprN /tmp/lcdproc-0.5.5/server/drivers/hd44780-rpi.h ./server/drivers/hd44780-rpi.h
--- /tmp/lcdproc-0.5.5/server/drivers/hd44780-rpi.h 1970-01-01 00:00:00.000000000 +0000
+++ ./server/drivers/hd44780-rpi.h 2012-08-19 13:04:42.693516174 +0000
@@ -0,0 +1,33 @@
+#ifndef HD_LCDRPI_H
+#define HD_LCDRPI_H
+
+#include "lcd.h" /* for Driver */
+
+// initialise this particular driver
+int hd_init_rpi(Driver *drvthis);
+
+//
+// How to access GPIO registers from C-code on the Raspberry-Pi
+// Example program
+// 15-January-2012
+// Dom and Gert
+//
+
+#define BCM2708_PERI_BASE 0x20000000
+#define GPIO_BASE (BCM2708_PERI_BASE + 0x200000) /* GPIO controller */
+
+#define PAGE_SIZE (4*1024)
+#define BLOCK_SIZE (4*1024)
+
+// GPIO setup macros. Always use INP_GPIO(x) before using OUT_GPIO(x) or SET_GPIO_ALT(x,y)
+#define INP_GPIO(g) *(gpio+((g)/10)) &= ~(7<<(((g)%10)*3))
+#define OUT_GPIO(g) *(gpio+((g)/10)) |= (1<<(((g)%10)*3))
+#define SET_GPIO_ALT(g,a) *(gpio+(((g)/10))) |= (((a)<=3?(a)+4:(a)==4?3:2)<<(((g)%10)*3))
+
+#define GPIO_SET *(gpio+7) // sets bits which are 1 ignores bits which are 0
+#define GPIO_CLR *(gpio+10) // clears bits which are 1 ignores bits which are 0
+
+#define OUT_SET(pin) (GPIO_SET = 0x01<<pin)
+#define OUT_CLR(pin) (GPIO_CLR = 0x01<<pin)
+
+#endif // HD_LCDRPI_H
diff -uprN /tmp/lcdproc-0.5.5/server/drivers/Makefile.am ./server/drivers/Makefile.am
--- /tmp/lcdproc-0.5.5/server/drivers/Makefile.am 2011-08-14 12:29:16.000000000 +0000
+++ ./server/drivers/Makefile.am 2012-08-17 22:41:18.243866469 +0000
@@ -20,7 +20,8 @@ AM_LDFLAGS = @LDSHARED@
## Keep the lists sorted!
-pkglib_PROGRAMS = @DRIVERS@
+libexecdir = $(pkglibdir)
+libexec_PROGRAMS = @DRIVERS@
EXTRA_PROGRAMS = bayrad CFontz CFontz633 CFontzPacket curses debug CwLnx ea65 EyeboxOne g15 glcdlib glk hd44780 icp_a106 imon imonlcd IOWarrior irman joy lb216 lcdm001 lcterm lirc lis MD8800 mdm166a ms6931 mtc_s16209x MtxOrb mx5000 NoritakeVFD picolcd pyramid sed1330 sed1520 serialPOS serialVFD shuttleVFD stv5730 SureElec svga t6963 text tyan sli ula200 xosd i2500vfd irtrans
noinst_LIBRARIES = libLCD.a libbignum.a
@@ -89,7 +90,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-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 port.h lpt-port.h timing.h hd44780-rpi.c hd44780-rpi.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