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]
|
||||||
# Server section with all kinds of settings for the LCDd server
|
# Server section with all kinds of settings for the LCDd server
|
||||||
|
|
||||||
Driver=HD44780
|
Driver=curses
|
||||||
#Driver=curses
|
#Driver=HD44780
|
||||||
#Driver=MtxOrb
|
#Driver=MtxOrb
|
||||||
#
|
#
|
||||||
# Tells the server to load the given drivers. Multiple lines can be given.
|
# Tells the server to load the given drivers. Multiple lines can be given.
|
||||||
@@ -46,7 +46,7 @@ Driver=HD44780
|
|||||||
Bind=127.0.0.1
|
Bind=127.0.0.1
|
||||||
# Tells the driver to bind to the given interface
|
# Tells the driver to bind to the given interface
|
||||||
|
|
||||||
Port=3777
|
Port=13666
|
||||||
# Listen on this specified port; defaults to 13666.
|
# Listen on this specified port; defaults to 13666.
|
||||||
|
|
||||||
#Debug=5
|
#Debug=5
|
||||||
@@ -59,10 +59,10 @@ User=nobody
|
|||||||
# User to run as. LCDd will drop its root priviledges,
|
# User to run as. LCDd will drop its root priviledges,
|
||||||
# if any, and run as this user instead.
|
# if any, and run as this user instead.
|
||||||
|
|
||||||
EnableServerScreen=yes
|
ServerScreen=no
|
||||||
# Enables the server screen also when other screens are active.
|
# 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.
|
# 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
|
# Hitachi HD44780 driver
|
||||||
# See docs/hd44780_howto.txt
|
# 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:
|
ConnectionType=4bit
|
||||||
# -p <port> Use the given port
|
# Select what type of connection. See documentation for types.
|
||||||
# -c <ct> Use the given connectiontype
|
|
||||||
# -k Keypad support
|
Keypad=no
|
||||||
# -b Backlight support
|
# 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]
|
[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
|
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.
|
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---|<---@--@--@
|
Y2 o---|<---@--@--@
|
||||||
| | |
|
| | |
|
||||||
Y3 o---|<---@--@--@ + 5V
|
Y3 o---|<---@--@--@ O 5V
|
||||||
| | | |
|
| | | |
|
||||||
diodes | | | ___ |
|
diodes | | | ___ |
|
||||||
1N4148 +----------|___|---+
|
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
|
shop. They usually call it a matrix keypad. To hook it to lcdproc, you
|
||||||
would only need to add the resistors and diodes.
|
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
|
1.2 4-bit
|
||||||
----------
|
----------
|
||||||
@@ -219,6 +267,8 @@ The optional keypad can be connected as follows:
|
|||||||
SELIN (13) X3
|
SELIN (13) X3
|
||||||
nFAULT (15) X4
|
nFAULT (15) X4
|
||||||
|
|
||||||
|
The optional backlight wiring should be connected to D5, pin 7.
|
||||||
|
|
||||||
|
|
||||||
1.3 8-bit "Winamp"
|
1.3 8-bit "Winamp"
|
||||||
-------------------
|
-------------------
|
||||||
@@ -267,6 +317,8 @@ The optional keypad can be connected as follows:
|
|||||||
SELIN (13) X3
|
SELIN (13) X3
|
||||||
nFAULT (15) X4
|
nFAULT (15) X4
|
||||||
|
|
||||||
|
The optional backlight wiring should be connected to nSEL, pin 17.
|
||||||
|
|
||||||
|
|
||||||
1.4 Extended 8-bit "lcdtime"
|
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/meter-0.2.tar.gz
|
||||||
http://metalab.unc.edu/pub/linux/system/status/portato-1.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:
|
The LCD connections are:
|
||||||
|
|
||||||
printer port LCD
|
printer port LCD
|
||||||
@@ -321,16 +376,153 @@ The optional keypad can be connected as follows:
|
|||||||
SELIN (13) X3
|
SELIN (13) X3
|
||||||
nFAULT (15) X4
|
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
|
1.5 Serial LPT
|
||||||
---------------
|
---------------
|
||||||
|
|
||||||
This interface uses a handful of wires to interface to the
|
This interface uses a handful of wires to interface to the
|
||||||
HD44780. Suitable for high noise, long connections. Designed by
|
HD44780. Suitable for high noise, long connections. Designed by
|
||||||
Andrew McMeikan <andrewm@engineer.com>. Refer to
|
Andrew McMeikan <andrewm@engineer.com>. The original wiring and
|
||||||
http://members.xoom.com/andrewmuck for details of the connections.
|
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
|
2. Compiling
|
||||||
@@ -344,33 +536,17 @@ can be done by specifying "--enable-drivers=all" or by
|
|||||||
3. Running
|
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.
|
Then as usual, start LCDd with the correct config file:
|
||||||
- Arguments that need to be passed to the driver should be in quotes after
|
LCDd -c ./LCDd.conf
|
||||||
the -d HD44780 arguments.
|
for example.
|
||||||
- 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.
|
|
||||||
|
|
||||||
|
If you want to override the driver selection in LCDd.conf then use:
|
||||||
EXAMPLES:
|
LCDd -c ./LCDd.conf -d HD44780
|
||||||
|
If you use this, the HD44780 driver will read the options from the config
|
||||||
For a 4bit connection, 16x2 display on port 0x278
|
file.
|
||||||
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"
|
|
||||||
|
|
||||||
|
|
||||||
4. Miscellania
|
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 February 2000, Benjamin Tse (blt@ComPorts.com)
|
||||||
|
|
||||||
|
Updated October 2001, Joris Robijn (joris at robijn.net)
|
||||||
|
|||||||
@@ -20,7 +20,11 @@
|
|||||||
* D6 (8) EN (6)
|
* D6 (8) EN (6)
|
||||||
* D7 (9) EN2 (LCD2 - 6) (optional)
|
* D7 (9) EN2 (LCD2 - 6) (optional)
|
||||||
*
|
*
|
||||||
|
* Backlight
|
||||||
|
* D5 (7) backlight (optional, see documentation)
|
||||||
|
*
|
||||||
* Extended interface (including LCD3 above)
|
* Extended interface (including LCD3 above)
|
||||||
|
* D5 (7) EN3
|
||||||
* STR (1) EN4
|
* STR (1) EN4
|
||||||
* LF (14) EN5
|
* LF (14) EN5
|
||||||
* INIT (16) EN6
|
* INIT (16) EN6
|
||||||
@@ -66,34 +70,37 @@
|
|||||||
#include <errno.h>
|
#include <errno.h>
|
||||||
|
|
||||||
// Generally, any function that accesses the LCD control lines needs to be
|
// Generally, any function that accesses the LCD control lines needs to be
|
||||||
// implemented separately for each HW design. This is typically just
|
// implemented separately for each HW design. This is typically (but not
|
||||||
// HD44780_senddata and HD44780_readkeypad
|
// restricted to):
|
||||||
|
// HD44780_senddata
|
||||||
|
// HD44780_readkeypad
|
||||||
|
|
||||||
void lcdstat_HD44780_senddata (unsigned char displayID, unsigned char flags, unsigned char ch);
|
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);
|
unsigned char lcdstat_HD44780_readkeypad (unsigned int YData);
|
||||||
|
|
||||||
#define RS 0x10
|
#define RS 0x10
|
||||||
#define RW 0x20
|
#define RW 0x20
|
||||||
#define EN1 0x40
|
#define EN1 0x40
|
||||||
#define EN2 0x80
|
#define EN2 0x80
|
||||||
#define EN3 0x20
|
#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 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 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
|
// initialisation function
|
||||||
int
|
int
|
||||||
hd_init_4bit (HD44780_functions * hd44780_functions, lcd_logical_driver * driver, char *args, unsigned int port)
|
hd_init_4bit (HD44780_functions * hd44780_functions, lcd_logical_driver * driver, char *args, unsigned int port)
|
||||||
{
|
{
|
||||||
// TODO: remove magic numbers below
|
int enableLines = EN1 | EN2;
|
||||||
char *argv[64];
|
|
||||||
int argc;
|
|
||||||
int i;
|
|
||||||
int displayID = EN1 | EN2;
|
|
||||||
|
|
||||||
// Reserve the port registers
|
// Reserve the port registers
|
||||||
lptPort = port;
|
lptPort = port;
|
||||||
@@ -102,44 +109,36 @@ hd_init_4bit (HD44780_functions * hd44780_functions, lcd_logical_driver * driver
|
|||||||
port_access(lptPort+2);
|
port_access(lptPort+2);
|
||||||
|
|
||||||
hd44780_functions->senddata = lcdstat_HD44780_senddata;
|
hd44780_functions->senddata = lcdstat_HD44780_senddata;
|
||||||
|
hd44780_functions->backlight = lcdstat_HD44780_backlight;
|
||||||
hd44780_functions->readkeypad = lcdstat_HD44780_readkeypad;
|
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
|
// powerup the lcd now
|
||||||
if (extIF) {
|
if (extIF) {
|
||||||
displayID |= EN3;
|
enableLines |= EN3;
|
||||||
port_out (lptPort + 2, 0 ^ OUTMASK);
|
port_out (lptPort + 2, 0 ^ OUTMASK);
|
||||||
}
|
}
|
||||||
|
|
||||||
port_out (lptPort, displayID | 0x03);
|
port_out (lptPort, enableLines | 0x03);
|
||||||
if (extIF)
|
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);
|
hd44780_functions->uPause (1);
|
||||||
port_out (lptPort, 0x03);
|
port_out (lptPort, 0x03);
|
||||||
if (extIF)
|
if (extIF)
|
||||||
port_out (lptPort + 2, 0 ^ OUTMASK);
|
port_out (lptPort + 2, 0 ^ OUTMASK);
|
||||||
hd44780_functions->uPause (4100);
|
hd44780_functions->uPause (4100);
|
||||||
|
|
||||||
port_out (lptPort, displayID | 0x03);
|
port_out (lptPort, enableLines | 0x03);
|
||||||
if (extIF)
|
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);
|
hd44780_functions->uPause (1);
|
||||||
port_out (lptPort, 0x03);
|
port_out (lptPort, 0x03);
|
||||||
if (extIF)
|
if (extIF)
|
||||||
port_out (lptPort + 2, 0 ^ OUTMASK);
|
port_out (lptPort + 2, 0 ^ OUTMASK);
|
||||||
hd44780_functions->uPause (100);
|
hd44780_functions->uPause (100);
|
||||||
|
|
||||||
port_out (lptPort, displayID | 0x03);
|
port_out (lptPort, enableLines | 0x03);
|
||||||
if (extIF)
|
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);
|
hd44780_functions->uPause (1);
|
||||||
port_out (lptPort, 0x03);
|
port_out (lptPort, 0x03);
|
||||||
if (extIF)
|
if (extIF)
|
||||||
@@ -147,9 +146,9 @@ hd_init_4bit (HD44780_functions * hd44780_functions, lcd_logical_driver * driver
|
|||||||
hd44780_functions->uPause (40);
|
hd44780_functions->uPause (40);
|
||||||
|
|
||||||
// now in 8-bit mode... set 4-bit mode
|
// now in 8-bit mode... set 4-bit mode
|
||||||
port_out (lptPort, displayID | 0x02);
|
port_out (lptPort, enableLines | 0x02);
|
||||||
if (extIF)
|
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);
|
hd44780_functions->uPause (1);
|
||||||
port_out (lptPort, 0x02);
|
port_out (lptPort, 0x02);
|
||||||
if (extIF)
|
if (extIF)
|
||||||
@@ -168,16 +167,18 @@ hd_init_4bit (HD44780_functions * hd44780_functions, lcd_logical_driver * driver
|
|||||||
|
|
||||||
// lcdstat_HD44780_senddata
|
// lcdstat_HD44780_senddata
|
||||||
void
|
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 h = (ch >> 4) & 0x0f; // high and low nibbles
|
||||||
unsigned char l = ch & 0x0f;
|
unsigned char l = ch & 0x0f;
|
||||||
|
|
||||||
if (iflags == RS_INSTR)
|
if (flags == RS_INSTR)
|
||||||
flags = 0;
|
portControl = 0;
|
||||||
else //if (iflags == RS_DATA)
|
else //if (flags == RS_DATA)
|
||||||
flags = RS;
|
portControl = RS;
|
||||||
|
|
||||||
|
portControl |= backlight_bit;
|
||||||
|
|
||||||
if (displayID <= 3) {
|
if (displayID <= 3) {
|
||||||
if (displayID == 0)
|
if (displayID == 0)
|
||||||
@@ -185,36 +186,43 @@ lcdstat_HD44780_senddata (unsigned char displayID, unsigned char iflags, unsigne
|
|||||||
else
|
else
|
||||||
enableLines = EnMask[displayID - 1];
|
enableLines = EnMask[displayID - 1];
|
||||||
|
|
||||||
port_out (lptPort, flags | h);
|
port_out (lptPort, portControl | h);
|
||||||
hd44780_functions->uPause (2);
|
hd44780_functions->uPause (2);
|
||||||
port_out (lptPort, enableLines | flags | h);
|
port_out (lptPort, enableLines | portControl | h);
|
||||||
hd44780_functions->uPause (4);
|
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);
|
hd44780_functions->uPause (4);
|
||||||
port_out (lptPort, flags | l);
|
port_out (lptPort, portControl | l);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (extIF && (displayID == 0 || displayID >= 4)) {
|
if (extIF && (displayID == 0 || displayID >= 4)) {
|
||||||
if (displayID == 0)
|
if (displayID == 0)
|
||||||
enableLines = EnMask[3] | EnMask[4] | EnMask[5] | EnMask[6];
|
enableLines = ALLEXT;
|
||||||
else
|
else
|
||||||
enableLines = EnMask[(displayID - 1) % EnMaskSize];
|
enableLines = EnMask[(displayID - 1)];
|
||||||
|
|
||||||
port_out (lptPort, flags | h);
|
port_out (lptPort, portControl | h);
|
||||||
hd44780_functions->uPause (2);
|
hd44780_functions->uPause (2);
|
||||||
port_out (lptPort + 2, enableLines ^ OUTMASK);
|
port_out (lptPort + 2, enableLines ^ OUTMASK);
|
||||||
hd44780_functions->uPause (4);
|
hd44780_functions->uPause (4);
|
||||||
port_out (lptPort + 2, 0 ^ OUTMASK);
|
port_out (lptPort + 2, 0 ^ OUTMASK);
|
||||||
|
|
||||||
port_out (lptPort, flags | l);
|
port_out (lptPort, portControl | l);
|
||||||
port_out (lptPort + 2, enableLines ^ OUTMASK);
|
port_out (lptPort + 2, enableLines ^ OUTMASK);
|
||||||
hd44780_functions->uPause (4);
|
hd44780_functions->uPause (4);
|
||||||
port_out (lptPort + 2, 0 ^ OUTMASK);
|
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 lcdstat_HD44780_readkeypad (unsigned int YData)
|
||||||
{
|
{
|
||||||
unsigned char readval;
|
unsigned char readval;
|
||||||
@@ -226,7 +234,12 @@ unsigned char lcdstat_HD44780_readkeypad (unsigned int YData)
|
|||||||
port_out (lptPort + 2, ( ((~YData & 0x03C0) << 6 )) ^ OUTMASK);
|
port_out (lptPort + 2, ( ((~YData & 0x03C0) << 6 )) ^ OUTMASK);
|
||||||
}
|
}
|
||||||
|
|
||||||
// And convert it back.
|
// Read inputs
|
||||||
readval = ~ port_in (lptPort + 1) ^ INMASK;
|
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;
|
return ( (readval >> 4 & 0x03) | (readval >> 5 & 0x04) | (readval >> 3 & 0x08) | (readval << 1 & 0x10) ) & ~stuckinputs;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -16,11 +16,13 @@
|
|||||||
* D5 (7) D5 (12)
|
* D5 (7) D5 (12)
|
||||||
* D6 (8) D6 (13)
|
* D6 (8) D6 (13)
|
||||||
* D7 (9) D7 (14)
|
* D7 (9) D7 (14)
|
||||||
* nSEL (17) -
|
|
||||||
* nSTRB (1) RS (4)
|
* nSTRB (1) RS (4)
|
||||||
* nLF (14) RW (5) (LCD2 - 6) (optional - pull all LCD RW low)
|
* nLF (14) RW (5) (LCD2 - 6) (optional - pull all LCD RW low)
|
||||||
* INIT (16) EN (6)
|
* INIT (16) EN (6)
|
||||||
*
|
*
|
||||||
|
* Backlight
|
||||||
|
* SEL (17) backlight (optional, see documentation)
|
||||||
|
*
|
||||||
* Keypad connection (optional):
|
* Keypad connection (optional):
|
||||||
* Some diodes and resistors are needed, see further documentation.
|
* Some diodes and resistors are needed, see further documentation.
|
||||||
* printer port keypad
|
* printer port keypad
|
||||||
@@ -65,20 +67,17 @@
|
|||||||
// HD44780_readkeypad
|
// HD44780_readkeypad
|
||||||
|
|
||||||
void lcdtime_HD44780_senddata (unsigned char displayID, unsigned char flags, unsigned char ch);
|
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);
|
unsigned char lcdtime_HD44780_readkeypad (unsigned int YData);
|
||||||
|
|
||||||
#define nRS nSTRB
|
#define RS STRB
|
||||||
#define nRW nLF
|
#define RW LF
|
||||||
#define EN1 INIT
|
#define EN1 INIT
|
||||||
#define METER_OFF nSEL
|
#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 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;
|
static int semid;
|
||||||
|
|
||||||
@@ -95,6 +94,7 @@ hd_init_ext8bit (HD44780_functions * hd44780_functions, lcd_logical_driver * dri
|
|||||||
port_access(lptPort+2);
|
port_access(lptPort+2);
|
||||||
|
|
||||||
hd44780_functions->senddata = lcdtime_HD44780_senddata;
|
hd44780_functions->senddata = lcdtime_HD44780_senddata;
|
||||||
|
hd44780_functions->backlight = lcdtime_HD44780_backlight;
|
||||||
hd44780_functions->readkeypad = lcdtime_HD44780_readkeypad;
|
hd44780_functions->readkeypad = lcdtime_HD44780_readkeypad;
|
||||||
|
|
||||||
// setup the lcd in 8 bit mode
|
// 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);
|
hd44780_functions->uPause (40);
|
||||||
|
|
||||||
common_init ();
|
common_init ();
|
||||||
|
|
||||||
|
if (have_keypad) {
|
||||||
|
// Remember which input lines are stuck
|
||||||
|
stuckinputs = lcdtime_HD44780_readkeypad (0);
|
||||||
|
}
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -113,31 +118,42 @@ hd_init_ext8bit (HD44780_functions * hd44780_functions, lcd_logical_driver * dri
|
|||||||
void
|
void
|
||||||
lcdtime_HD44780_senddata (unsigned char displayID, unsigned char flags, unsigned char ch)
|
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)
|
// Only one controller is supported
|
||||||
dispID |= EN1;
|
enableLines = EN1;
|
||||||
else //if (displayID == 0)
|
|
||||||
dispID |= EN1;
|
|
||||||
|
|
||||||
if (flags == RS_DATA)
|
if (flags == RS_INSTR)
|
||||||
portControl = CHAR;
|
portControl = 0;
|
||||||
else
|
else //if (iflags == RS_DATA)
|
||||||
portControl = CTRL;
|
portControl = RS;
|
||||||
|
|
||||||
|
portControl |= backlight_bit;
|
||||||
|
|
||||||
sem_wait (semid);
|
sem_wait (semid);
|
||||||
port_out (lptPort + 2, SETUPLCD);
|
port_out (lptPort + 2, portControl ^ OUTMASK);
|
||||||
port_out (lptPort, ch);
|
port_out (lptPort, ch);
|
||||||
port_out (lptPort + 2, dispID | portControl);
|
port_out (lptPort + 2, (enableLines|portControl) ^ OUTMASK);
|
||||||
hd44780_functions->uPause (1);
|
hd44780_functions->uPause (1);
|
||||||
port_out (lptPort + 2, portControl);
|
port_out (lptPort + 2, portControl ^ OUTMASK);
|
||||||
sem_signal (semid);
|
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 lcdtime_HD44780_readkeypad (unsigned int YData)
|
||||||
{
|
{
|
||||||
unsigned char readval;
|
unsigned char readval;
|
||||||
|
|
||||||
|
sem_wait (semid);
|
||||||
|
|
||||||
// 10 bits output
|
// 10 bits output
|
||||||
// Convert the positive logic to the negative logic on the LPT port
|
// Convert the positive logic to the negative logic on the LPT port
|
||||||
port_out (lptPort, ~YData & 0x00FF );
|
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);
|
port_out (lptPort + 2, ( ((~YData & 0x0100) >> 8) | ((~YData & 0x0200) >> 6)) ^ OUTMASK);
|
||||||
}
|
}
|
||||||
|
|
||||||
// And convert it back.
|
// Read inputs
|
||||||
readval = ~ port_in (lptPort + 1) ^ INMASK;
|
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;
|
return ( (readval >> 4 & 0x03) | (readval >> 5 & 0x04) | (readval >> 3 & 0x08) | (readval << 1 & 0x10) ) & ~stuckinputs;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -14,26 +14,29 @@ typedef struct hwDependentFns {
|
|||||||
// microsec pauses
|
// microsec pauses
|
||||||
void (*uPause) (int microSecondsTenths);
|
void (*uPause) (int microSecondsTenths);
|
||||||
|
|
||||||
// senddata to the LCD
|
// Senddata to the LCD
|
||||||
// dispID - display to send data to (0 = all displays)
|
// dispID - display to send data to (0 = all displays)
|
||||||
// flags - data or instruction command (RS_DATA | RS_INSTR)
|
// flags - data or instruction command (RS_DATA | RS_INSTR)
|
||||||
// ch - character to display or instruction value
|
// ch - character to display or instruction value
|
||||||
void (*senddata) (unsigned char dispID, unsigned char flags, unsigned char ch);
|
void (*senddata) (unsigned char dispID, unsigned char flags, unsigned char ch);
|
||||||
|
|
||||||
// position the cursor
|
// Switch the backlight on or off
|
||||||
// dispID - display to send data to (0 = all displays)
|
// state - to be or not to be on
|
||||||
// DDaddr - display data address (see sect 2.5.2 of the LCD module FAQ)
|
void (*backlight) (unsigned char state);
|
||||||
void (*position) (int dispID, int DDaddr);
|
|
||||||
|
|
||||||
// toggle vertical autoscroll on all displays
|
// Read the keypad
|
||||||
// on - non-zero turns autoscroll on, zero value turns it off
|
|
||||||
void (*autoscroll) (int on);
|
|
||||||
|
|
||||||
// read the keypad
|
|
||||||
// Ydata - the up to 11 bits that should be put on the Y side of the matrix
|
// 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
|
// return - the up to 5 bits that are read out on the X side of the matrix
|
||||||
unsigned char (*readkeypad) (unsigned int Ydata);
|
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 :-) */
|
} HD44780_functions; /* for want of a better name :-) */
|
||||||
|
|
||||||
extern HD44780_functions *hd44780_functions;
|
extern HD44780_functions *hd44780_functions;
|
||||||
|
|||||||
@@ -36,6 +36,7 @@
|
|||||||
* Q4 (7) Y3
|
* Q4 (7) Y3
|
||||||
* Q5 (14) Y4
|
* Q5 (14) Y4
|
||||||
* Q6 (13) Y5
|
* Q6 (13) Y5
|
||||||
|
* Q7 (12) Y6
|
||||||
* The 'output' of the keys should be connected to the following LPT pins:
|
* The 'output' of the keys should be connected to the following LPT pins:
|
||||||
* nACK (10) X0
|
* nACK (10) X0
|
||||||
* BUSY (11) X1
|
* BUSY (11) X1
|
||||||
@@ -59,9 +60,9 @@
|
|||||||
|
|
||||||
// Hardware specific functions
|
// Hardware specific functions
|
||||||
void lcdserLpt_HD44780_senddata (unsigned char displayID, unsigned char flags, unsigned char ch);
|
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 rawshift (unsigned char r);
|
||||||
void shiftreg (unsigned char displayID, 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
|
#define EN2 32
|
||||||
|
|
||||||
static unsigned int lptPort;
|
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
|
// Initialisation
|
||||||
int
|
int
|
||||||
@@ -89,11 +87,9 @@ hd_init_serialLpt (HD44780_functions * hd44780_functions, lcd_logical_driver * d
|
|||||||
port_access(lptPort+2);
|
port_access(lptPort+2);
|
||||||
|
|
||||||
hd44780_functions->senddata = lcdserLpt_HD44780_senddata;
|
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
|
// Clear the shiftregister
|
||||||
rawshift (0);
|
rawshift (0);
|
||||||
|
|
||||||
@@ -114,17 +110,6 @@ hd_init_serialLpt (HD44780_functions * hd44780_functions, lcd_logical_driver * d
|
|||||||
|
|
||||||
common_init ();
|
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;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -149,47 +134,67 @@ lcdserLpt_HD44780_senddata (unsigned char displayID, unsigned char flags, unsign
|
|||||||
|
|
||||||
shiftreg (enableLines, portControl | h);
|
shiftreg (enableLines, portControl | h);
|
||||||
shiftreg (enableLines, portControl | l);
|
shiftreg (enableLines, portControl | l);
|
||||||
|
|
||||||
/* TODO: instead of delay read keys here */
|
|
||||||
}
|
}
|
||||||
|
|
||||||
char
|
void
|
||||||
lcdserLpt_HD44780_getkey ()
|
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 !
|
unsigned char lcdserLpt_HD44780_scankeypad ()
|
||||||
return 0;
|
{
|
||||||
|
// Unfortunately just bit shifting does not work with the 2 IC version...
|
||||||
|
|
||||||
rawshift (0); //send all line on shift register low
|
unsigned char keybits;
|
||||||
hd44780_functions->uPause (1);
|
unsigned int shiftcount;
|
||||||
if ((port_in (lptPort + 1) & 32) == 0) //test if line back is low - if not return(0)
|
unsigned int shiftingbit;
|
||||||
{ //else
|
unsigned char readval, inputs_zero, r;
|
||||||
//start walking a single zero across the eight lines
|
int i;
|
||||||
for (n = 7; n >= 0; n--) {
|
unsigned int scancode = 0;
|
||||||
rawshift (255 - (1 << n));
|
|
||||||
hd44780_functions->uPause (1);
|
|
||||||
|
|
||||||
if ((port_in (lptPort + 1) & 32) == 0) // check if line back is low if yes debounce
|
|
||||||
{
|
r = 0xFF; // This command will set the cursor position, so it's harmless
|
||||||
if (lastkey == keytr[n])
|
|
||||||
return (0);
|
readval = ~ port_in (lptPort + 1) ^ INMASK;
|
||||||
// printf("key is %c %d\n",keytr[n],n);
|
inputs_zero = ( (readval >> 4 & 0x03) | (readval >> 5 & 0x04) | (readval >> 3 & 0x08) | (readval << 1 & 0x10) );
|
||||||
lastkey = keytr[n];
|
|
||||||
return (keytr[n]); //return correct key code.
|
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)
|
hd44780_functions->uPause (4);
|
||||||
{
|
|
||||||
return 0;
|
// 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 */
|
/* this function sends r out onto the shift register */
|
||||||
@@ -197,6 +202,8 @@ void
|
|||||||
rawshift (unsigned char r)
|
rawshift (unsigned char r)
|
||||||
{
|
{
|
||||||
int i;
|
int i;
|
||||||
|
// r |= 0x80; // just to make sure ...
|
||||||
|
|
||||||
for (i = 7; i >= 0; i--) { /* MSB first */
|
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); /*set up data */
|
||||||
port_out (lptPort, (((r >> i) & 1) * LCDDATA) | LCDCLOCK); /*rising edge of clock */
|
port_out (lptPort, (((r >> i) & 1) * LCDDATA) | LCDCLOCK); /*rising edge of clock */
|
||||||
@@ -207,13 +214,9 @@ rawshift (unsigned char r)
|
|||||||
void
|
void
|
||||||
shiftreg (unsigned char enableLines, unsigned char r)
|
shiftreg (unsigned char enableLines, unsigned char r)
|
||||||
{
|
{
|
||||||
//unsigned char mr;
|
rawshift (r | 0x80); // highest bit always set to 1 for Clear for wiring with 2 ICs
|
||||||
//mr = (r & 0xF0) | ((r<<3) & 0x0F) | ((r<<1) & 0x04) |
|
port_out (lptPort, enableLines); // latch it, to correct display
|
||||||
// ((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
|
|
||||||
hd44780_functions->uPause (1);
|
hd44780_functions->uPause (1);
|
||||||
port_out (lptPort, 0);
|
port_out (lptPort, 0); // for wiring with 1 IC
|
||||||
hd44780_functions->uPause (3);
|
hd44780_functions->uPause (3);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -29,6 +29,9 @@
|
|||||||
* INIT (16) RS (4)
|
* INIT (16) RS (4)
|
||||||
* nSEL (17) EN2 (6 - LCD 2) (optional)
|
* nSEL (17) EN2 (6 - LCD 2) (optional)
|
||||||
*
|
*
|
||||||
|
* Backlight
|
||||||
|
* SEL (17) backlight (optional, see documentation)
|
||||||
|
*
|
||||||
* Keypad connection (optional):
|
* Keypad connection (optional):
|
||||||
* Some diodes and resistors are needed, see further documentation.
|
* Some diodes and resistors are needed, see further documentation.
|
||||||
* printer port keypad
|
* printer port keypad
|
||||||
@@ -64,32 +67,33 @@
|
|||||||
#include <string.h>
|
#include <string.h>
|
||||||
#include <errno.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_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);
|
unsigned char lcdwinamp_HD44780_readkeypad (unsigned int YData);
|
||||||
|
|
||||||
#define EN1 STRB
|
#define EN1 STRB
|
||||||
#define EN2 SEL
|
#define EN2 SEL
|
||||||
#define EN3 LF
|
#define EN3 LF
|
||||||
#define RS INIT
|
#define RW LF
|
||||||
|
#define RS INIT
|
||||||
|
#define BL SEL
|
||||||
|
|
||||||
static unsigned char EnMask[] = { EN1, EN2, EN3 };
|
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 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
|
// initialise the driver
|
||||||
int
|
int
|
||||||
hd_init_winamp (HD44780_functions * hd44780_functions, lcd_logical_driver * driver, char *args, unsigned int port)
|
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
|
// Reserve the port registers
|
||||||
lptPort = port;
|
lptPort = port;
|
||||||
port_access(lptPort);
|
port_access(lptPort);
|
||||||
@@ -97,16 +101,9 @@ hd_init_winamp (HD44780_functions * hd44780_functions, lcd_logical_driver * driv
|
|||||||
port_access(lptPort+2);
|
port_access(lptPort+2);
|
||||||
|
|
||||||
hd44780_functions->senddata = lcdwinamp_HD44780_senddata;
|
hd44780_functions->senddata = lcdwinamp_HD44780_senddata;
|
||||||
|
hd44780_functions->backlight = lcdwinamp_HD44780_backlight;
|
||||||
hd44780_functions->readkeypad = lcdwinamp_HD44780_readkeypad;
|
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
|
// setup the lcd in 8 bit mode
|
||||||
hd44780_functions->senddata (0, RS_INSTR, FUNCSET | IF_8BIT);
|
hd44780_functions->senddata (0, RS_INSTR, FUNCSET | IF_8BIT);
|
||||||
hd44780_functions->uPause (4100);
|
hd44780_functions->uPause (4100);
|
||||||
@@ -123,7 +120,7 @@ hd_init_winamp (HD44780_functions * hd44780_functions, lcd_logical_driver * driv
|
|||||||
void
|
void
|
||||||
lcdwinamp_HD44780_senddata (unsigned char displayID, unsigned char flags, unsigned char ch)
|
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)
|
if (flags == RS_DATA)
|
||||||
portControl = RS;
|
portControl = RS;
|
||||||
@@ -131,29 +128,36 @@ lcdwinamp_HD44780_senddata (unsigned char displayID, unsigned char flags, unsign
|
|||||||
portControl = 0;
|
portControl = 0;
|
||||||
|
|
||||||
if (displayID == 0)
|
if (displayID == 0)
|
||||||
dispID = EnMask[0] | EnMask[1] | ((extIF) ? EnMask[2] : 0);
|
enableLines = EnMask[0] | EnMask[1] | ((extIF) ? EnMask[2] : 0);
|
||||||
else
|
else
|
||||||
dispID = EnMask[displayID - 1];
|
enableLines = EnMask[displayID - 1];
|
||||||
|
|
||||||
// 40 nS setup time for RS valid to EN high, so set RS
|
// 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
|
// Output the actual data
|
||||||
port_out (lptPort, ch);
|
port_out (lptPort, ch);
|
||||||
|
|
||||||
// then set EN high
|
// 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
|
// 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!)
|
// 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...
|
// 230 nS minimum E high time provided by ISA bus delays as well...
|
||||||
|
|
||||||
// Set EN low and we're done...
|
// 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
|
// 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 lcdwinamp_HD44780_readkeypad (unsigned int YData)
|
||||||
{
|
{
|
||||||
unsigned char readval;
|
unsigned char readval;
|
||||||
@@ -163,7 +167,12 @@ unsigned char lcdwinamp_HD44780_readkeypad (unsigned int YData)
|
|||||||
port_out (lptPort, ~YData & 0x00FF );
|
port_out (lptPort, ~YData & 0x00FF );
|
||||||
port_out (lptPort + 2, ( ((~YData & 0x0100) >> 7) | ((~YData & 0x0200) >> 7 )) ^ OUTMASK);
|
port_out (lptPort + 2, ( ((~YData & 0x0100) >> 7) | ((~YData & 0x0200) >> 7 )) ^ OUTMASK);
|
||||||
|
|
||||||
// And convert it back.
|
// Read inputs
|
||||||
readval = ~ port_in (lptPort + 1) ^ INMASK;
|
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;
|
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
|
* Character mapping for correct display of some special ASCII chars added
|
||||||
* Sep 2001, Mark Haemmerling <mail@markh.de>.
|
* 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
|
* This file is released under the GNU General Public License. Refer to the
|
||||||
* COPYING file distributed with this package.
|
* COPYING file distributed with this package.
|
||||||
*
|
*
|
||||||
* Copyright (c) 2000, 1999, 1995 Benjamin Tse <blt@Comports.com>
|
* Copyright (c) 2000, 1999, 1995 Benjamin Tse <blt@Comports.com>
|
||||||
* 2001 Joris Robijn <joris@robijn.net>
|
* 2001 Joris Robijn <joris@robijn.net>
|
||||||
* 2001 Mark Haemmerling <mail@markh.de>
|
* 2001 Mark Haemmerling <mail@markh.de>
|
||||||
* 2000 Charles Steinkuehler <cstein@newtek.com>
|
* 2000 Charles Steinkuehler <cstein@newtek.com>
|
||||||
* 1999 Andrew McMeikan <andrewm@engineer.com>
|
* 1999 Andrew McMeikan <andrewm@engineer.com>
|
||||||
* 1998 Richard Rognlie <rrognlie@gamerz.net>
|
* 1998 Richard Rognlie <rrognlie@gamerz.net>
|
||||||
@@ -48,8 +50,6 @@
|
|||||||
#endif
|
#endif
|
||||||
#include "port.h"
|
#include "port.h"
|
||||||
|
|
||||||
#define atest(i)
|
|
||||||
|
|
||||||
// Uncomment one of the lines below to select your desired delay generation
|
// Uncomment one of the lines below to select your desired delay generation
|
||||||
// mechanism. If both defines are commented, the original I/O read timing
|
// mechanism. If both defines are commented, the original I/O read timing
|
||||||
// loop is used. Using DELAY_NANOSLEEP seems to provide the best performance.
|
// loop is used. Using DELAY_NANOSLEEP seems to provide the best performance.
|
||||||
@@ -76,7 +76,7 @@
|
|||||||
#endif
|
#endif
|
||||||
|
|
||||||
#include "shared/str.h"
|
#include "shared/str.h"
|
||||||
|
#include "render.h"
|
||||||
#include "lcd.h"
|
#include "lcd.h"
|
||||||
#include "hd44780.h"
|
#include "hd44780.h"
|
||||||
// #include "drv_base.h"
|
// #include "drv_base.h"
|
||||||
@@ -97,7 +97,7 @@ HD44780_functions *hd44780_functions;
|
|||||||
|
|
||||||
// default value
|
// default value
|
||||||
static enum connectionType connection = HD_4bit;
|
static enum connectionType connection = HD_4bit;
|
||||||
static int connIdx = 0;
|
static int connectiontype_index = 0;
|
||||||
|
|
||||||
// spanList[line number] = display line number is in
|
// spanList[line number] = display line number is in
|
||||||
static int *spanList = NULL;
|
static int *spanList = NULL;
|
||||||
@@ -112,15 +112,13 @@ static int numDisplays = 0;
|
|||||||
// input span list but is kept to save some cpu cycles.
|
// input span list but is kept to save some cpu cycles.
|
||||||
static int *dispSizes = NULL;
|
static int *dispSizes = NULL;
|
||||||
|
|
||||||
// Keypad option
|
// Keypad and backlight option
|
||||||
char have_keypad = 0; // off by default
|
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...
|
// 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
|
// Autorepeat values
|
||||||
#define KEYPAD_AUTOREPEAT_DELAY 500
|
#define KEYPAD_AUTOREPEAT_DELAY 500
|
||||||
#define KEYPAD_AUTOREPEAT_FREQ 15
|
#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
|
// keyMapMatrix contrains an array with arrays of the ascii-codes that should be generated
|
||||||
// when a key in the matrix is pressed.
|
// when a key in the matrix is pressed.
|
||||||
static char keyMapMatrix[KEYPAD_MAXY][KEYPAD_MAXX] = {
|
static char keyMapMatrix[KEYPAD_MAXY][KEYPAD_MAXX] = {
|
||||||
{ '1', '2', '3', 'A', 0 },
|
{ '1', '2', '3', 'A', 'E' },
|
||||||
{ '4', '5', '6', 'B', 0 },
|
{ '4', '5', '6', 'B', 'F' },
|
||||||
{ '7', '8', '9', 'C', 0 },
|
{ '7', '8', '9', 'C', 'G' },
|
||||||
{ '*', '0', '#', 'D', 0 },
|
{ '*', '0', '#', 'D', 'H' },
|
||||||
{ 0, 0, 0, 0, 0 },
|
{ 'I', 'J', 'K', 'L', 'M' },
|
||||||
{ 0, 0, 0, 0, 0 },
|
{ 'N', 'O', 'P', 'Q', 'R' },
|
||||||
{ 0, 0, 0, 0, 0 },
|
{ 'S', 'T', 'U', 'V', 'W' },
|
||||||
{ 0, 0, 0, 0, 0 },
|
{ 'X', 'Y', 'Z', 'a', 'b' },
|
||||||
{ 0, 0, 0, 0, 0 },
|
{ 'c', 'd', 'e', 'f', 'g' },
|
||||||
{ 0, 0, 0, 0, 0 },
|
{ 'h', 'i', 'j', 'k', 'l' },
|
||||||
{ 0, 0, 0, 0, 0 }};
|
{ 'm', 'n', 'o', 'p', 'q' }};
|
||||||
|
|
||||||
static char pressed_key = 0;
|
static char pressed_key = 0;
|
||||||
static int pressed_key_repetitions = 0;
|
static int pressed_key_repetitions = 0;
|
||||||
static struct timeval pressed_key_time;
|
static struct timeval pressed_key_time;
|
||||||
|
|
||||||
|
|
||||||
// function declarations
|
// function declarations
|
||||||
|
void HD44780_close ();
|
||||||
void HD44780_flush ();
|
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_flush_box (int lft, int top, int rgt, int bot);
|
||||||
void HD44780_backlight (int on);
|
void HD44780_backlight (int on);
|
||||||
void HD44780_init_vbar ();
|
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_hbar (int x, int y, int len);
|
||||||
void HD44780_init_num ();
|
void HD44780_init_num ();
|
||||||
void HD44780_num (int x, int num);
|
void HD44780_num (int x, int num);
|
||||||
|
void HD44780_heartbeat (int type);
|
||||||
void HD44780_set_char (int n, char *dat);
|
void HD44780_set_char (int n, char *dat);
|
||||||
void HD44780_icon (int which, char dest);
|
void HD44780_icon (int which, char dest);
|
||||||
void HD44780_draw_frame (char *dat);
|
void HD44780_draw_frame (char *dat);
|
||||||
void HD44780_close ();
|
char HD44780_getkey ();
|
||||||
|
|
||||||
static void HD44780_linewrap (int on);
|
void HD44780_position (int x, int y);
|
||||||
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);
|
|
||||||
static void uPause (int delayCalls);
|
static void uPause (int delayCalls);
|
||||||
static void HD44780_senddata (unsigned char displayID, unsigned char flags, unsigned char ch);
|
unsigned char HD44780_scankeypad();
|
||||||
static char HD44780_getkey ();
|
|
||||||
|
|
||||||
static int parse_span_list (int *spanListArray[], int *spLsize, int *dispOffsets[], int *dOffsize, int *dispSizeArray[], char *spanlist);
|
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: remove the two magic numbers below
|
||||||
// TODO: single point of return
|
// TODO: single point of return
|
||||||
char *argv[64], *str;
|
//char *argv[64];
|
||||||
int argc, i;
|
//int i;
|
||||||
|
char buf[40];
|
||||||
|
char *s;
|
||||||
|
|
||||||
HD44780 = driver;
|
HD44780 = driver;
|
||||||
|
|
||||||
// get_args inserts \0 into args - nasty !
|
// TODO: replace DriverName with driver->name when that field exists.
|
||||||
if (args)
|
#define DriverName "HD44780"
|
||||||
if ((str = (char *) malloc (strlen (args) + 1)))
|
|
||||||
strcpy (str, args);
|
|
||||||
else {
|
//// READ THE CONFIG FILE
|
||||||
fprintf (stderr, "Error mallocing\n");
|
|
||||||
return -1;
|
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
|
} else
|
||||||
str = NULL;
|
connection = connectionMapping[connectiontype_index].type;
|
||||||
|
|
||||||
argc = get_args (argv, args, 64);
|
// Get and parse vspan only when specified
|
||||||
|
s = driver->config_get_string( DriverName, "vspan", 0, "" );
|
||||||
// arguments are passed in with -d HD44780 "-p 0x278"
|
if( s[0] != 0 ) {
|
||||||
// getopt will work well here
|
if (parse_span_list (&spanList, &numLines, &dispVOffset, &numDisplays, &dispSizes, s) == -1) {
|
||||||
for (i = 0; i < argc; i++) {
|
fprintf (stderr, "HD44780_init: invalid vspan value: %s\n", s );
|
||||||
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);
|
|
||||||
}
|
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
/* ignore invalid arguments as they might be valid to the lower-level init
|
}
|
||||||
else
|
|
||||||
{
|
extIF = driver->config_get_bool( DriverName, "extended", 0, 0 );
|
||||||
printf("Invalid parameter: %s\n", argv[i]);
|
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
|
// default case for when spans aren't indicated
|
||||||
// - add a sanity check against HD44780->hgt ??
|
// - add a sanity check against HD44780->hgt ??
|
||||||
// - this only works if the -t option is specified before -d
|
|
||||||
if (numLines == 0) {
|
if (numLines == 0) {
|
||||||
if ((spanList = (int *) malloc (sizeof (int) * HD44780->hgt))) {
|
if ((spanList = (int *) malloc (sizeof (int) * HD44780->hgt))) {
|
||||||
int i;
|
int i;
|
||||||
@@ -293,6 +243,8 @@ HD44780_init (lcd_logical_driver * driver, char *args)
|
|||||||
} else
|
} else
|
||||||
fprintf (stderr, "Error mallocing for display sizes list\n");
|
fprintf (stderr, "Error mallocing for display sizes list\n");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
#if defined DELAY_NANOSLEEP
|
#if defined DELAY_NANOSLEEP
|
||||||
// Change to Round-Robin scheduling for nanosleep
|
// Change to Round-Robin scheduling for nanosleep
|
||||||
{
|
{
|
||||||
@@ -306,8 +258,6 @@ HD44780_init (lcd_logical_driver * driver, char *args)
|
|||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
atest( port );
|
|
||||||
|
|
||||||
// Make sure the frame buffer is there...
|
// Make sure the frame buffer is there...
|
||||||
if (!HD44780->framebuf)
|
if (!HD44780->framebuf)
|
||||||
HD44780->framebuf = (unsigned char *) malloc (HD44780->wid * HD44780->hgt);
|
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...
|
// Set the functions the driver supports...
|
||||||
// These are the default HD44780 functions
|
// 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->init = HD44780_init;
|
||||||
driver->close = (void *) -1;
|
driver->close = HD44780_close;
|
||||||
driver->flush = HD44780_flush;
|
driver->flush = HD44780_flush;
|
||||||
driver->flush_box = HD44780_flush_box;
|
driver->clear = HD44780_clear;
|
||||||
//driver->contrast = HD44780_contrast; // contrast by potmeter
|
driver->chr = HD44780_chr;
|
||||||
driver->backlight = HD44780_backlight;
|
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->set_char = HD44780_set_char;
|
||||||
driver->icon = HD44780_icon;
|
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;
|
driver->getkey = HD44780_getkey;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -346,21 +300,27 @@ HD44780_init (lcd_logical_driver * driver, char *args)
|
|||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
hd44780_functions->uPause = uPause;
|
hd44780_functions->uPause = uPause;
|
||||||
hd44780_functions->position = common_position;
|
hd44780_functions->scankeypad = HD44780_scankeypad;
|
||||||
hd44780_functions->autoscroll = common_autoscroll;
|
|
||||||
|
|
||||||
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;
|
return port;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/////////////////////////////////////////////////////////////////
|
||||||
// Common initialisation sequence - sets cursor off and not blinking,
|
// Common initialisation sequence - sets cursor off and not blinking,
|
||||||
// clear display and homecursor
|
// clear display and homecursor
|
||||||
// Does not set twoline mode nor small characters (5x8). The init function of
|
// Does not set twoline mode nor small characters (5x8). The init function of
|
||||||
// the connectiontype should do this.
|
// the connectiontype should do this.
|
||||||
|
//
|
||||||
void
|
void
|
||||||
common_init ()
|
common_init ()
|
||||||
{
|
{
|
||||||
@@ -372,7 +332,9 @@ common_init ()
|
|||||||
hd44780_functions->uPause (1600);
|
hd44780_functions->uPause (1600);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/////////////////////////////////////////////////////////////////
|
||||||
// IO delay to avoid a task switch
|
// IO delay to avoid a task switch
|
||||||
|
//
|
||||||
void
|
void
|
||||||
uPause (int delayCalls)
|
uPause (int delayCalls)
|
||||||
{
|
{
|
||||||
@@ -408,26 +370,18 @@ uPause (int delayCalls)
|
|||||||
#endif
|
#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
|
// Clean-up
|
||||||
//
|
//
|
||||||
/*
|
void HD44780_close()
|
||||||
void HD44780_close()
|
{
|
||||||
{
|
}
|
||||||
drv_base_close();
|
|
||||||
}
|
|
||||||
*/
|
|
||||||
|
|
||||||
|
/////////////////////////////////////////////////////////////////
|
||||||
|
// Set position (not part of API)
|
||||||
|
//
|
||||||
// x and y here are for the virtual HD44780->hgt x HD44780->wid display
|
// x and y here are for the virtual HD44780->hgt x HD44780->wid display
|
||||||
static void
|
void
|
||||||
HD44780_position (int x, int y)
|
HD44780_position (int x, int y)
|
||||||
{
|
{
|
||||||
int dispID = spanList[y];
|
int dispID = spanList[y];
|
||||||
@@ -435,37 +389,74 @@ HD44780_position (int x, int y)
|
|||||||
int DDaddr;
|
int DDaddr;
|
||||||
|
|
||||||
// 16x1 is a special case
|
// 16x1 is a special case
|
||||||
if (dispSizes[dispID - 1] == 1 && HD44780->wid == 16)
|
if (dispSizes[dispID - 1] == 1 && HD44780->wid == 16) {
|
||||||
if (x >= 8) {
|
if (x >= 8) {
|
||||||
x -= 8;
|
x -= 8;
|
||||||
relY = 1;
|
relY = 1;
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
DDaddr = x + (relY % 2) * 0x40;
|
DDaddr = x + (relY % 2) * 0x40;
|
||||||
if ((relY % 4) >= 2)
|
if ((relY % 4) >= 2)
|
||||||
DDaddr += HD44780->wid;
|
DDaddr += HD44780->wid;
|
||||||
|
|
||||||
hd44780_functions->position (dispID, DDaddr);
|
hd44780_functions->senddata (dispID, RS_INSTR, POSITION | DDaddr);
|
||||||
}
|
|
||||||
|
|
||||||
void
|
|
||||||
common_position (int display, int DDaddr)
|
|
||||||
{
|
|
||||||
hd44780_functions->senddata (display, RS_INSTR, POSITION | DDaddr);
|
|
||||||
hd44780_functions->uPause (40); // Minimum exec time for all commands
|
hd44780_functions->uPause (40); // Minimum exec time for all commands
|
||||||
}
|
}
|
||||||
|
|
||||||
void HD44780_chr (int x, int y, char ch)
|
/////////////////////////////////////////////////////////////////
|
||||||
{
|
// Flush the framebuffer to the display
|
||||||
HD44780->framebuf[ (y * HD44780->wid) + x] = ch;
|
//
|
||||||
}
|
|
||||||
|
|
||||||
void
|
void
|
||||||
HD44780_flush ()
|
HD44780_flush ()
|
||||||
{
|
{
|
||||||
HD44780_draw_frame (HD44780->framebuf);
|
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
|
void
|
||||||
HD44780_flush_box (int lft, int top, int rgt, int bot)
|
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);
|
HD44780_position (lft, y);
|
||||||
//printf("\n%d,%d :",lft,y);
|
//printf("\n%d,%d :",lft,y);
|
||||||
for (x = lft; x <= rgt; x++) {
|
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]);
|
//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
|
void
|
||||||
HD44780_backlight (int on)
|
HD44780_backlight (int on)
|
||||||
{
|
{
|
||||||
//hd44780_functions->backlight (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);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/////////////////////////////////////////////////////////////////
|
/////////////////////////////////////////////////////////////////
|
||||||
@@ -703,7 +672,7 @@ HD44780_hbar (int x, int y, int len)
|
|||||||
void
|
void
|
||||||
HD44780_init_num ()
|
HD44780_init_num ()
|
||||||
{
|
{
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/////////////////////////////////////////////////////////////////
|
/////////////////////////////////////////////////////////////////
|
||||||
@@ -716,6 +685,38 @@ HD44780_num (int x, int num)
|
|||||||
HD44780->framebuf[x+offset] = num + '0';
|
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...
|
// Sets a custom character from 0-7...
|
||||||
//
|
//
|
||||||
@@ -734,7 +735,8 @@ HD44780_set_char (int n, char *dat)
|
|||||||
if (!dat)
|
if (!dat)
|
||||||
return;
|
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++) {
|
for (row = 0; row < HD44780->cellhgt; row++) {
|
||||||
letter = 0;
|
letter = 0;
|
||||||
@@ -742,10 +744,14 @@ HD44780_set_char (int n, char *dat)
|
|||||||
letter <<= 1;
|
letter <<= 1;
|
||||||
letter |= (dat[(row * HD44780->cellwid) + col] > 0);
|
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
|
void
|
||||||
HD44780_icon (int which, char dest)
|
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
|
// Input is a character array, sized HD44780->wid*hgt
|
||||||
//
|
//
|
||||||
|
// TO BE REMOVED (move it into flush())
|
||||||
void
|
void
|
||||||
HD44780_draw_frame (char *dat)
|
HD44780_draw_frame (char *dat)
|
||||||
{
|
{
|
||||||
@@ -802,15 +809,136 @@ HD44780_draw_frame (char *dat)
|
|||||||
return;
|
return;
|
||||||
|
|
||||||
for (y = 0; y < HD44780->hgt; y++) {
|
for (y = 0; y < HD44780->hgt; y++) {
|
||||||
HD44780_position (0, y);
|
|
||||||
//printf("\n%d :",y);
|
//printf("\n%d :",y);
|
||||||
for (x = 0; x < HD44780->wid; x++) {
|
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
|
// Parse the span list
|
||||||
// spanListArray - array to store vertical spans
|
// spanListArray - array to store vertical spans
|
||||||
// spLsize - size of spanListArray
|
// spLsize - size of spanListArray
|
||||||
@@ -862,90 +990,3 @@ parse_span_list (int *spanListArray[], int *spLsize, int *dispOffsets[], int *dO
|
|||||||
return retVal;
|
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
|
#ifndef HD44780_H
|
||||||
#define 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);
|
int HD44780_init (struct lcd_logical_driver *driver, char *args);
|
||||||
/* The following methods can all be hidden. They are used through function ptrs
|
/* The following methods can all be hidden. They are used through function ptrs
|
||||||
|
|||||||
Reference in New Issue
Block a user