diff options
-rw-r--r-- | drv_HD44780.c | 62 | ||||
-rw-r--r-- | lcd4linux.conf.sample | 19 | ||||
-rw-r--r-- | udelay.c | 99 | ||||
-rw-r--r-- | udelay.h | 17 |
4 files changed, 90 insertions, 107 deletions
diff --git a/drv_HD44780.c b/drv_HD44780.c index 52b03dd..6d66903 100644 --- a/drv_HD44780.c +++ b/drv_HD44780.c @@ -1,4 +1,4 @@ -/* $Id: drv_HD44780.c,v 1.56 2005/12/12 05:52:03 reinelt Exp $ +/* $Id: drv_HD44780.c,v 1.57 2005/12/12 09:08:08 reinelt Exp $ * * new style driver for HD44780-based displays * @@ -32,6 +32,9 @@ * * * $Log: drv_HD44780.c,v $ + * Revision 1.57 2005/12/12 09:08:08 reinelt + * finally removed old udelay code path; read timing values from config + * * Revision 1.56 2005/12/12 05:52:03 reinelt * type of delays is 'unsigned long' * @@ -298,28 +301,9 @@ static int Model; static int Capabilities; -/* low level communication timings [nanoseconds] - * as these values differ from spec to spec, - * we use the worst-case values. - */ - -#define T_CYCLE 1000 /* Enable cycle time */ -#define T_PW 450 /* Enable pulse width */ -#define T_AS 140 /* Address setup time */ -#define T_H 40 /* Data hold time */ -#define T_AH 20 /* Address hold time */ - - -/* HD44780 execution timings [microseconds] - * as these values differ from spec to spec, - * we use the worst-case values. - */ - -#define T_INIT1 4100 /* first init sequence: 4.1 msec */ -#define T_INIT2 100 /* second init sequence: 100 usec */ -#define T_EXEC 80 /* normal execution time */ -#define T_WRCG 120 /* CG RAM Write */ -#define T_CLEAR 2250 /* Clear Display */ +/* Timings */ +static int T_CY, T_PW, T_AS, T_AH; +static int T_INIT1, T_INIT2, T_EXEC, T_WRCG, T_CLEAR, T_HOME, T_ONOFF; static int Bits = 0; @@ -561,8 +545,8 @@ static void drv_HD_PP_byte(const unsigned char controller, const unsigned char d /* send high nibble of the data */ drv_HD_PP_nibble(controller, ((data >> 4) & 0x0f) | RS); - /* Make sure we honour T_CYCLE */ - ndelay(T_CYCLE - T_AS - T_PW); + /* Make sure we honour T_CY */ + ndelay(T_CY - T_AS - T_PW); /* send low nibble of the data */ drv_HD_PP_nibble(controller, (data & 0x0f) | RS); @@ -769,6 +753,30 @@ static int drv_HD_PP_load(const char *section) Capabilities &= ~CAP_GPO; } + /* Timings */ + + /* low level communication timings [nanoseconds] + * as these values differ from spec to spec, + * we use the worst-case default values, but allow + * modification from the config file. + */ + T_CY = timing(Name, section, "CY", 1000, "ns"); /* Enable cycle time */ + T_PW = timing(Name, section, "PW", 450, "ns"); /* Enable pulse width */ + T_AS = timing(Name, section, "AS", 140, "ns"); /* Address setup time */ + T_AH = timing(Name, section, "AH", 20, "ns"); /* Address hold time */ + + /* HD44780 execution timings [microseconds] + * as these values differ from spec to spec, + * we use the worst-case default values, but allow + * modification from the config file. + */ + T_INIT1 = timing(Name, section, "INIT1", 4100, "us"); /* first init sequence: 4.1 msec */ + T_INIT2 = timing(Name, section, "INIT2", 100, "us"); /* second init sequence: 100 usec */ + T_EXEC = timing(Name, section, "EXEC", 80, "us"); /* normal execution time */ + T_WRCG = timing(Name, section, "WRCG", 120, "us"); /* CG RAM Write */ + T_CLEAR = timing(Name, section, "CLEAR", 2250, "us"); /* Clear Display */ + T_HOME = timing(Name, section, "HOME", 2250, "us"); /* Return Cursor Home */ + T_ONOFF = timing(Name, section, "ONOFF", 2250, "us"); /* Display On/Off Control */ /* clear all signals */ if (Bits == 8) { @@ -1313,7 +1321,7 @@ static int drv_HD_start(const char *section, const int quiet) } drv_HD_command(allControllers, 0x08, T_EXEC); /* Controller off, cursor off, blink off */ - drv_HD_command(allControllers, 0x0c, T_CLEAR); /* Display on, cursor off, blink off, wait 1.64 ms */ + drv_HD_command(allControllers, 0x0c, T_ONOFF); /* Display on, cursor off, blink off, wait 1.64 ms */ drv_HD_command(allControllers, 0x06, T_EXEC); /* curser moves to right, no shift */ if ((Capabilities & CAP_HD66712) && DROWS > 2) { @@ -1323,7 +1331,7 @@ static int drv_HD_start(const char *section, const int quiet) } drv_HD_clear(); /* clear *all* displays */ - drv_HD_command(allControllers, 0x03, T_CLEAR); /* return home */ + drv_HD_command(allControllers, 0x03, T_HOME); /* return home */ /* maybe set backlight */ if (Capabilities & CAP_BACKLIGHT) { diff --git a/lcd4linux.conf.sample b/lcd4linux.conf.sample index da346fb..d75acbf 100644 --- a/lcd4linux.conf.sample +++ b/lcd4linux.conf.sample @@ -119,6 +119,21 @@ Display HD44780-winamp { ENABLE2 'GND' GPO 'GND' } + Timing { + # low-level communication [ns] + CY 1000 # Enable cycle time + PW 450 # Enable pulse width + AS 140 # Address setup time + AH 20 # Address hold time + # HD44780 execution timings [us] + INIT1 4100 # first init sequence: 4.1 msec + INIT2 100 # second init sequence: 100 usec + EXEC 80 # normal execution time + WRCG 120 # CG RAM Write + CLEAR 2250 # Clear Display + HOME 2250 # Return Cursor Home + ONOFF 2250 # Display On/Off Control + } } # Dual-HD44780 display from Pollin @@ -828,7 +843,7 @@ Layout testMySQL { #Display 'MI240' #Display 'CW12232' #Display 'HD44780-generic' -#Display 'HD44780-WinAmp' +Display 'HD44780-WinAmp' #Display 'WDC2704M' #Display 'SC1602D' #Display 'LCM-162' @@ -839,7 +854,7 @@ Layout testMySQL { #Display 'M50530-24x8' #Display 'LCDTerm' #Display 'SimpleLCD' -Display 'BA63' +#Display 'BA63' #Display 'CT20x4' #Display 'T6963-240x64' #Display 'XWindow' @@ -1,4 +1,4 @@ -/* $Id: udelay.c,v 1.20 2005/05/08 04:32:45 reinelt Exp $ +/* $Id: udelay.c,v 1.21 2005/12/12 09:08:08 reinelt Exp $ * * short delays * @@ -23,6 +23,9 @@ * * * $Log: udelay.c,v $ + * Revision 1.21 2005/12/12 09:08:08 reinelt + * finally removed old udelay code path; read timing values from config + * * Revision 1.20 2005/05/08 04:32:45 reinelt * CodingStyle added and applied * @@ -112,21 +115,19 @@ * * exported fuctions: * - * void udelay (unsigned long usec) - * delays program execution for usec microseconds - * uses global variable 'loops_per_usec', which has to be set before. - * This function does busy-waiting! so use only for delays smaller - * than 10 msec - * - * void udelay_calibrate (void) (if USE_OLD_UDELAY is defined) - * does a binary approximation for 'loops_per_usec' - * should be called several times on an otherwise idle machine - * the maximum value should be used - * * void udelay_init (void) * selects delay method (gettimeofday() ord rdtsc() according * to processor features * + * unsigned long timing (const char *driver, const char *section, const char *name, const int defval, const char *unit); + * returns a timing value from config or the default value + * + * void udelay (unsigned long usec) + * delays program execution for usec microseconds + * uses global variable 'loops_per_usec', which has to be set before. + * This function does busy-waiting! so use only for delays smaller + * than 10 msec + * */ #include "config.h" @@ -134,12 +135,6 @@ #include <stdio.h> -#ifdef USE_OLD_UDELAY - -#include <time.h> - -#else - #include <math.h> #include <unistd.h> #include <fcntl.h> @@ -151,58 +146,16 @@ #include <asm/msr.h> #endif -#endif - #include "debug.h" +#include "cfg.h" +#include "qprintf.h" #include "udelay.h" -#ifdef USE_OLD_UDELAY - -unsigned long loops_per_usec; - -void ndelay(const unsigned long nsec) -{ - unsigned long loop = (nsec * loops_per_usec + 999) / 1000; - - __asm__(".align 16\n" "1:\tdecl %0\n" "\tjne 1b": /* no result */ - :"a"(loop)); -} - -/* adopted from /usr/src/linux/init/main.c */ - -void udelay_calibrate(void) -{ - clock_t tick; - unsigned long bit; - - loops_per_usec = 1; - while (loops_per_usec <<= 1) { - tick = clock(); - while (clock() == tick); - tick = clock(); - ndelay(1000000000 / CLOCKS_PER_SEC); - if (clock() > tick) - break; - } - - loops_per_usec >>= 1; - bit = loops_per_usec; - while (bit >>= 1) { - loops_per_usec |= bit; - tick = clock(); - while (clock() == tick); - tick = clock(); - ndelay(1000000000 / CLOCKS_PER_SEC); - if (clock() > tick) - loops_per_usec &= ~bit; - } -} - -#else static unsigned int ticks_per_usec = 0; + static void getCPUinfo(int *hasTSC, double *MHz) { int fd; @@ -269,7 +222,6 @@ void udelay_init(void) error("udelay: Even if your CPU supports TSC, it will not be used!"); error("udelay: You *really* should install msr.h and recompile LCD4linux!"); #endif - { ticks_per_usec = 0; info("udelay: using gettimeofday() delay loop"); @@ -277,6 +229,23 @@ void udelay_init(void) } +unsigned long timing(const char *driver, const char *section, const char *name, const int defval, const char *unit) +{ + char sec[256]; + int ret, val; + + qprintf(sec, sizeof(sec), "%s.Timing", section); + + ret = cfg_number(sec, name, defval, 0, -1, &val); + if (val != defval) { + info("%s: timing: %6s = %5d %s (default %d %s)", driver, name, val, unit, defval, unit); + } else { + info("%s: timing: %6s = %5d %s (default)", driver, name, defval, unit); + } + return val; +} + + void ndelay(const unsigned long nsec) { @@ -314,5 +283,3 @@ void ndelay(const unsigned long nsec) } while (now.tv_sec == end.tv_sec ? now.tv_usec < end.tv_usec : now.tv_sec < end.tv_sec); } } - -#endif @@ -1,4 +1,4 @@ -/* $Id: udelay.h,v 1.10 2005/05/08 04:32:45 reinelt Exp $ +/* $Id: udelay.h,v 1.11 2005/12/12 09:08:08 reinelt Exp $ * * short delays * @@ -23,6 +23,9 @@ * * * $Log: udelay.h,v $ + * Revision 1.11 2005/12/12 09:08:08 reinelt + * finally removed old udelay code path; read timing values from config + * * Revision 1.10 2005/05/08 04:32:45 reinelt * CodingStyle added and applied * @@ -79,18 +82,8 @@ static inline void rep_nop(void) __asm__ __volatile__("rep; nop"); } - -#ifdef USE_OLD_UDELAY - -extern unsigned long loops_per_usec; -void udelay_calibrate(void); - -#else - void udelay_init(void); - -#endif - +unsigned long timing(const char *driver, const char *section, const char *name, const int defval, const char *unit); void ndelay(const unsigned long nsec); #define udelay(usec) ndelay(usec*1000) |