diff --git a/server/drivers/hd44780-4bit.c b/server/drivers/hd44780-4bit.c new file mode 100644 index 0000000..1a8d6ce --- /dev/null +++ b/server/drivers/hd44780-4bit.c @@ -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 + * 1999 Andrew McMeikan + * 1998 Richard Rognlie + * 1997 Matthias Prinke + * + * 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 + * + * Based on Matthias Prinke's 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 +#include +#include +#include + +// 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); + } +} diff --git a/server/drivers/hd44780-4bit.h b/server/drivers/hd44780-4bit.h new file mode 100644 index 0000000..458a927 --- /dev/null +++ b/server/drivers/hd44780-4bit.h @@ -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 diff --git a/server/drivers/hd44780-drivers.h b/server/drivers/hd44780-drivers.h new file mode 100644 index 0000000..90a7c68 --- /dev/null +++ b/server/drivers/hd44780-drivers.h @@ -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 diff --git a/server/drivers/hd44780-ext8bit.c b/server/drivers/hd44780-ext8bit.c new file mode 100644 index 0000000..3f04411 --- /dev/null +++ b/server/drivers/hd44780-ext8bit.c @@ -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 + * + * 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 + * + * 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 +#include +#include +#include + +// 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); +} diff --git a/server/drivers/hd44780-ext8bit.h b/server/drivers/hd44780-ext8bit.h new file mode 100644 index 0000000..674f233 --- /dev/null +++ b/server/drivers/hd44780-ext8bit.h @@ -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 diff --git a/server/drivers/hd44780-low.h b/server/drivers/hd44780-low.h new file mode 100644 index 0000000..0b9903c --- /dev/null +++ b/server/drivers/hd44780-low.h @@ -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 + + diff --git a/server/drivers/hd44780-serialLpt.c b/server/drivers/hd44780-serialLpt.c new file mode 100644 index 0000000..dd2efa5 --- /dev/null +++ b/server/drivers/hd44780-serialLpt.c @@ -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 + * modular driver 1999 Benjamin Tse + * + * 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<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); +} diff --git a/server/drivers/hd44780-serialLpt.h b/server/drivers/hd44780-serialLpt.h new file mode 100644 index 0000000..90a6233 --- /dev/null +++ b/server/drivers/hd44780-serialLpt.h @@ -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 diff --git a/server/drivers/hd44780-winamp.c b/server/drivers/hd44780-winamp.c new file mode 100644 index 0000000..0bfb353 --- /dev/null +++ b/server/drivers/hd44780-winamp.c @@ -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 + * modular driver 1999-2000 Benjamin Tse + * + * 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 + * + * 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 +#include +#include +#include + +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); +} + diff --git a/server/drivers/hd44780-winamp.h b/server/drivers/hd44780-winamp.h new file mode 100644 index 0000000..647fc46 --- /dev/null +++ b/server/drivers/hd44780-winamp.h @@ -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 diff --git a/server/drivers/lcd_sem.c b/server/drivers/lcd_sem.c new file mode 100644 index 0000000..c12699a --- /dev/null +++ b/server/drivers/lcd_sem.c @@ -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 +#include +#include /* for semaphore functions */ +#include +#include +#include + +#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; +} + diff --git a/server/drivers/lcd_sem.h b/server/drivers/lcd_sem.h new file mode 100644 index 0000000..46b7423 --- /dev/null +++ b/server/drivers/lcd_sem.h @@ -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