HD44780 update:
- supports new API - major clean up, more consistent code - uses configfile options - serialLpt works also with only 2 output lines - serialLpt can now use keypad
This commit is contained in:
@@ -37,8 +37,8 @@
|
||||
[server]
|
||||
# Server section with all kinds of settings for the LCDd server
|
||||
|
||||
Driver=HD44780
|
||||
#Driver=curses
|
||||
Driver=curses
|
||||
#Driver=HD44780
|
||||
#Driver=MtxOrb
|
||||
#
|
||||
# Tells the server to load the given drivers. Multiple lines can be given.
|
||||
@@ -46,7 +46,7 @@ Driver=HD44780
|
||||
Bind=127.0.0.1
|
||||
# Tells the driver to bind to the given interface
|
||||
|
||||
Port=3777
|
||||
Port=13666
|
||||
# Listen on this specified port; defaults to 13666.
|
||||
|
||||
#Debug=5
|
||||
@@ -59,10 +59,10 @@ User=nobody
|
||||
# User to run as. LCDd will drop its root priviledges,
|
||||
# if any, and run as this user instead.
|
||||
|
||||
EnableServerScreen=yes
|
||||
ServerScreen=no
|
||||
# Enables the server screen also when other screens are active.
|
||||
|
||||
Foreground=no
|
||||
Foreground=yes
|
||||
# The server will stay in the foreground if set to true.
|
||||
|
||||
|
||||
@@ -94,13 +94,30 @@ Arguments="-d /dev/ttyS0 -t 20x2 -c 120"
|
||||
# Hitachi HD44780 driver
|
||||
# See docs/hd44780_howto.txt
|
||||
|
||||
Arguments="-p 0x378 -c 4bit -k -b"
|
||||
Port=0x378
|
||||
# Port where the LPT is. Usual values are 0x278, 0x378 and 0x3BC
|
||||
|
||||
# Meaning:
|
||||
# -p <port> Use the given port
|
||||
# -c <ct> Use the given connectiontype
|
||||
# -k Keypad support
|
||||
# -b Backlight support
|
||||
ConnectionType=4bit
|
||||
# Select what type of connection. See documentation for types.
|
||||
|
||||
Keypad=no
|
||||
# If you have a keypad connected. Keypad layout is currently not
|
||||
# configureable from the config file.
|
||||
|
||||
Backlight=no
|
||||
# If you have a switchable backlight.
|
||||
|
||||
Size=20x4
|
||||
# Specifies the size of the LCD.
|
||||
# In case of multiple combined displays, this should be the total size.
|
||||
|
||||
#vspan=1,2
|
||||
# For multiple displays: at what 'logical' lines do the individual displays
|
||||
# start.
|
||||
|
||||
#extended=yes
|
||||
# If you want to use more than 3 HD44780 controllers on the LPT, you need to
|
||||
# specify this. See documentation.
|
||||
|
||||
|
||||
[LB216]
|
||||
|
||||
+207
-30
@@ -79,7 +79,7 @@ to the input pins.
|
||||
If you connect a key like sketched below, then you can only connect one key
|
||||
per input pin. It is a simple solution if you need only few keys.
|
||||
|
||||
+ 5V
|
||||
O 5V
|
||||
|
|
||||
|
|
||||
-
|
||||
@@ -136,7 +136,7 @@ Y1 o---|<---@--@--@
|
||||
| | |
|
||||
Y2 o---|<---@--@--@
|
||||
| | |
|
||||
Y3 o---|<---@--@--@ + 5V
|
||||
Y3 o---|<---@--@--@ O 5V
|
||||
| | | |
|
||||
diodes | | | ___ |
|
||||
1N4148 +----------|___|---+
|
||||
@@ -168,6 +168,54 @@ You can buy arrays of keys that are connected like this in the electronics
|
||||
shop. They usually call it a matrix keypad. To hook it to lcdproc, you
|
||||
would only need to add the resistors and diodes.
|
||||
|
||||
If the driver generates keypresses without that you actually press a key,
|
||||
it might be that the unconnected input lines are picking up
|
||||
electromagnetic waves from the air. In that case connect the unconnected
|
||||
input lines (pin 10, 11, 12, 13 and 15 of the LPT) to VCC.
|
||||
|
||||
|
||||
1.1.3 Backlight
|
||||
---------------
|
||||
|
||||
A small extension allows you to switch the backlight of the display on
|
||||
and off. At the moment only the 4bit and winamp connection types support
|
||||
this. The extension uses one output pin, you cannot use that pin for other
|
||||
functions anymore. The wiring looks like this:
|
||||
|
||||
O 5V
|
||||
___ |
|
||||
+---|___|--------+
|
||||
LPT Sub-D connector | 4k7 |
|
||||
| |e
|
||||
| ___ b |/
|
||||
BL pin o---------------+---|___|------|
|
||||
330E |\
|
||||
bc327 |c
|
||||
| LCD connector
|
||||
|
|
||||
+--------o 15 backlight
|
||||
|
||||
+--------o 16 GND backlight
|
||||
|
|
||||
=== GND
|
||||
|
||||
Note: 4k7 means 4,7 kohm and 330E means 330 ohm.
|
||||
The BC327 has the following connections:
|
||||
|
||||
_____
|
||||
| |
|
||||
|bc327|
|
||||
|_____|
|
||||
| | |
|
||||
| | |
|
||||
| | |
|
||||
c b e
|
||||
|
||||
Sometimes the backlight connections are not on the 'main' connector, but on
|
||||
the side. If that is the case, there is usually NO RESISTOR present to limit
|
||||
the current through the LEDs. Therefor you should add a resistor after
|
||||
the transistor of 10 ohm.
|
||||
|
||||
|
||||
1.2 4-bit
|
||||
----------
|
||||
@@ -219,6 +267,8 @@ The optional keypad can be connected as follows:
|
||||
SELIN (13) X3
|
||||
nFAULT (15) X4
|
||||
|
||||
The optional backlight wiring should be connected to D5, pin 7.
|
||||
|
||||
|
||||
1.3 8-bit "Winamp"
|
||||
-------------------
|
||||
@@ -267,6 +317,8 @@ The optional keypad can be connected as follows:
|
||||
SELIN (13) X3
|
||||
nFAULT (15) X4
|
||||
|
||||
The optional backlight wiring should be connected to nSEL, pin 17.
|
||||
|
||||
|
||||
1.4 Extended 8-bit "lcdtime"
|
||||
-----------------------------
|
||||
@@ -280,6 +332,9 @@ http://metalab.unc.edu/pub/linux/system/status/lcdtime-0.2.tar.gz
|
||||
http://metalab.unc.edu/pub/linux/system/status/meter-0.2.tar.gz
|
||||
http://metalab.unc.edu/pub/linux/system/status/portato-1.2.tar.gz
|
||||
|
||||
Theoretically this wiring sends the data over twice as slow as the
|
||||
winamp or ext8bit wirings, because it only sends 4 bits at a time.
|
||||
|
||||
The LCD connections are:
|
||||
|
||||
printer port LCD
|
||||
@@ -321,16 +376,153 @@ The optional keypad can be connected as follows:
|
||||
SELIN (13) X3
|
||||
nFAULT (15) X4
|
||||
|
||||
The backlight wiring should be attached to nSEL, pin 17. Because the portato
|
||||
program (mentioned above) also uses this pin to control the bargraph, you
|
||||
cannot use the backlight control together with the bargraph.
|
||||
|
||||
|
||||
1.5 Serial LPT
|
||||
---------------
|
||||
|
||||
This interface uses a handful of wires to interface to the
|
||||
HD44780. Suitable for high noise, long connections. Designed by
|
||||
Andrew McMeikan <andrewm@engineer.com>. Refer to
|
||||
http://members.xoom.com/andrewmuck for details of the connections.
|
||||
Andrew McMeikan <andrewm@engineer.com>. The original wiring and
|
||||
driver can be found at:
|
||||
http://members.xoom.com/andrewmuck
|
||||
|
||||
Note from Joris: I still need to add keypad stuff here
|
||||
I (Joris) have extended this driver and the wiring a bit. It now supports
|
||||
keys again (it had earlier supported keys, but some time did not).
|
||||
|
||||
Further I have extended the driver and the wiring to be able to run
|
||||
using 2 instead of 3 output pins. That's even one less pin ! :)
|
||||
|
||||
Of course the use of fewer lines than the other wirings can not stay
|
||||
without drawbacks. In this case the simplicity of the long feeding wires
|
||||
is compensated by some intelligence in the decoding of the data. If you
|
||||
have no experience with the soldering iron, I do not recommend to build
|
||||
this wiring.
|
||||
|
||||
OK, so here is the wiring. First of the 'simple' 3 wires version. IC1 is
|
||||
the shift register, a 4094. Do not forget to connect the 5V to pin 16 and
|
||||
GND to pin 8 of the IC.
|
||||
|
||||
IC1
|
||||
-----------
|
||||
| 4094 |
|
||||
5V | shift reg | display
|
||||
O | | /keys
|
||||
| 1| |3
|
||||
+----|STR Q0|---------------------o 7 D0
|
||||
| | |4 /Y0
|
||||
Data | 2| Q1|---------------------o 8 D1
|
||||
D3 5 o---------------------------|D |5 /Y1
|
||||
| | Q2|---------------------o 9 D2
|
||||
| 3|CK |6 /Y2
|
||||
D4 6 o---------------------------| Q3|---------------------o 10 D3
|
||||
| | |10 /Y3
|
||||
| 15| Q4|---------------------o Y4
|
||||
+----|OE |11
|
||||
| Q5|---------------------o 4 RS
|
||||
| |12 /Y5
|
||||
| Q6|---------------------o Y6
|
||||
| |13
|
||||
| Q7|---------------------o Y7
|
||||
| |9
|
||||
| QS|-- +--o 5 RW
|
||||
| __|10 |
|
||||
| QS|-- ===
|
||||
| |
|
||||
-----------
|
||||
|
||||
|
||||
D2 4 o-------------------------------------------------------------o 6 EN
|
||||
|
||||
D7 9 o-------------------------------------------------------------o 6 EN2
|
||||
(2nd LCD)
|
||||
|
||||
|
||||
5V O-----+--------+----------------------------------+-----o 2 VCC
|
||||
| | |
|
||||
| | |
|
||||
|100n O 16 .-.
|
||||
--- IC1 | |<---o 3 Vlcd
|
||||
--- O 8 | |10k
|
||||
| | '-'
|
||||
GND | | |
|
||||
18..25 o-----------+--------+--------------------------+-------+-----o 1 GND
|
||||
|
|
||||
=== GND
|
||||
|
||||
|
||||
|
||||
The second possible wiring is with 2 output lines. This one is a bit more
|
||||
complex. If you do not understand the schematic, do not build it.
|
||||
|
||||
IC2
|
||||
-----------
|
||||
| 74HCT164 |
|
||||
| shift reg | display
|
||||
| | /keys
|
||||
Data 1| |3
|
||||
D3 5 o-----------------------+---|D Q0|---------------------o 7 D0
|
||||
| | |4 /Y0
|
||||
| 2| Q1|---------------------o 8 D1
|
||||
+---|D |5 /Y1
|
||||
| Q2|---------------------o 9 D2
|
||||
| |6 /Y2
|
||||
| Q3|---------------------o 10 D3
|
||||
| |10 /Y3
|
||||
Clock 8| Q4|---------------------o Y4
|
||||
D4 6 o---------------------------|CK |11
|
||||
| Q5|---------------------o 4 RS
|
||||
___ 9|\ 8 9|_ |12 /Y5
|
||||
+--|___|--+----| >o----|R Q6|---------------------o Y6
|
||||
| 22k | |/ | |13
|
||||
| --- IC1 | Q7|---+ +--o 5 RW
|
||||
| --- | | | 5V |
|
||||
| |100p ----------- | O ===
|
||||
| | | |
|
||||
| === | .-.
|
||||
| | | |22k
|
||||
+--------------------------------------+ | |
|
||||
| '-'
|
||||
| ___ 11|\ 10 | 5|\ 6
|
||||
+--|___|--+----| >o-------------------||----+-----| >o---o 6 EN
|
||||
22k | |/ 22p |/
|
||||
--- IC1 IC1
|
||||
---
|
||||
|22p
|
||||
| IC1=74HCT14 (6x Schmitt trigger inverter)
|
||||
===
|
||||
|
||||
|
||||
5V O--+-------+------+------+------------------------+-----o 2 VCC
|
||||
| | | | 13|\ 12 |
|
||||
| | | +---| >o- |
|
||||
|100n O 14 O 14 |/ .-.
|
||||
--- IC1 IC2 | |<---o 3 Vlcd
|
||||
--- O 7 O 7 1|\ 2 3|\ 4 | |10k
|
||||
| | | +--| >o- +--| >o- '-'
|
||||
GND | | | | |/ | |/ |
|
||||
18..25 o--------+-------+------+-------+----------+-----+------+-----o 1 GND
|
||||
|
|
||||
=== GND
|
||||
|
||||
Also the serialLpt wiring supports a keypad. The 3 wires version supports
|
||||
8 keys, or if you use multiple return lines up to 8 x 5 = 40 lines. The
|
||||
2 wires version supports 7 keys, or with multiple return lines
|
||||
7 x 5 = 35 keys.
|
||||
|
||||
The return lines are the following:
|
||||
|
||||
nACK (10) X0
|
||||
BUSY (11) X1
|
||||
PAPEREND (12) X2
|
||||
SELIN (13) X3
|
||||
nFAULT (15) X4
|
||||
|
||||
To understand some of this keypad documentation, do also read the keypad
|
||||
section in this document.
|
||||
|
||||
|
||||
2. Compiling
|
||||
@@ -344,33 +536,17 @@ can be done by specifying "--enable-drivers=all" or by
|
||||
3. Running
|
||||
----------
|
||||
|
||||
Keep in mind the following points.
|
||||
Modify the LCDd.conf file before you run LCDd. In this config file are
|
||||
detailed instructions on how to configure the HD44780 driver.
|
||||
|
||||
- When specifying the lcd size, do so before the -d argument.
|
||||
- Arguments that need to be passed to the driver should be in quotes after
|
||||
the -d HD44780 arguments.
|
||||
- Use the "-e" argument for extended interfaces (e.g. 3 or more displays as
|
||||
indicated by "optional" connections above).
|
||||
- Use "-k" to enable the keypad code.
|
||||
Then as usual, start LCDd with the correct config file:
|
||||
LCDd -c ./LCDd.conf
|
||||
for example.
|
||||
|
||||
|
||||
EXAMPLES:
|
||||
|
||||
For a 4bit connection, 16x2 display on port 0x278
|
||||
LCDd -t 16x2 -d HD44780 "-p 0x278"
|
||||
|
||||
For a 4bit, 40x4 display (effectively two 40x2 displays)
|
||||
LCDd -t 40x4 -d HD44780 "-v 2,2"
|
||||
|
||||
For a Winamp connection, 20x2 and 20x1 displays
|
||||
LCDd -t 20x3 -d HD44780 "-c winamp -v 2,1"
|
||||
|
||||
For a 4bit, 16x2, 16x4 and 16x1 displays
|
||||
LCDd -t 16x7 -d HD44780 "-v 2,4,1 -e"
|
||||
|
||||
For help on the parameters for the 8-bit driver (make sure --help is the
|
||||
last arguments in quotes):
|
||||
LCDd -d HD44780 "-c 8bit --help"
|
||||
If you want to override the driver selection in LCDd.conf then use:
|
||||
LCDd -c ./LCDd.conf -d HD44780
|
||||
If you use this, the HD44780 driver will read the options from the config
|
||||
file.
|
||||
|
||||
|
||||
4. Miscellania
|
||||
@@ -381,3 +557,4 @@ This text originally taken from a message by Bill Farrow
|
||||
|
||||
Updated February 2000, Benjamin Tse (blt@ComPorts.com)
|
||||
|
||||
Updated October 2001, Joris Robijn (joris at robijn.net)
|
||||
|
||||
@@ -20,7 +20,11 @@
|
||||
* D6 (8) EN (6)
|
||||
* D7 (9) EN2 (LCD2 - 6) (optional)
|
||||
*
|
||||
* Backlight
|
||||
* D5 (7) backlight (optional, see documentation)
|
||||
*
|
||||
* Extended interface (including LCD3 above)
|
||||
* D5 (7) EN3
|
||||
* STR (1) EN4
|
||||
* LF (14) EN5
|
||||
* INIT (16) EN6
|
||||
@@ -66,34 +70,37 @@
|
||||
#include <errno.h>
|
||||
|
||||
// Generally, any function that accesses the LCD control lines needs to be
|
||||
// implemented separately for each HW design. This is typically just
|
||||
// HD44780_senddata and HD44780_readkeypad
|
||||
// implemented separately for each HW design. This is typically (but not
|
||||
// restricted to):
|
||||
// HD44780_senddata
|
||||
// HD44780_readkeypad
|
||||
|
||||
void lcdstat_HD44780_senddata (unsigned char displayID, unsigned char flags, unsigned char ch);
|
||||
void lcdstat_HD44780_backlight (unsigned char state);
|
||||
unsigned char lcdstat_HD44780_readkeypad (unsigned int YData);
|
||||
|
||||
#define RS 0x10
|
||||
#define RW 0x20
|
||||
#define EN1 0x40
|
||||
#define EN2 0x80
|
||||
#define EN3 0x20
|
||||
#define RS 0x10
|
||||
#define RW 0x20
|
||||
#define EN1 0x40
|
||||
#define EN2 0x80
|
||||
#define EN3 0x20
|
||||
#define BL 0x20
|
||||
// note that the above bits are all meant for the data port of LPT
|
||||
|
||||
static unsigned char EnMask[] = { EN1, EN2, EN3, STRB, LF, INIT, SEL };
|
||||
static int EnMaskSize = sizeof (EnMask) / sizeof (unsigned char);
|
||||
|
||||
static int extIF = 0; // non-zero if extended interface
|
||||
#define ALLEXT (STRB|LF|INIT|SEL)
|
||||
// The above bits are on the control port of LPT
|
||||
|
||||
static unsigned int lptPort;
|
||||
static char stuckinputs = 0; // if an input line is stuck, it will be ignored
|
||||
static char stuckinputs = 0; // if an input line is stuck, it will be ignored
|
||||
static char backlight_bit = 0; // default to low to enable three displays
|
||||
|
||||
// initialisation function
|
||||
int
|
||||
hd_init_4bit (HD44780_functions * hd44780_functions, lcd_logical_driver * driver, char *args, unsigned int port)
|
||||
{
|
||||
// TODO: remove magic numbers below
|
||||
char *argv[64];
|
||||
int argc;
|
||||
int i;
|
||||
int displayID = EN1 | EN2;
|
||||
int enableLines = EN1 | EN2;
|
||||
|
||||
// Reserve the port registers
|
||||
lptPort = port;
|
||||
@@ -102,44 +109,36 @@ hd_init_4bit (HD44780_functions * hd44780_functions, lcd_logical_driver * driver
|
||||
port_access(lptPort+2);
|
||||
|
||||
hd44780_functions->senddata = lcdstat_HD44780_senddata;
|
||||
hd44780_functions->backlight = lcdstat_HD44780_backlight;
|
||||
hd44780_functions->readkeypad = lcdstat_HD44780_readkeypad;
|
||||
|
||||
// parse command-line arguments
|
||||
argc = get_args (argv, args, 64);
|
||||
|
||||
for (i = 0; i < argc; ++i) {
|
||||
if (strcmp (argv[i], "-e") == 0 || strcmp (argv[i], "--extended") == 0) {
|
||||
extIF = 1;
|
||||
}
|
||||
}
|
||||
|
||||
// powerup the lcd now
|
||||
if (extIF) {
|
||||
displayID |= EN3;
|
||||
enableLines |= EN3;
|
||||
port_out (lptPort + 2, 0 ^ OUTMASK);
|
||||
}
|
||||
|
||||
port_out (lptPort, displayID | 0x03);
|
||||
port_out (lptPort, enableLines | 0x03);
|
||||
if (extIF)
|
||||
port_out (lptPort + 2, (EnMask[3] | EnMask[4] | EnMask[5] | EnMask[6]) ^ OUTMASK);
|
||||
port_out (lptPort + 2, ALLEXT ^ OUTMASK);
|
||||
hd44780_functions->uPause (1);
|
||||
port_out (lptPort, 0x03);
|
||||
if (extIF)
|
||||
port_out (lptPort + 2, 0 ^ OUTMASK);
|
||||
hd44780_functions->uPause (4100);
|
||||
|
||||
port_out (lptPort, displayID | 0x03);
|
||||
port_out (lptPort, enableLines | 0x03);
|
||||
if (extIF)
|
||||
port_out (lptPort + 2, (EnMask[3] | EnMask[4] | EnMask[5] | EnMask[6]) ^ OUTMASK);
|
||||
port_out (lptPort + 2, ALLEXT ^ OUTMASK);
|
||||
hd44780_functions->uPause (1);
|
||||
port_out (lptPort, 0x03);
|
||||
if (extIF)
|
||||
port_out (lptPort + 2, 0 ^ OUTMASK);
|
||||
hd44780_functions->uPause (100);
|
||||
|
||||
port_out (lptPort, displayID | 0x03);
|
||||
port_out (lptPort, enableLines | 0x03);
|
||||
if (extIF)
|
||||
port_out (lptPort + 2, (EnMask[3] | EnMask[4] | EnMask[5] | EnMask[6]) ^ OUTMASK);
|
||||
port_out (lptPort + 2, ALLEXT ^ OUTMASK);
|
||||
hd44780_functions->uPause (1);
|
||||
port_out (lptPort, 0x03);
|
||||
if (extIF)
|
||||
@@ -147,9 +146,9 @@ hd_init_4bit (HD44780_functions * hd44780_functions, lcd_logical_driver * driver
|
||||
hd44780_functions->uPause (40);
|
||||
|
||||
// now in 8-bit mode... set 4-bit mode
|
||||
port_out (lptPort, displayID | 0x02);
|
||||
port_out (lptPort, enableLines | 0x02);
|
||||
if (extIF)
|
||||
port_out (lptPort + 2, (EnMask[3] | EnMask[4] | EnMask[5] | EnMask[6]) ^ OUTMASK);
|
||||
port_out (lptPort + 2, ALLEXT ^ OUTMASK);
|
||||
hd44780_functions->uPause (1);
|
||||
port_out (lptPort, 0x02);
|
||||
if (extIF)
|
||||
@@ -168,16 +167,18 @@ hd_init_4bit (HD44780_functions * hd44780_functions, lcd_logical_driver * driver
|
||||
|
||||
// lcdstat_HD44780_senddata
|
||||
void
|
||||
lcdstat_HD44780_senddata (unsigned char displayID, unsigned char iflags, unsigned char ch)
|
||||
lcdstat_HD44780_senddata (unsigned char displayID, unsigned char flags, unsigned char ch)
|
||||
{
|
||||
unsigned char enableLines = 0, flags = 0;
|
||||
unsigned char enableLines = 0, portControl = 0;
|
||||
unsigned char h = (ch >> 4) & 0x0f; // high and low nibbles
|
||||
unsigned char l = ch & 0x0f;
|
||||
|
||||
if (iflags == RS_INSTR)
|
||||
flags = 0;
|
||||
else //if (iflags == RS_DATA)
|
||||
flags = RS;
|
||||
if (flags == RS_INSTR)
|
||||
portControl = 0;
|
||||
else //if (flags == RS_DATA)
|
||||
portControl = RS;
|
||||
|
||||
portControl |= backlight_bit;
|
||||
|
||||
if (displayID <= 3) {
|
||||
if (displayID == 0)
|
||||
@@ -185,36 +186,43 @@ lcdstat_HD44780_senddata (unsigned char displayID, unsigned char iflags, unsigne
|
||||
else
|
||||
enableLines = EnMask[displayID - 1];
|
||||
|
||||
port_out (lptPort, flags | h);
|
||||
port_out (lptPort, portControl | h);
|
||||
hd44780_functions->uPause (2);
|
||||
port_out (lptPort, enableLines | flags | h);
|
||||
port_out (lptPort, enableLines | portControl | h);
|
||||
hd44780_functions->uPause (4);
|
||||
port_out (lptPort, flags | h);
|
||||
port_out (lptPort, portControl | h);
|
||||
|
||||
port_out (lptPort, enableLines | flags | l);
|
||||
port_out (lptPort, enableLines | portControl | l);
|
||||
hd44780_functions->uPause (4);
|
||||
port_out (lptPort, flags | l);
|
||||
port_out (lptPort, portControl | l);
|
||||
}
|
||||
|
||||
if (extIF && (displayID == 0 || displayID >= 4)) {
|
||||
if (displayID == 0)
|
||||
enableLines = EnMask[3] | EnMask[4] | EnMask[5] | EnMask[6];
|
||||
enableLines = ALLEXT;
|
||||
else
|
||||
enableLines = EnMask[(displayID - 1) % EnMaskSize];
|
||||
enableLines = EnMask[(displayID - 1)];
|
||||
|
||||
port_out (lptPort, flags | h);
|
||||
port_out (lptPort, portControl | h);
|
||||
hd44780_functions->uPause (2);
|
||||
port_out (lptPort + 2, enableLines ^ OUTMASK);
|
||||
hd44780_functions->uPause (4);
|
||||
port_out (lptPort + 2, 0 ^ OUTMASK);
|
||||
|
||||
port_out (lptPort, flags | l);
|
||||
port_out (lptPort, portControl | l);
|
||||
port_out (lptPort + 2, enableLines ^ OUTMASK);
|
||||
hd44780_functions->uPause (4);
|
||||
port_out (lptPort + 2, 0 ^ OUTMASK);
|
||||
}
|
||||
}
|
||||
|
||||
void lcdstat_HD44780_backlight (unsigned char state)
|
||||
{
|
||||
backlight_bit = (state?0:0x20); // D5 line
|
||||
|
||||
port_out (lptPort, backlight_bit);
|
||||
}
|
||||
|
||||
unsigned char lcdstat_HD44780_readkeypad (unsigned int YData)
|
||||
{
|
||||
unsigned char readval;
|
||||
@@ -226,7 +234,12 @@ unsigned char lcdstat_HD44780_readkeypad (unsigned int YData)
|
||||
port_out (lptPort + 2, ( ((~YData & 0x03C0) << 6 )) ^ OUTMASK);
|
||||
}
|
||||
|
||||
// And convert it back.
|
||||
// Read inputs
|
||||
readval = ~ port_in (lptPort + 1) ^ INMASK;
|
||||
|
||||
// Put port back into idle state for backlight
|
||||
port_out (lptPort, backlight_bit ^ OUTMASK);
|
||||
|
||||
// And convert value back.
|
||||
return ( (readval >> 4 & 0x03) | (readval >> 5 & 0x04) | (readval >> 3 & 0x08) | (readval << 1 & 0x10) ) & ~stuckinputs;
|
||||
}
|
||||
|
||||
@@ -16,11 +16,13 @@
|
||||
* D5 (7) D5 (12)
|
||||
* D6 (8) D6 (13)
|
||||
* D7 (9) D7 (14)
|
||||
* nSEL (17) -
|
||||
* nSTRB (1) RS (4)
|
||||
* nLF (14) RW (5) (LCD2 - 6) (optional - pull all LCD RW low)
|
||||
* INIT (16) EN (6)
|
||||
*
|
||||
* Backlight
|
||||
* SEL (17) backlight (optional, see documentation)
|
||||
*
|
||||
* Keypad connection (optional):
|
||||
* Some diodes and resistors are needed, see further documentation.
|
||||
* printer port keypad
|
||||
@@ -65,20 +67,17 @@
|
||||
// HD44780_readkeypad
|
||||
|
||||
void lcdtime_HD44780_senddata (unsigned char displayID, unsigned char flags, unsigned char ch);
|
||||
void lcdtime_HD44780_backlight (unsigned char state);
|
||||
unsigned char lcdtime_HD44780_readkeypad (unsigned int YData);
|
||||
|
||||
#define nRS nSTRB
|
||||
#define nRW nLF
|
||||
#define EN1 INIT
|
||||
#define METER_OFF nSEL
|
||||
#define RS STRB
|
||||
#define RW LF
|
||||
#define EN1 INIT
|
||||
#define BL SEL
|
||||
|
||||
#define SETUPLCD (METER_OFF | nRS)
|
||||
#define CTRL (nRW | METER_OFF | nRS)
|
||||
#define CHAR (nRW | METER_OFF)
|
||||
|
||||
static int extIF = 0; // non-zero if extended interface
|
||||
static unsigned int lptPort;
|
||||
static char stuckinputs = 0; // if an input line is stuck, it will be ignored
|
||||
static char stuckinputs = 0; // if an input line is stuck, it will be ignored
|
||||
static char backlight_bit = 0;
|
||||
|
||||
static int semid;
|
||||
|
||||
@@ -95,6 +94,7 @@ hd_init_ext8bit (HD44780_functions * hd44780_functions, lcd_logical_driver * dri
|
||||
port_access(lptPort+2);
|
||||
|
||||
hd44780_functions->senddata = lcdtime_HD44780_senddata;
|
||||
hd44780_functions->backlight = lcdtime_HD44780_backlight;
|
||||
hd44780_functions->readkeypad = lcdtime_HD44780_readkeypad;
|
||||
|
||||
// setup the lcd in 8 bit mode
|
||||
@@ -106,6 +106,11 @@ hd_init_ext8bit (HD44780_functions * hd44780_functions, lcd_logical_driver * dri
|
||||
hd44780_functions->uPause (40);
|
||||
|
||||
common_init ();
|
||||
|
||||
if (have_keypad) {
|
||||
// Remember which input lines are stuck
|
||||
stuckinputs = lcdtime_HD44780_readkeypad (0);
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
@@ -113,31 +118,42 @@ hd_init_ext8bit (HD44780_functions * hd44780_functions, lcd_logical_driver * dri
|
||||
void
|
||||
lcdtime_HD44780_senddata (unsigned char displayID, unsigned char flags, unsigned char ch)
|
||||
{
|
||||
unsigned char dispID = 0, portControl;
|
||||
unsigned char enableLines = 0, portControl;
|
||||
|
||||
if (displayID == 1)
|
||||
dispID |= EN1;
|
||||
else //if (displayID == 0)
|
||||
dispID |= EN1;
|
||||
// Only one controller is supported
|
||||
enableLines = EN1;
|
||||
|
||||
if (flags == RS_DATA)
|
||||
portControl = CHAR;
|
||||
else
|
||||
portControl = CTRL;
|
||||
if (flags == RS_INSTR)
|
||||
portControl = 0;
|
||||
else //if (iflags == RS_DATA)
|
||||
portControl = RS;
|
||||
|
||||
portControl |= backlight_bit;
|
||||
|
||||
sem_wait (semid);
|
||||
port_out (lptPort + 2, SETUPLCD);
|
||||
port_out (lptPort + 2, portControl ^ OUTMASK);
|
||||
port_out (lptPort, ch);
|
||||
port_out (lptPort + 2, dispID | portControl);
|
||||
port_out (lptPort + 2, (enableLines|portControl) ^ OUTMASK);
|
||||
hd44780_functions->uPause (1);
|
||||
port_out (lptPort + 2, portControl);
|
||||
port_out (lptPort + 2, portControl ^ OUTMASK);
|
||||
sem_signal (semid);
|
||||
}
|
||||
|
||||
void lcdtime_HD44780_backlight (unsigned char state)
|
||||
{
|
||||
backlight_bit = (state?0:SEL);
|
||||
|
||||
// Semaphores not needed because backlight will not go together with
|
||||
// the bacrgraph anyway...
|
||||
port_out (lptPort + 2, backlight_bit ^ OUTMASK);
|
||||
}
|
||||
|
||||
unsigned char lcdtime_HD44780_readkeypad (unsigned int YData)
|
||||
{
|
||||
unsigned char readval;
|
||||
|
||||
sem_wait (semid);
|
||||
|
||||
// 10 bits output
|
||||
// Convert the positive logic to the negative logic on the LPT port
|
||||
port_out (lptPort, ~YData & 0x00FF );
|
||||
@@ -145,7 +161,13 @@ unsigned char lcdtime_HD44780_readkeypad (unsigned int YData)
|
||||
port_out (lptPort + 2, ( ((~YData & 0x0100) >> 8) | ((~YData & 0x0200) >> 6)) ^ OUTMASK);
|
||||
}
|
||||
|
||||
// And convert it back.
|
||||
// Read inputs
|
||||
readval = ~ port_in (lptPort + 1) ^ INMASK;
|
||||
|
||||
// Put port back into idle state for backlight
|
||||
port_out (lptPort, backlight_bit ^ OUTMASK);
|
||||
sem_signal (semid);
|
||||
|
||||
// And convert value back.
|
||||
return ( (readval >> 4 & 0x03) | (readval >> 5 & 0x04) | (readval >> 3 & 0x08) | (readval << 1 & 0x10) ) & ~stuckinputs;
|
||||
}
|
||||
|
||||
@@ -14,26 +14,29 @@ typedef struct hwDependentFns {
|
||||
// microsec pauses
|
||||
void (*uPause) (int microSecondsTenths);
|
||||
|
||||
// senddata to the LCD
|
||||
// Senddata to the LCD
|
||||
// dispID - display to send data to (0 = all displays)
|
||||
// flags - data or instruction command (RS_DATA | RS_INSTR)
|
||||
// ch - character to display or instruction value
|
||||
void (*senddata) (unsigned char dispID, unsigned char flags, unsigned char ch);
|
||||
|
||||
// position the cursor
|
||||
// dispID - display to send data to (0 = all displays)
|
||||
// DDaddr - display data address (see sect 2.5.2 of the LCD module FAQ)
|
||||
void (*position) (int dispID, int DDaddr);
|
||||
// Switch the backlight on or off
|
||||
// state - to be or not to be on
|
||||
void (*backlight) (unsigned char state);
|
||||
|
||||
// toggle vertical autoscroll on all displays
|
||||
// on - non-zero turns autoscroll on, zero value turns it off
|
||||
void (*autoscroll) (int on);
|
||||
|
||||
// read the keypad
|
||||
// Read the keypad
|
||||
// Ydata - the up to 11 bits that should be put on the Y side of the matrix
|
||||
// return - the up to 5 bits that are read out on the X side of the matrix
|
||||
unsigned char (*readkeypad) (unsigned int Ydata);
|
||||
|
||||
// Scan the keypad and return a scancode.
|
||||
// The code is the Yvalue in the high nibble and the Xvalue in the low nibble.
|
||||
// A subdriver should do only one of two things:
|
||||
// - set readkeypad; or
|
||||
// - override scankeypad.
|
||||
unsigned char (*scankeypad) ();
|
||||
|
||||
|
||||
} HD44780_functions; /* for want of a better name :-) */
|
||||
|
||||
extern HD44780_functions *hd44780_functions;
|
||||
|
||||
@@ -36,6 +36,7 @@
|
||||
* Q4 (7) Y3
|
||||
* Q5 (14) Y4
|
||||
* Q6 (13) Y5
|
||||
* Q7 (12) Y6
|
||||
* The 'output' of the keys should be connected to the following LPT pins:
|
||||
* nACK (10) X0
|
||||
* BUSY (11) X1
|
||||
@@ -59,9 +60,9 @@
|
||||
|
||||
// Hardware specific functions
|
||||
void lcdserLpt_HD44780_senddata (unsigned char displayID, unsigned char flags, unsigned char ch);
|
||||
unsigned char lcdserLpt_HD44780_readkeypad (unsigned int YData);
|
||||
void lcdserLpt_HD44780_backlight (unsigned char state);
|
||||
|
||||
static char lcdserLpt_HD44780_getkey (void); // old keypad code
|
||||
unsigned char lcdserLpt_HD44780_scankeypad ();
|
||||
void rawshift (unsigned char r);
|
||||
void shiftreg (unsigned char displayID, unsigned char r);
|
||||
|
||||
@@ -72,9 +73,6 @@ void shiftreg (unsigned char displayID, unsigned char r);
|
||||
#define EN2 32
|
||||
|
||||
static unsigned int lptPort;
|
||||
static char stuckinputs = 0; // if an input line is stuck, it will be ignored
|
||||
|
||||
static char lastkey = 0; // currently not in use, old keypad code
|
||||
|
||||
// Initialisation
|
||||
int
|
||||
@@ -89,11 +87,9 @@ hd_init_serialLpt (HD44780_functions * hd44780_functions, lcd_logical_driver * d
|
||||
port_access(lptPort+2);
|
||||
|
||||
hd44780_functions->senddata = lcdserLpt_HD44780_senddata;
|
||||
hd44780_functions->readkeypad = lcdserLpt_HD44780_readkeypad;
|
||||
hd44780_functions->backlight = lcdserLpt_HD44780_backlight;
|
||||
hd44780_functions->scankeypad = lcdserLpt_HD44780_scankeypad;
|
||||
|
||||
if (have_keypad) {
|
||||
driver->getkey = lcdserLpt_HD44780_getkey;
|
||||
}
|
||||
// Clear the shiftregister
|
||||
rawshift (0);
|
||||
|
||||
@@ -114,17 +110,6 @@ hd_init_serialLpt (HD44780_functions * hd44780_functions, lcd_logical_driver * d
|
||||
|
||||
common_init ();
|
||||
|
||||
/*
|
||||
// set display type functions
|
||||
lcdserLpt_HD44780_senddata (0, RS_INSTR, FUNCSET | IF_4BIT | TWOLINE | SMALLCHAR);
|
||||
// clear
|
||||
lcdserLpt_HD44780_senddata (0, RS_INSTR, CLEAR);
|
||||
hd44780_functions->uPause (1600);
|
||||
// Now turn on the display
|
||||
lcdserLpt_HD44780_senddata (displayID, RS_INSTR, ONOFFCTRL | DISPON | CURSOROFF | CURSORNOBLINK);
|
||||
hd44780_functions->uPause (1600);
|
||||
*/
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
@@ -149,47 +134,67 @@ lcdserLpt_HD44780_senddata (unsigned char displayID, unsigned char flags, unsign
|
||||
|
||||
shiftreg (enableLines, portControl | h);
|
||||
shiftreg (enableLines, portControl | l);
|
||||
|
||||
/* TODO: instead of delay read keys here */
|
||||
}
|
||||
|
||||
char
|
||||
lcdserLpt_HD44780_getkey ()
|
||||
void
|
||||
lcdserLpt_HD44780_backlight (unsigned char state)
|
||||
{
|
||||
// TODO: a keypad scan that does not use shift register
|
||||
// define a key table
|
||||
char keytr[] = "ABCDEFGH";
|
||||
int n;
|
||||
}
|
||||
|
||||
// disabled now !
|
||||
return 0;
|
||||
unsigned char lcdserLpt_HD44780_scankeypad ()
|
||||
{
|
||||
// Unfortunately just bit shifting does not work with the 2 IC version...
|
||||
|
||||
rawshift (0); //send all line on shift register low
|
||||
hd44780_functions->uPause (1);
|
||||
if ((port_in (lptPort + 1) & 32) == 0) //test if line back is low - if not return(0)
|
||||
{ //else
|
||||
//start walking a single zero across the eight lines
|
||||
for (n = 7; n >= 0; n--) {
|
||||
rawshift (255 - (1 << n));
|
||||
hd44780_functions->uPause (1);
|
||||
unsigned char keybits;
|
||||
unsigned int shiftcount;
|
||||
unsigned int shiftingbit;
|
||||
unsigned char readval, inputs_zero, r;
|
||||
int i;
|
||||
unsigned int scancode = 0;
|
||||
|
||||
if ((port_in (lptPort + 1) & 32) == 0) // check if line back is low if yes debounce
|
||||
{
|
||||
if (lastkey == keytr[n])
|
||||
return (0);
|
||||
// printf("key is %c %d\n",keytr[n],n);
|
||||
lastkey = keytr[n];
|
||||
return (keytr[n]); //return correct key code.
|
||||
|
||||
r = 0xFF; // This command will set the cursor position, so it's harmless
|
||||
|
||||
readval = ~ port_in (lptPort + 1) ^ INMASK;
|
||||
inputs_zero = ( (readval >> 4 & 0x03) | (readval >> 5 & 0x04) | (readval >> 3 & 0x08) | (readval << 1 & 0x10) );
|
||||
|
||||
if( inputs_zero == 0 ) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
// Scan the keypad while sending the first half of the command (high nibble)
|
||||
for (i = 7; i >= 0; i--) { /* MSB first */
|
||||
port_out (lptPort, ((r >> i) & 1) * LCDDATA); /*set up data */
|
||||
port_out (lptPort, (((r >> i) & 1) * LCDDATA) | LCDCLOCK); /*rising edge of clock */
|
||||
|
||||
hd44780_functions->uPause (2);
|
||||
|
||||
// Do keyscan too !
|
||||
if( !scancode ) {
|
||||
// Read input line(s)
|
||||
readval = ~ port_in (lptPort + 1) ^ INMASK;
|
||||
keybits = ( (readval >> 4 & 0x03) | (readval >> 5 & 0x04) | (readval >> 3 & 0x08) | (readval << 1 & 0x10) );
|
||||
if( keybits != inputs_zero ) {
|
||||
shiftingbit = 1;
|
||||
for (shiftcount=0; shiftcount<KEYPAD_MAXX && !scancode; shiftcount++) {
|
||||
if ( (keybits ^ inputs_zero ) & shiftingbit) {
|
||||
// Found !
|
||||
scancode = ((8-i)<<4) | (shiftcount+1);
|
||||
}
|
||||
shiftingbit <<= 1;
|
||||
}
|
||||
}
|
||||
}
|
||||
} //else fall out and return(0) [too transient a keypress]
|
||||
lastkey = 0;
|
||||
return (0);
|
||||
}
|
||||
}
|
||||
|
||||
unsigned char lcdserLpt_HD44780_readkeypad (unsigned int YData)
|
||||
{
|
||||
return 0;
|
||||
hd44780_functions->uPause (4);
|
||||
|
||||
// And again for the second half of the command (low nibble)
|
||||
rawshift (r);
|
||||
|
||||
hd44780_functions->uPause (4);
|
||||
|
||||
return scancode;
|
||||
}
|
||||
|
||||
/* this function sends r out onto the shift register */
|
||||
@@ -197,6 +202,8 @@ void
|
||||
rawshift (unsigned char r)
|
||||
{
|
||||
int i;
|
||||
// r |= 0x80; // just to make sure ...
|
||||
|
||||
for (i = 7; i >= 0; i--) { /* MSB first */
|
||||
port_out (lptPort, ((r >> i) & 1) * LCDDATA); /*set up data */
|
||||
port_out (lptPort, (((r >> i) & 1) * LCDDATA) | LCDCLOCK); /*rising edge of clock */
|
||||
@@ -207,13 +214,9 @@ rawshift (unsigned char r)
|
||||
void
|
||||
shiftreg (unsigned char enableLines, unsigned char r)
|
||||
{
|
||||
//unsigned char mr;
|
||||
//mr = (r & 0xF0) | ((r<<3) & 0x0F) | ((r<<1) & 0x04) |
|
||||
// ((r>>1) & 0x02) | ((r>>3) & 0x01);
|
||||
|
||||
rawshift (r | 0x80); // highest bit always set to 1 for Clear
|
||||
port_out (lptPort, enableLines); //latch it, to correct display
|
||||
rawshift (r | 0x80); // highest bit always set to 1 for Clear for wiring with 2 ICs
|
||||
port_out (lptPort, enableLines); // latch it, to correct display
|
||||
hd44780_functions->uPause (1);
|
||||
port_out (lptPort, 0);
|
||||
port_out (lptPort, 0); // for wiring with 1 IC
|
||||
hd44780_functions->uPause (3);
|
||||
}
|
||||
|
||||
@@ -29,6 +29,9 @@
|
||||
* INIT (16) RS (4)
|
||||
* nSEL (17) EN2 (6 - LCD 2) (optional)
|
||||
*
|
||||
* Backlight
|
||||
* SEL (17) backlight (optional, see documentation)
|
||||
*
|
||||
* Keypad connection (optional):
|
||||
* Some diodes and resistors are needed, see further documentation.
|
||||
* printer port keypad
|
||||
@@ -64,32 +67,33 @@
|
||||
#include <string.h>
|
||||
#include <errno.h>
|
||||
|
||||
#include "port.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 lcdwinamp_HD44780_senddata (unsigned char displayID, unsigned char flags, unsigned char ch);
|
||||
void lcdwinamp_HD44780_backlight (unsigned char state);
|
||||
unsigned char lcdwinamp_HD44780_readkeypad (unsigned int YData);
|
||||
|
||||
#define EN1 STRB
|
||||
#define EN2 SEL
|
||||
#define EN3 LF
|
||||
#define RS INIT
|
||||
#define EN1 STRB
|
||||
#define EN2 SEL
|
||||
#define EN3 LF
|
||||
#define RW LF
|
||||
#define RS INIT
|
||||
#define BL SEL
|
||||
|
||||
static unsigned char EnMask[] = { EN1, EN2, EN3 };
|
||||
static int EnMaskSize = sizeof (EnMask) / sizeof (unsigned char);
|
||||
|
||||
static int extIF = 0; // non-zero if extended interface
|
||||
static unsigned int lptPort;
|
||||
static char stuckinputs = 0; // if an input line is stuck, it will be ignored
|
||||
static char stuckinputs = 0; // if an input line is stuck, it will be ignored
|
||||
static char backlight_bit = 0; // default to low to enable two displays
|
||||
|
||||
// initialise the driver
|
||||
int
|
||||
hd_init_winamp (HD44780_functions * hd44780_functions, lcd_logical_driver * driver, char *args, unsigned int port)
|
||||
{
|
||||
// TODO: remove magic numbers below
|
||||
char *argv[64];
|
||||
int argc;
|
||||
int i;
|
||||
|
||||
// Reserve the port registers
|
||||
lptPort = port;
|
||||
port_access(lptPort);
|
||||
@@ -97,16 +101,9 @@ hd_init_winamp (HD44780_functions * hd44780_functions, lcd_logical_driver * driv
|
||||
port_access(lptPort+2);
|
||||
|
||||
hd44780_functions->senddata = lcdwinamp_HD44780_senddata;
|
||||
hd44780_functions->backlight = lcdwinamp_HD44780_backlight;
|
||||
hd44780_functions->readkeypad = lcdwinamp_HD44780_readkeypad;
|
||||
|
||||
// parse command-line arguments
|
||||
argc = get_args (argv, args, 64);
|
||||
|
||||
for (i = 0; i < argc; ++i) {
|
||||
if (strcmp (argv[i], "-e") == 0 || strcmp (argv[i], "--extended") == 0)
|
||||
extIF = 1;
|
||||
}
|
||||
|
||||
// setup the lcd in 8 bit mode
|
||||
hd44780_functions->senddata (0, RS_INSTR, FUNCSET | IF_8BIT);
|
||||
hd44780_functions->uPause (4100);
|
||||
@@ -123,7 +120,7 @@ hd_init_winamp (HD44780_functions * hd44780_functions, lcd_logical_driver * driv
|
||||
void
|
||||
lcdwinamp_HD44780_senddata (unsigned char displayID, unsigned char flags, unsigned char ch)
|
||||
{
|
||||
unsigned char dispID = 0, portControl;
|
||||
unsigned char enableLines = 0, portControl;
|
||||
|
||||
if (flags == RS_DATA)
|
||||
portControl = RS;
|
||||
@@ -131,29 +128,36 @@ lcdwinamp_HD44780_senddata (unsigned char displayID, unsigned char flags, unsign
|
||||
portControl = 0;
|
||||
|
||||
if (displayID == 0)
|
||||
dispID = EnMask[0] | EnMask[1] | ((extIF) ? EnMask[2] : 0);
|
||||
enableLines = EnMask[0] | EnMask[1] | ((extIF) ? EnMask[2] : 0);
|
||||
else
|
||||
dispID = EnMask[displayID - 1];
|
||||
enableLines = EnMask[displayID - 1];
|
||||
|
||||
// 40 nS setup time for RS valid to EN high, so set RS
|
||||
port_out (lptPort + 2, portControl ^ OUTMASK);
|
||||
port_out (lptPort + 2, (portControl|backlight_bit) ^ OUTMASK);
|
||||
|
||||
// Output the actual data
|
||||
port_out (lptPort, ch);
|
||||
|
||||
// then set EN high
|
||||
port_out (lptPort + 2, (dispID | portControl) ^ OUTMASK);
|
||||
port_out (lptPort + 2, (enableLines|portControl|backlight_bit) ^ OUTMASK);
|
||||
|
||||
// 80 nS setup from valid data to EN low will be met without any delay
|
||||
// unless you are running a REALLY FAST ISA bus (like 75 MHZ!)
|
||||
// 230 nS minimum E high time provided by ISA bus delays as well...
|
||||
|
||||
// Set EN low and we're done...
|
||||
port_out (lptPort + 2, portControl ^ OUTMASK);
|
||||
port_out (lptPort + 2, (portControl|backlight_bit) ^ OUTMASK);
|
||||
|
||||
// 10 nS data hold time provided by the length of ISA write for EN
|
||||
}
|
||||
|
||||
void lcdwinamp_HD44780_backlight (unsigned char state)
|
||||
{
|
||||
backlight_bit = (state?0:nSEL);
|
||||
|
||||
port_out (lptPort + 2, backlight_bit ^ OUTMASK);
|
||||
}
|
||||
|
||||
unsigned char lcdwinamp_HD44780_readkeypad (unsigned int YData)
|
||||
{
|
||||
unsigned char readval;
|
||||
@@ -163,7 +167,12 @@ unsigned char lcdwinamp_HD44780_readkeypad (unsigned int YData)
|
||||
port_out (lptPort, ~YData & 0x00FF );
|
||||
port_out (lptPort + 2, ( ((~YData & 0x0100) >> 7) | ((~YData & 0x0200) >> 7 )) ^ OUTMASK);
|
||||
|
||||
// And convert it back.
|
||||
// Read inputs
|
||||
readval = ~ port_in (lptPort + 1) ^ INMASK;
|
||||
|
||||
// Set output back to idle state for backlight
|
||||
port_out (lptPort + 2, backlight_bit ^ INMASK );
|
||||
|
||||
// And convert value back.
|
||||
return ( (readval >> 4 & 0x03) | (readval >> 5 & 0x04) | (readval >> 3 & 0x08) | (readval << 1 & 0x10) ) & ~stuckinputs;
|
||||
}
|
||||
|
||||
+323
-282
@@ -25,12 +25,14 @@
|
||||
* Character mapping for correct display of some special ASCII chars added
|
||||
* Sep 2001, Mark Haemmerling <mail@markh.de>.
|
||||
*
|
||||
* Modified October 2001 to read the configfile.
|
||||
*
|
||||
* This file is released under the GNU General Public License. Refer to the
|
||||
* COPYING file distributed with this package.
|
||||
*
|
||||
* Copyright (c) 2000, 1999, 1995 Benjamin Tse <blt@Comports.com>
|
||||
* 2001 Joris Robijn <joris@robijn.net>
|
||||
* 2001 Mark Haemmerling <mail@markh.de>
|
||||
* 2001 Mark Haemmerling <mail@markh.de>
|
||||
* 2000 Charles Steinkuehler <cstein@newtek.com>
|
||||
* 1999 Andrew McMeikan <andrewm@engineer.com>
|
||||
* 1998 Richard Rognlie <rrognlie@gamerz.net>
|
||||
@@ -48,8 +50,6 @@
|
||||
#endif
|
||||
#include "port.h"
|
||||
|
||||
#define atest(i)
|
||||
|
||||
// Uncomment one of the lines below to select your desired delay generation
|
||||
// mechanism. If both defines are commented, the original I/O read timing
|
||||
// loop is used. Using DELAY_NANOSLEEP seems to provide the best performance.
|
||||
@@ -76,7 +76,7 @@
|
||||
#endif
|
||||
|
||||
#include "shared/str.h"
|
||||
|
||||
#include "render.h"
|
||||
#include "lcd.h"
|
||||
#include "hd44780.h"
|
||||
// #include "drv_base.h"
|
||||
@@ -97,7 +97,7 @@ HD44780_functions *hd44780_functions;
|
||||
|
||||
// default value
|
||||
static enum connectionType connection = HD_4bit;
|
||||
static int connIdx = 0;
|
||||
static int connectiontype_index = 0;
|
||||
|
||||
// spanList[line number] = display line number is in
|
||||
static int *spanList = NULL;
|
||||
@@ -112,15 +112,13 @@ static int numDisplays = 0;
|
||||
// input span list but is kept to save some cpu cycles.
|
||||
static int *dispSizes = NULL;
|
||||
|
||||
// Keypad option
|
||||
// Keypad and backlight option
|
||||
char have_keypad = 0; // off by default
|
||||
// This var is not static, so it's accessable from all sub-drivers
|
||||
char have_backlight = 0; // off by default
|
||||
char extIF = 0; // off by default
|
||||
// These vars is not static, so it's accessable from all sub-drivers
|
||||
// Indeed, this should become cleaner... later...
|
||||
|
||||
// Maximum sizes of the keypad
|
||||
// DO NOT CHANGE THESE 2 VALUES, unless you change the functions too
|
||||
#define KEYPAD_MAXX 5
|
||||
#define KEYPAD_MAXY 11
|
||||
// Autorepeat values
|
||||
#define KEYPAD_AUTOREPEAT_DELAY 500
|
||||
#define KEYPAD_AUTOREPEAT_FREQ 15
|
||||
@@ -132,25 +130,28 @@ static char keyMapDirect[KEYPAD_MAXX] = { 'A', 'B', 'C', 'D', 'E' };
|
||||
// keyMapMatrix contrains an array with arrays of the ascii-codes that should be generated
|
||||
// when a key in the matrix is pressed.
|
||||
static char keyMapMatrix[KEYPAD_MAXY][KEYPAD_MAXX] = {
|
||||
{ '1', '2', '3', 'A', 0 },
|
||||
{ '4', '5', '6', 'B', 0 },
|
||||
{ '7', '8', '9', 'C', 0 },
|
||||
{ '*', '0', '#', 'D', 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', '2', '3', 'A', 'E' },
|
||||
{ '4', '5', '6', 'B', 'F' },
|
||||
{ '7', '8', '9', 'C', 'G' },
|
||||
{ '*', '0', '#', 'D', 'H' },
|
||||
{ 'I', 'J', 'K', 'L', 'M' },
|
||||
{ 'N', 'O', 'P', 'Q', 'R' },
|
||||
{ 'S', 'T', 'U', 'V', 'W' },
|
||||
{ 'X', 'Y', 'Z', 'a', 'b' },
|
||||
{ 'c', 'd', 'e', 'f', 'g' },
|
||||
{ 'h', 'i', 'j', 'k', 'l' },
|
||||
{ 'm', 'n', 'o', 'p', 'q' }};
|
||||
|
||||
static char pressed_key = 0;
|
||||
static int pressed_key_repetitions = 0;
|
||||
static struct timeval pressed_key_time;
|
||||
|
||||
|
||||
// function declarations
|
||||
void HD44780_close ();
|
||||
void HD44780_flush ();
|
||||
void HD44780_clear ();
|
||||
void HD44780_chr (int x, int y, char ch);
|
||||
void HD44780_string (int x, int y, char *s);
|
||||
void HD44780_flush_box (int lft, int top, int rgt, int bot);
|
||||
void HD44780_backlight (int on);
|
||||
void HD44780_init_vbar ();
|
||||
@@ -159,22 +160,15 @@ void HD44780_vbar (int x, int len);
|
||||
void HD44780_hbar (int x, int y, int len);
|
||||
void HD44780_init_num ();
|
||||
void HD44780_num (int x, int num);
|
||||
void HD44780_heartbeat (int type);
|
||||
void HD44780_set_char (int n, char *dat);
|
||||
void HD44780_icon (int which, char dest);
|
||||
void HD44780_draw_frame (char *dat);
|
||||
void HD44780_close ();
|
||||
char HD44780_getkey ();
|
||||
|
||||
static void HD44780_linewrap (int on);
|
||||
static void HD44780_autoscroll (int on);
|
||||
static void HD44780_position (int x, int y);
|
||||
static void HD44780_chr (int x, int y, char ch);
|
||||
|
||||
static void common_position (int display, int DDaddr);
|
||||
static void common_autoscroll (int on);
|
||||
void HD44780_position (int x, int y);
|
||||
static void uPause (int delayCalls);
|
||||
static void HD44780_senddata (unsigned char displayID, unsigned char flags, unsigned char ch);
|
||||
static char HD44780_getkey ();
|
||||
|
||||
unsigned char HD44780_scankeypad();
|
||||
static int parse_span_list (int *spanListArray[], int *spLsize, int *dispOffsets[], int *dOffsize, int *dispSizeArray[], char *spanlist);
|
||||
|
||||
/////////////////////////////////////////////////////////////////
|
||||
@@ -185,96 +179,52 @@ HD44780_init (lcd_logical_driver * driver, char *args)
|
||||
{
|
||||
// TODO: remove the two magic numbers below
|
||||
// TODO: single point of return
|
||||
char *argv[64], *str;
|
||||
int argc, i;
|
||||
//char *argv[64];
|
||||
//int i;
|
||||
char buf[40];
|
||||
char *s;
|
||||
|
||||
HD44780 = driver;
|
||||
|
||||
// get_args inserts \0 into args - nasty !
|
||||
if (args)
|
||||
if ((str = (char *) malloc (strlen (args) + 1)))
|
||||
strcpy (str, args);
|
||||
else {
|
||||
fprintf (stderr, "Error mallocing\n");
|
||||
return -1;
|
||||
// TODO: replace DriverName with driver->name when that field exists.
|
||||
#define DriverName "HD44780"
|
||||
|
||||
|
||||
//// READ THE CONFIG FILE
|
||||
|
||||
port = driver->config_get_int( DriverName, "port", 0, 0x278 );
|
||||
|
||||
// Get and search for the connection type
|
||||
s = driver->config_get_string( DriverName, "connectiontype", 0, "4bit" );
|
||||
for (connectiontype_index = 0; strcmp (s, connectionMapping[connectiontype_index].connectionTypeStr) != 0 && connectionMapping[connectiontype_index].type != HD_unknown; ++connectiontype_index);
|
||||
|
||||
if (connectionMapping[connectiontype_index].type == HD_unknown) {
|
||||
fprintf (stderr, "HD44780_init: Unknown connection type: %s\n", s);
|
||||
return -1; // fatal error
|
||||
} else
|
||||
str = NULL;
|
||||
connection = connectionMapping[connectiontype_index].type;
|
||||
|
||||
argc = get_args (argv, args, 64);
|
||||
|
||||
// arguments are passed in with -d HD44780 "-p 0x278"
|
||||
// getopt will work well here
|
||||
for (i = 0; i < argc; i++) {
|
||||
if (0 == strcmp (argv[i], "-p") || 0 == strcmp (argv[i], "--port")) {
|
||||
if (i + 1 >= argc) {
|
||||
fprintf (stderr, "HD44780_init: %s requires an argument\n", argv[i]);
|
||||
return -1;
|
||||
} else {
|
||||
int myport;
|
||||
if (sscanf (argv[i + 1], "%i", &myport) != 1) {
|
||||
fprintf (stderr, "HD44780_init: Couldn't read port address -" " using default value 0x%x\n", port);
|
||||
return -1;
|
||||
} else {
|
||||
port = myport;
|
||||
++i;
|
||||
}
|
||||
}
|
||||
} else if (0 == strcmp (argv[i], "-c") || 0 == strcmp (argv[i], "--connect")) {
|
||||
int j = 0;
|
||||
if (i + 1 >= argc) {
|
||||
fprintf (stderr, "HD44780_init: %s requires an argument\n", argv[i]);
|
||||
return -1;
|
||||
}
|
||||
// search the next argument for the connection type
|
||||
for (j = 0; strcmp (argv[i + 1], connectionMapping[j].connectionTypeStr) != 0 && connectionMapping[j].type != HD_unknown; ++j);
|
||||
|
||||
if (connectionMapping[j].type == HD_unknown) {
|
||||
fprintf (stderr, "HD44780_init: Unknown connection type - using default %s driver\n", connectionMapping[0].connectionTypeStr);
|
||||
connection = connectionMapping[0].type;
|
||||
j = 0;
|
||||
} else
|
||||
connection = connectionMapping[j].type;
|
||||
|
||||
connIdx = j;
|
||||
++i;
|
||||
} else if (0 == strcmp (argv[i], "-v") || 0 == strcmp (argv[i], "--vspan")) {
|
||||
if (i + 1 >= argc) {
|
||||
fprintf (stderr, "HD44780_init: %s requires an argument\n", argv[i]);
|
||||
return -1;
|
||||
}
|
||||
if (parse_span_list (&spanList, &numLines, &dispVOffset, &numDisplays, &dispSizes, argv[i + 1]) == -1) {
|
||||
fprintf (stderr, "HD44780_init: invalid vspan argument\n");
|
||||
return -1;
|
||||
}
|
||||
++i;
|
||||
} else if (strcmp (argv[i], "-k") == 0 || strcmp (argv[i], "--keypad") == 0) {
|
||||
have_keypad = 1;
|
||||
printf( "HD44780 keypad extension enabled\n" );
|
||||
|
||||
} else if (0 == strcmp (argv[i], "-h") || 0 == strcmp (argv[i], "--help")) {
|
||||
int i;
|
||||
printf ("LCDproc HD44780 driver\n" "\t-p n\t--port n\tSelect the output device to use port n\n" "\t-c type\t--connect type\tSet the connection type (default 4 bit)\n" "\t\t\t\ttype = %s", connectionMapping[0].connectionTypeStr);
|
||||
for (i = 1; connectionMapping[i].type != HD_unknown; ++i)
|
||||
printf (" | %s", connectionMapping[i].connectionTypeStr);
|
||||
printf ("\n\t-v spanlist\t--vspan spanlist\tvertical span n{,m}\n" "\t-h\t--help\t\tShow this help information\n" "\n\tNote that the '-t' option should precede the '-d' option\n");
|
||||
|
||||
if (connectionMapping[connIdx].type != HD_unknown) {
|
||||
printf ("\n Parameters for %s driver\n", connectionMapping[connIdx].connectionTypeStr);
|
||||
printf ("%s", connectionMapping[connIdx].helpMsg);
|
||||
}
|
||||
// Get and parse vspan only when specified
|
||||
s = driver->config_get_string( DriverName, "vspan", 0, "" );
|
||||
if( s[0] != 0 ) {
|
||||
if (parse_span_list (&spanList, &numLines, &dispVOffset, &numDisplays, &dispSizes, s) == -1) {
|
||||
fprintf (stderr, "HD44780_init: invalid vspan value: %s\n", s );
|
||||
return -1;
|
||||
}
|
||||
/* ignore invalid arguments as they might be valid to the lower-level init
|
||||
else
|
||||
{
|
||||
printf("Invalid parameter: %s\n", argv[i]);
|
||||
}
|
||||
*/
|
||||
}
|
||||
|
||||
extIF = driver->config_get_bool( DriverName, "extended", 0, 0 );
|
||||
have_keypad = driver->config_get_bool( DriverName, "keypad", 0, 0 );
|
||||
have_backlight = driver->config_get_bool( DriverName, "backlight", 0, 0 );
|
||||
|
||||
// Get and parse size
|
||||
s = driver->config_get_string( DriverName, "size", 0, "20x4" );
|
||||
if( sscanf( s, "%dx%d", &(driver->wid), &(driver->hgt) ) != 2 ) {
|
||||
fprintf( stderr, "HD44780_init: Cannot read size: %s\n", s );
|
||||
}
|
||||
|
||||
// default case for when spans aren't indicated
|
||||
// - add a sanity check against HD44780->hgt ??
|
||||
// - this only works if the -t option is specified before -d
|
||||
if (numLines == 0) {
|
||||
if ((spanList = (int *) malloc (sizeof (int) * HD44780->hgt))) {
|
||||
int i;
|
||||
@@ -293,6 +243,8 @@ HD44780_init (lcd_logical_driver * driver, char *args)
|
||||
} else
|
||||
fprintf (stderr, "Error mallocing for display sizes list\n");
|
||||
}
|
||||
|
||||
|
||||
#if defined DELAY_NANOSLEEP
|
||||
// Change to Round-Robin scheduling for nanosleep
|
||||
{
|
||||
@@ -306,8 +258,6 @@ HD44780_init (lcd_logical_driver * driver, char *args)
|
||||
}
|
||||
#endif
|
||||
|
||||
atest( port );
|
||||
|
||||
// Make sure the frame buffer is there...
|
||||
if (!HD44780->framebuf)
|
||||
HD44780->framebuf = (unsigned char *) malloc (HD44780->wid * HD44780->hgt);
|
||||
@@ -318,27 +268,31 @@ HD44780_init (lcd_logical_driver * driver, char *args)
|
||||
}
|
||||
// Set the functions the driver supports...
|
||||
// These are the default HD44780 functions
|
||||
driver->clear = (void *) -1;
|
||||
driver->string = (void *) -1;
|
||||
driver->chr = HD44780_chr;
|
||||
driver->vbar = HD44780_vbar;
|
||||
driver->init_vbar = HD44780_init_vbar;
|
||||
driver->hbar = HD44780_hbar;
|
||||
driver->init_hbar = HD44780_init_hbar;
|
||||
driver->num = HD44780_num;
|
||||
driver->init_num = HD44780_init_num;
|
||||
|
||||
driver->init = HD44780_init;
|
||||
driver->close = (void *) -1;
|
||||
driver->close = HD44780_close;
|
||||
driver->flush = HD44780_flush;
|
||||
driver->flush_box = HD44780_flush_box;
|
||||
//driver->contrast = HD44780_contrast; // contrast by potmeter
|
||||
driver->backlight = HD44780_backlight;
|
||||
driver->clear = HD44780_clear;
|
||||
driver->chr = HD44780_chr;
|
||||
driver->string = HD44780_string;
|
||||
driver->flush_box = HD44780_flush_box; // TO BE REMOVED
|
||||
//driver->contrast = HD44780_contrast; // contrast is set by potmeter we assume
|
||||
|
||||
//driver->output = HD44780_output; // not implemented
|
||||
driver->init_vbar = HD44780_init_vbar;
|
||||
driver->init_hbar = HD44780_init_hbar;
|
||||
driver->vbar = HD44780_vbar;
|
||||
driver->hbar = HD44780_hbar;
|
||||
driver->init_num = HD44780_init_num;
|
||||
driver->num = HD44780_num;
|
||||
driver->heartbeat = HD44780_heartbeat;
|
||||
driver->set_char = HD44780_set_char;
|
||||
driver->icon = HD44780_icon;
|
||||
driver->draw_frame = HD44780_draw_frame;
|
||||
driver->draw_frame = HD44780_draw_frame; // TO BE REMOVED
|
||||
|
||||
if( have_keypad ) {
|
||||
if ( have_backlight ) {
|
||||
driver->backlight = HD44780_backlight;
|
||||
}
|
||||
if ( have_keypad ) {
|
||||
driver->getkey = HD44780_getkey;
|
||||
}
|
||||
|
||||
@@ -346,21 +300,27 @@ HD44780_init (lcd_logical_driver * driver, char *args)
|
||||
return -1;
|
||||
}
|
||||
hd44780_functions->uPause = uPause;
|
||||
hd44780_functions->position = common_position;
|
||||
hd44780_functions->autoscroll = common_autoscroll;
|
||||
hd44780_functions->scankeypad = HD44780_scankeypad;
|
||||
|
||||
connectionMapping[connIdx].init_fn (hd44780_functions, driver, str, port);
|
||||
connectionMapping[connectiontype_index].init_fn (hd44780_functions, driver, args, port);
|
||||
|
||||
HD44780_autoscroll (0);
|
||||
HD44780_clear ();
|
||||
sprintf (buf, "HD44780 %dx%d", HD44780->wid, HD44780->hgt );
|
||||
HD44780_string (1, 1, buf);
|
||||
sprintf (buf, "LPT 0x%x %s %s", port, (have_backlight?"bl":""), (have_keypad?"key":"") );
|
||||
HD44780_string (1, 2, buf);
|
||||
HD44780_flush ();
|
||||
sleep (1);
|
||||
|
||||
return port;
|
||||
}
|
||||
|
||||
/////////////////////////////////////////////////////////////////
|
||||
// Common initialisation sequence - sets cursor off and not blinking,
|
||||
// clear display and homecursor
|
||||
// Does not set twoline mode nor small characters (5x8). The init function of
|
||||
// the connectiontype should do this.
|
||||
|
||||
//
|
||||
void
|
||||
common_init ()
|
||||
{
|
||||
@@ -372,7 +332,9 @@ common_init ()
|
||||
hd44780_functions->uPause (1600);
|
||||
}
|
||||
|
||||
/////////////////////////////////////////////////////////////////
|
||||
// IO delay to avoid a task switch
|
||||
//
|
||||
void
|
||||
uPause (int delayCalls)
|
||||
{
|
||||
@@ -408,26 +370,18 @@ uPause (int delayCalls)
|
||||
#endif
|
||||
}
|
||||
|
||||
// displayID - ID of display to use (0 = all displays)
|
||||
static void
|
||||
HD44780_senddata (unsigned char displayID, unsigned char flags, unsigned char ch)
|
||||
{
|
||||
hd44780_functions->senddata (displayID, flags, ch);
|
||||
hd44780_functions->uPause (40); // Minimum exec time for all commands
|
||||
}
|
||||
|
||||
/////////////////////////////////////////////////////////////////
|
||||
// Clean-up
|
||||
//
|
||||
/*
|
||||
void HD44780_close()
|
||||
{
|
||||
drv_base_close();
|
||||
}
|
||||
*/
|
||||
void HD44780_close()
|
||||
{
|
||||
}
|
||||
|
||||
/////////////////////////////////////////////////////////////////
|
||||
// Set position (not part of API)
|
||||
//
|
||||
// x and y here are for the virtual HD44780->hgt x HD44780->wid display
|
||||
static void
|
||||
void
|
||||
HD44780_position (int x, int y)
|
||||
{
|
||||
int dispID = spanList[y];
|
||||
@@ -435,37 +389,74 @@ HD44780_position (int x, int y)
|
||||
int DDaddr;
|
||||
|
||||
// 16x1 is a special case
|
||||
if (dispSizes[dispID - 1] == 1 && HD44780->wid == 16)
|
||||
if (dispSizes[dispID - 1] == 1 && HD44780->wid == 16) {
|
||||
if (x >= 8) {
|
||||
x -= 8;
|
||||
relY = 1;
|
||||
}
|
||||
}
|
||||
|
||||
DDaddr = x + (relY % 2) * 0x40;
|
||||
if ((relY % 4) >= 2)
|
||||
DDaddr += HD44780->wid;
|
||||
|
||||
hd44780_functions->position (dispID, DDaddr);
|
||||
}
|
||||
|
||||
void
|
||||
common_position (int display, int DDaddr)
|
||||
{
|
||||
hd44780_functions->senddata (display, RS_INSTR, POSITION | DDaddr);
|
||||
hd44780_functions->senddata (dispID, RS_INSTR, POSITION | DDaddr);
|
||||
hd44780_functions->uPause (40); // Minimum exec time for all commands
|
||||
}
|
||||
|
||||
void HD44780_chr (int x, int y, char ch)
|
||||
{
|
||||
HD44780->framebuf[ (y * HD44780->wid) + x] = ch;
|
||||
}
|
||||
|
||||
/////////////////////////////////////////////////////////////////
|
||||
// Flush the framebuffer to the display
|
||||
//
|
||||
void
|
||||
HD44780_flush ()
|
||||
{
|
||||
HD44780_draw_frame (HD44780->framebuf);
|
||||
}
|
||||
|
||||
/////////////////////////////////////////////////////////////////
|
||||
// Clear the framebuffer
|
||||
//
|
||||
void HD44780_clear ()
|
||||
{
|
||||
memset(HD44780->framebuf, ' ', HD44780->wid * HD44780->hgt);
|
||||
}
|
||||
|
||||
/////////////////////////////////////////////////////////////////
|
||||
// Place a character in the framebuffer
|
||||
//
|
||||
void
|
||||
HD44780_chr (int x, int y, char ch)
|
||||
{
|
||||
y--;
|
||||
x--;
|
||||
|
||||
HD44780->framebuf[ (y * HD44780->wid) + x] = ch;
|
||||
}
|
||||
|
||||
/////////////////////////////////////////////////////////////////
|
||||
// Place a string in the framebuffer
|
||||
//
|
||||
void
|
||||
HD44780_string (int x, int y, char *s)
|
||||
{
|
||||
int i;
|
||||
|
||||
x --; // Convert 1-based coords to 0-based
|
||||
y --;
|
||||
|
||||
for (i = 0; s[i]; i++) {
|
||||
// Check for buffer overflows...
|
||||
if ((y * HD44780->wid) + x + i > (HD44780->wid * HD44780->hgt))
|
||||
break;
|
||||
HD44780->framebuf[(y*HD44780->wid) + x + i] = s[i];
|
||||
}
|
||||
}
|
||||
|
||||
/////////////////////////////////////////////////////////////////
|
||||
// Flush box
|
||||
//
|
||||
// TO BE REMOVED
|
||||
//
|
||||
void
|
||||
HD44780_flush_box (int lft, int top, int rgt, int bot)
|
||||
{
|
||||
@@ -477,7 +468,9 @@ HD44780_flush_box (int lft, int top, int rgt, int bot)
|
||||
HD44780_position (lft, y);
|
||||
//printf("\n%d,%d :",lft,y);
|
||||
for (x = lft; x <= rgt; x++) {
|
||||
HD44780_senddata (spanList[y], RS_DATA, HD44780->framebuf[(y * HD44780->wid) + x]);
|
||||
|
||||
hd44780_functions->senddata (spanList[y], RS_DATA, HD44780->framebuf[(y * HD44780->wid) + x]);
|
||||
hd44780_functions->uPause (40); // Minimum exec time for all commands
|
||||
}
|
||||
//write(fd, HD44780->framebuf[(y*HD44780->wid)+lft, rgt-lft+1]);
|
||||
}
|
||||
@@ -490,31 +483,7 @@ HD44780_flush_box (int lft, int top, int rgt, int bot)
|
||||
void
|
||||
HD44780_backlight (int on)
|
||||
{
|
||||
//hd44780_functions->backlight (on);
|
||||
}
|
||||
|
||||
/////////////////////////////////////////////////////////////////
|
||||
// Toggle the built-in linewrapping feature
|
||||
//
|
||||
static void
|
||||
HD44780_linewrap (int on)
|
||||
{
|
||||
}
|
||||
|
||||
/////////////////////////////////////////////////////////////////
|
||||
// Toggle the built-in automatic scrolling feature
|
||||
//
|
||||
static void
|
||||
HD44780_autoscroll (int on)
|
||||
{
|
||||
hd44780_functions->autoscroll (on);
|
||||
}
|
||||
|
||||
void
|
||||
common_autoscroll (int on)
|
||||
{
|
||||
hd44780_functions->senddata (0, RS_INSTR, ENTRYMODE | E_MOVERIGHT | ((on) ? EDGESCROLL : NOSCROLL));
|
||||
hd44780_functions->uPause (40);
|
||||
hd44780_functions->backlight (on);
|
||||
}
|
||||
|
||||
/////////////////////////////////////////////////////////////////
|
||||
@@ -703,7 +672,7 @@ HD44780_hbar (int x, int y, int len)
|
||||
void
|
||||
HD44780_init_num ()
|
||||
{
|
||||
|
||||
|
||||
}
|
||||
|
||||
/////////////////////////////////////////////////////////////////
|
||||
@@ -716,6 +685,38 @@ HD44780_num (int x, int num)
|
||||
HD44780->framebuf[x+offset] = num + '0';
|
||||
}
|
||||
|
||||
/////////////////////////////////////////////////////////////
|
||||
// Does the heartbeat...
|
||||
//
|
||||
void
|
||||
HD44780_heartbeat (int type)
|
||||
{
|
||||
static int timer = 0;
|
||||
int whichIcon;
|
||||
static int saved_type = HEARTBEAT_ON;
|
||||
|
||||
if (type)
|
||||
saved_type = type;
|
||||
|
||||
if (type == HEARTBEAT_ON) {
|
||||
// Set this to pulsate like a real heart beat...
|
||||
whichIcon = (! ((timer + 4) & 5));
|
||||
|
||||
// This defines a custom character EVERY time...
|
||||
// not efficient... is this necessary?
|
||||
HD44780_icon (whichIcon, 0);
|
||||
|
||||
// Put character on screen...
|
||||
HD44780_chr (HD44780->wid, 1, 0);
|
||||
|
||||
// change display...
|
||||
HD44780_flush ();
|
||||
}
|
||||
|
||||
timer++;
|
||||
timer &= 0x0f;
|
||||
}
|
||||
|
||||
/////////////////////////////////////////////////////////////////
|
||||
// Sets a custom character from 0-7...
|
||||
//
|
||||
@@ -734,7 +735,8 @@ HD44780_set_char (int n, char *dat)
|
||||
if (!dat)
|
||||
return;
|
||||
|
||||
HD44780_senddata (0, RS_INSTR, SETCHAR | n * 8);
|
||||
hd44780_functions->senddata (0, RS_INSTR, SETCHAR | n * 8);
|
||||
hd44780_functions->uPause (40); // Minimum exec time for all commands
|
||||
|
||||
for (row = 0; row < HD44780->cellhgt; row++) {
|
||||
letter = 0;
|
||||
@@ -742,10 +744,14 @@ HD44780_set_char (int n, char *dat)
|
||||
letter <<= 1;
|
||||
letter |= (dat[(row * HD44780->cellwid) + col] > 0);
|
||||
}
|
||||
HD44780_senddata (0, RS_DATA, letter);
|
||||
hd44780_functions->senddata (0, RS_DATA, letter);
|
||||
hd44780_functions->uPause (40); // Minimum exec time for all commands
|
||||
}
|
||||
}
|
||||
|
||||
/////////////////////////////////////////////////////////////
|
||||
// Set default icon into a userdef char
|
||||
//
|
||||
void
|
||||
HD44780_icon (int which, char dest)
|
||||
{
|
||||
@@ -793,6 +799,7 @@ HD44780_icon (int which, char dest)
|
||||
//
|
||||
// Input is a character array, sized HD44780->wid*hgt
|
||||
//
|
||||
// TO BE REMOVED (move it into flush())
|
||||
void
|
||||
HD44780_draw_frame (char *dat)
|
||||
{
|
||||
@@ -802,15 +809,136 @@ HD44780_draw_frame (char *dat)
|
||||
return;
|
||||
|
||||
for (y = 0; y < HD44780->hgt; y++) {
|
||||
HD44780_position (0, y);
|
||||
//printf("\n%d :",y);
|
||||
for (x = 0; x < HD44780->wid; x++) {
|
||||
HD44780_senddata (spanList[y], RS_DATA, HD44780_charmap[(unsigned char)dat[(y * HD44780->wid) + x]]);
|
||||
|
||||
if( x % 8 == 0 )
|
||||
HD44780_position (x, y);
|
||||
hd44780_functions->senddata (spanList[y], RS_DATA, HD44780_charmap[(unsigned char)dat[(y * HD44780->wid) + x]]);
|
||||
hd44780_functions->uPause (40); // Minimum exec time for all commands
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
/////////////////////////////////////////////////////////////
|
||||
// Get a key from the keypad (if there is one)
|
||||
//
|
||||
char HD44780_getkey()
|
||||
{
|
||||
unsigned char scancode;
|
||||
char ch;
|
||||
struct timeval curr_time, time_diff;
|
||||
|
||||
gettimeofday(&curr_time,NULL);
|
||||
|
||||
scancode = hd44780_functions->scankeypad();
|
||||
if( scancode ) {
|
||||
if( scancode & 0xF0 ) {
|
||||
ch = keyMapMatrix[((scancode&0xF0)>>4)-1][(scancode&0x0F)-1];
|
||||
}
|
||||
else {
|
||||
ch = keyMapDirect[scancode - 1];
|
||||
}
|
||||
}
|
||||
else {
|
||||
ch = 0;
|
||||
}
|
||||
|
||||
if (ch) {
|
||||
if (ch == pressed_key) {
|
||||
timersub (&curr_time, &pressed_key_time, &time_diff);
|
||||
if (((time_diff.tv_usec / 1000 + time_diff.tv_sec * 1000) - KEYPAD_AUTOREPEAT_DELAY) < 1000 * pressed_key_repetitions / KEYPAD_AUTOREPEAT_FREQ ) {
|
||||
// The key is already pressed quite some time
|
||||
// but it's not yet time to return a repeated keypress
|
||||
return 0;
|
||||
}
|
||||
// Otherwise a keypress will be returned
|
||||
pressed_key_repetitions ++;
|
||||
}
|
||||
else {
|
||||
// It's a new keypress
|
||||
pressed_key_time = curr_time;
|
||||
pressed_key_repetitions = 0;
|
||||
printf( "Key: %c (%d,%d)\n", ch, scancode&0x0F, (scancode&0xF0)>>4 );
|
||||
}
|
||||
}
|
||||
|
||||
// Store the key for the next round
|
||||
pressed_key = ch;
|
||||
|
||||
return ch;
|
||||
}
|
||||
|
||||
/////////////////////////////////////////////////////////////
|
||||
// Scan the keypad
|
||||
//
|
||||
unsigned char HD44780_scankeypad()
|
||||
{
|
||||
unsigned int keybits;
|
||||
unsigned int shiftcount;
|
||||
unsigned int shiftingbit;
|
||||
unsigned int Ypattern;
|
||||
unsigned int Yval;
|
||||
char exp;
|
||||
|
||||
unsigned char scancode = 0;
|
||||
|
||||
// First check if a directly connected key is pressed
|
||||
// Put all zeros on Y of keypad
|
||||
keybits = hd44780_functions->readkeypad (0);
|
||||
|
||||
if (keybits) {
|
||||
// A directly connected key was pressed
|
||||
// Which key was it ?
|
||||
shiftingbit = 1;
|
||||
for (shiftcount=0; shiftcount<KEYPAD_MAXX && !scancode; shiftcount++) {
|
||||
if ( keybits & shiftingbit) {
|
||||
// Found ! Return from function.
|
||||
scancode = shiftcount+1;
|
||||
}
|
||||
shiftingbit <<= 1;
|
||||
}
|
||||
}
|
||||
else {
|
||||
// Now check the matrix
|
||||
// First check with all 1's
|
||||
Ypattern = (1 << KEYPAD_MAXY) - 1;
|
||||
if( hd44780_functions->readkeypad (Ypattern)) {
|
||||
// Yes, a key on the matrix is pressed
|
||||
|
||||
// OK, now we know a key is pressed.
|
||||
// Determine which one it is
|
||||
|
||||
// First determine the row
|
||||
// Do a 'binary search' to minimize I/O
|
||||
Ypattern = 0;
|
||||
Yval = 0;
|
||||
for (exp=3; exp>=0; exp--) {
|
||||
Ypattern = ((1 << (1 << exp)) - 1) << Yval;
|
||||
keybits = hd44780_functions->readkeypad (Ypattern);
|
||||
if (!keybits) {
|
||||
Yval += (1 << exp);
|
||||
}
|
||||
}
|
||||
|
||||
// Which key is pressed in that row ?
|
||||
keybits = hd44780_functions->readkeypad (1<<Yval);
|
||||
shiftingbit=1;
|
||||
for (shiftcount=0; shiftcount<KEYPAD_MAXX && !scancode; shiftcount++) {
|
||||
if ( keybits & shiftingbit) {
|
||||
// Found !
|
||||
scancode = (Yval+1) << 4 | (shiftcount+1);
|
||||
}
|
||||
shiftingbit <<= 1;
|
||||
}
|
||||
}
|
||||
}
|
||||
return scancode;
|
||||
}
|
||||
|
||||
|
||||
/////////////////////////////////////////////////////////////
|
||||
// Parse the span list
|
||||
// spanListArray - array to store vertical spans
|
||||
// spLsize - size of spanListArray
|
||||
@@ -862,90 +990,3 @@ parse_span_list (int *spanListArray[], int *spLsize, int *dispOffsets[], int *dO
|
||||
return retVal;
|
||||
}
|
||||
|
||||
char HD44780_getkey()
|
||||
{
|
||||
unsigned int keybits;
|
||||
unsigned int shiftcount;
|
||||
unsigned int shiftingbit;
|
||||
unsigned int Ypattern;
|
||||
unsigned int Yval;
|
||||
char exp;
|
||||
char ch = 0;
|
||||
char ch_set = 0;
|
||||
struct timeval curr_time, time_diff;
|
||||
|
||||
gettimeofday(&curr_time,NULL);
|
||||
|
||||
// First check if a directly connected key is pressed
|
||||
// Put all zeros on Y of keypad
|
||||
keybits = hd44780_functions->readkeypad (0);
|
||||
|
||||
if (keybits) {
|
||||
// A directly connected key was pressed
|
||||
// Which key was it ?
|
||||
shiftingbit = 1;
|
||||
for (shiftcount=0; shiftcount<KEYPAD_MAXX && !ch; shiftcount++) {
|
||||
if ( keybits & shiftingbit) {
|
||||
// Found ! Return from function.
|
||||
ch = keyMapDirect[shiftcount];
|
||||
}
|
||||
shiftingbit <<= 1;
|
||||
}
|
||||
}
|
||||
else {
|
||||
// Now check the matrix
|
||||
// First check with all 1's
|
||||
Ypattern = (1 << KEYPAD_MAXY) - 1;
|
||||
if( hd44780_functions->readkeypad (Ypattern)) {
|
||||
// Yes, a key on the matrix is pressed
|
||||
|
||||
// OK, now we know a key is pressed.
|
||||
// Determine which one it is
|
||||
// Do a 'binary search' to determine in what row a key is pressed
|
||||
Ypattern = 0;
|
||||
Yval = 0;
|
||||
for (exp=3; exp>=0; exp--) {
|
||||
Ypattern = ((1 << (1 << exp)) - 1) << Yval;
|
||||
keybits = hd44780_functions->readkeypad (Ypattern);
|
||||
if (!keybits) {
|
||||
Yval += (1 << exp);
|
||||
}
|
||||
}
|
||||
|
||||
// Which key is pressed in that row ?
|
||||
keybits = hd44780_functions->readkeypad (1<<Yval);
|
||||
shiftingbit=1;
|
||||
for (shiftcount=0; shiftcount<KEYPAD_MAXX && !ch; shiftcount++) {
|
||||
if ( keybits & shiftingbit) {
|
||||
// Found !
|
||||
ch = keyMapMatrix[Yval][shiftcount];
|
||||
}
|
||||
shiftingbit <<= 1;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (ch) {
|
||||
if (ch == pressed_key) {
|
||||
timersub (&curr_time, &pressed_key_time, &time_diff);
|
||||
if (((time_diff.tv_usec / 1000 + time_diff.tv_sec * 1000) - KEYPAD_AUTOREPEAT_DELAY) < 1000 * pressed_key_repetitions / KEYPAD_AUTOREPEAT_FREQ ) {
|
||||
// The key is already pressed quite some time
|
||||
// but it's not yet time to return a repeated keypress
|
||||
return 0;
|
||||
}
|
||||
// Otherwise a keypress will be returned
|
||||
pressed_key_repetitions ++;
|
||||
}
|
||||
else {
|
||||
// It's a new keypress
|
||||
pressed_key_time = curr_time;
|
||||
pressed_key_repetitions = 0;
|
||||
printf( "Key: %c\n", ch );
|
||||
}
|
||||
}
|
||||
|
||||
// Store the key for the next round
|
||||
pressed_key = ch;
|
||||
|
||||
return ch;
|
||||
}
|
||||
|
||||
@@ -16,7 +16,14 @@
|
||||
#ifndef HD44780_H
|
||||
#define HD44780_H
|
||||
|
||||
extern char have_keypad; // non-zero if the keypad code is activated
|
||||
// Maximum sizes of the keypad
|
||||
// DO NOT CHANGE THESE 2 VALUES, unless you change the functions too
|
||||
#define KEYPAD_MAXX 5
|
||||
#define KEYPAD_MAXY 11
|
||||
|
||||
extern char have_keypad; // non-zero if the keypad code is activated
|
||||
extern char have_backlight; // non-zero if we can control the backlight
|
||||
extern char extIF; // non-zero if we should control > 2 LCDs
|
||||
|
||||
int HD44780_init (struct lcd_logical_driver *driver, char *args);
|
||||
/* The following methods can all be hidden. They are used through function ptrs
|
||||
|
||||
Reference in New Issue
Block a user