Add 'raspberrypi' connection type to HD44780 driver (by P. Corner).
This commit is contained in:
@@ -10,6 +10,7 @@ v0.5dev (ongoing development)
|
||||
* sed1520: Add an option for inverted segment mapping (idea by R. Buchert)
|
||||
* Fix build if compiled with --enable-permissive-menu-goto (#3599609)
|
||||
* glcd driver: Add direct support for framebuffer with paged memory layout
|
||||
+ hd44780: Added 'raspberrypi' connection type (P. Corner)
|
||||
|
||||
v0.5.6
|
||||
- Remove deprecated CFontz633 driver. Use CFontzPacket with Model=633 instead!
|
||||
|
||||
@@ -228,6 +228,15 @@ dnl else
|
||||
if test "$x_ac_have_i2c" = yes; then
|
||||
HD44780_DRIVERS="$HD44780_DRIVERS hd44780-hd44780-i2c.o"
|
||||
fi
|
||||
dnl The hd4470-rpi driver only works on a Raspberry Pi,
|
||||
dnl which is an ARM platform. Require people to compile on
|
||||
dnl (or for) ARM to get it.
|
||||
case $host in
|
||||
arm*-*-linux*)
|
||||
HD44780_DRIVERS="$HD44780_DRIVERS hd44780-hd44780-rpi.o"
|
||||
AC_DEFINE([WITH_RASPBERRYPI],[1],[Define if you are using a Raspberry Pi.])
|
||||
;;
|
||||
esac
|
||||
DRIVERS="$DRIVERS hd44780${SO}"
|
||||
actdrivers=["$actdrivers hd44780"]
|
||||
;;
|
||||
|
||||
@@ -155,6 +155,12 @@ Last but not least, for special purposes, there are even more connection types:
|
||||
<link linkend="hd44780-ethlcd">ethlcd</link>:
|
||||
Display connected via TCP to PoE powered ethlcd device (<ulink url="http://manio.skyboo.net/ethlcd/"></ulink>)
|
||||
</para></listitem>
|
||||
|
||||
<listitem><para>
|
||||
<link linkend="hd44780-raspberrypi">raspberrypi</link>:
|
||||
LCD connected to the GPIO header of a Raspberry Pi
|
||||
</para></listitem>
|
||||
|
||||
</itemizedlist>
|
||||
|
||||
|
||||
@@ -2953,6 +2959,161 @@ software adjustable contrast and brightness (backlight).
|
||||
</sect3>
|
||||
|
||||
|
||||
<sect3 id="hd44780-raspberrypi">
|
||||
<title>Raspberry Pi</title>
|
||||
|
||||
<para>This connection type supports a single LCD connected to the GPIO header P1
|
||||
on a Raspberry Pi.</para>
|
||||
|
||||
<para>It supports a switchable backlight connected to pin P1-11 by default. Use
|
||||
the switch circuit as described in <xref linkend="hd44780-ftdi-backlight"/>.</para>
|
||||
|
||||
<warning>
|
||||
<para>The signal level on the GPIO pins is 3.3 V and they are said not to
|
||||
be 5 V tolerant. Therefore the R/W pin of the display <emphasis>must
|
||||
</emphasis> be wired to GND to prevent 5V logic appearing on the GPIO
|
||||
pins. For the same reason the backlight cicuit from <xref linkend=
|
||||
"hd44780-connections-backlight.circuit"/> <emphasis>must not</emphasis> be
|
||||
used.</para>
|
||||
<para>Powering a LCD that uses 5 V from pin P1-02 will work. Powering a
|
||||
LCD from 3.3 V (pin P1-01) will only work if it is designed for 3.3 V
|
||||
operation.</para>
|
||||
</warning>
|
||||
|
||||
<table id="hd44780-raspberrypi.pin-mapping">
|
||||
<title>HD44780: Default pin mapping for Raspberry Pi</title>
|
||||
<tgroup cols="5" align="left">
|
||||
<colspec colname="rp1"/>
|
||||
<colspec colname="rpi2" align="right"/>
|
||||
<colspec colname="base" align="center"/>
|
||||
<colspec colname="lcd1"/>
|
||||
<colspec colname="lcd2"/>
|
||||
<thead>
|
||||
<row>
|
||||
<entry namest="rpi1" nameend="rpi2" align="center">Connector</entry>
|
||||
<entry morerows="1"><-></entry>
|
||||
<entry namest="lcd1" nameend="lcd2" align="center">LCD</entry>
|
||||
</row>
|
||||
<row>
|
||||
<entry>Pin Name</entry>
|
||||
<entry>Pin Number</entry>
|
||||
<entry>Name</entry>
|
||||
<entry>Pin</entry>
|
||||
</row>
|
||||
</thead>
|
||||
<tbody>
|
||||
<row>
|
||||
<entry>GPIO18</entry>
|
||||
<entry>P1-12</entry>
|
||||
<entry></entry>
|
||||
<entry>D7</entry>
|
||||
<entry>14</entry>
|
||||
</row>
|
||||
<row>
|
||||
<entry>GPIO23</entry>
|
||||
<entry>P1-16</entry>
|
||||
<entry></entry>
|
||||
<entry>D6</entry>
|
||||
<entry>13</entry>
|
||||
</row>
|
||||
<row>
|
||||
<entry>GPIO24</entry>
|
||||
<entry>P1-18</entry>
|
||||
<entry></entry>
|
||||
<entry>D5</entry>
|
||||
<entry>12</entry>
|
||||
</row>
|
||||
<row>
|
||||
<entry>GPIO25</entry>
|
||||
<entry>P1-22</entry>
|
||||
<entry></entry>
|
||||
<entry>D4</entry>
|
||||
<entry>11</entry>
|
||||
</row>
|
||||
<row>
|
||||
<entry>GPIO08</entry>
|
||||
<entry>P1-24</entry>
|
||||
<entry></entry>
|
||||
<entry>EN</entry>
|
||||
<entry>6</entry>
|
||||
</row>
|
||||
<row>
|
||||
<entry>GPIO07</entry>
|
||||
<entry>P1-26</entry>
|
||||
<entry></entry>
|
||||
<entry>RS</entry>
|
||||
<entry>4</entry>
|
||||
</row>
|
||||
<row>
|
||||
<entry>GND</entry>
|
||||
<entry>P1-06</entry>
|
||||
<entry></entry>
|
||||
<entry>RW</entry>
|
||||
<entry>5</entry>
|
||||
</row>
|
||||
<row>
|
||||
<entry>GPIO17</entry>
|
||||
<entry>P1-11</entry>
|
||||
<entry></entry>
|
||||
<entry>BL</entry>
|
||||
<entry>Backlight (optional)</entry>
|
||||
</row>
|
||||
</tbody>
|
||||
</tgroup>
|
||||
</table>
|
||||
|
||||
<para>GPIO07 and GPIO08 used for RS and EN signal are also used by the SPI
|
||||
bus. If you loaded the SPI driver you will need to assign them to a different
|
||||
GPIO, e.g. GPIO04 and GPIO22.</para>
|
||||
|
||||
<sect4 id="hd44780-raspberrypi-config">
|
||||
<title>Special Raspberry Pi configuration options</title>
|
||||
|
||||
<para>This connection driver can be configured to use other pins than the
|
||||
one described in <link linkend="hd44780-raspberrypi.pin-mapping">the table
|
||||
above</link>. Using the <literal> pin_<replaceable><name>
|
||||
</replaceable></literal> configuration option, any LCD pin can be assigned
|
||||
to any GPIO pin.</para>
|
||||
|
||||
<important>
|
||||
<para>The values for the <literal>pin_<replaceable><name>
|
||||
</replaceable></literal> configuration option are the number part from the
|
||||
GPIO signal name, not the pin number from the header connector! To find
|
||||
out which signal is routed to which connector pin refer to the <ulink url=
|
||||
"http://elinux.org/RPi_Low-level_peripherals">RPi Low-level peripherals</ulink>
|
||||
description.</para>
|
||||
</important>
|
||||
|
||||
<para>The connection driver contains a check for possible signal names. You
|
||||
will receive an error message if you try to assign a pin to a signal that is
|
||||
not available on connector P1 or P5.</para>
|
||||
|
||||
<example id="hd44780-raspberrypi-config.example">
|
||||
<title>HD44780: Alternate configuration for Raspberry Pi GPIO pins</title>
|
||||
<screen>
|
||||
<![CDATA[
|
||||
[hd44780]
|
||||
ConnectionType=raspberrypi
|
||||
Backlight=yes
|
||||
Size=16x2
|
||||
|
||||
pin_D4=25
|
||||
pin_D5=24
|
||||
pin_D6=23
|
||||
pin_D7=18
|
||||
pin_EN=8
|
||||
pin_RS=7
|
||||
pin_BL=17
|
||||
|
||||
]]>
|
||||
</screen>
|
||||
</example>
|
||||
|
||||
</sect4>
|
||||
|
||||
</sect3>
|
||||
|
||||
|
||||
</sect2>
|
||||
|
||||
|
||||
@@ -3008,6 +3169,7 @@ This can be done by specifying <option>--enable-drivers=all</option> or by inclu
|
||||
<term>
|
||||
<property>ConnectionType</property> =
|
||||
{
|
||||
<!-- Keep this list sorted according to the table in hd44780-drivers.h -->
|
||||
<emphasis><parameter><literal>4bit</literal></parameter></emphasis> |
|
||||
<parameter><literal>8bit</literal></parameter> |
|
||||
<parameter><literal>winamp</literal></parameter> |
|
||||
@@ -3018,14 +3180,18 @@ This can be done by specifying <option>--enable-drivers=all</option> or by inclu
|
||||
<parameter><literal>vdr-lcd</literal></parameter> |
|
||||
<parameter><literal>vdr-wakeup</literal></parameter> |
|
||||
<parameter><literal>pertelian</literal></parameter> |
|
||||
<parameter><literal>bwctusb</literal></parameter> |
|
||||
<parameter><literal>lcd2usb</literal></parameter> |
|
||||
<parameter><literal>usb4all</literal></parameter> |
|
||||
<parameter><literal>lis2</literal></parameter> |
|
||||
<parameter><literal>mplay</literal></parameter> |
|
||||
<parameter><literal>i2c</literal></parameter> |
|
||||
<parameter><literal>usblcd</literal></parameter> |
|
||||
<parameter><literal>bwctusb</literal></parameter> |
|
||||
<parameter><literal>lcd2usb</literal></parameter> |
|
||||
<parameter><literal>usbtiny</literal></parameter> |
|
||||
<parameter><literal>uss720</literal></parameter> |
|
||||
<parameter><literal>usb4all</literal></parameter> |
|
||||
<parameter><literal>ftdi</literal></parameter> |
|
||||
<parameter><literal>usblcd</literal></parameter>
|
||||
<parameter><literal>i2c</literal></parameter> |
|
||||
<parameter><literal>ethlcd</literal></parameter> |
|
||||
<parameter><literal>raspberrypi</literal></parameter>
|
||||
}
|
||||
</term>
|
||||
<listitem>
|
||||
@@ -3079,11 +3245,23 @@ This can be done by specifying <option>--enable-drivers=all</option> or by inclu
|
||||
<entry><literal><link linkend="hd44780-vdr-wakeup">vdr-wakeup</link></literal></entry>
|
||||
<entry>VDR-Wakeup module "vdr-wakeup"</entry>
|
||||
</row>
|
||||
<!-- USB -->
|
||||
<row>
|
||||
<entry><literal><link linkend="hd44780-pertelian">pertelian</link></literal></entry>
|
||||
<entry>Pertelian X2040 LCD display (<ulink url="http://pertelian.com/joomla/index.php?option=com_content&task=view&id=43&Itemid=48"></ulink>)</entry>
|
||||
</row>
|
||||
<!-- USB -->
|
||||
<row>
|
||||
<entry><literal><link linkend="hd44780-lis2">lis2</link></literal></entry>
|
||||
<entry>LIS2 from VLSystem (<ulink url="http://www.vlsys.co.kr"></ulink>)</entry>
|
||||
</row>
|
||||
<row>
|
||||
<entry><literal><link linkend="hd44780-mplay">mplay</link></literal></entry>
|
||||
<entry>MPlay Blast from VLSystem (<ulink url="http://www.vlsys.co.kr"></ulink>)</entry>
|
||||
</row>
|
||||
<row>
|
||||
<entry><literal><link linkend="hd44780-usblcd">usblcd</link></literal></entry>
|
||||
<entry>USBLCD adapter from Adams IT Services (<ulink url="http://www.usblcd.de/"></ulink>)</entry>
|
||||
</row>
|
||||
<row>
|
||||
<entry><literal><link linkend="hd44780-bwctusb">bwctusb</link></literal></entry>
|
||||
<entry>BWCT USB device "bwctusb" (<ulink url="http://www.bwct.de/lcd.html"></ulink>)</entry>
|
||||
@@ -3092,35 +3270,37 @@ This can be done by specifying <option>--enable-drivers=all</option> or by inclu
|
||||
<entry><literal><link linkend="hd44780-lcd2usb">lcd2usb</link></literal></entry>
|
||||
<entry>Till Harbaum's LCD2USB (<ulink url="http://www.harbaum.org/till/lcd2usb/"></ulink>)</entry>
|
||||
</row>
|
||||
<row>
|
||||
<entry><literal><link linkend="hd44780-usb4all">USB-4-all</link></literal></entry>
|
||||
<entry>The USB-4-all controller board from Sprut (<ulink url="http://www.sprut.de/electronic/pic/projekte/usb4all/usb4all.htm"></ulink>)</entry>
|
||||
</row>
|
||||
<row>
|
||||
<entry><literal><link linkend="hd44780-usbtiny">usbtiny</link></literal></entry>
|
||||
<entry>Dick Streefland's USBtiny (<ulink url="http://www.xs4all.nl/~dicks/avr/usbtiny/"></ulink>)</entry>
|
||||
</row>
|
||||
<row>
|
||||
<entry><literal><link linkend="hd44780-lis2">lis2</link></literal></entry>
|
||||
<entry>LIS2 from VLSystem (<ulink url="http://www.vlsys.co.kr"></ulink>)</entry>
|
||||
<entry><literal><link linkend="hd44780-uss720">uss720</link></literal></entry>
|
||||
<entry>Belkin USS-720 USB-to-IEEE 1284 Bridge</entry>
|
||||
</row>
|
||||
<row>
|
||||
<entry><literal><link linkend="hd44780-mplay">mplay</link></literal></entry>
|
||||
<entry>MPlay Blast from VLSystem (<ulink url="http://www.vlsys.co.kr"></ulink>)</entry>
|
||||
<entry><literal><link linkend="hd44780-usb4all">USB-4-all</link></literal></entry>
|
||||
<entry>The USB-4-all controller board from Sprut (<ulink url="http://www.sprut.de/electronic/pic/projekte/usb4all/usb4all.htm"></ulink>)</entry>
|
||||
</row>
|
||||
<row>
|
||||
<entry><literal><link linkend="hd44780-ftdi">ftdi</link></literal></entry>
|
||||
<entry>Display connected to a dual channel FTDI 2232D USB chip</entry>
|
||||
</row>
|
||||
<row>
|
||||
<entry><literal><link linkend="hd44780-usblcd">usblcd</link></literal></entry>
|
||||
<entry>USBLCD adapter from Adams IT Services (<ulink url="http://www.usblcd.de/"></ulink>)</entry>
|
||||
</row>
|
||||
<!-- I2C -->
|
||||
<row>
|
||||
<entry><literal><link linkend="hd44780-i2c">i2c</link></literal></entry>
|
||||
<entry>LCD driven by PCF8574(A)/PCA9554(A) connected via I<superscript>2</superscript>C</entry>
|
||||
</row>
|
||||
<!-- Ethernet -->
|
||||
<row>
|
||||
<entry><literal><link linkend="hd44780-ethlcd">ethlcd</link></literal></entry>
|
||||
<entry>ethlcd device (<ulink url="http://manio.skyboo.net/ethlcd/"></ulink>)</entry>
|
||||
</row>
|
||||
<!-- Other -->
|
||||
<row>
|
||||
<entry><literal><link linkend="hd44780-raspberrypi">raspberrypi</link></literal></entry>
|
||||
<entry>LCD connected to the GPIO header of a Raspberry Pi</entry>
|
||||
</row>
|
||||
</tbody>
|
||||
</tgroup>
|
||||
</informaltable>
|
||||
|
||||
@@ -95,7 +95,7 @@ EXTRA_glcd_SOURCES = glcd-t6963.c t6963_low.c t6963_low.h glcd-png.c glcd-serdis
|
||||
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 hd44780-usb4all.c hd44780-usb4all.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 hd44780-rpi.c hd44780-rpi.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
|
||||
|
||||
@@ -35,7 +35,10 @@
|
||||
#ifdef WITH_ETHLCD
|
||||
# include "hd44780-ethlcd.h"
|
||||
#endif
|
||||
# include "hd44780-usblcd.h"
|
||||
#include "hd44780-usblcd.h"
|
||||
#ifdef WITH_RASPBERRYPI
|
||||
# include "hd44780-rpi.h"
|
||||
#endif
|
||||
/* add new connection type header files to the correct section above or here */
|
||||
|
||||
|
||||
@@ -81,6 +84,9 @@ static const ConnectionMapping connectionMapping[] = {
|
||||
/* TCP socket connection types */
|
||||
#ifdef WITH_ETHLCD
|
||||
{ "ethlcd", HD44780_CT_ETHLCD, IF_TYPE_TCP, hd_init_ethlcd },
|
||||
#endif
|
||||
#ifdef WITH_RASPBERRYPI
|
||||
{ "raspberrypi", HD44780_CT_RASPBERRYPI, IF_TYPE_PARPORT, hd_init_rpi },
|
||||
#endif
|
||||
/* add new connection types in the correct section above or here */
|
||||
|
||||
|
||||
@@ -53,6 +53,7 @@
|
||||
#define HD44780_CT_USBLCD 19
|
||||
#define HD44780_CT_USBTINY 20
|
||||
#define HD44780_CT_USB4ALL 21
|
||||
#define HD44780_CT_RASPBERRYPI 22
|
||||
/**@}*/
|
||||
|
||||
/** \name Symbolic names for interface types
|
||||
@@ -104,7 +105,7 @@ typedef struct ConnectionMapping {
|
||||
int if_type;
|
||||
/** Pointer to connection type's initialization function */
|
||||
int (*init_fn) (Driver *drvthis);
|
||||
} ConnectionMapping;
|
||||
} ConnectionMapping;
|
||||
|
||||
|
||||
/**
|
||||
@@ -153,6 +154,9 @@ typedef struct hd44780_private_data {
|
||||
#ifdef WITH_ETHLCD
|
||||
int sock; /**< socket for TCP devices */
|
||||
#endif
|
||||
#ifdef WITH_RASPBERRYPI
|
||||
struct rpi_gpio_map *rpi_gpio; /**< GPIO pin mapping for Raspberry Pi */
|
||||
#endif
|
||||
|
||||
int charmap; /**< index of currently used charmap */
|
||||
|
||||
|
||||
@@ -0,0 +1,458 @@
|
||||
/** \file server/drivers/hd44780-rpi.c
|
||||
* \c rpi connection type of \c hd44780 driver for Hitachi HD44780 based LCD
|
||||
* displays connected to the GPIO pins on the Raspberry Pi.
|
||||
*
|
||||
* The LCD is operated in its 4 bit-mode. R/W (5) on the LCD MUST be hard wired
|
||||
* low to prevent 5V logic appearing on the GPIO pins.
|
||||
*
|
||||
* The default 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)
|
||||
* GND R/W (5)
|
||||
* P1-26 (7) RS (4)
|
||||
* P1-11 (17) BL (backlight optional)
|
||||
*
|
||||
* Mappings can be set in the config file using the key-words:
|
||||
* pin_EN, pin_RS, pin_D7, pin_D6, pin_D5, pin_D4, pin_BL
|
||||
* in the [HD44780] section.
|
||||
*
|
||||
* Only a single LCD is currently supported.
|
||||
*/
|
||||
|
||||
/*-
|
||||
* Copyright (c) 2012-2013 Paul Corner <paul_c@users.sourceforge.net>
|
||||
* 2013 warhog <warhog@gmx.de> (Conditional ARM test)
|
||||
* 2013 Serac <Raspberry Pi forum>
|
||||
* (Backlight & Rev2 board support)
|
||||
*
|
||||
* The code to access the GPIO on a Raspberry Pi draws on an example program
|
||||
* by Dom and Gert van Loo from:
|
||||
* http://elinux.org/Rpi_Low-level_peripherals#GPIO_Driving_Example_.28C.29
|
||||
*
|
||||
* This file is released under the GNU General Public License. Refer to the
|
||||
* COPYING file distributed with this package.
|
||||
*/
|
||||
|
||||
/* Default GPIO pin assignment */
|
||||
#define RPI_DEF_D7 18
|
||||
#define RPI_DEF_D6 23
|
||||
#define RPI_DEF_D5 24
|
||||
#define RPI_DEF_D4 25
|
||||
#define RPI_DEF_RS 7
|
||||
#define RPI_DEF_EN 8
|
||||
#define RPI_DEF_BL 17
|
||||
|
||||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
#include <stdlib.h>
|
||||
#include <fcntl.h>
|
||||
#include <sys/mman.h>
|
||||
#include <unistd.h>
|
||||
#include <errno.h>
|
||||
|
||||
#include "hd44780-rpi.h"
|
||||
#include "hd44780-low.h"
|
||||
#include "report.h"
|
||||
|
||||
void lcdrpi_HD44780_senddata(PrivateData *p, unsigned char displayID, unsigned char flags, unsigned char ch);
|
||||
void lcdrpi_HD44780_backlight(PrivateData *p, unsigned char state);
|
||||
void lcdrpi_HD44780_close(PrivateData *p);
|
||||
|
||||
/**
|
||||
* Pointer to the memory mapped GPIO registers. Note the pointer type is
|
||||
* (unsigned int) not (char). This is important when calculating offset
|
||||
* adresses!
|
||||
*
|
||||
* This pointer is outside PrivataData as it needs to be volatile!
|
||||
*/
|
||||
static volatile unsigned int *gpio_map = NULL;
|
||||
|
||||
/*
|
||||
* Two different board revisions are currently in widespread use. The
|
||||
* GPIO mappings differ slightly - Not enough to kill a system yet.
|
||||
* Future models *may* have extra pins added or reassigned to other
|
||||
* functions. Having a revision dependent mapping gives the user fair
|
||||
* warning if they mess up.
|
||||
*/
|
||||
static const int gpio_pins_R1[GPIO_PINS] = {
|
||||
0, 1, -1, -1, 4, -1, -1, 7,
|
||||
8, 9, 10, 11, -1, -1, 14, 15,
|
||||
-1, 17, 18, -1, -1, 21, 22, 23,
|
||||
24, 25, -1, -1, -1, -1, -1, -1
|
||||
};
|
||||
|
||||
static const int gpio_pins_R2[GPIO_PINS] = {
|
||||
-1, -1, -1, 3, 4, -1, -1, 7,
|
||||
8, 9, 10, 11, -1, -1, 14, 15,
|
||||
-1, 17, 18, -1, -1, -1, 22, 23,
|
||||
/* 28-31 accessible via P5 */
|
||||
24, 25, -1, 27, 28, 29, 30, 31
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* Maps a memory region to the address space of the BM2835 GPIO controller.
|
||||
* \param drvthis Pointer to driver structure.
|
||||
* \return 0 on success, -1 on error.
|
||||
*/
|
||||
static int
|
||||
setup_io(Driver *drvthis)
|
||||
{
|
||||
int mem_fd = 0;
|
||||
|
||||
if (gpio_map != NULL) {
|
||||
report(RPT_ERR, "setup_io: IO already in use");
|
||||
return -1;
|
||||
}
|
||||
|
||||
if ((mem_fd = open("/dev/mem", O_RDWR | O_SYNC)) < 0) {
|
||||
report(RPT_ERR, "setup_io: can not open /dev/mem");
|
||||
return -1;
|
||||
}
|
||||
|
||||
gpio_map = (unsigned int *) mmap(NULL,
|
||||
GPIO_BLOCK_SIZE,
|
||||
PROT_READ | PROT_WRITE,
|
||||
MAP_SHARED,
|
||||
mem_fd,
|
||||
GPIO_BASE);
|
||||
|
||||
if ((long) gpio_map < 0) {
|
||||
report(RPT_ERR, "setup_io: mmap error %s", strerror(errno));
|
||||
close(mem_fd);
|
||||
return -1;
|
||||
}
|
||||
close(mem_fd);
|
||||
|
||||
debug(RPT_INFO, "setup_io: finished");
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Check if LCDd runs on a Raspberry Pi board and which revision (Rev 1 or
|
||||
* Rev 2) it is.
|
||||
* \param drvthis Pointer to driver structure.
|
||||
* \return Pointer to a GPIO mapping table or NULL on error.
|
||||
*/
|
||||
static int const *
|
||||
check_board_rev(Driver *drvthis)
|
||||
{
|
||||
FILE *fp;
|
||||
char buf[80];
|
||||
char hw[8];
|
||||
unsigned int rev = 0;
|
||||
|
||||
if ((fp = fopen("/proc/cpuinfo", "r")) == NULL) {
|
||||
report(RPT_ERR, "check_board_rev: Can not open /proc/cpuinfo");
|
||||
return NULL;
|
||||
}
|
||||
|
||||
while (!feof(fp)) {
|
||||
fgets(buf, sizeof(buf), fp);
|
||||
sscanf(buf, "Hardware : %7s", hw);
|
||||
sscanf(buf, "Revision : %x", &rev);
|
||||
}
|
||||
fclose(fp);
|
||||
|
||||
/* On boards that have been overvolted, the MSB will be set */
|
||||
rev &= 0x00ff;
|
||||
|
||||
if (strcmp(hw, "BCM2708") != 0 || rev == 0) {
|
||||
report(RPT_ERR, "check_board_rev: This board is not recognized as a Raspberry Pi!");
|
||||
return NULL;
|
||||
}
|
||||
|
||||
/* Rev 1 boards will be 0x002 or 0x003 (not sure if 0x001 ever existed
|
||||
* in the wild). */
|
||||
if (rev < 4) {
|
||||
report(RPT_INFO, "check_board_rev: Revision 1 board detected");
|
||||
return gpio_pins_R1;
|
||||
}
|
||||
/* Currently, Rev 2 boards are 0x004, 0x005, or 0x006. This will need
|
||||
* updating as new revisions are released, but it is unlikely that P1
|
||||
* will change. */
|
||||
if (rev > 3) {
|
||||
report(RPT_INFO, "check_board_rev: Revision 2 board detected");
|
||||
return gpio_pins_R2;
|
||||
}
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Check user provided GPIO pin configuration.
|
||||
* \param drvthis Pointer to driver structure.
|
||||
* \param pin Number of the GPIO pin to use.
|
||||
* \param allowed_pins Pointer to array of allowed GPIO pins (depends on
|
||||
* board revision).
|
||||
* \param used_pins Pointer to array of pin usage status.
|
||||
* \return 0 on success, -1 on error.
|
||||
*/
|
||||
static int
|
||||
check_pin(Driver *drvthis, int pin, const int *allowed_pins, int *used_pins)
|
||||
{
|
||||
/* Check for errors */
|
||||
if (pin >= GPIO_PINS || pin < 0) {
|
||||
report(RPT_ERR, "check_pin: GPIO pin %i out of range", pin);
|
||||
return -1;
|
||||
}
|
||||
if (allowed_pins[pin] < 0) {
|
||||
report(RPT_ERR, "check_pin: Use of GPIO pin %i not allowed", pin, allowed_pins[pin]);
|
||||
return -1;
|
||||
}
|
||||
if (used_pins[pin] == 1) {
|
||||
report(RPT_ERR, "check_pin: GPIO pin %i already used", pin);
|
||||
return -1;
|
||||
}
|
||||
|
||||
/* Mark used */
|
||||
used_pins[pin] = 1;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Configures a GPIO pin: Disable pull-up/down and set it up as output.
|
||||
* \param drvthis Pointer to driver structure.
|
||||
* \param gpio Number of the GPIO pin to use.
|
||||
*/
|
||||
static void
|
||||
setup_gpio(Driver *drvthis, int gpio)
|
||||
{
|
||||
volatile int i;
|
||||
|
||||
#define GPPUP gpio_map + 37
|
||||
#define GPPUDCLK gpio_map + 38
|
||||
|
||||
/* Disable pull-up/down */
|
||||
*(GPPUP) &= ~3;
|
||||
|
||||
/*
|
||||
* After writing to the GPPUD register, need to wait 150 cycles as per
|
||||
* p101 BCM2835.pdf. The following while loop uses approx five
|
||||
* instructions plus another two to load the counter. Note: the int
|
||||
* must be volatile or gcc will optimize loop out.
|
||||
*/
|
||||
i = 30;
|
||||
while (--i);
|
||||
|
||||
/* Enable Pull-up/down clock register for the pin */
|
||||
*(GPPUDCLK + (gpio / 32)) = 1 << (gpio % 32);
|
||||
|
||||
/* Another 150 cycle wait required after a write to GPPUDCLK */
|
||||
i = 30;
|
||||
while (--i);
|
||||
|
||||
/* Write again to GPPUD and disable clock */
|
||||
*(GPPUP) &= ~3;
|
||||
*(GPPUDCLK + (gpio / 32)) = 0;
|
||||
|
||||
/*
|
||||
* Now configure the pin as output: This reads the complete GPSELx
|
||||
* register, clears all bits for the selected pin, enables it as
|
||||
* output, and writes back the register.
|
||||
*/
|
||||
*(gpio_map + (gpio / 10)) =
|
||||
(*(gpio_map + (gpio / 10)) & ~(7 << ((gpio % 10) * 3))) | (1 << ((gpio % 10) * 3));
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Free resources used by this connection type.
|
||||
* \param p Pointer to driver's PrivateData structure.
|
||||
*/
|
||||
void
|
||||
lcdrpi_HD44780_close(PrivateData *p)
|
||||
{
|
||||
/* Configure all pins as input */
|
||||
INP_GPIO(p->rpi_gpio->en);
|
||||
INP_GPIO(p->rpi_gpio->rs);
|
||||
INP_GPIO(p->rpi_gpio->d7);
|
||||
INP_GPIO(p->rpi_gpio->d6);
|
||||
INP_GPIO(p->rpi_gpio->d5);
|
||||
INP_GPIO(p->rpi_gpio->d4);
|
||||
if (p->have_backlight)
|
||||
INP_GPIO(p->backlight_bit);
|
||||
|
||||
/* Unmap and free memory */
|
||||
if (gpio_map != NULL)
|
||||
munmap((caddr_t) gpio_map, GPIO_BLOCK_SIZE);
|
||||
if (p->rpi_gpio != NULL)
|
||||
free(p->rpi_gpio);
|
||||
p->rpi_gpio = NULL;
|
||||
}
|
||||
|
||||
/**
|
||||
* 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;
|
||||
const int *allowed_gpio_pins = NULL;
|
||||
int used_pins[GPIO_PINS] = {};
|
||||
|
||||
if ((allowed_gpio_pins = check_board_rev(drvthis)) == NULL)
|
||||
return -1;
|
||||
|
||||
/* Get GPIO configuration */
|
||||
p->rpi_gpio = malloc(sizeof(struct rpi_gpio_map));
|
||||
if (p->rpi_gpio == NULL) {
|
||||
report(RPT_ERR, "hd_init_rpi: unable to allocate memory");
|
||||
return -1;
|
||||
}
|
||||
|
||||
p->rpi_gpio->en = drvthis->config_get_int(drvthis->name, "pin_EN", 0, RPI_DEF_EN);
|
||||
p->rpi_gpio->rs = drvthis->config_get_int(drvthis->name, "pin_RS", 0, RPI_DEF_RS);
|
||||
p->rpi_gpio->d7 = drvthis->config_get_int(drvthis->name, "pin_D7", 0, RPI_DEF_D7);
|
||||
p->rpi_gpio->d6 = drvthis->config_get_int(drvthis->name, "pin_D6", 0, RPI_DEF_D6);
|
||||
p->rpi_gpio->d5 = drvthis->config_get_int(drvthis->name, "pin_D5", 0, RPI_DEF_D5);
|
||||
p->rpi_gpio->d4 = drvthis->config_get_int(drvthis->name, "pin_D4", 0, RPI_DEF_D4);
|
||||
|
||||
debug(RPT_INFO, "hd_init_rpi: Pin EN mapped to GPIO%d", p->rpi_gpio->en);
|
||||
debug(RPT_INFO, "hd_init_rpi: Pin RS mapped to GPIO%d", p->rpi_gpio->rs);
|
||||
debug(RPT_INFO, "hd_init_rpi: Pin D4 mapped to GPIO%d", p->rpi_gpio->d4);
|
||||
debug(RPT_INFO, "hd_init_rpi: Pin D5 mapped to GPIO%d", p->rpi_gpio->d5);
|
||||
debug(RPT_INFO, "hd_init_rpi: Pin D6 mapped to GPIO%d", p->rpi_gpio->d6);
|
||||
debug(RPT_INFO, "hd_init_rpi: Pin D7 mapped to GPIO%d", p->rpi_gpio->d7);
|
||||
|
||||
if (check_pin(drvthis, p->rpi_gpio->en, allowed_gpio_pins, used_pins) ||
|
||||
check_pin(drvthis, p->rpi_gpio->rs, allowed_gpio_pins, used_pins) ||
|
||||
check_pin(drvthis, p->rpi_gpio->d7, allowed_gpio_pins, used_pins) ||
|
||||
check_pin(drvthis, p->rpi_gpio->d6, allowed_gpio_pins, used_pins) ||
|
||||
check_pin(drvthis, p->rpi_gpio->d5, allowed_gpio_pins, used_pins) ||
|
||||
check_pin(drvthis, p->rpi_gpio->d4, allowed_gpio_pins, used_pins)) {
|
||||
free(p->rpi_gpio);
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (p->have_backlight) { /* Backlight setup is optional */
|
||||
p->backlight_bit = drvthis->config_get_int(drvthis->name, "pin_BL", 0, RPI_DEF_BL);
|
||||
debug(RPT_INFO, "hd_init_rpi: Backlight mapped to GPIO%d", p->backlight_bit);
|
||||
|
||||
if (check_pin(drvthis, p->backlight_bit, allowed_gpio_pins, used_pins) != 0) {
|
||||
report(RPT_WARNING, "hd_init_rpi: Invalid backlight configuration - disabling backlight");
|
||||
p->have_backlight = 0;
|
||||
}
|
||||
}
|
||||
|
||||
/* Now that configuration should be correct, set up the GPIO pins */
|
||||
if (setup_io(drvthis) < 0) {
|
||||
report(RPT_ERR, "hd_init_rpi: Failed to set up GPIO");
|
||||
free(p->rpi_gpio);
|
||||
return -1;
|
||||
}
|
||||
|
||||
setup_gpio(drvthis, p->rpi_gpio->en);
|
||||
setup_gpio(drvthis, p->rpi_gpio->rs);
|
||||
setup_gpio(drvthis, p->rpi_gpio->d7);
|
||||
setup_gpio(drvthis, p->rpi_gpio->d6);
|
||||
setup_gpio(drvthis, p->rpi_gpio->d5);
|
||||
setup_gpio(drvthis, p->rpi_gpio->d4);
|
||||
|
||||
p->hd44780_functions->senddata = lcdrpi_HD44780_senddata;
|
||||
p->hd44780_functions->close = lcdrpi_HD44780_close;
|
||||
|
||||
if (p->have_backlight) {
|
||||
setup_gpio(drvthis, p->backlight_bit);
|
||||
p->hd44780_functions->backlight = lcdrpi_HD44780_backlight;
|
||||
}
|
||||
|
||||
/* Setup the lcd in 4 bit mode: Send (FUNCSET | IF_8BIT) three times
|
||||
* followed by (FUNCSET | IF_4BIT) using four nibbles. Timing is not
|
||||
* exactly what is required by HD44780. */
|
||||
p->hd44780_functions->senddata(p, 0, RS_INSTR, 0x33);
|
||||
p->hd44780_functions->uPause(p, 4100);
|
||||
p->hd44780_functions->senddata(p, 0, RS_INSTR, 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)
|
||||
{
|
||||
/* Only one display is (currently) supported */
|
||||
if (displayID > 1) {
|
||||
return;
|
||||
}
|
||||
/* Safeguard: This should never happen */
|
||||
if (gpio_map == NULL) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (flags == RS_INSTR) {
|
||||
SET_GPIO(p->rpi_gpio->rs, 0);
|
||||
}
|
||||
else { /* flags == RS_DATA */
|
||||
SET_GPIO(p->rpi_gpio->rs, 1);
|
||||
}
|
||||
/* Clear data lines ready for nibbles */
|
||||
SET_GPIO(p->rpi_gpio->d7, 0);
|
||||
SET_GPIO(p->rpi_gpio->d6, 0);
|
||||
SET_GPIO(p->rpi_gpio->d5, 0);
|
||||
SET_GPIO(p->rpi_gpio->d4, 0);
|
||||
p->hd44780_functions->uPause(p, 50);
|
||||
|
||||
/* Output upper nibble first */
|
||||
SET_GPIO(p->rpi_gpio->d7, (ch & 0x80));
|
||||
SET_GPIO(p->rpi_gpio->d6, (ch & 0x40));
|
||||
SET_GPIO(p->rpi_gpio->d5, (ch & 0x20));
|
||||
SET_GPIO(p->rpi_gpio->d4, (ch & 0x10));
|
||||
p->hd44780_functions->uPause(p, 50);
|
||||
|
||||
/* Data is clocked on the falling edge of EN */
|
||||
SET_GPIO(p->rpi_gpio->en, 1);
|
||||
p->hd44780_functions->uPause(p, 50);
|
||||
SET_GPIO(p->rpi_gpio->en, 0);
|
||||
p->hd44780_functions->uPause(p, 50);
|
||||
|
||||
/* Do same for lower nibble */
|
||||
SET_GPIO(p->rpi_gpio->d7, 0);
|
||||
SET_GPIO(p->rpi_gpio->d6, 0);
|
||||
SET_GPIO(p->rpi_gpio->d5, 0);
|
||||
SET_GPIO(p->rpi_gpio->d4, 0);
|
||||
p->hd44780_functions->uPause(p, 50);
|
||||
SET_GPIO(p->rpi_gpio->d7, (ch & 0x08));
|
||||
SET_GPIO(p->rpi_gpio->d6, (ch & 0x04));
|
||||
SET_GPIO(p->rpi_gpio->d5, (ch & 0x02));
|
||||
SET_GPIO(p->rpi_gpio->d4, (ch & 0x01));
|
||||
p->hd44780_functions->uPause(p, 50);
|
||||
SET_GPIO(p->rpi_gpio->en, 1);
|
||||
p->hd44780_functions->uPause(p, 50);
|
||||
SET_GPIO(p->rpi_gpio->en, 0);
|
||||
p->hd44780_functions->uPause(p, 50);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* 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)
|
||||
{
|
||||
if (p->backlight_bit > -1 && p->backlight_bit < 32)
|
||||
SET_GPIO(p->backlight_bit, (state == BACKLIGHT_ON) ? 1 : 0);
|
||||
}
|
||||
@@ -0,0 +1,36 @@
|
||||
#ifndef HD_LCDRPI_H
|
||||
#define HD_LCDRPI_H
|
||||
|
||||
#include "lcd.h" /* for Driver */
|
||||
|
||||
/* initialize this particular driver */
|
||||
int hd_init_rpi(Driver *drvthis);
|
||||
|
||||
/**
|
||||
* rpi_gpio_map is addressed through the hd44780_private_data struct. Data
|
||||
* stored here is used for mapping physical GPIO pins to BCM2835 gpio. */
|
||||
struct rpi_gpio_map {
|
||||
int en;
|
||||
int rs;
|
||||
int d7;
|
||||
int d6;
|
||||
int d5;
|
||||
int d4;
|
||||
};
|
||||
|
||||
/** Peripheral base address of the BCM2835 */
|
||||
#define BCM2835_PERI_BASE 0x20000000
|
||||
/** GPIO register start address */
|
||||
#define GPIO_BASE BCM2835_PERI_BASE + 0x200000
|
||||
/** Length of register space */
|
||||
#define GPIO_BLOCK_SIZE 180
|
||||
/** The Pi has 32 GPIO pins */
|
||||
#define GPIO_PINS 32
|
||||
|
||||
|
||||
/** Setup a GPIO pin as input */
|
||||
#define INP_GPIO(g) *(gpio_map+((g)/10)) &= ~(7<<(((g)%10)*3))
|
||||
/** Sets or clears a GPIO pin */
|
||||
#define SET_GPIO(g,a) *(gpio_map+((a)?7:10))=1<<((g)%32);
|
||||
|
||||
#endif // HD_LCDRPI_H
|
||||
Reference in New Issue
Block a user