From af99913d34fe343b2b9346438f5c14708f6e7d30 Mon Sep 17 00:00:00 2001 From: cstein Date: Tue, 25 Jul 2000 22:12:21 +0000 Subject: [PATCH] Support for nanosleep and gettimeofday delay methods added --- server/drivers/hd44780-winamp.c | 24 +++++++++++-- server/drivers/hd44780.c | 60 +++++++++++++++++++++++++++++++++ 2 files changed, 81 insertions(+), 3 deletions(-) diff --git a/server/drivers/hd44780-winamp.c b/server/drivers/hd44780-winamp.c index ab58669..2602896 100644 --- a/server/drivers/hd44780-winamp.c +++ b/server/drivers/hd44780-winamp.c @@ -6,6 +6,11 @@ * Copyright (c) 1999 Andrew McMeikan * modular driver 1999-2000 Benjamin Tse * + * Modified July 2000 by Charles Steinkuehler for enhanced + * performance and reduced CPU usage + * - provided required setup time for RS valid to E high + * - 1 uS call to uPause removed as it is unnecessary + * * The connections are: * printer port LCD * D0 (2) D0 (7) @@ -93,8 +98,21 @@ lcdwinamp_HD44780_senddata (unsigned char displayID, unsigned char flags, unsign else dispID = EnMask[displayID - 1]; - port_out (lptPort, ch); - port_out (lptPort + 2, (dispID | portControl) ^ OUTMASK); - hd44780_functions->uPause (1); + // 40 nS setup time for RS valid to EN high, so set RS port_out (lptPort + 2, portControl ^ OUTMASK); + + // then set EN high + port_out (lptPort + 2, (dispID | portControl) ^ OUTMASK); + + // Output the actual data + port_out (lptPort, ch); + + // 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... + + // Set EN low and we're done... + port_out (lptPort + 2, portControl ^ OUTMASK); + + // 10 nS data hold time provided by the length of ISA write for EN } diff --git a/server/drivers/hd44780.c b/server/drivers/hd44780.c index 678693d..3232295 100644 --- a/server/drivers/hd44780.c +++ b/server/drivers/hd44780.c @@ -16,10 +16,15 @@ * Modular driver created and generic support for multiple displays added * Dec 1999, Benjamin Tse * + * Modified July 2000 by Charles Steinkuehler to use one of 3 methods for delay + * timing. I/O reads, gettimeofday, and nanosleep. Of the three, nanosleep + * seems to work best, so that's what is set by default. + * * This file is released under the GNU General Public License. Refer to the * COPYING file distributed with this package. * * Copyright (c) 2000, 1999, 1995 Benjamin Tse + * 2000, Charles Steinkuehler * 1999 Andrew McMeikan * 1998 Richard Rognlie * 1997 Matthias Prinke @@ -33,6 +38,22 @@ #include #include +// Uncomment one of the lines below to select your desired delay generation +// mechanism. If both defines are commented, the original I/O read timing +// loop is used. Using DELAY_NANOSLEEP seems to provide the best performance. +//#define DELAY_GETTIMEOFDAY +#define DELAY_NANOSLEEP + +#if defined DELAY_GETTIMEOFDAY +#include +#include +// Only one alternate delay method at a time, please ;-) +#undef DELAY_NANOSLEEP +#elif defined DELAY_NANOSLEEP +#include +#include +#endif + #include "../../shared/str.h" #include "lcd.h" @@ -209,6 +230,18 @@ HD44780_init (lcd_logical_driver * driver, char *args) } else fprintf (stderr, "Error mallocing for display sizes list\n"); } +#if defined DELAY_NANOSLEEP + // Change to Round-Robin scheduling for nanosleep + { + // Set priority to 1 + struct sched_param param; + param.sched_priority=1; + if (( sched_setscheduler(0, SCHED_RR, ¶m)) == -1) { + fprintf (stderr, "HD44780_init: failed (%s)\n", strerror (errno)); + return -1; + } + } +#endif // Set up io port correctly, and open it... if ((ioperm (port, 1, 255)) == -1) { fprintf (stderr, "HD44780_init: failed (%s)\n", strerror (errno)); @@ -293,10 +326,37 @@ common_init (enum ifWidth ifwidth) void uPause (int delayCalls) { +#if defined DELAY_GETTIMEOFDAY + struct timeval current_time,delay_time,wait_time; + + // Get current time first thing + gettimeofday(¤t_time,NULL); + + // Calculate when delay is over + delay_time.tv_sec = 0; + delay_time.tv_usec = delayCalls; + timeradd(¤t_time,&delay_time,&wait_time); + + do { + gettimeofday(¤t_time,NULL); + } while (timercmp(¤t_time,&wait_time,<)); + +#elif defined DELAY_NANOSLEEP + struct timespec delay,remaining; + + delay.tv_sec = 0; + delay.tv_nsec = delayCalls * 1000; + while ( nanosleep(&delay,&remaining) == -1 ) + { + delay.tv_sec = remaining.tv_sec; + delay.tv_nsec = remaining.tv_nsec; + } +#else int i; for (i = 0; i < delayCalls; ++i) port_in (port); //TODO: put in option for nanosleep rather than dummy I/O call +#endif } // displayID - ID of display to use (0 = all displays)