Files
lcdproc/server/drivers/hd44780-serialLpt.c
T

221 lines
5.8 KiB
C
Raw Normal View History

/*
* Serial LPT driver module for Hitachi HD44780 based LCD displays by
* Andrew McMeikan. The LCD is operated in it's 4 bit-mode through a
* 4094 shift register and supports a keypad.
*
* Copyright (c) 1999 Andrew McMeikan <andrewm@engineer.com>
2001-10-05 21:01:24 +00:00
* 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
*
2001-10-05 21:01:24 +00:00
* printer port 4094/LCD
* D2 (4) EN (6 - LCD)
* D3 (5) D (2 - 4094)
* D4 (6) CLK (3 - 4094)
2001-10-05 21:01:24 +00:00
* +Vcc OE, STR (15, 1 - 4094)
* D7 (9) EN2 (6 - LCD2) (optional)
*
2001-10-05 21:01:24 +00:00
* 4094 LCD
* Q1 (4) D4 (11)
* Q2 (5) D5 (12)
* Q3 (6) D6 (13)
* Q4 (7) D7 (14)
* Q6 (13) RS (4)
2001-10-05 21:01:24 +00:00
* 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
* COPYING file distributed with this package.
*/
2001-10-05 21:01:24 +00:00
#include "hd44780-serialLpt.h"
#include "hd44780.h"
#include "port.h"
#include "shared/str.h"
#include <stdio.h>
#include <string.h>
#include <errno.h>
// Hardware specific functions
void lcdserLpt_HD44780_senddata (unsigned char displayID, unsigned char flags, unsigned char ch);
2001-10-05 21:01:24 +00:00
unsigned char lcdserLpt_HD44780_readkeypad (unsigned int YData);
2001-10-05 21:01:24 +00:00
static char lcdserLpt_HD44780_getkey (void); // old keypad code
void rawshift (unsigned char r);
void shiftreg (unsigned char displayID, unsigned char r);
2001-10-05 21:01:24 +00:00
#define RS 32
#define LCDDATA 8
#define LCDCLOCK 16
2001-10-05 21:01:24 +00:00
#define EN1 4
#define EN2 32
2001-10-05 21:01:24 +00:00
static unsigned int lptPort;
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
int
hd_init_serialLpt (HD44780_functions * hd44780_functions, lcd_logical_driver * driver, char *args, unsigned int port)
{
2001-10-05 21:01:24 +00:00
unsigned char enableLines = EN1 | EN2;
2001-10-05 21:01:24 +00:00
// Reserve the port registers
lptPort = port;
port_access(lptPort);
port_access(lptPort+1);
port_access(lptPort+2);
2000-04-03 22:13:57 +00:00
hd44780_functions->senddata = lcdserLpt_HD44780_senddata;
2001-10-05 21:01:24 +00:00
hd44780_functions->readkeypad = lcdserLpt_HD44780_readkeypad;
2001-10-05 21:01:24 +00:00
if (keypad) {
driver->getkey = lcdserLpt_HD44780_getkey;
}
// Clear the shiftregister
rawshift (0);
2000-04-03 22:13:57 +00:00
// setup the lcd in 4 bit mode
2001-10-05 21:01:24 +00:00
shiftreg (enableLines, 3);
2000-04-03 22:13:57 +00:00
hd44780_functions->uPause (4100);
2001-10-05 21:01:24 +00:00
shiftreg (enableLines, 3);
2000-04-03 22:13:57 +00:00
hd44780_functions->uPause (100);
2001-10-05 21:01:24 +00:00
shiftreg (enableLines, 3);
2000-04-03 22:13:57 +00:00
hd44780_functions->uPause (40);
2001-10-05 21:01:24 +00:00
shiftreg (enableLines, 2);
2000-04-03 22:13:57 +00:00
hd44780_functions->uPause (40);
2001-10-05 21:01:24 +00:00
hd44780_functions->senddata (0, RS_INSTR, FUNCSET | IF_4BIT | TWOLINE | SMALLCHAR);
common_init ();
/*
2000-04-03 22:13:57 +00:00
// 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);
2001-10-05 21:01:24 +00:00
*/
2000-04-03 22:13:57 +00:00
return 0;
}
void
lcdserLpt_HD44780_senddata (unsigned char displayID, unsigned char flags, unsigned char ch)
{
2001-10-05 21:01:24 +00:00
unsigned char enableLines;
unsigned char portControl = 0;
unsigned char h = ch >> 4, l = ch & 15;
2000-04-03 22:13:57 +00:00
if (displayID == 1)
2001-10-05 21:01:24 +00:00
enableLines = EN1;
2000-04-03 22:13:57 +00:00
else if (displayID == 2)
2001-10-05 21:01:24 +00:00
enableLines = EN2;
2000-04-03 22:13:57 +00:00
else
2001-10-05 21:01:24 +00:00
enableLines = EN1 | EN2;
2000-04-03 22:13:57 +00:00
if (flags == RS_DATA)
portControl = RS;
else
portControl = 0;
2001-10-05 21:01:24 +00:00
shiftreg (enableLines, portControl | h);
shiftreg (enableLines, portControl | l);
2000-04-03 22:13:57 +00:00
/* TODO: instead of delay read keys here */
}
char
lcdserLpt_HD44780_getkey ()
{
2000-04-03 22:13:57 +00:00
// TODO: a keypad scan that does not use shift register
2001-10-05 21:01:24 +00:00
// define a key table
2000-04-03 22:13:57 +00:00
char keytr[] = "ABCDEFGH";
int n;
2001-10-05 21:01:24 +00:00
// disabled now !
return 0;
rawshift (0); //send all line on shift register low
2000-04-03 22:13:57 +00:00
hd44780_functions->uPause (1);
2001-10-05 21:01:24 +00:00
if ((port_in (lptPort + 1) & 32) == 0) //test if line back is low - if not return(0)
{ //else
//start walking a single zero across the eight lines
2000-04-03 22:13:57 +00:00
for (n = 7; n >= 0; n--) {
rawshift (255 - (1 << n));
hd44780_functions->uPause (1);
2001-10-05 21:01:24 +00:00
if ((port_in (lptPort + 1) & 32) == 0) // check if line back is low if yes debounce
2000-04-03 22:13:57 +00:00
{
if (lastkey == keytr[n])
return (0);
// printf("key is %c %d\n",keytr[n],n);
lastkey = keytr[n];
2001-10-05 21:01:24 +00:00
return (keytr[n]); //return correct key code.
2000-04-03 22:13:57 +00:00
}
}
2001-10-05 21:01:24 +00:00
} //else fall out and return(0) [too transient a keypress]
2000-04-03 22:13:57 +00:00
lastkey = 0;
return (0);
}
2001-10-05 21:01:24 +00:00
unsigned char lcdserLpt_HD44780_readkeypad (unsigned int YData)
{
return 0;
}
/* this function sends r out onto the shift register */
void
rawshift (unsigned char r)
{
2000-04-03 22:13:57 +00:00
int i;
2001-10-05 21:01:24 +00:00
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 */
2000-04-03 22:13:57 +00:00
}
}
2001-10-05 21:01:24 +00:00
// enableLines = value on parallel port to toggle the correct display
void
2001-10-05 21:01:24 +00:00
shiftreg (unsigned char enableLines, unsigned char r)
{
2001-10-05 21:01:24 +00:00
//unsigned char mr;
//mr = (r & 0xF0) | ((r<<3) & 0x0F) | ((r<<1) & 0x04) |
// ((r>>1) & 0x02) | ((r>>3) & 0x01);
rawshift (r | 0x80); // highest bit always set to 1 for Clear
port_out (lptPort, enableLines); //latch it, to correct display
hd44780_functions->uPause (1);
port_out (lptPort, 0);
hd44780_functions->uPause (3);
}