Portable and maintable HD44780 driver files.
This commit is contained in:
@@ -0,0 +1,196 @@
|
||||
/*
|
||||
* 4-bit driver module for Hitachi HD44780 based LCD displays.
|
||||
* The LCD is operated in it's 4 bit-mode to be connected to a single
|
||||
* 8 bit-port.
|
||||
*
|
||||
* Copyright (c) 2000, 1999, 1995 Benjamin Tse <blt@Comports.com>
|
||||
* 1999 Andrew McMeikan <andrewm@engineer.com>
|
||||
* 1998 Richard Rognlie <rrognlie@gamerz.net>
|
||||
* 1997 Matthias Prinke <m.prinke@trashcan.mcnet.de>
|
||||
*
|
||||
* The connections are:
|
||||
* printer port LCD
|
||||
* D0 (2) D4 (11)
|
||||
* D1 (3) D5 (12)
|
||||
* D2 (4) D6 (13)
|
||||
* D3 (5) D7 (14)
|
||||
* D4 (6) RS (4)
|
||||
* D5 (7) RW (5) (LCD3 - 6) (optional - pull all LCD RW low)
|
||||
* D6 (8) EN (6)
|
||||
* D7 (9) EN2 (LCD2 - 6) (optional)
|
||||
*
|
||||
* Extended interface (including LCD3 above)
|
||||
* STR (1) EN4
|
||||
* LF (14) EN5
|
||||
* INIT (16) EN6
|
||||
* SEL (17) EN7
|
||||
*
|
||||
* Added support for up to 7 LCDs Jan 2000, Benjamin Tse
|
||||
* Created modular driver Dec 1999, Benjamin Tse <blt@Comports.com>
|
||||
*
|
||||
* Based on Matthias Prinke's <m.prinke@trashcan.mcnet.de> lcd4.c module
|
||||
* in lcdstat. This was in turn based on Benjamin Tse's lcdtime package
|
||||
* which uses the LCD controller in its 8-bit mode.
|
||||
*
|
||||
* This file is released under the GNU General Public License. Refer to the
|
||||
* COPYING file distributed with this package.
|
||||
*/
|
||||
|
||||
#include "hd44780-4bit.h"
|
||||
#include "port.h"
|
||||
|
||||
#include "../../shared/str.h"
|
||||
#include <sys/perm.h>
|
||||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
#include <errno.h>
|
||||
|
||||
// Generally, any function that accesses the LCD control lines needs to be
|
||||
// implemented separately for each HW design. This is typically just
|
||||
// HD44780_senddata
|
||||
|
||||
void lcdstat_HD44780_senddata(unsigned char displayID,
|
||||
unsigned char flags,
|
||||
unsigned char ch);
|
||||
|
||||
|
||||
#define RS 0x10
|
||||
#define RW 0x20
|
||||
#define EN1 0x40
|
||||
#define EN2 0x80
|
||||
#define EN3 0x20
|
||||
|
||||
static unsigned char EnMask[] = { EN1, EN2, EN3, STRB, LF, INIT, SEL };
|
||||
static int EnMaskSize = sizeof(EnMask) / sizeof(unsigned char);
|
||||
|
||||
static unsigned int lptPort;
|
||||
static int extIF = 0; // non-zero if extended interface
|
||||
|
||||
// initialisation function
|
||||
int hd_init_4bit(HD44780_functions *hd44780_functions,
|
||||
lcd_logical_driver *driver,
|
||||
char *args,
|
||||
unsigned int port)
|
||||
{
|
||||
// TODO: remove magic numbers below
|
||||
char *argv[64];
|
||||
int argc;
|
||||
int i;
|
||||
int displayID = EN1 | EN2;
|
||||
|
||||
lptPort = port;
|
||||
|
||||
hd44780_functions->senddata = lcdstat_HD44780_senddata;
|
||||
|
||||
// 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;
|
||||
if ((ioperm(port + 2, 1, 255)) == -1) {
|
||||
fprintf(stderr, "HD44780_init: failed (%s)\n", strerror(errno));
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// powerup the lcd now
|
||||
if (extIF)
|
||||
{
|
||||
displayID |= EN3;
|
||||
port_out(lptPort + 2, 0 ^ OUTMASK);
|
||||
}
|
||||
|
||||
port_out(lptPort, displayID | 0x03);
|
||||
if (extIF) port_out(lptPort + 2,
|
||||
(EnMask[3] | EnMask[4] | EnMask[5] | EnMask[6]) ^ OUTMASK);
|
||||
hd44780_functions->uPause(1);
|
||||
port_out(lptPort, 0x03);
|
||||
if (extIF) port_out(lptPort + 2, 0 ^ OUTMASK);
|
||||
hd44780_functions->uPause(4100);
|
||||
|
||||
port_out(lptPort, displayID | 0x03);
|
||||
if (extIF) port_out(lptPort + 2,
|
||||
(EnMask[3] | EnMask[4] | EnMask[5] | EnMask[6]) ^ OUTMASK);
|
||||
hd44780_functions->uPause(1);
|
||||
port_out(lptPort, 0x03);
|
||||
if (extIF) port_out(lptPort + 2, 0 ^ OUTMASK);
|
||||
hd44780_functions->uPause(100);
|
||||
|
||||
port_out(lptPort, displayID | 0x03);
|
||||
if (extIF) port_out(lptPort + 2,
|
||||
(EnMask[3] | EnMask[4] | EnMask[5] | EnMask[6]) ^ OUTMASK);
|
||||
hd44780_functions->uPause(1);
|
||||
port_out(lptPort, 0x03);
|
||||
if (extIF) port_out(lptPort + 2, 0 ^ OUTMASK);
|
||||
hd44780_functions->uPause(40);
|
||||
|
||||
// now in 8-bit mode... set 4-bit mode
|
||||
port_out(lptPort,displayID | 0x02);
|
||||
if (extIF) port_out(lptPort + 2,
|
||||
(EnMask[3] | EnMask[4] | EnMask[5] | EnMask[6]) ^ OUTMASK);
|
||||
hd44780_functions->uPause(1);
|
||||
port_out(lptPort, 0x02);
|
||||
if (extIF) port_out(lptPort + 2, 0 ^ OUTMASK);
|
||||
hd44780_functions->uPause(40);
|
||||
|
||||
common_init(IF_4bit);
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
// lcdstat_HD44780_senddata
|
||||
void lcdstat_HD44780_senddata(unsigned char displayID,
|
||||
unsigned char iflags,
|
||||
unsigned char ch)
|
||||
{
|
||||
unsigned char dispID = 0, flags = 0;
|
||||
unsigned char h = (ch >> 4) & 0x0f; // high and low nibbles
|
||||
unsigned char l = ch & 0x0f;
|
||||
|
||||
if (iflags == RS_INSTR)
|
||||
flags = 0;
|
||||
else //if (iflags == RS_DATA)
|
||||
flags = RS;
|
||||
|
||||
if (displayID <= 3)
|
||||
{
|
||||
if (displayID == 0)
|
||||
dispID = EnMask[0] | EnMask[1] | EnMask[2];
|
||||
else
|
||||
dispID = EnMask[displayID - 1];
|
||||
|
||||
port_out(lptPort, flags | h);
|
||||
hd44780_functions->uPause(2);
|
||||
port_out(lptPort, dispID | flags | h);
|
||||
hd44780_functions->uPause(4);
|
||||
port_out(lptPort, flags | h);
|
||||
|
||||
port_out(lptPort, dispID | flags | l);
|
||||
hd44780_functions->uPause(4);
|
||||
port_out(lptPort, flags | l);
|
||||
}
|
||||
|
||||
if (extIF && (displayID == 0 || displayID >= 4))
|
||||
{
|
||||
if (displayID == 0)
|
||||
dispID = EnMask[3] | EnMask[4] | EnMask[5] | EnMask[6];
|
||||
else
|
||||
dispID = EnMask[(displayID - 1) % EnMaskSize];
|
||||
|
||||
port_out(lptPort, flags | h);
|
||||
hd44780_functions->uPause(2);
|
||||
port_out(lptPort + 2, dispID ^ OUTMASK);
|
||||
hd44780_functions->uPause(4);
|
||||
port_out(lptPort + 2, 0 ^ OUTMASK);
|
||||
|
||||
port_out(lptPort, flags | l);
|
||||
port_out(lptPort + 2, dispID ^ OUTMASK);
|
||||
hd44780_functions->uPause(4);
|
||||
port_out(lptPort + 2, 0 ^ OUTMASK);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,13 @@
|
||||
#ifndef HD_LCDSTAT_H
|
||||
#define HD_LCDSTAT_H
|
||||
|
||||
#include "lcd.h" /* for lcd_logical_driver */
|
||||
#include "hd44780-low.h" /* for HD44780_functions */
|
||||
|
||||
// initialise this particular driver
|
||||
int hd_init_4bit(HD44780_functions *hd44780_functions,
|
||||
lcd_logical_driver *driver,
|
||||
char *args,
|
||||
unsigned int port);
|
||||
|
||||
#endif
|
||||
@@ -0,0 +1,53 @@
|
||||
/*
|
||||
* Low-level driver types, headers and names.
|
||||
*
|
||||
* To add support for a new driver in this file:
|
||||
* 1. include your header file
|
||||
* 2. Add a new connectionType
|
||||
* 3. Add an entry in the connectionMapping structure
|
||||
*/
|
||||
|
||||
#ifndef HD44780_DRIVERS_H
|
||||
#define HD44780_DRIVERS_H
|
||||
|
||||
// hd44780 specific header files
|
||||
#include "hd44780-4bit.h"
|
||||
#include "hd44780-ext8bit.h"
|
||||
#include "hd44780-serialLpt.h"
|
||||
#include "hd44780-winamp.h"
|
||||
// add new connection type header files here
|
||||
|
||||
enum connectionType { HD_4bit, HD_8bit, HD_serialLpt, HD_winamp,
|
||||
// add new connection types here
|
||||
|
||||
HD_unknown };
|
||||
|
||||
static struct ConnectionMapping
|
||||
{
|
||||
enum connectionType type;
|
||||
char *connectionTypeStr;
|
||||
int (*init_fn)(HD44780_functions *hd44780_functions,
|
||||
lcd_logical_driver *driver,
|
||||
char *args,
|
||||
unsigned int port);
|
||||
const char *helpMsg;
|
||||
} connectionMapping[] = {
|
||||
// connectionType enumerator
|
||||
// string to identify connection on command line
|
||||
// your initialisation function
|
||||
// help string for your particular connection
|
||||
{ HD_4bit, "4bit", hd_init_4bit,
|
||||
"\t-e\t--extended\tEnable three or more displays\n" },
|
||||
{ HD_8bit, "8bit", hd_init_ext8bit,
|
||||
"\tnone\n" },
|
||||
{ HD_serialLpt, "serialLpt", hd_init_serialLpt,
|
||||
"\tnone\n" },
|
||||
{ HD_winamp, "winamp", hd_init_winamp,
|
||||
"\t-e\t--extended\tEnable three or more displays\n" },
|
||||
// add new connection types and their string specifier here
|
||||
|
||||
// default, end of structure element (do not delete)
|
||||
{ HD_unknown, "", NULL, "" }
|
||||
};
|
||||
|
||||
#endif
|
||||
@@ -0,0 +1,109 @@
|
||||
/*
|
||||
* 8-bit driver module for Hitachi HD44780 based LCD displays.
|
||||
* The LCD is operated in it's 8 bit-mode to be connected to a single
|
||||
* PC parallel port.
|
||||
*
|
||||
* Copyright (c) 1999, 1995 Benjamin Tse <blt@Comports.com>
|
||||
*
|
||||
* The connections are:
|
||||
* printer port LCD
|
||||
* D0 (2) D0 (7)
|
||||
* D1 (3) D1 (8)
|
||||
* D2 (4) D2 (9)
|
||||
* D3 (5) D3 (10)
|
||||
* D4 (6) D4 (11)
|
||||
* D5 (7) D5 (12)
|
||||
* D6 (8) D6 (13)
|
||||
* D7 (9) D7 (14)
|
||||
* nSEL (17) -
|
||||
* nSTRB (1) RS (4)
|
||||
* nLF (14) RW (5) (LCD2 - 6) (optional - pull all LCD RW low)
|
||||
* INIT (16) EN (6)
|
||||
*
|
||||
* Created modular driver Dec 1999, Benjamin Tse <blt@Comports.com>
|
||||
*
|
||||
* Based on the code in the lcdtime package which uses the LCD
|
||||
* controller in its 8-bit mode.
|
||||
*
|
||||
* This file is released under the GNU General Public License. Refer to the
|
||||
* COPYING file distributed with this package.
|
||||
*/
|
||||
|
||||
#include "hd44780-ext8bit.h"
|
||||
#include "port.h"
|
||||
|
||||
#include "lcd_sem.h"
|
||||
#include <sys/perm.h>
|
||||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
#include <errno.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
|
||||
|
||||
void lcdtime_HD44780_senddata(unsigned char displayID,
|
||||
unsigned char flags,
|
||||
unsigned char ch);
|
||||
|
||||
|
||||
#define nRS nSTRB
|
||||
#define nRW nLF
|
||||
#define EN1 INIT
|
||||
#define METER_OFF nSEL
|
||||
|
||||
#define SETUPLCD (METER_OFF | nRS)
|
||||
#define CTRL (nRW | METER_OFF | nRS)
|
||||
#define CHAR (nRW | METER_OFF)
|
||||
|
||||
static unsigned int lptPort;
|
||||
static int semid;
|
||||
|
||||
|
||||
// initialise the driver
|
||||
int hd_init_ext8bit(HD44780_functions *hd44780_functions,
|
||||
lcd_logical_driver *driver,
|
||||
char *args,
|
||||
unsigned int port)
|
||||
{
|
||||
lptPort = port;
|
||||
semid = sem_get();
|
||||
|
||||
hd44780_functions->senddata = lcdtime_HD44780_senddata;
|
||||
|
||||
if ((ioperm(port + 2, 1, 255)) == -1) {
|
||||
fprintf(stderr, "HD44780_init: failed (%s)\n", strerror(errno));
|
||||
return -1;
|
||||
}
|
||||
|
||||
common_init(IF_8bit);
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
// lcdtime_HD44780_senddata
|
||||
void lcdtime_HD44780_senddata(unsigned char displayID,
|
||||
unsigned char flags,
|
||||
unsigned char ch)
|
||||
{
|
||||
unsigned char dispID = 0, portControl;
|
||||
|
||||
if (displayID == 1)
|
||||
dispID |= EN1;
|
||||
else //if (displayID == 0)
|
||||
dispID |= EN1;
|
||||
|
||||
if (flags == RS_DATA)
|
||||
portControl = CHAR;
|
||||
else
|
||||
portControl = CTRL;
|
||||
|
||||
sem_wait(semid);
|
||||
port_out(lptPort + 2, SETUPLCD);
|
||||
port_out(lptPort, ch);
|
||||
port_out(lptPort + 2, dispID | portControl);
|
||||
hd44780_functions->uPause(1);
|
||||
port_out(lptPort + 2, portControl);
|
||||
sem_signal(semid);
|
||||
}
|
||||
@@ -0,0 +1,13 @@
|
||||
#ifndef HD_EXT8BIT_H
|
||||
#define HD_EXT8BIT_H
|
||||
|
||||
#include "lcd.h" /* for lcd_logical_driver */
|
||||
#include "hd44780-low.h" /* for HD44780_functions */
|
||||
|
||||
// initialise this particular driver
|
||||
int hd_init_ext8bit(HD44780_functions *hd44780_functions,
|
||||
lcd_logical_driver *driver,
|
||||
char *args,
|
||||
unsigned int port);
|
||||
|
||||
#endif
|
||||
@@ -0,0 +1,102 @@
|
||||
// This header contains low level code to export from hd44780.c to "lower" HW
|
||||
// implementation dependent files.
|
||||
|
||||
#ifndef HD_LOW_H
|
||||
#define HD_LOW_H
|
||||
|
||||
enum ifWidth { IF_4bit, IF_8bit };
|
||||
|
||||
void common_init(enum ifWidth ifwidth);
|
||||
|
||||
// Structures holding pointers to HD44780 specific functions
|
||||
typedef struct hwDependentFns
|
||||
{
|
||||
// microsec pauses
|
||||
void (*uPause)(int microSecondsTenths);
|
||||
|
||||
// senddata to the LCD
|
||||
// dispID - display to send data to (0 = all displays)
|
||||
// flags - data or instruction command (RS_DATA | RS_INSTR)
|
||||
// ch - character to display or instruction value
|
||||
void (*senddata)(unsigned char dispID, unsigned char flags, unsigned char ch);
|
||||
|
||||
// position the cursor
|
||||
// dispID - display to send data to (0 = all displays)
|
||||
// DDaddr - display data address (see sect 2.5.2 of the LCD module FAQ)
|
||||
void (*position)(int dispID, int DDaddr);
|
||||
|
||||
// toggle vertical autoscroll on all displays
|
||||
// on - non-zero turns autoscroll on, zero value turns it off
|
||||
void (*autoscroll)(int on);
|
||||
} HD44780_functions; /* for want of a better name :-) */
|
||||
|
||||
extern HD44780_functions *hd44780_functions;
|
||||
|
||||
// commands for senddata
|
||||
#define RS_DATA 0x00
|
||||
#define RS_INSTR 0x01
|
||||
|
||||
|
||||
#define CLEAR 0x01
|
||||
|
||||
#define HOMECURSOR 0x02
|
||||
|
||||
#define ENTRYMODE 0x04
|
||||
#define E_MOVERIGHT 0x02
|
||||
#define E_MOVELEFT 0x00
|
||||
#define EDGESCROLL 0x01
|
||||
#define NOSCROLL 0x00
|
||||
|
||||
#define ONOFFCTRL 0x08
|
||||
#define DISPON 0x04
|
||||
#define DISPOFF 0x00
|
||||
#define CURSORON 0x02
|
||||
#define CURSOROFF 0x00
|
||||
#define CURSORBLINK 0x01
|
||||
#define CURSORNOBLINK 0x00
|
||||
|
||||
#define CURSORSHIFT 0x10
|
||||
#define SCROLLDISP 0x08
|
||||
#define MOVECURSOR 0x00
|
||||
#define MOVERIGHT 0x04
|
||||
#define MOVELEFT 0x00
|
||||
|
||||
#define FUNCSET 0x20
|
||||
#define IF_8BIT 0x10
|
||||
#define IF_4BIT 0x00
|
||||
#define TWOLINE 0x08
|
||||
#define ONELINE 0x00
|
||||
#define LARGECHAR 0x04 /* 5x11 characters */
|
||||
#define SMALLCHAR 0x00 /* 5x8 characters */
|
||||
|
||||
#define SETCHAR 0x40
|
||||
|
||||
#define POSITION 0x80
|
||||
|
||||
|
||||
// Parallel port pin definitions
|
||||
// Output lines
|
||||
#define nSTRB 0x01 /* negative logic */
|
||||
#define STRB 0x01
|
||||
#define nLF 0x02
|
||||
#define LF 0x02
|
||||
#define INIT 0x04 /* the only positive logic output line */
|
||||
#define nSEL 0x08
|
||||
#define SEL 0x08
|
||||
|
||||
#define OUTMASK 0x0B
|
||||
|
||||
// Input lines
|
||||
#define nFAULT 0x08
|
||||
#define FAULT 0x08
|
||||
#define SELIN 0x10
|
||||
#define PAPEREND 0x20
|
||||
#define nACK 0x40
|
||||
#define ACK 0x40
|
||||
#define BUSY 0x80
|
||||
|
||||
#define INMASK 0x48
|
||||
|
||||
#endif
|
||||
|
||||
|
||||
@@ -0,0 +1,173 @@
|
||||
/*
|
||||
* 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>
|
||||
* modular driver 1999 Benjamin Tse <blt@Comports.com>
|
||||
*
|
||||
* Full connection details at http://members.xoom.com/andrewmuck/LCD.htm
|
||||
*
|
||||
* printer port 4094/LCD
|
||||
* D2 (4) EN (6 - LCD)
|
||||
* D3 (5) D (2 - 4094)
|
||||
* D4 (6) CLK (3 - 4094)
|
||||
* +Vcc OE, STR (15, 1 - 4094)
|
||||
* D7 (9) EN2 (6 - LCD2) (optional)
|
||||
*
|
||||
* 4094 LCD
|
||||
* Q1 (4) D4 (11)
|
||||
* Q2 (5) D5 (12)
|
||||
* Q3 (6) D6 (13)
|
||||
* Q4 (7) D7 (14)
|
||||
* Q6 (13) RS (4)
|
||||
* Gnd nRW (5)
|
||||
*
|
||||
* This file is released under the GNU General Public License. Refer to the
|
||||
* COPYING file distributed with this package.
|
||||
*/
|
||||
|
||||
#include "hd44780-serialLpt.h"
|
||||
#include "port.h"
|
||||
|
||||
// Hardware specific functions
|
||||
void lcdserLpt_HD44780_senddata(unsigned char displayID,
|
||||
unsigned char flags,
|
||||
unsigned char ch);
|
||||
|
||||
static char lcdserLpt_HD44780_getkey(void);
|
||||
void rawshift(unsigned char r);
|
||||
void shiftreg(unsigned char displayID, unsigned char r);
|
||||
|
||||
#define RS 16
|
||||
#define LCDDATA 8
|
||||
#define LCDCLOCK 16
|
||||
#define EN1 4
|
||||
#define EN2 32
|
||||
|
||||
|
||||
static unsigned int lp;
|
||||
static char lastkey=0;
|
||||
|
||||
|
||||
// Initialisation
|
||||
int hd_init_serialLpt(HD44780_functions *hd44780_functions,
|
||||
lcd_logical_driver *driver,
|
||||
char *args,
|
||||
unsigned int port)
|
||||
{
|
||||
int displayID = EN1 | EN2;
|
||||
|
||||
lp = port;
|
||||
|
||||
hd44780_functions->senddata = lcdserLpt_HD44780_senddata;
|
||||
|
||||
// TODO: enable keypad only if specified on command line
|
||||
driver->getkey = lcdserLpt_HD44780_getkey;
|
||||
|
||||
// setup the lcd in 4 bit mode
|
||||
shiftreg(displayID,3);
|
||||
hd44780_functions->uPause(4100);
|
||||
|
||||
shiftreg(displayID,3);
|
||||
hd44780_functions->uPause(100);
|
||||
|
||||
shiftreg(displayID,3);
|
||||
hd44780_functions->uPause(40);
|
||||
|
||||
shiftreg(displayID,2);
|
||||
hd44780_functions->uPause(40);
|
||||
|
||||
// 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;
|
||||
}
|
||||
|
||||
|
||||
void lcdserLpt_HD44780_senddata(unsigned char displayID,
|
||||
unsigned char flags,
|
||||
unsigned char ch)
|
||||
{
|
||||
unsigned char dispID = 0,
|
||||
portControl = 0,
|
||||
h = ch >> 4,
|
||||
l = ch & 15;
|
||||
|
||||
if (displayID == 1)
|
||||
dispID |= EN1;
|
||||
else if (displayID == 2)
|
||||
dispID |= EN2;
|
||||
else
|
||||
dispID |= EN1 | EN2;
|
||||
|
||||
if (flags == RS_DATA)
|
||||
portControl = RS;
|
||||
else
|
||||
portControl = 0;
|
||||
|
||||
shiftreg(displayID,flags | portControl | h);
|
||||
shiftreg(displayID,flags | portControl | l);
|
||||
|
||||
/* TODO: instead of delay read keys here */
|
||||
}
|
||||
|
||||
char lcdserLpt_HD44780_getkey()
|
||||
{
|
||||
// TODO: a keypad scan that does not use shift register
|
||||
// define a key table
|
||||
char keytr[]="ABCDEFGH";
|
||||
int n;
|
||||
|
||||
rawshift(0); //send all line on shift register low
|
||||
hd44780_functions->uPause(1);
|
||||
if ((port_in(lp+1)&32)==0) //test if line back is low - if not return(0)
|
||||
{ //else
|
||||
//start walking a single zero across the eight lines
|
||||
for(n=7;n>=0;n--)
|
||||
{
|
||||
rawshift(255 - (1<<n));
|
||||
hd44780_functions->uPause(1);
|
||||
|
||||
if ((port_in(lp+1)&32)==0) // check if line back is low if yes debounce
|
||||
{
|
||||
if (lastkey==keytr[n])
|
||||
return(0);
|
||||
// printf("key is %c %d\n",keytr[n],n);
|
||||
lastkey=keytr[n];
|
||||
return(keytr[n]); //return correct key code.
|
||||
}
|
||||
}
|
||||
} //else fall out and return(0) [too transient a keypress]
|
||||
lastkey=0;
|
||||
return(0);
|
||||
}
|
||||
|
||||
/* this function sends r out onto the shift register */
|
||||
void rawshift (unsigned char r)
|
||||
{
|
||||
int i;
|
||||
for (i=7;i>=0;i--) /* MSB first */
|
||||
{
|
||||
port_out(lp,((r>>i)&1)*LCDDATA); /*set up data */
|
||||
port_out(lp,(((r>>i)&1)*LCDDATA)|LCDCLOCK);/*rising edge of clock */
|
||||
}
|
||||
}
|
||||
|
||||
// displayID = value on parallel port to toggle the correct display
|
||||
void shiftreg (unsigned char displayID, unsigned char r)
|
||||
{
|
||||
rawshift(r);
|
||||
port_out(lp,displayID); //latch it, to correct display
|
||||
port_out(lp,0);
|
||||
}
|
||||
@@ -0,0 +1,13 @@
|
||||
#ifndef HD_SERIALLPT_H
|
||||
#define HD_SERIALLPT_H
|
||||
|
||||
#include "lcd.h" /* for lcd_logical_driver */
|
||||
#include "hd44780-low.h" /* for HD44780_functions */
|
||||
|
||||
// initialise this particular driver
|
||||
int hd_init_serialLpt(HD44780_functions *hd44780_functions,
|
||||
lcd_logical_driver *driver,
|
||||
char *args,
|
||||
unsigned int port);
|
||||
|
||||
#endif
|
||||
@@ -0,0 +1,109 @@
|
||||
/*
|
||||
* "Winamp" 8-bit driver module for Hitachi HD44780 based LCD displays.
|
||||
* The LCD is operated in it's 8 bit-mode to be connected to a single
|
||||
* PC parallel port.
|
||||
*
|
||||
* Copyright (c) 1999 Andrew McMeikan <andrewm@engineer.com>
|
||||
* modular driver 1999-2000 Benjamin Tse <blt@Comports.com>
|
||||
*
|
||||
* The connections are:
|
||||
* printer port LCD
|
||||
* D0 (2) D0 (7)
|
||||
* D1 (3) D1 (8)
|
||||
* D2 (4) D2 (9)
|
||||
* D3 (5) D3 (10)
|
||||
* D4 (6) D4 (11)
|
||||
* D5 (7) D5 (12)
|
||||
* D6 (8) D6 (13)
|
||||
* D7 (9) D7 (14)
|
||||
* nSTRB (1) EN (6)
|
||||
* nLF (14) nRW (5) (EN3 6 - LCD 3) (optional)
|
||||
* INIT (16) RS (4)
|
||||
* nSEL (17) EN2 (6 - LCD 2) (optional)
|
||||
*
|
||||
* Created modular driver Dec 1999, Benjamin Tse <blt@Comports.com>
|
||||
*
|
||||
* This file is released under the GNU General Public License. Refer to the
|
||||
* COPYING file distributed with this package.
|
||||
*/
|
||||
|
||||
#include "hd44780-winamp.h"
|
||||
#include "port.h"
|
||||
|
||||
#include "../../shared/str.h"
|
||||
#include <sys/perm.h>
|
||||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
#include <errno.h>
|
||||
|
||||
void lcdwinamp_HD44780_senddata(unsigned char displayID,
|
||||
unsigned char flags,
|
||||
unsigned char ch);
|
||||
|
||||
#define EN1 STRB
|
||||
#define EN2 SEL
|
||||
#define EN3 LF
|
||||
#define RS INIT
|
||||
|
||||
static unsigned char EnMask[] = { EN1, EN2, EN3 };
|
||||
static int EnMaskSize = sizeof(EnMask) / sizeof(unsigned char);
|
||||
|
||||
static unsigned int lptPort;
|
||||
static int extIF = 0; // non-zero if extended interface
|
||||
|
||||
|
||||
// initialise the driver
|
||||
int hd_init_winamp(HD44780_functions *hd44780_functions,
|
||||
lcd_logical_driver *driver,
|
||||
char *args,
|
||||
unsigned int port)
|
||||
{
|
||||
// TODO: remove magic numbers below
|
||||
char *argv[64];
|
||||
int argc;
|
||||
int i;
|
||||
|
||||
hd44780_functions->senddata = lcdwinamp_HD44780_senddata;
|
||||
lptPort = port;
|
||||
|
||||
// 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;
|
||||
|
||||
if ((ioperm(lptPort + 2, 1, 255)) == -1) {
|
||||
fprintf(stderr, "HD44780_init: failed (%s)\n", strerror(errno));
|
||||
return -1;
|
||||
}
|
||||
|
||||
common_init(IF_8bit);
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
// lcdwinamp_HD44780_senddata
|
||||
void lcdwinamp_HD44780_senddata(unsigned char displayID,
|
||||
unsigned char flags,
|
||||
unsigned char ch)
|
||||
{
|
||||
unsigned char dispID = 0, portControl;
|
||||
|
||||
if (flags == RS_DATA)
|
||||
portControl = RS;
|
||||
else
|
||||
portControl = 0;
|
||||
|
||||
if (displayID == 0)
|
||||
dispID = EnMask[0] | EnMask [1] | ((extIF) ? EnMask[2] : 0);
|
||||
else
|
||||
dispID = EnMask[displayID - 1];
|
||||
|
||||
port_out(lptPort, ch);
|
||||
port_out(lptPort + 2, (dispID | portControl) ^ OUTMASK);
|
||||
hd44780_functions->uPause(1);
|
||||
port_out(lptPort + 2, portControl ^ OUTMASK);
|
||||
}
|
||||
|
||||
@@ -0,0 +1,14 @@
|
||||
#ifndef HD_WINAMP_H
|
||||
#define HD_WINAMP_H
|
||||
|
||||
#include "lcd.h" /* for lcd_logical_driver */
|
||||
#include "hd44780-low.h" /* for HD44780_functions */
|
||||
|
||||
// initialise this particular driver, args is probably not used but keep
|
||||
// for consistency
|
||||
int hd_init_winamp(HD44780_functions *hd44780_functions,
|
||||
lcd_logical_driver *driver,
|
||||
char *args,
|
||||
unsigned int port);
|
||||
|
||||
#endif
|
||||
@@ -0,0 +1,170 @@
|
||||
/*
|
||||
* lcd_sem.c -- semaphore code written for lcdtime and meter to mediate
|
||||
* access to the parallel port.
|
||||
*
|
||||
* Written by Benjamin Tse (blt@mundil.cs.mu.edu.au); August,October 1995
|
||||
*
|
||||
* Functions in this file:
|
||||
* getkey returns the key for the semaphore
|
||||
* sem_get create the semaphore (and initialise) if one doesn't exist
|
||||
* otherwise return its key
|
||||
* sem_wait wait on the semaphore
|
||||
* sem_signal signal on the semaphore
|
||||
* sem_remove remove the semaphore
|
||||
*
|
||||
* Legal stuff: At no stage was this program written, assembled or compiled on
|
||||
* any computer at the University of Melbourne, Australia. This program is
|
||||
* Copyright (C) 1995 Benjamin Tse (blt@mundil.cs.mu.oz.au) and covered by
|
||||
* GNU's GPL. In particular, this program is free software and comes WITHOUT
|
||||
* ANY WARRANTY.
|
||||
*
|
||||
* $Id$
|
||||
*/
|
||||
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <sys/types.h> /* for semaphore functions */
|
||||
#include <sys/ipc.h>
|
||||
#include <sys/sem.h>
|
||||
#include <errno.h>
|
||||
|
||||
#include "lcd_sem.h"
|
||||
|
||||
#define SEMAPHORE "portctrl"
|
||||
#define SEMKEY 0x706f7274 /* semaphore key */
|
||||
#define SEMCOUNT 1 /* number of semaphores to create */
|
||||
#define WMODE 0660 /* access permissions */
|
||||
|
||||
#define SEM_SIGNAL 0,1,SEM_UNDO
|
||||
#define SEM_WAIT 0,-1,SEM_UNDO
|
||||
|
||||
/* functions local to this file */
|
||||
static key_t getkey(register char *p);
|
||||
|
||||
/* global variables */
|
||||
static struct sembuf semaphore_wait = {SEM_WAIT};
|
||||
static struct sembuf semaphore_signal = {SEM_SIGNAL};
|
||||
|
||||
static char rcsId[] = "$Id$";
|
||||
|
||||
/*
|
||||
* getkey returns the key for the semaphore
|
||||
*/
|
||||
|
||||
static key_t
|
||||
getkey(register char *p)
|
||||
{
|
||||
return((key_t) SEMKEY);
|
||||
}
|
||||
|
||||
/*
|
||||
* create the semaphore if one doesn't exist and initialise it to 1, else
|
||||
* return the semaphore set id
|
||||
*/
|
||||
|
||||
int
|
||||
sem_get(void)
|
||||
{
|
||||
int semid;
|
||||
union semun semval;
|
||||
|
||||
if ((semid = semget(getkey(SEMAPHORE), SEMCOUNT,
|
||||
IPC_CREAT | IPC_EXCL | WMODE)) < 0)
|
||||
{
|
||||
switch (errno)
|
||||
{
|
||||
case EEXIST:
|
||||
/* semaphore set exists, get id and return it */
|
||||
if ((semid = semget(getkey(SEMAPHORE), SEMCOUNT,
|
||||
IPC_EXCL | WMODE)) < 0)
|
||||
{
|
||||
perror("semget");
|
||||
exit(1);
|
||||
}
|
||||
return semid;
|
||||
break;
|
||||
case EACCES:
|
||||
/* don't have permissions for semaphore, need to change key */
|
||||
perror("semget, can't get permissions for semaphore");
|
||||
exit(1);
|
||||
break;
|
||||
default:
|
||||
perror("semget");
|
||||
exit(1);
|
||||
break;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
/* initialise semaphore to 1 */
|
||||
semval.val = 1;
|
||||
|
||||
if (semctl(semid, 0, SETVAL, semval) < 0)
|
||||
{
|
||||
perror("setval, can't initialise semaphore");
|
||||
exit(1);
|
||||
}
|
||||
}
|
||||
|
||||
return semid;
|
||||
}
|
||||
|
||||
/*
|
||||
* wait on the semaphore
|
||||
*/
|
||||
|
||||
int
|
||||
sem_wait(int sid)
|
||||
{
|
||||
if (semop(sid, &semaphore_wait, 1) < -1)
|
||||
{
|
||||
perror(SEMAPHORE);
|
||||
exit(1);
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*
|
||||
* signal on the semaphore
|
||||
*/
|
||||
|
||||
int
|
||||
sem_signal(int sid)
|
||||
{
|
||||
if (semop(sid, &semaphore_signal, 1) < -1)
|
||||
{
|
||||
perror(SEMAPHORE);
|
||||
exit(1);
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*
|
||||
* remove the semaphore
|
||||
*/
|
||||
|
||||
int
|
||||
sem_remove(int sid)
|
||||
{
|
||||
int i;
|
||||
union semun dummy;
|
||||
|
||||
if ((i = semctl(sid, 0, IPC_RMID, dummy)) < 0)
|
||||
{
|
||||
switch(i)
|
||||
{
|
||||
case EIDRM:
|
||||
/* semaphore removed */
|
||||
return 0;
|
||||
break;
|
||||
default:
|
||||
perror("semctl, removing semaphore");
|
||||
exit(1);
|
||||
}
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
@@ -0,0 +1,13 @@
|
||||
/*
|
||||
* header file for lcd semaphore operations
|
||||
*/
|
||||
|
||||
#ifndef LCD_SEM_H
|
||||
#define LCD_SEM_H
|
||||
|
||||
int sem_get(void);
|
||||
int sem_wait(int sid);
|
||||
int sem_signal(int sid);
|
||||
int sem_remove(int sid);
|
||||
|
||||
#endif
|
||||
Reference in New Issue
Block a user