From 46174150ce691d05c000a9807c3551ac71a37823 Mon Sep 17 00:00:00 2001 From: robijn Date: Thu, 1 Nov 2001 15:38:49 +0000 Subject: [PATCH] Added HD44780 delay options. --- LCDd.conf | 10 ++++++++ server/drivers/hd44780-4bit.c | 26 +++++++++++++-------- server/drivers/hd44780-ext8bit.c | 4 +++- server/drivers/hd44780-winamp.c | 8 +++++++ server/drivers/hd44780.c | 39 ++++++++++++++++++++------------ server/drivers/hd44780.h | 2 ++ 6 files changed, 63 insertions(+), 26 deletions(-) diff --git a/LCDd.conf b/LCDd.conf index 6002036..63091fc 100644 --- a/LCDd.conf +++ b/LCDd.conf @@ -119,6 +119,16 @@ Size=20x4 # If you want to use more than 3 HD44780 controllers on the LPT, you need to # specify this. See documentation. +#DelayMult=2 +# If your display is slow and cannot keep up with the flow of data from +# LCDd, garbage can appear on the LCDd. Set this delay factor to 2 or 4 +# to increase the delays. Default: 1. + +DelayBus=true +# You can reduce the inserted dalays by setting this to false. +# On fast PCs it is possible your LCD does not respond correctly. +# Default: true. + [LB216] # LB216 driver diff --git a/server/drivers/hd44780-4bit.c b/server/drivers/hd44780-4bit.c index 2a3f578..e964e83 100644 --- a/server/drivers/hd44780-4bit.c +++ b/server/drivers/hd44780-4bit.c @@ -118,10 +118,12 @@ hd_init_4bit (HD44780_functions * hd44780_functions, lcd_logical_driver * driver port_out (lptPort + 2, 0 ^ OUTMASK); } + port_out (lptPort, 0x03); + if( delayBus ) hd44780_functions->uPause (1); port_out (lptPort, enableLines | 0x03); if (extIF) port_out (lptPort + 2, ALLEXT ^ OUTMASK); - hd44780_functions->uPause (1); + if( delayBus ) hd44780_functions->uPause (1); port_out (lptPort, 0x03); if (extIF) port_out (lptPort + 2, 0 ^ OUTMASK); @@ -130,7 +132,7 @@ hd_init_4bit (HD44780_functions * hd44780_functions, lcd_logical_driver * driver port_out (lptPort, enableLines | 0x03); if (extIF) port_out (lptPort + 2, ALLEXT ^ OUTMASK); - hd44780_functions->uPause (1); + if( delayBus ) hd44780_functions->uPause (1); port_out (lptPort, 0x03); if (extIF) port_out (lptPort + 2, 0 ^ OUTMASK); @@ -139,7 +141,7 @@ hd_init_4bit (HD44780_functions * hd44780_functions, lcd_logical_driver * driver port_out (lptPort, enableLines | 0x03); if (extIF) port_out (lptPort + 2, ALLEXT ^ OUTMASK); - hd44780_functions->uPause (1); + if( delayBus ) hd44780_functions->uPause (1); port_out (lptPort, 0x03); if (extIF) port_out (lptPort + 2, 0 ^ OUTMASK); @@ -149,7 +151,7 @@ hd_init_4bit (HD44780_functions * hd44780_functions, lcd_logical_driver * driver port_out (lptPort, enableLines | 0x02); if (extIF) port_out (lptPort + 2, ALLEXT ^ OUTMASK); - hd44780_functions->uPause (1); + if( delayBus ) hd44780_functions->uPause (1); port_out (lptPort, 0x02); if (extIF) port_out (lptPort + 2, 0 ^ OUTMASK); @@ -187,13 +189,15 @@ lcdstat_HD44780_senddata (unsigned char displayID, unsigned char flags, unsigned enableLines = EnMask[displayID - 1]; port_out (lptPort, portControl | h); - hd44780_functions->uPause (2); + if( delayBus ) hd44780_functions->uPause (1); port_out (lptPort, enableLines | portControl | h); - hd44780_functions->uPause (4); + if( delayBus ) hd44780_functions->uPause (1); port_out (lptPort, portControl | h); + port_out (lptPort, portControl | l); + if( delayBus ) hd44780_functions->uPause (1); port_out (lptPort, enableLines | portControl | l); - hd44780_functions->uPause (4); + if( delayBus ) hd44780_functions->uPause (1); port_out (lptPort, portControl | l); } @@ -204,14 +208,15 @@ lcdstat_HD44780_senddata (unsigned char displayID, unsigned char flags, unsigned enableLines = EnMask[(displayID - 1)]; port_out (lptPort, portControl | h); - hd44780_functions->uPause (2); + if( delayBus ) hd44780_functions->uPause (1); port_out (lptPort + 2, enableLines ^ OUTMASK); - hd44780_functions->uPause (4); + if( delayBus ) hd44780_functions->uPause (1); port_out (lptPort + 2, 0 ^ OUTMASK); port_out (lptPort, portControl | l); + if( delayBus ) hd44780_functions->uPause (1); port_out (lptPort + 2, enableLines ^ OUTMASK); - hd44780_functions->uPause (4); + if( delayBus ) hd44780_functions->uPause (1); port_out (lptPort + 2, 0 ^ OUTMASK); } } @@ -233,6 +238,7 @@ unsigned char lcdstat_HD44780_readkeypad (unsigned int YData) if (!extIF) { port_out (lptPort + 2, ( ((~YData & 0x03C0) << 6 )) ^ OUTMASK); } + if( delayBus ) hd44780_functions->uPause (1); // Read inputs readval = ~ port_in (lptPort + 1) ^ INMASK; diff --git a/server/drivers/hd44780-ext8bit.c b/server/drivers/hd44780-ext8bit.c index f2a8102..1967945 100644 --- a/server/drivers/hd44780-ext8bit.c +++ b/server/drivers/hd44780-ext8bit.c @@ -133,8 +133,9 @@ lcdtime_HD44780_senddata (unsigned char displayID, unsigned char flags, unsigned sem_wait (semid); port_out (lptPort + 2, portControl ^ OUTMASK); port_out (lptPort, ch); + if( delayBus ) hd44780_functions->uPause (1); port_out (lptPort + 2, (enableLines|portControl) ^ OUTMASK); - hd44780_functions->uPause (1); + if( delayBus ) hd44780_functions->uPause (1); port_out (lptPort + 2, portControl ^ OUTMASK); sem_signal (semid); } @@ -160,6 +161,7 @@ unsigned char lcdtime_HD44780_readkeypad (unsigned int YData) if (!extIF) { port_out (lptPort + 2, ( ((~YData & 0x0100) >> 8) | ((~YData & 0x0200) >> 6)) ^ OUTMASK); } + if( delayBus ) hd44780_functions->uPause (1); // Read inputs readval = ~ port_in (lptPort + 1) ^ INMASK; diff --git a/server/drivers/hd44780-winamp.c b/server/drivers/hd44780-winamp.c index 61ec1f6..ee53074 100644 --- a/server/drivers/hd44780-winamp.c +++ b/server/drivers/hd44780-winamp.c @@ -138,13 +138,19 @@ lcdwinamp_HD44780_senddata (unsigned char displayID, unsigned char flags, unsign // Output the actual data port_out (lptPort, ch); + if( delayBus ) hd44780_functions->uPause (1); + // then set EN high port_out (lptPort + 2, (enableLines|portControl|backlight_bit) ^ OUTMASK); + if( delayBus ) hd44780_functions->uPause (1); + // 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!) // 230 nS minimum E high time provided by ISA bus delays as well... + // ABOVE TEXT ignored now, using delays if delayBus is specified + // Set EN low and we're done... port_out (lptPort + 2, (portControl|backlight_bit) ^ OUTMASK); @@ -167,6 +173,8 @@ unsigned char lcdwinamp_HD44780_readkeypad (unsigned int YData) port_out (lptPort, ~YData & 0x00FF ); port_out (lptPort + 2, ( ((~YData & 0x0100) >> 7) | ((~YData & 0x0200) >> 7 )) ^ OUTMASK); + if( delayBus ) hd44780_functions->uPause (1); + // Read inputs readval = ~ port_in (lptPort + 1) ^ INMASK; diff --git a/server/drivers/hd44780.c b/server/drivers/hd44780.c index e6fba59..a633a8e 100644 --- a/server/drivers/hd44780.c +++ b/server/drivers/hd44780.c @@ -112,11 +112,16 @@ static int numDisplays = 0; // input span list but is kept to save some cpu cycles. static int *dispSizes = NULL; -// Keypad and backlight option +// Keypad, backlight extended interface and delay options char have_keypad = 0; // off by default char have_backlight = 0; // off by default char extIF = 0; // off by default - // These vars is not static, so it's accessable from all sub-drivers +int delayMult = 1; // Delay multiplier for slow displays +char delayBus = 0; // Delay if the computer can send data too fast over + // its bus to LPT port + + // These vars is not static, so it's accessable from + // all sub-drivers // Indeed, this should become cleaner... later... // Autorepeat values @@ -193,6 +198,11 @@ HD44780_init (lcd_logical_driver * driver, char *args) //// READ THE CONFIG FILE port = driver->config_get_int( DriverName, "port", 0, 0x278 ); + extIF = driver->config_get_bool( DriverName, "extended", 0, 0 ); + have_keypad = driver->config_get_bool( DriverName, "keypad", 0, 0 ); + have_backlight = driver->config_get_bool( DriverName, "backlight", 0, 0 ); + delayMult = driver->config_get_int( DriverName, "delaymult", 0, 1 ); + delayBus = driver->config_get_bool( DriverName, "delaybus", 0, 0 ); // Get and search for the connection type s = driver->config_get_string( DriverName, "connectiontype", 0, "4bit" ); @@ -213,10 +223,6 @@ HD44780_init (lcd_logical_driver * driver, char *args) } } - extIF = driver->config_get_bool( DriverName, "extended", 0, 0 ); - have_keypad = driver->config_get_bool( DriverName, "keypad", 0, 0 ); - have_backlight = driver->config_get_bool( DriverName, "backlight", 0, 0 ); - // Get and parse size s = driver->config_get_string( DriverName, "size", 0, "20x4" ); if( sscanf( s, "%dx%d", &(driver->wid), &(driver->hgt) ) != 2 ) { @@ -336,8 +342,10 @@ common_init () // IO delay to avoid a task switch // void -uPause (int delayCalls) +uPause (int usecs) { + int delay = usecs * delayMult; // To correct for slower displays + #if defined DELAY_GETTIMEOFDAY struct timeval current_time,delay_time,wait_time; @@ -346,7 +354,7 @@ uPause (int delayCalls) // Calculate when delay is over delay_time.tv_sec = 0; - delay_time.tv_usec = delayCalls; + delay_time.tv_usec = delay; timeradd(¤t_time,&delay_time,&wait_time); do { @@ -354,18 +362,19 @@ uPause (int delayCalls) } while (timercmp(¤t_time,&wait_time,<)); #elif defined DELAY_NANOSLEEP - struct timespec delay,remaining; + struct timespec delay_time,remaining; - delay.tv_sec = 0; - delay.tv_nsec = delayCalls * 1000; - while ( nanosleep(&delay,&remaining) == -1 ) + delay_time.tv_sec = 0; + delay_time.tv_nsec = delay * 1000; + while ( nanosleep(&delay_time,&remaining) == -1 ) { - delay.tv_sec = remaining.tv_sec; - delay.tv_nsec = remaining.tv_nsec; + delay_time.tv_sec = remaining.tv_sec; + delay_time.tv_nsec = remaining.tv_nsec; } #else // using I/O timing + // Assuming every call takes 1us (which can be quite incorrect) int i; - for (i = 0; i < delayCalls; ++i) + for (i = 0; i < delay; ++i) port_in (port); #endif } diff --git a/server/drivers/hd44780.h b/server/drivers/hd44780.h index 15c8be7..b78f67d 100644 --- a/server/drivers/hd44780.h +++ b/server/drivers/hd44780.h @@ -24,6 +24,8 @@ extern char have_keypad; // non-zero if the keypad code is activated extern char have_backlight; // non-zero if we can control the backlight extern char extIF; // non-zero if we should control > 2 LCDs +extern char delayBus; // non-zero if axtra delays for the bus speed + // should be inserted. int HD44780_init (struct lcd_logical_driver *driver, char *args); /* The following methods can all be hidden. They are used through function ptrs