aboutsummaryrefslogtreecommitdiffstats
path: root/drv_HD44780.c
diff options
context:
space:
mode:
authorreinelt <>2004-01-30 07:12:35 +0000
committerreinelt <>2004-01-30 07:12:35 +0000
commit1ffb8be56b4017149d8c108aee2eeaf881a88d3e (patch)
tree9a58587d75c2e4334d8ce18f0a08858939920f1d /drv_HD44780.c
parent8291ba6f73d75fa5dc4376c333bd9772567dce12 (diff)
downloadlcd4linux-1ffb8be56b4017149d8c108aee2eeaf881a88d3e.tar.gz
[lcd4linux @ 2004-01-30 07:12:35 by reinelt]
HD44780 busy-flag support from Martin Hejl loadavg() uClibc replacement from Martin Heyl round() uClibc replacement from Martin Hejl warning in i2c_sensors fixed [
Diffstat (limited to 'drv_HD44780.c')
-rw-r--r--drv_HD44780.c216
1 files changed, 180 insertions, 36 deletions
diff --git a/drv_HD44780.c b/drv_HD44780.c
index 7ca7d5b..7bcaade 100644
--- a/drv_HD44780.c
+++ b/drv_HD44780.c
@@ -1,4 +1,4 @@
-/* $Id: drv_HD44780.c,v 1.6 2004/01/29 04:40:02 reinelt Exp $
+/* $Id: drv_HD44780.c,v 1.7 2004/01/30 07:12:35 reinelt Exp $
*
* new style driver for HD44780-based displays
*
@@ -29,6 +29,13 @@
*
*
* $Log: drv_HD44780.c,v $
+ * Revision 1.7 2004/01/30 07:12:35 reinelt
+ * HD44780 busy-flag support from Martin Hejl
+ * loadavg() uClibc replacement from Martin Heyl
+ * round() uClibc replacement from Martin Hejl
+ * warning in i2c_sensors fixed
+ * [
+ *
* Revision 1.6 2004/01/29 04:40:02 reinelt
* every .c file includes "config.h" now
*
@@ -70,6 +77,7 @@
#include <unistd.h>
#include <termios.h>
#include <fcntl.h>
+#include <sys/time.h>
#include "debug.h"
#include "cfg.h"
@@ -95,6 +103,7 @@ static char Name[]="HD44780";
#define T_PW 450 // Enable pulse width
#define T_AS 60 // Address setup time
#define T_H 40 // Data hold time
+#define T_AH 20 // Address hold time
/* HD44780 execution timings [microseconds]
@@ -106,12 +115,13 @@ static char Name[]="HD44780";
#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 1640 // Clear Display
+#define T_CLEAR 1680 // Clear Display
static int Bits=0;
-static int Controllers = 0;
-static int Controller = 0;
+static int numControllers = 0;
+static int allControllers = 0;
+static int currController = 0;
static unsigned char SIGNAL_RW;
static unsigned char SIGNAL_RS;
@@ -119,6 +129,11 @@ static unsigned char SIGNAL_ENABLE;
static unsigned char SIGNAL_ENABLE2;
static unsigned char SIGNAL_GPO;
+/* maximum time to wait for the busy-flag (in usec) */
+#define MAX_BUSYFLAG_WAIT 100000
+static int use_busy_flag = 0;
+
+
// Fixme
static int GPOS;
// static int GPO=0;
@@ -128,6 +143,107 @@ static int GPOS;
// *** hardware dependant functions ***
// ****************************************
+static void wait_for_busy_flag(int controller)
+{
+ unsigned char enable;
+ unsigned int counter;
+ unsigned char data=0xFF;
+ unsigned char busymask=0;
+
+ if (Bits==8) {
+ busymask = 0x80;
+ } else {
+ /* Since in 4-Bit mode DB0 on the parport is mapped to DB4 on the LCD
+ (and consequently, DB3 on the partport is mapped to DB7 on the LCD)
+ we need to listen for DB3 on the parport to go low
+ */
+ busymask = 0x8;
+ }
+
+ enable=SIGNAL_ENABLE;
+
+ while (controller > 0) {
+ if (controller&0x01 && enable!=0) {
+ /* set data-lines to input*/
+ drv_generic_parport_direction(1);
+
+ if (Bits==8) {
+ // Set RW, clear RS
+ drv_generic_parport_control(SIGNAL_RW|SIGNAL_RS,SIGNAL_RW);
+ } else {
+ drv_generic_parport_data(SIGNAL_RW);
+ }
+
+ // Address set-up time
+ ndelay(T_AS);
+
+ // rise ENABLE
+ if (Bits==8) {
+ drv_generic_parport_control(enable,enable);
+ } else {
+ drv_generic_parport_data(SIGNAL_RW|enable);
+ }
+
+ counter=0;
+ while (1) {
+ /* read the busy flag */
+ data = drv_generic_parport_read();
+ if ((data&busymask)==0) break;
+
+ /* make sure we don't wait forever
+ - but only check after 5 iterations
+ that way, we won't slow down normal mode
+ (where we don't need the timeout anyway) */
+ counter++;
+
+ if (counter >= 5) {
+ struct timeval now, end;
+
+ if (counter == 5) {
+ // determine the time when the timeout has expired
+ gettimeofday (&end, NULL);
+ end.tv_usec+=MAX_BUSYFLAG_WAIT;
+ while (end.tv_usec>1000000) {
+ end.tv_usec-=1000000;
+ end.tv_sec++;
+ }
+ }
+
+ // get the current time
+ gettimeofday(&now, NULL);
+ if (now.tv_sec==end.tv_sec?now.tv_usec>=end.tv_usec:now.tv_sec>=end.tv_sec) {
+ error ("HD44780: timeout waiting for busy flag on controller %x (%x)", controller, data);
+ break;
+
+ }
+ }
+ }
+
+ // RS=low, RW=low, EN=low
+ if (Bits==8) {
+ // Lower EN
+ drv_generic_parport_control(enable,0);
+
+ // Address hold time
+ ndelay(T_AH);
+
+ drv_generic_parport_control(SIGNAL_RW|SIGNAL_RS,0);
+ } else {
+ // Lower EN
+ drv_generic_parport_data(SIGNAL_RW);
+ ndelay(T_AH);
+ drv_generic_parport_data(0);
+ }
+
+ /* set data-lines to output*/
+ drv_generic_parport_direction(0);
+ }
+ enable=SIGNAL_ENABLE2;
+ controller=controller >> 1;
+ }
+}
+
+
static void drv_HD_nibble(unsigned char controller, unsigned char nibble)
{
unsigned char enable;
@@ -205,8 +321,8 @@ static void drv_HD_command (unsigned char controller, unsigned char cmd, int del
}
// wait for command completion
- udelay(delay);
-
+ if (!use_busy_flag) udelay(delay);
+
}
@@ -217,6 +333,8 @@ static void drv_HD_data (unsigned char controller, char *string, int len, int de
// sanity check
if (len<=0) return;
+ if (use_busy_flag) wait_for_busy_flag(controller);
+
if (Bits==8) {
// enable signal: 'controller' is a bitmask
@@ -227,13 +345,22 @@ static void drv_HD_data (unsigned char controller, char *string, int len, int de
if (controller&0x01) enable|=SIGNAL_ENABLE;
if (controller&0x02) enable|=SIGNAL_ENABLE2;
- // clear RW, set RS
- drv_generic_parport_control (SIGNAL_RW | SIGNAL_RS, SIGNAL_RS);
-
- // Address set-up time
- ndelay(T_AS);
+ if (!use_busy_flag) {
+ // clear RW, set RS
+ drv_generic_parport_control (SIGNAL_RW | SIGNAL_RS, SIGNAL_RS);
+ // Address set-up time
+ ndelay(T_AS);
+ }
while (len--) {
+
+ if (use_busy_flag) {
+ wait_for_busy_flag(controller);
+ // clear RW, set RS
+ drv_generic_parport_control (SIGNAL_RW | SIGNAL_RS, SIGNAL_RS);
+ // Address set-up time
+ ndelay(T_AS);
+ }
// put data on DB1..DB8
drv_generic_parport_data (*(string++));
@@ -242,18 +369,19 @@ static void drv_HD_data (unsigned char controller, char *string, int len, int de
drv_generic_parport_toggle (enable, 1, T_PW);
// wait for command completion
- udelay(delay);
+ if (!use_busy_flag) udelay(delay);
}
} else { // 4 bit mode
while (len--) {
+ if (use_busy_flag) wait_for_busy_flag(controller);
// send data with RS enabled
drv_HD_byte (controller, *(string++), SIGNAL_RS);
// wait for command completion
- udelay(delay);
+ if (!use_busy_flag) udelay(delay);
}
}
}
@@ -264,11 +392,11 @@ static void drv_HD_goto (int row, int col)
int pos;
// handle multiple displays/controllers
- if (Controllers>1 && row>=DROWS/2) {
+ if (numControllers>1 && row>=DROWS/2) {
row -= DROWS/2;
- Controller = 2;
+ currController = 2;
} else {
- Controller = 1;
+ currController = 1;
}
// 16x1 Displays are organized as 8x2 :-(
@@ -284,7 +412,7 @@ static void drv_HD_goto (int row, int col)
pos=(row%2)*64+(row/2)*20+col;
}
- drv_HD_command (Controller, (0x80|pos), T_EXEC);
+ drv_HD_command (currController, (0x80|pos), T_EXEC);
}
@@ -306,11 +434,14 @@ static int drv_HD_start (char *section)
if (cfg_number(section, "GPOs", 0, 0, 8, &gpos)<0) return -1;
info ("%s: controlling %d GPO's", Name, gpos);
- if (cfg_number(section, "Controllers", 1, 1, 2, &Controllers)<0) return -1;
- info ("%s: using display with %d controllers", Name, Controllers);
+ if (cfg_number(section, "Controllers", 1, 1, 2, &numControllers)<0) return -1;
+ info ("%s: using display with %d controllers", Name, numControllers);
// current controller
- Controller=1;
+ currController=1;
+
+ // Bitmask for *all* Controllers
+ allControllers = numControllers==2 ? 3 : 1;
DROWS = rows;
DCOLS = cols;
@@ -354,22 +485,35 @@ static int drv_HD_start (char *section)
// initialize *both* displays
if (Bits==8) {
- drv_HD_command (0x03, 0x30, T_INIT1); // 8 Bit mode, wait 4.1 ms
- drv_HD_command (0x03, 0x30, T_INIT2); // 8 Bit mode, wait 100 us
- drv_HD_command (0x03, 0x38, T_EXEC); // 8 Bit mode, 1/16 duty cycle, 5x8 font
+ drv_HD_command (allControllers, 0x30, T_INIT1); // 8 Bit mode, wait 4.1 ms
+ drv_HD_command (allControllers, 0x30, T_INIT2); // 8 Bit mode, wait 100 us
+ drv_HD_command (allControllers, 0x38, T_EXEC); // 8 Bit mode, 1/16 duty cycle, 5x8 font
} else {
- drv_HD_nibble(0x03, 0x03); udelay(T_INIT1); // 4 Bit mode, wait 4.1 ms
- drv_HD_nibble(0x03, 0x03); udelay(T_INIT2); // 4 Bit mode, wait 100 us
- drv_HD_nibble(0x03, 0x03); udelay(T_INIT1); // 4 Bit mode, wait 4.1 ms
- drv_HD_nibble(0x03, 0x02); udelay(T_INIT2); // 4 Bit mode, wait 100 us
- drv_HD_command (0x03, 0x28, T_EXEC); // 4 Bit mode, 1/16 duty cycle, 5x8 font
+ drv_HD_nibble (allControllers, 0x03); udelay(T_INIT1); // 4 Bit mode, wait 4.1 ms
+ drv_HD_nibble (allControllers, 0x03); udelay(T_INIT2); // 4 Bit mode, wait 100 us
+ drv_HD_nibble (allControllers, 0x03); udelay(T_INIT1); // 4 Bit mode, wait 4.1 ms
+ drv_HD_nibble (allControllers, 0x02); udelay(T_INIT2); // 4 Bit mode, wait 100 us
+ drv_HD_command (allControllers, 0x28, T_EXEC); // 4 Bit mode, 1/16 duty cycle, 5x8 font
+ }
+
+ drv_HD_command (allControllers, 0x08, T_EXEC); // Display 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, 0x06, T_EXEC); // curser moves to right, no shift
+
+ // Save it in a local variable, until init is complete (for init, we can't use the busy flag)
+ if (cfg_number(section, "UseBusy", 0, 0, 1, &use_busy_flag)<0) return -1;
+
+ // Make sure we don't use the busy flag, if it's set to GND
+ if (SIGNAL_RW == 0 && use_busy_flag != 0 ) {
+ debug("HD44780: Busyflag is to be used, but wiring set RW to GND. Disabling busy-flag");
+ use_busy_flag=0;
}
- drv_HD_command (0x03, 0x08, T_EXEC); // Display off, cursor off, blink off
- drv_HD_command (0x03, 0x0c, T_CLEAR); // Display on, cursor off, blink off, wait 1.64 ms
- drv_HD_command (0x03, 0x06, T_EXEC); // curser moves to right, no shift
- drv_HD_command (0x03, 0x01, T_CLEAR); // clear *both* displays
- drv_HD_command (0x03, 0x03, T_CLEAR); // return home
+ info("HD44780: %susing Busyflag", use_busy_flag?"":"not ");
+
+ drv_HD_command (allControllers, 0x01, T_CLEAR); // clear *both* displays
+ drv_HD_command (allControllers, 0x03, T_CLEAR); // return home
+
return 0;
}
@@ -377,15 +521,15 @@ static int drv_HD_start (char *section)
static void drv_HD_write (char *string, int len)
{
- drv_HD_data (Controller, string, len, T_EXEC);
+ drv_HD_data (currController, string, len, T_EXEC);
}
static void drv_HD_defchar (int ascii, char *buffer)
{
// define chars on *both* controllers!
- drv_HD_command (0x03, 0x40|8*ascii, T_EXEC);
- drv_HD_data (0x03, buffer, 8, T_WRCG);
+ drv_HD_command (allControllers, 0x40|8*ascii, T_EXEC);
+ drv_HD_data (allControllers, buffer, 8, T_WRCG);
}