HD44780 keypad update. (second try)

This commit is contained in:
robijn
2001-10-05 21:01:24 +00:00
parent 4829ed367f
commit 16cce2fe2d
4 changed files with 355 additions and 141 deletions
+10 -3
View File
@@ -6,7 +6,8 @@
enum ifWidth { IF_4bit, IF_8bit }; enum ifWidth { IF_4bit, IF_8bit };
void common_init (enum ifWidth ifwidth); //void common_init (enum ifWidth ifwidth);
void common_init ();
// Structures holding pointers to HD44780 specific functions // Structures holding pointers to HD44780 specific functions
typedef struct hwDependentFns { typedef struct hwDependentFns {
@@ -27,6 +28,12 @@ typedef struct hwDependentFns {
// toggle vertical autoscroll on all displays // toggle vertical autoscroll on all displays
// on - non-zero turns autoscroll on, zero value turns it off // on - non-zero turns autoscroll on, zero value turns it off
void (*autoscroll) (int on); void (*autoscroll) (int on);
// 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);
} 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;
@@ -81,7 +88,7 @@ extern HD44780_functions *hd44780_functions;
#define nSEL 0x08 #define nSEL 0x08
#define SEL 0x08 #define SEL 0x08
#define OUTMASK 0x0B #define OUTMASK 0x0B /* SEL, LF and STRB are hardware inverted */
// Input lines // Input lines
#define nFAULT 0x08 #define nFAULT 0x08
@@ -92,6 +99,6 @@ extern HD44780_functions *hd44780_functions;
#define ACK 0x40 #define ACK 0x40
#define BUSY 0x80 #define BUSY 0x80
#define INMASK 0x48 #define INMASK 0x84 /* BUSY input and the IRQ indicator are inverted */
#endif #endif
+86 -33
View File
@@ -6,6 +6,10 @@
* Copyright (c) 1999 Andrew McMeikan <andrewm@engineer.com> * Copyright (c) 1999 Andrew McMeikan <andrewm@engineer.com>
* modular driver 1999 Benjamin Tse <blt@Comports.com> * modular driver 1999 Benjamin Tse <blt@Comports.com>
* *
* 2001 Joris Robijn <joris@robijn.net>
* - Keypad support
* - Changed for 2 line wire control
*
* Full connection details at http://members.xoom.com/andrewmuck/LCD.htm * Full connection details at http://members.xoom.com/andrewmuck/LCD.htm
* *
* printer port 4094/LCD * printer port 4094/LCD
@@ -23,63 +27,95 @@
* Q6 (13) RS (4) * Q6 (13) RS (4)
* Gnd nRW (5) * Gnd nRW (5)
* *
* Keypad connection (optional):
* This is connected on the 4094 parallel to the LCD.
* Some diodes and resistors are needed, see further documentation.
* Q1 (4) Y0
* Q2 (5) Y1
* Q3 (6) Y2
* Q4 (7) Y3
* Q5 (14) Y4
* Q6 (13) Y5
* The 'output' of the keys should be connected to the following LPT pins:
* nACK (10) X0
* BUSY (11) X1
* PAPEREND (12) X2
* SELIN (13) X3
* nFAULT (15) X4
* If you want to use as few LPT lines as possible, only use X0.
*
* 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.
*/ */
#include "hd44780-serialLpt.h"
#include "hd44780.h"
#include "port.h"
#include "shared/str.h"
#include <stdio.h> #include <stdio.h>
#include <string.h> #include <string.h>
#include <errno.h> #include <errno.h>
#include "hd44780-serialLpt.h"
#include "port.h"
// 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);
static char lcdserLpt_HD44780_getkey (void); static char lcdserLpt_HD44780_getkey (void); // old keypad code
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);
#define RS 16 #define RS 32
#define LCDDATA 8 #define LCDDATA 8
#define LCDCLOCK 16 #define LCDCLOCK 16
#define EN1 4 #define EN1 4
#define EN2 32 #define EN2 32
static unsigned int lp; static unsigned int lptPort;
static char lastkey = 0; static char keypad;
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
hd_init_serialLpt (HD44780_functions * hd44780_functions, lcd_logical_driver * driver, char *args, unsigned int port) hd_init_serialLpt (HD44780_functions * hd44780_functions, lcd_logical_driver * driver, char *args, unsigned int port)
{ {
int displayID = EN1 | EN2; unsigned char enableLines = EN1 | EN2;
lp = port; // Reserve the port registers
if (port_access (lp) || port_access (lp +1)) { lptPort = port;
fprintf (stderr, "HD44780_init: failed (%s)\n", strerror (errno)); port_access(lptPort);
return( -1 ); port_access(lptPort+1);
}; port_access(lptPort+2);
hd44780_functions->senddata = lcdserLpt_HD44780_senddata; hd44780_functions->senddata = lcdserLpt_HD44780_senddata;
hd44780_functions->readkeypad = lcdserLpt_HD44780_readkeypad;
// TODO: enable keypad only if specified on command line if (keypad) {
driver->getkey = lcdserLpt_HD44780_getkey; driver->getkey = lcdserLpt_HD44780_getkey;
}
// Clear the shiftregister
rawshift (0);
// setup the lcd in 4 bit mode // setup the lcd in 4 bit mode
shiftreg (displayID, 3); shiftreg (enableLines, 3);
hd44780_functions->uPause (4100); hd44780_functions->uPause (4100);
shiftreg (displayID, 3); shiftreg (enableLines, 3);
hd44780_functions->uPause (100); hd44780_functions->uPause (100);
shiftreg (displayID, 3); shiftreg (enableLines, 3);
hd44780_functions->uPause (40); hd44780_functions->uPause (40);
shiftreg (displayID, 2); shiftreg (enableLines, 2);
hd44780_functions->uPause (40); hd44780_functions->uPause (40);
hd44780_functions->senddata (0, RS_INSTR, FUNCSET | IF_4BIT | TWOLINE | SMALLCHAR);
common_init ();
/*
// set display type functions // set display type functions
lcdserLpt_HD44780_senddata (0, RS_INSTR, FUNCSET | IF_4BIT | TWOLINE | SMALLCHAR); lcdserLpt_HD44780_senddata (0, RS_INSTR, FUNCSET | IF_4BIT | TWOLINE | SMALLCHAR);
// clear // clear
@@ -88,6 +124,7 @@ hd_init_serialLpt (HD44780_functions * hd44780_functions, lcd_logical_driver * d
// Now turn on the display // Now turn on the display
lcdserLpt_HD44780_senddata (displayID, RS_INSTR, ONOFFCTRL | DISPON | CURSOROFF | CURSORNOBLINK); lcdserLpt_HD44780_senddata (displayID, RS_INSTR, ONOFFCTRL | DISPON | CURSOROFF | CURSORNOBLINK);
hd44780_functions->uPause (1600); hd44780_functions->uPause (1600);
*/
return 0; return 0;
} }
@@ -95,22 +132,24 @@ hd_init_serialLpt (HD44780_functions * hd44780_functions, lcd_logical_driver * d
void void
lcdserLpt_HD44780_senddata (unsigned char displayID, unsigned char flags, unsigned char ch) lcdserLpt_HD44780_senddata (unsigned char displayID, unsigned char flags, unsigned char ch)
{ {
unsigned char dispID = 0, portControl = 0, h = ch >> 4, l = ch & 15; unsigned char enableLines;
unsigned char portControl = 0;
unsigned char h = ch >> 4, l = ch & 15;
if (displayID == 1) if (displayID == 1)
dispID |= EN1; enableLines = EN1;
else if (displayID == 2) else if (displayID == 2)
dispID |= EN2; enableLines = EN2;
else else
dispID |= EN1 | EN2; enableLines = EN1 | EN2;
if (flags == RS_DATA) if (flags == RS_DATA)
portControl = RS; portControl = RS;
else else
portControl = 0; portControl = 0;
shiftreg (displayID, flags | portControl | h); shiftreg (enableLines, portControl | h);
shiftreg (displayID, flags | portControl | l); shiftreg (enableLines, portControl | l);
/* TODO: instead of delay read keys here */ /* TODO: instead of delay read keys here */
} }
@@ -123,16 +162,19 @@ lcdserLpt_HD44780_getkey ()
char keytr[] = "ABCDEFGH"; char keytr[] = "ABCDEFGH";
int n; int n;
// disabled now !
return 0;
rawshift (0); //send all line on shift register low rawshift (0); //send all line on shift register low
hd44780_functions->uPause (1); hd44780_functions->uPause (1);
if ((port_in (lp + 1) & 32) == 0) //test if line back is low - if not return(0) if ((port_in (lptPort + 1) & 32) == 0) //test if line back is low - if not return(0)
{ //else { //else
//start walking a single zero across the eight lines //start walking a single zero across the eight lines
for (n = 7; n >= 0; n--) { for (n = 7; n >= 0; n--) {
rawshift (255 - (1 << n)); rawshift (255 - (1 << n));
hd44780_functions->uPause (1); hd44780_functions->uPause (1);
if ((port_in (lp + 1) & 32) == 0) // check if line back is low if yes debounce if ((port_in (lptPort + 1) & 32) == 0) // check if line back is low if yes debounce
{ {
if (lastkey == keytr[n]) if (lastkey == keytr[n])
return (0); return (0);
@@ -146,22 +188,33 @@ lcdserLpt_HD44780_getkey ()
return (0); return (0);
} }
unsigned char lcdserLpt_HD44780_readkeypad (unsigned int YData)
{
return 0;
}
/* this function sends r out onto the shift register */ /* this function sends r out onto the shift register */
void void
rawshift (unsigned char r) rawshift (unsigned char r)
{ {
int i; int i;
for (i = 7; i >= 0; i--) { /* MSB first */ for (i = 7; i >= 0; i--) { /* MSB first */
port_out (lp, ((r >> i) & 1) * LCDDATA); /*set up data */ port_out (lptPort, ((r >> i) & 1) * LCDDATA); /*set up data */
port_out (lp, (((r >> i) & 1) * LCDDATA) | LCDCLOCK); /*rising edge of clock */ port_out (lptPort, (((r >> i) & 1) * LCDDATA) | LCDCLOCK); /*rising edge of clock */
} }
} }
// displayID = value on parallel port to toggle the correct display // enableLines = value on parallel port to toggle the correct display
void void
shiftreg (unsigned char displayID, unsigned char r) shiftreg (unsigned char enableLines, unsigned char r)
{ {
rawshift (r); //unsigned char mr;
port_out (lp, displayID); //latch it, to correct display //mr = (r & 0xF0) | ((r<<3) & 0x0F) | ((r<<1) & 0x04) |
port_out (lp, 0); // ((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);
port_out (lptPort, 0);
hd44780_functions->uPause (3);
} }
+64 -12
View File
@@ -11,6 +11,9 @@
* - provided required setup time for RS valid to E high * - provided required setup time for RS valid to E high
* - 1 uS call to uPause removed as it is unnecessary * - 1 uS call to uPause removed as it is unnecessary
* *
* 2001 Joris Robijn <joris@robijn.net>
* - Keypad support
*
* The connections are: * The connections are:
* printer port LCD * printer port LCD
* D0 (2) D0 (7) * D0 (2) D0 (7)
@@ -26,6 +29,26 @@
* INIT (16) RS (4) * INIT (16) RS (4)
* nSEL (17) EN2 (6 - LCD 2) (optional) * nSEL (17) EN2 (6 - LCD 2) (optional)
* *
* Keypad connection (optional):
* Some diodes and resistors are needed, see further documentation.
* printer port keypad
* D0 (2) Y0
* D1 (3) Y1
* D2 (4) Y2
* D3 (5) Y3
* D4 (6) Y4
* D5 (7) Y5
* D6 (7) Y6
* D7 (7) Y7
* nLF (14) Y8
* INIT (16) Y9
* nSEL (17) Y10
* nACK (10) X0
* BUSY (11) X1
* PAPEREND (12) X2
* SELIN (13) X3
* nFAULT (15) X4
*
* Created modular driver Dec 1999, Benjamin Tse <blt@Comports.com> * Created modular driver Dec 1999, Benjamin Tse <blt@Comports.com>
* *
* 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
@@ -33,14 +56,18 @@
*/ */
#include "hd44780-winamp.h" #include "hd44780-winamp.h"
#include "port.h" #include "hd44780.h"
#include "port.h"
#include "shared/str.h" #include "shared/str.h"
#include <stdio.h> #include <stdio.h>
#include <string.h> #include <string.h>
#include <errno.h> #include <errno.h>
#include "port.h"
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);
unsigned char lcdwinamp_HD44780_readkeypad (unsigned int YData);
#define EN1 STRB #define EN1 STRB
#define EN2 SEL #define EN2 SEL
@@ -50,8 +77,9 @@ void lcdwinamp_HD44780_senddata (unsigned char displayID, unsigned char flags, u
static unsigned char EnMask[] = { EN1, EN2, EN3 }; static unsigned char EnMask[] = { EN1, EN2, EN3 };
static int EnMaskSize = sizeof (EnMask) / sizeof (unsigned char); static int EnMaskSize = sizeof (EnMask) / sizeof (unsigned char);
static unsigned int lptPort;
static int extIF = 0; // non-zero if extended interface 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
// initialise the driver // initialise the driver
int int
@@ -62,22 +90,32 @@ hd_init_winamp (HD44780_functions * hd44780_functions, lcd_logical_driver * driv
int argc; int argc;
int i; int i;
hd44780_functions->senddata = lcdwinamp_HD44780_senddata; // Reserve the port registers
lptPort = port; lptPort = port;
port_access(lptPort);
port_access(lptPort+1);
port_access(lptPort+2);
hd44780_functions->senddata = lcdwinamp_HD44780_senddata;
hd44780_functions->readkeypad = lcdwinamp_HD44780_readkeypad;
// parse command-line arguments // parse command-line arguments
argc = get_args (argv, args, 64); argc = get_args (argv, args, 64);
for (i = 0; i < argc; ++i) for (i = 0; i < argc; ++i) {
if (strcmp (argv[i], "-e") == 0 || strcmp (argv[i], "--extended") == 0) if (strcmp (argv[i], "-e") == 0 || strcmp (argv[i], "--extended") == 0)
extIF = 1; extIF = 1;
if (port_access (lptPort + 2) || port_access (lptPort)) {
fprintf (stderr, "HD44780_init: failed (%s)\n", strerror (errno));
return -1;
} }
common_init (IF_8bit); // setup the lcd in 8 bit mode
hd44780_functions->senddata (0, RS_INSTR, FUNCSET | IF_8BIT);
hd44780_functions->uPause (4100);
hd44780_functions->senddata (0, RS_INSTR, FUNCSET | IF_8BIT);
hd44780_functions->uPause (100);
hd44780_functions->senddata (0, RS_INSTR, FUNCSET | IF_8BIT | TWOLINE | SMALLCHAR);
hd44780_functions->uPause (40);
common_init ();
return 0; return 0;
} }
@@ -100,12 +138,12 @@ lcdwinamp_HD44780_senddata (unsigned char displayID, unsigned char flags, unsign
// 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 ^ OUTMASK);
// then set EN high
port_out (lptPort + 2, (dispID | portControl) ^ OUTMASK);
// Output the actual data // Output the actual data
port_out (lptPort, ch); port_out (lptPort, ch);
// then set EN high
port_out (lptPort + 2, (dispID | portControl) ^ 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...
@@ -115,3 +153,17 @@ lcdwinamp_HD44780_senddata (unsigned char displayID, unsigned char flags, unsign
// 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
} }
unsigned char lcdwinamp_HD44780_readkeypad (unsigned int YData)
{
unsigned char readval;
// 10 bits output
// Convert the positive logic to the negative logic on the LPT port
port_out (lptPort, ~YData & 0x00FF );
port_out (lptPort + 2, ( ((~YData & 0x0100) >> 7) | ((~YData & 0x0200) >> 7 )) ^ OUTMASK);
// And convert it back.
readval = ~ port_in (lptPort + 1) ^ INMASK;
return ( (readval >> 4 & 0x03) | (readval >> 5 & 0x04) | (readval >> 3 & 0x08) | (readval << 1 & 0x10) ) & ~stuckinputs;
}
+157 -55
View File
@@ -14,20 +14,23 @@
* 4. Modify the makefile * 4. Modify the makefile
* *
* Modular driver created and generic support for multiple displays added * Modular driver created and generic support for multiple displays added
* Dec 1999, Benjamin Tse <blt@Comports.com>. * Dec 1999, Benjamin Tse <blt@Comports.com>
* *
* Modified July 2000 by Charles Steinkuehler to use one of 3 methods for delay * Modified July 2000 by Charles Steinkuehler to use one of 3 methods for delay
* timing. I/O reads, gettimeofday, and nanosleep. Of the three, nanosleep * timing. I/O reads, gettimeofday, and nanosleep. Of the three, nanosleep
* seems to work best, so that's what is set by default. * seems to work best, so that's what is set by default.
* *
* Modified May 2001 by Joris Robijn to add Keypad support.
*
* 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>.
* *
* 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) 2001 Mark Haemmerling <mail@markh.de> * Copyright (c) 2000, 1999, 1995 Benjamin Tse <blt@Comports.com>
* 2000, 1999, 1995 Benjamin Tse <blt@Comports.com> * 2001 Joris Robijn <joris@robijn.net>
* 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>
@@ -51,7 +54,6 @@
//#define DELAY_GETTIMEOFDAY //#define DELAY_GETTIMEOFDAY
#define DELAY_NANOSLEEP #define DELAY_NANOSLEEP
#if defined DELAY_GETTIMEOFDAY
# if TIME_WITH_SYS_TIME # if TIME_WITH_SYS_TIME
# include <sys/time.h> # include <sys/time.h>
# include <time.h> # include <time.h>
@@ -64,6 +66,7 @@
# endif # endif
// Only one alternate delay method at a time, please ;-) // Only one alternate delay method at a time, please ;-)
#if defined DELAY_GETTIMEOFDAY
# undef DELAY_NANOSLEEP # undef DELAY_NANOSLEEP
#elif defined DELAY_NANOSLEEP #elif defined DELAY_NANOSLEEP
# include <sched.h> # include <sched.h>
@@ -107,10 +110,46 @@ 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
char keypad = 0; // off by default
// This var 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
// keyMapDirect contains an array of the ascii-codes that should be generated
// when a directly connected key is pressed (not in matrix).
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 }};
static char pressed_key = 0;
static int pressed_key_repetitions = 0;
static struct timeval pressed_key_time;
// function declarations // function declarations
void HD44780_flush (); void HD44780_flush ();
void HD44780_flush_box (int lft, int top, int rgt, int bot); void HD44780_flush_box (int lft, int top, int rgt, int bot);
int HD44780_contrast (int contrast);
void HD44780_backlight (int on); void HD44780_backlight (int on);
void HD44780_init_vbar (); void HD44780_init_vbar ();
void HD44780_init_hbar (); void HD44780_init_hbar ();
@@ -132,6 +171,7 @@ static void common_position (int display, int DDaddr);
static void common_autoscroll (int on); 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); static void HD44780_senddata (unsigned char displayID, unsigned char flags, unsigned char ch);
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);
@@ -205,6 +245,10 @@ HD44780_init (lcd_logical_driver * driver, char *args)
return -1; return -1;
} }
++i; ++i;
} else if (strcmp (argv[i], "-k") == 0 || strcmp (argv[i], "--keypad") == 0) {
keypad = 1;
printf( "HD44780 keypad extension enabled\n" );
} else if (0 == strcmp (argv[i], "-h") || 0 == strcmp (argv[i], "--help")) { } else if (0 == strcmp (argv[i], "-h") || 0 == strcmp (argv[i], "--help")) {
int i; 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); 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);
@@ -259,11 +303,6 @@ HD44780_init (lcd_logical_driver * driver, char *args)
} }
} }
#endif #endif
// Set up io port correctly, and open it...
if (port_access (port)) {
fprintf (stderr, "HD44780_init: failed (%s)\n", strerror (errno));
return -1;
}
// 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);
@@ -288,12 +327,15 @@ HD44780_init (lcd_logical_driver * driver, char *args)
driver->close = (void *) -1; driver->close = (void *) -1;
driver->flush = HD44780_flush; driver->flush = HD44780_flush;
driver->flush_box = HD44780_flush_box; driver->flush_box = HD44780_flush_box;
driver->contrast = HD44780_contrast; //driver->contrast = HD44780_contrast; // contrast by potmeter
driver->backlight = HD44780_backlight; driver->backlight = HD44780_backlight;
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;
driver->getkey = NULL;
if( keypad ) {
driver->getkey = HD44780_getkey;
}
if ((hd44780_functions = (HD44780_functions *) malloc (sizeof (HD44780_functions))) == NULL) { if ((hd44780_functions = (HD44780_functions *) malloc (sizeof (HD44780_functions))) == NULL) {
return -1; return -1;
@@ -309,28 +351,14 @@ HD44780_init (lcd_logical_driver * driver, char *args)
return port; return port;
} }
// common initialisation sequence - sets twoline, small characters (5x8), // Common initialisation sequence - sets cursor off and not blinking,
// 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
// the connectiontype should do this.
void void
common_init (enum ifWidth ifwidth) common_init ()
{ {
if (ifwidth == IF_8bit) {
// setup the lcd in 8 bit mode
hd44780_functions->senddata (0, RS_INSTR, FUNCSET | IF_8BIT);
hd44780_functions->uPause (4100);
hd44780_functions->senddata (0, RS_INSTR, FUNCSET | IF_8BIT);
hd44780_functions->uPause (100);
hd44780_functions->senddata (0, RS_INSTR, FUNCSET | IF_8BIT);
hd44780_functions->uPause (40);
}
// else 4bit
// senddata can't generate the timings to initialise a four bit device
// properly but it might just work properly anyway ....
// set display type functions
hd44780_functions->senddata (0, RS_INSTR, FUNCSET | ((ifwidth == IF_4BIT) ? IF_4BIT : IF_8BIT) | TWOLINE | SMALLCHAR);
hd44780_functions->uPause (40);
hd44780_functions->senddata (0, RS_INSTR, ONOFFCTRL | DISPON | CURSOROFF | CURSORNOBLINK); hd44780_functions->senddata (0, RS_INSTR, ONOFFCTRL | DISPON | CURSOROFF | CURSORNOBLINK);
hd44780_functions->uPause (40); hd44780_functions->uPause (40);
hd44780_functions->senddata (0, RS_INSTR, CLEAR); hd44780_functions->senddata (0, RS_INSTR, CLEAR);
@@ -368,11 +396,10 @@ uPause (int delayCalls)
delay.tv_sec = remaining.tv_sec; delay.tv_sec = remaining.tv_sec;
delay.tv_nsec = remaining.tv_nsec; delay.tv_nsec = remaining.tv_nsec;
} }
#else #else // using I/O timing
int i; int i;
for (i = 0; i < delayCalls; ++i) for (i = 0; i < delayCalls; ++i)
port_in (port); port_in (port);
//TODO: put in option for nanosleep rather than dummy I/O call
#endif #endif
} }
@@ -381,7 +408,7 @@ static void
HD44780_senddata (unsigned char displayID, unsigned char flags, unsigned char ch) HD44780_senddata (unsigned char displayID, unsigned char flags, unsigned char ch)
{ {
hd44780_functions->senddata (displayID, flags, ch); hd44780_functions->senddata (displayID, flags, ch);
hd44780_functions->uPause (40); hd44780_functions->uPause (40); // Minimum exec time for all commands
} }
///////////////////////////////////////////////////////////////// /////////////////////////////////////////////////////////////////
@@ -420,7 +447,7 @@ void
common_position (int display, int DDaddr) common_position (int display, int DDaddr)
{ {
hd44780_functions->senddata (display, RS_INSTR, POSITION | DDaddr); hd44780_functions->senddata (display, RS_INSTR, POSITION | DDaddr);
hd44780_functions->uPause (40); hd44780_functions->uPause (40); // Minimum exec time for all commands
} }
void HD44780_chr (int x, int y, char ch) void HD44780_chr (int x, int y, char ch)
@@ -453,21 +480,12 @@ HD44780_flush_box (int lft, int top, int rgt, int bot)
} }
///////////////////////////////////////////////////////////////// /////////////////////////////////////////////////////////////////
// Changes screen contrast (0-255; 140 seems good) // Sets the backlight on or off
//
int
HD44780_contrast (int contrast)
{
return 0;
}
/////////////////////////////////////////////////////////////////
// Sets the backlight on or off -- can be done quickly for
// an intermediate brightness...
// //
void void
HD44780_backlight (int on) HD44780_backlight (int on)
{ {
//hd44780_functions->backlight (on);
} }
///////////////////////////////////////////////////////////////// /////////////////////////////////////////////////////////////////
@@ -491,7 +509,7 @@ void
common_autoscroll (int on) common_autoscroll (int on)
{ {
hd44780_functions->senddata (0, RS_INSTR, ENTRYMODE | E_MOVERIGHT | ((on) ? EDGESCROLL : NOSCROLL)); hd44780_functions->senddata (0, RS_INSTR, ENTRYMODE | E_MOVERIGHT | ((on) ? EDGESCROLL : NOSCROLL));
hd44780_functions->uPause (1600); hd44780_functions->uPause (40);
} }
///////////////////////////////////////////////////////////////// /////////////////////////////////////////////////////////////////
@@ -680,9 +698,7 @@ HD44780_hbar (int x, int y, int len)
void void
HD44780_init_num () HD44780_init_num ()
{ {
char out[3];
snprintf (out, sizeof(out), "%cn", 254);
//write(fd, out, 2);
} }
///////////////////////////////////////////////////////////////// /////////////////////////////////////////////////////////////////
@@ -691,10 +707,8 @@ HD44780_init_num ()
void void
HD44780_num (int x, int num) HD44780_num (int x, int num)
{ {
char out[5]; int offset = HD44780->wid * ( HD44780->hgt / 2 );
printf("Size of out is %d\n", sizeof(out)); HD44780->framebuf[x+offset] = num + '0';
snprintf (out, sizeof(out), "%c#%c%c", 254, x, num);
//write(fd, out, 4);
} }
///////////////////////////////////////////////////////////////// /////////////////////////////////////////////////////////////////
@@ -842,3 +856,91 @@ 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;
}