diff --git a/LCDd.conf b/LCDd.conf index 7cbfbce..81f12d7 100644 --- a/LCDd.conf +++ b/LCDd.conf @@ -290,9 +290,10 @@ Size=20x4 # 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. +#ExtendedMode=yes +# If you have a KS0073 or an other 'almost HD44780-compatible', set this +# flag to get into extended mode (4-line linear). +# This flag is NOT the old obsolete Extended option. #DelayMult=2 # If your display is slow and cannot keep up with the flow of data from diff --git a/server/drivers/hd44780-4bit.c b/server/drivers/hd44780-4bit.c index 3679989..544cc48 100644 --- a/server/drivers/hd44780-4bit.c +++ b/server/drivers/hd44780-4bit.c @@ -99,7 +99,7 @@ hd_init_4bit (Driver *drvthis) PrivateData *p = (PrivateData*) drvthis->private_data; HD44780_functions *hd44780_functions = p->hd44780_functions; - int enableLines = EN1 | EN2; + int enableLines = EN1 | EN2 | EN3; // Reserve the port registers port_access_multiple(p->port,3); @@ -109,47 +109,38 @@ hd_init_4bit (Driver *drvthis) hd44780_functions->readkeypad = lcdstat_HD44780_readkeypad; // powerup the lcd now - if (p->extIF) { - enableLines |= EN3; - port_out (p->port + 2, 0 ^ OUTMASK); - } + port_out (p->port + 2, 0 ^ OUTMASK); port_out (p->port, 0x03); if( p->delayBus ) hd44780_functions->uPause (p, 1); + /* We'll now send 0x03 a coulpe of times, + * which is in fact (FUNCSET | IF_8BIT) >> 4 */ port_out (p->port, enableLines | 0x03); - if (p->extIF) - port_out (p->port + 2, ALLEXT ^ OUTMASK); + port_out (p->port + 2, ALLEXT ^ OUTMASK); if( p->delayBus ) hd44780_functions->uPause (p, 1); port_out (p->port, 0x03); - if (p->extIF) - port_out (p->port + 2, 0 ^ OUTMASK); + port_out (p->port + 2, 0 ^ OUTMASK); hd44780_functions->uPause (p, 15000); port_out (p->port, enableLines | 0x03); - if (p->extIF) - port_out (p->port + 2, ALLEXT ^ OUTMASK); + port_out (p->port + 2, ALLEXT ^ OUTMASK); if( p->delayBus ) hd44780_functions->uPause (p, 1); port_out (p->port, 0x03); - if (p->extIF) - port_out (p->port + 2, 0 ^ OUTMASK); + port_out (p->port + 2, 0 ^ OUTMASK); hd44780_functions->uPause (p, 5000); port_out (p->port, enableLines | 0x03); - if (p->extIF) - port_out (p->port + 2, ALLEXT ^ OUTMASK); + port_out (p->port + 2, ALLEXT ^ OUTMASK); if( p->delayBus ) hd44780_functions->uPause (p, 1); port_out (p->port, 0x03); - if (p->extIF) - port_out (p->port + 2, 0 ^ OUTMASK); + port_out (p->port + 2, 0 ^ OUTMASK); hd44780_functions->uPause (p, 100); port_out (p->port, enableLines | 0x03); - if (p->extIF) - port_out (p->port + 2, ALLEXT ^ OUTMASK); + port_out (p->port + 2, ALLEXT ^ OUTMASK); if( p->delayBus ) hd44780_functions->uPause (p, 1); port_out (p->port, 0x03); - if (p->extIF) - port_out (p->port + 2, 0 ^ OUTMASK); + port_out (p->port + 2, 0 ^ OUTMASK); hd44780_functions->uPause (p, 100); // now in 8-bit mode... set 4-bit mode @@ -157,19 +148,17 @@ hd_init_4bit (Driver *drvthis) if( p->delayBus ) hd44780_functions->uPause (p, 1); port_out (p->port, enableLines | 0x02); - if (p->extIF) - port_out (p->port + 2, ALLEXT ^ OUTMASK); + port_out (p->port + 2, ALLEXT ^ OUTMASK); if( p->delayBus ) hd44780_functions->uPause (p, 1); port_out (p->port, 0x02); - if (p->extIF) - port_out (p->port + 2, 0 ^ OUTMASK); + port_out (p->port + 2, 0 ^ OUTMASK); hd44780_functions->uPause (p, 100); // Set up two-line, small character (5x8) mode - hd44780_functions->senddata (p, 0, RS_INSTR, FUNCSET | TWOLINE | SMALLCHAR ); + hd44780_functions->senddata (p, 0, RS_INSTR, FUNCSET | IF_4BIT | TWOLINE | SMALLCHAR ); hd44780_functions->uPause (p, 40); - common_init (p); + common_init (p, IF_4BIT); if (p->have_keypad) { // Remember which input lines are stuck @@ -196,10 +185,7 @@ lcdstat_HD44780_senddata (PrivateData *p, unsigned char displayID, unsigned char if (displayID <= 3) { if (displayID == 0) { - enableLines = EnMask[0] | EnMask[1]; - if (p->extIF) { - enableLines |= EnMask[2]; - } + enableLines = EnMask[0] | EnMask[1] | EnMask[2]; } else { enableLines = EnMask[displayID - 1]; } @@ -217,11 +203,12 @@ lcdstat_HD44780_senddata (PrivateData *p, unsigned char displayID, unsigned char port_out (p->port, portControl | l); } - if (p->extIF && (displayID == 0 || displayID >= 4)) { - if (displayID == 0) + if (p->numDisplays > 3) { + if (displayID == 0) { enableLines = ALLEXT; - else + } else { enableLines = EnMask[(displayID - 1)]; + } port_out (p->port, portControl | h); if( p->delayBus ) p->hd44780_functions->uPause (p, 1); @@ -251,7 +238,8 @@ unsigned char lcdstat_HD44780_readkeypad (PrivateData *p, unsigned int YData) // 10 bits output or 6 bits if >=3 displays // Convert the positive logic to the negative logic on the LPT port port_out (p->port, ~YData & 0x003F ); - if (!p->extIF) { + if (p->numDisplays<=3) { + // Can't combine >3 displays with >6 keypad output lines port_out (p->port + 2, ( ((~YData & 0x03C0) << 6 )) ^ OUTMASK); } if( p->delayBus ) p->hd44780_functions->uPause (p, 1); diff --git a/server/drivers/hd44780-ext8bit.c b/server/drivers/hd44780-ext8bit.c index 084fa77..2b98bcc 100644 --- a/server/drivers/hd44780-ext8bit.c +++ b/server/drivers/hd44780-ext8bit.c @@ -104,7 +104,7 @@ hd_init_ext8bit (Driver *drvthis) hd44780_functions->senddata (p, 0, RS_INSTR, FUNCSET | IF_8BIT | TWOLINE | SMALLCHAR); hd44780_functions->uPause (p, 40); - common_init (p); + common_init (p, IF_8BIT); if (p->have_keypad) { // Remember which input lines are stuck @@ -156,10 +156,11 @@ unsigned char lcdtime_HD44780_readkeypad (PrivateData *p, unsigned int YData) sem_wait (semid); - // 10 bits output or 8 bits if >=3 displays + // 10 bits output or 8 bits if >=2 displays // Convert the positive logic to the negative logic on the LPT port port_out (p->port, ~YData & 0x00FF ); - if (!p->extIF) { + if (p->numDisplays<=2) { + // Can't combine >3 displays with >8 keypad output lines port_out (p->port + 2, ( ((~YData & 0x0100) >> 8) | ((~YData & 0x0200) >> 6)) ^ OUTMASK); } if( p->delayBus ) p->hd44780_functions->uPause (p, 1); diff --git a/server/drivers/hd44780-low.h b/server/drivers/hd44780-low.h index 0411023..28801ec 100644 --- a/server/drivers/hd44780-low.h +++ b/server/drivers/hd44780-low.h @@ -78,10 +78,10 @@ typedef struct driver_private_data { int *dispSizes; // Keypad, backlight extended interface and delay options - char have_keypad; // off by default - char have_backlight; // off by default - char extIF; // off by default - char have_output; // have extra output port (off by default) + char have_keypad; // off by default + char have_backlight; // off by default + char have_output; // have extra output port (off by default) + char ext_mode; // use of extended mode required for some weird controllers int delayMult; // Delay multiplier for slow displays char delayBus; // Delay if the computer can send data too fast over // its bus to LPT port @@ -141,7 +141,7 @@ typedef struct hwDependentFns { } HD44780_functions; /* for want of a better name :-) */ -void common_init (PrivateData *p); +void common_init (PrivateData *p, unsigned char if_bit); // commands for senddata @@ -158,7 +158,7 @@ void common_init (PrivateData *p); #define EDGESCROLL 0x01 #define NOSCROLL 0x00 -#define ONOFFCTRL 0x08 +#define ONOFFCTRL 0x08 /* Only reachable with EXTREG clear */ #define DISPON 0x04 #define DISPOFF 0x00 #define CURSORON 0x02 @@ -166,22 +166,36 @@ void common_init (PrivateData *p); #define CURSORBLINK 0x01 #define CURSORNOBLINK 0x00 -#define CURSORSHIFT 0x10 +#define EXTMODESET 0x08 /* Only reachable with EXTREG set */ +#define FONT6WIDE 0x04 +#define INVCURSOR 0x02 +#define FOURLINE 0x01 + +#define CURSORSHIFT 0x10 /* Only reachable with EXTREG clear */ #define SCROLLDISP 0x08 #define MOVECURSOR 0x00 #define MOVERIGHT 0x04 #define MOVELEFT 0x00 +#define HSCROLLEN 0x10 /* Only reachable with EXTREG set */ + #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 LARGECHAR 0x04 /* 5x11 characters */ +#define SMALLCHAR 0x00 /* 5x8 characters */ +#define EXTREG 0x04 /* Select ext. registers (Yes, the same bits)*/ +#define SEGBLINK 0x02 /* Only reachable with EXTREG set */ +#define POWERDOWN 0x01 /* Only reachable with EXTREG set */ -#define SETCHAR 0x40 +#define SETCHAR 0x40 /* Only reachable with EXTREG clear */ -#define POSITION 0x80 +#define SETSEG 0x40 /* Only reachable with EXTREG set */ + +#define POSITION 0x80 /* Only reachable with EXTREG clear */ + +#define HSCROLLAMOUNT 0x80 /* Only reachable with EXTREG set */ #endif diff --git a/server/drivers/hd44780-picanlcd.c b/server/drivers/hd44780-picanlcd.c index edcd9f3..19b405f 100644 --- a/server/drivers/hd44780-picanlcd.c +++ b/server/drivers/hd44780-picanlcd.c @@ -105,7 +105,7 @@ hd_init_picanlcd (Driver *drvthis) p->hd44780_functions->backlight = picanlcd_HD44780_backlight; p->hd44780_functions->scankeypad = picanlcd_HD44780_scankeypad; - common_init (p); + common_init (p, IF_8BIT); return 0; } diff --git a/server/drivers/hd44780-serialLpt.c b/server/drivers/hd44780-serialLpt.c index d791aa7..5e988cd 100644 --- a/server/drivers/hd44780-serialLpt.c +++ b/server/drivers/hd44780-serialLpt.c @@ -106,7 +106,7 @@ hd_init_serialLpt (Driver *drvthis) hd44780_functions->senddata (p, 0, RS_INSTR, FUNCSET | IF_4BIT | TWOLINE | SMALLCHAR); hd44780_functions->uPause (p, 40); - common_init (p); + common_init (p, IF_8BIT); return 0; } diff --git a/server/drivers/hd44780-winamp.c b/server/drivers/hd44780-winamp.c index 1235107..481f94d 100644 --- a/server/drivers/hd44780-winamp.c +++ b/server/drivers/hd44780-winamp.c @@ -109,10 +109,8 @@ hd_init_winamp (Driver *drvthis) hd44780_functions->uPause (p, 4100); hd44780_functions->senddata (p, 0, RS_INSTR, FUNCSET | IF_8BIT); hd44780_functions->uPause (p, 100); - hd44780_functions->senddata (p, 0, RS_INSTR, FUNCSET | IF_8BIT | TWOLINE | SMALLCHAR); - hd44780_functions->uPause (p, 40); - common_init (p); + common_init (p, IF_8BIT); if (p->have_keypad) { // Remember which input lines are stuck @@ -139,7 +137,7 @@ lcdwinamp_HD44780_senddata (PrivateData *p, unsigned char displayID, unsigned ch portControl |= p->backlight_bit; if (displayID == 0) - enableLines = EnMask[0] | EnMask[1] | ((p->extIF) ? EnMask[2] : 0); + enableLines = EnMask[0] | EnMask[1] | EnMask[2]; else enableLines = EnMask[displayID - 1]; diff --git a/server/drivers/hd44780.c b/server/drivers/hd44780.c index 59b08d6..2e06d3f 100644 --- a/server/drivers/hd44780.c +++ b/server/drivers/hd44780.c @@ -148,7 +148,7 @@ HD44780_init (Driver * drvthis, char *args) //// READ THE CONFIG FILE p->port = drvthis->config_get_int( drvthis->name, "port", 0, LPTPORT ); - p->extIF = drvthis->config_get_bool( drvthis->name, "extended", 0, 0 ); + p->ext_mode = drvthis->config_get_bool( drvthis->name, "extendedmode", 0, 0 ); p->have_keypad = drvthis->config_get_bool( drvthis->name, "keypad", 0, 0 ); p->have_backlight = drvthis->config_get_bool( drvthis->name, "backlight", 0, 0 ); p->have_output = drvthis->config_get_bool( drvthis->name, "outputport", 0, 0 ); @@ -321,8 +321,17 @@ HD44780_init (Driver * drvthis, char *args) // the connectiontype should do this. // void -common_init (PrivateData *p) +common_init (PrivateData *p, unsigned char if_bit) { + if (p->ext_mode) { + // Set up extended mode */ + p->hd44780_functions->senddata (p, 0, RS_INSTR, FUNCSET | if_bit | TWOLINE | SMALLCHAR | EXTREG ); + p->hd44780_functions->uPause (p, 40); + p->hd44780_functions->senddata (p, 0, RS_INSTR, EXTMODESET | FOURLINE ); + p->hd44780_functions->uPause (p, 40); + } + p->hd44780_functions->senddata (p, 0, RS_INSTR, FUNCSET | if_bit | TWOLINE | SMALLCHAR ); + p->hd44780_functions->uPause (p, 40); p->hd44780_functions->senddata (p, 0, RS_INSTR, ONOFFCTRL | DISPON | CURSOROFF | CURSORNOBLINK); p->hd44780_functions->uPause (p, 40); p->hd44780_functions->senddata (p, 0, RS_INSTR, CLEAR); @@ -386,18 +395,22 @@ HD44780_position (Driver *drvthis, int x, int y) int relY = y - p->dispVOffset[dispID - 1]; int DDaddr; - // 16x1 is a special case - if (p->dispSizes[dispID - 1] == 1 && p->width == 16) { - if (x >= 8) { - x -= 8; - relY = 1; + if (p->ext_mode) { + // Linear addressing, each line starts 0x20 higher. + DDaddr = x + relY * 0x20; + } else { + // 16x1 is a special case + if (p->dispSizes[dispID - 1] == 1 && p->width == 16) { + if (x >= 8) { + x -= 8; + relY = 1; + } } + + DDaddr = x + (relY % 2) * 0x40; + if ((relY % 4) >= 2) + DDaddr += p->width; } - - DDaddr = x + (relY % 2) * 0x40; - if ((relY % 4) >= 2) - DDaddr += p->width; - p->hd44780_functions->senddata (p, dispID, RS_INSTR, POSITION | DDaddr); p->hd44780_functions->uPause (p, 40); // Minimum exec time for all commands }