aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--drv_HD44780.c299
-rw-r--r--drv_generic_parport.c8
-rw-r--r--lcd4linux.conf.sample1
-rw-r--r--udelay.c32
4 files changed, 231 insertions, 109 deletions
diff --git a/drv_HD44780.c b/drv_HD44780.c
index 30bb8ea..b08216f 100644
--- a/drv_HD44780.c
+++ b/drv_HD44780.c
@@ -1,4 +1,4 @@
-/* $Id: drv_HD44780.c,v 1.34 2004/09/18 08:22:59 reinelt Exp $
+/* $Id: drv_HD44780.c,v 1.35 2004/09/18 09:48:29 reinelt Exp $
*
* new style driver for HD44780-based displays
*
@@ -29,6 +29,10 @@
*
*
* $Log: drv_HD44780.c,v $
+ * Revision 1.35 2004/09/18 09:48:29 reinelt
+ * HD44780 cleanup and prepararation for I2C backend
+ * LCM-162 submodel framework
+ *
* Revision 1.34 2004/09/18 08:22:59 reinelt
* drv_generic_parport_status() to read status lines
*
@@ -272,21 +276,34 @@ typedef struct {
#define CAP_BRIGHTNESS (1<<0)
#define CAP_BUSY4BIT (1<<1)
#define CAP_HD66712 (1<<2)
+#define CAP_LCM162 (1<<3)
static MODEL Models[] = {
{ 0x01, "generic", 0 },
{ 0x02, "Noritake", CAP_BRIGHTNESS },
{ 0x03, "Soekris", CAP_BUSY4BIT },
{ 0x04, "HD66712", CAP_HD66712 },
+ { 0x05, "LCM-162", CAP_LCM162 },
{ 0xff, "Unknown", 0 }
};
+
+/****************************************/
+/*** generic functions ***/
+/****************************************/
+
+static void (*drv_HD_command) (const unsigned char controller, const unsigned char cmd, const int delay);
+static void (*drv_HD_data) (const unsigned char controller, const char *string, const int len, const int delay);
+static void (*drv_HD_stop) (void);
+
+
+
/****************************************/
-/*** hardware dependant functions ***/
+/*** parport dependant functions ***/
/****************************************/
-static void wait_for_busy_flag(int controller)
+static void drv_HD_PP_busy(int controller)
{
unsigned char enable;
unsigned int counter;
@@ -387,7 +404,7 @@ static void wait_for_busy_flag(int controller)
}
-static void drv_HD_nibble(const unsigned char controller, const unsigned char nibble)
+static void drv_HD_PP_nibble(const unsigned char controller, const unsigned char nibble)
{
unsigned char enable;
@@ -418,24 +435,24 @@ static void drv_HD_nibble(const unsigned char controller, const unsigned char ni
}
-static void drv_HD_byte (const unsigned char controller, const unsigned char data, const unsigned char RS)
+static void drv_HD_PP_byte (const unsigned char controller, const unsigned char data, const unsigned char RS)
{
/* send high nibble of the data */
- drv_HD_nibble (controller, ((data>>4)&0x0f)|RS);
+ drv_HD_PP_nibble (controller, ((data>>4)&0x0f)|RS);
/* Make sure we honour T_CYCLE */
ndelay(T_CYCLE-T_AS-T_PW);
/* send low nibble of the data */
- drv_HD_nibble(controller, (data&0x0f)|RS);
+ drv_HD_PP_nibble(controller, (data&0x0f)|RS);
}
-static void drv_HD_command (const unsigned char controller, const unsigned char cmd, const int delay)
+static void drv_HD_PP_command (const unsigned char controller, const unsigned char cmd, const int delay)
{
unsigned char enable;
- if (UseBusy) wait_for_busy_flag(controller);
+ if (UseBusy) drv_HD_PP_busy(controller);
if (Bits==8) {
@@ -461,7 +478,7 @@ static void drv_HD_command (const unsigned char controller, const unsigned char
} else {
- drv_HD_byte (controller, cmd, 0);
+ drv_HD_PP_byte (controller, cmd, 0);
}
@@ -471,7 +488,7 @@ static void drv_HD_command (const unsigned char controller, const unsigned char
}
-static void drv_HD_data (const unsigned char controller, const char *string, const int len, const int delay)
+static void drv_HD_PP_data (const unsigned char controller, const char *string, const int len, const int delay)
{
int l = len;
unsigned char enable;
@@ -499,7 +516,7 @@ static void drv_HD_data (const unsigned char controller, const char *string, con
while (l--) {
if (UseBusy) {
- wait_for_busy_flag(controller);
+ drv_HD_PP_busy(controller);
/* clear RW, set RS */
drv_generic_parport_control (SIGNAL_RW | SIGNAL_RS, SIGNAL_RS);
/* Address set-up time */
@@ -519,10 +536,10 @@ static void drv_HD_data (const unsigned char controller, const char *string, con
} else { /* 4 bit mode */
while (l--) {
- if (UseBusy) wait_for_busy_flag(controller);
+ if (UseBusy) drv_HD_PP_busy(controller);
/* send data with RS enabled */
- drv_HD_byte (controller, *(string++), SIGNAL_RS);
+ drv_HD_PP_byte (controller, *(string++), SIGNAL_RS);
/* wait for command completion */
if (!UseBusy) udelay(delay);
@@ -531,6 +548,143 @@ static void drv_HD_data (const unsigned char controller, const char *string, con
}
+static int drv_HD_PP_start (const char *section)
+{
+ if (cfg_number(section, "Bits", 8, 4, 8, &Bits)<0) return -1;
+ if (Bits!=4 && Bits!=8) {
+ error ("%s: bad %s.Bits '%d' from %s, should be '4' or '8'", Name, section, Bits, cfg_source());
+ return -1;
+ }
+ info ("%s: using %d bit mode", Name, Bits);
+
+ if (drv_generic_parport_open(section, Name) != 0) {
+ error ("%s: could not initialize parallel port!", Name);
+ return -1;
+ }
+
+ if (Bits==8) {
+ if ((SIGNAL_RS = drv_generic_parport_wire_ctrl ("RS", "AUTOFD"))==0xff) return -1;
+ if ((SIGNAL_RW = drv_generic_parport_wire_ctrl ("RW", "GND" ))==0xff) return -1;
+ if ((SIGNAL_ENABLE = drv_generic_parport_wire_ctrl ("ENABLE", "STROBE"))==0xff) return -1;
+ if ((SIGNAL_ENABLE2 = drv_generic_parport_wire_ctrl ("ENABLE2", "GND" ))==0xff) return -1;
+ if ((SIGNAL_GPO = drv_generic_parport_wire_ctrl ("GPO", "GND" ))==0xff) return -1;
+ } else {
+ if ((SIGNAL_RS = drv_generic_parport_wire_data ("RS", "DB4"))==0xff) return -1;
+ if ((SIGNAL_RW = drv_generic_parport_wire_data ("RW", "DB5"))==0xff) return -1;
+ if ((SIGNAL_ENABLE = drv_generic_parport_wire_data ("ENABLE", "DB6"))==0xff) return -1;
+ if ((SIGNAL_ENABLE2 = drv_generic_parport_wire_data ("ENABLE2", "GND"))==0xff) return -1;
+ if ((SIGNAL_GPO = drv_generic_parport_wire_data ("GPO", "GND"))==0xff) return -1;
+ }
+
+ /* clear all signals */
+ if (Bits==8) {
+ drv_generic_parport_control (SIGNAL_RS|SIGNAL_RW|SIGNAL_ENABLE|SIGNAL_ENABLE2|SIGNAL_GPO, 0);
+ } else {
+ drv_generic_parport_data (0);
+ }
+
+ /* set direction: write */
+ drv_generic_parport_direction (0);
+
+ /* initialize *both* displays */
+ if (Bits==8) {
+ drv_HD_PP_command (allControllers, 0x30, T_INIT1); /* 8 Bit mode, wait 4.1 ms */
+ drv_HD_PP_command (allControllers, 0x30, T_INIT2); /* 8 Bit mode, wait 100 us */
+ drv_HD_PP_command (allControllers, 0x38, T_EXEC); /* 8 Bit mode, 1/16 duty cycle, 5x8 font */
+ } else {
+ drv_HD_PP_nibble (allControllers, 0x03); udelay(T_INIT1); /* 4 Bit mode, wait 4.1 ms */
+ drv_HD_PP_nibble (allControllers, 0x03); udelay(T_INIT2); /* 4 Bit mode, wait 100 us */
+ drv_HD_PP_nibble (allControllers, 0x03); udelay(T_INIT1); /* 4 Bit mode, wait 4.1 ms */
+ drv_HD_PP_nibble (allControllers, 0x02); udelay(T_INIT2); /* 4 Bit mode, wait 100 us */
+ drv_HD_PP_command (allControllers, 0x28, T_EXEC); /* 4 Bit mode, 1/16 duty cycle, 5x8 font */
+ }
+
+ /* maybe use busy-flag from now on */
+ /* (we can't use the busy flag during the init sequence) */
+ cfg_number(section, "UseBusy", 0, 0, 1, &UseBusy);
+
+ /* make sure we don't use the busy flag with RW wired to GND */
+ if (UseBusy && !SIGNAL_RW) {
+ error("%s: Busyflag is to be used, but RW is wired to GND", Name);
+ UseBusy=0;
+ }
+
+ /* make sure the display supports busy-flag checking in 4-Bit-Mode */
+ /* at the moment this is inly possible with Martin Hejl's gpio driver, */
+ /* which allows to use 4 bits as input and 4 bits as output */
+ if (UseBusy && Bits==4 && !(Capabilities&CAP_BUSY4BIT)) {
+ error("%s: Model '%s' does not support busy-flag checking in 4-bit-mode", Name, Models[Model].name);
+ UseBusy=0;
+ }
+
+ info("%s: %susing busy-flag checking", Name, UseBusy?"":"not ");
+
+ return 0;
+}
+
+
+static void drv_HD_PP_stop (void)
+{
+ /* clear all signals */
+ if (Bits==8) {
+ drv_generic_parport_control (SIGNAL_RS|SIGNAL_RW|SIGNAL_ENABLE|SIGNAL_ENABLE2|SIGNAL_GPO, 0);
+ } else {
+ drv_generic_parport_data (0);
+ }
+
+ drv_generic_parport_close();
+
+}
+
+
+
+/****************************************/
+/*** i2c dependant functions ***/
+/****************************************/
+
+
+static void drv_HD_I2C_command (const unsigned char controller, const unsigned char cmd, const int delay)
+{
+ /* send data with RS disabled */
+ // drv_HD_I2C_byte (controller, cmd, 0);
+}
+
+
+static void drv_HD_I2C_data (const unsigned char controller, const char *string, const int len, const int delay)
+{
+ int l = len;
+ unsigned char enable;
+
+ /* sanity check */
+ if (len<=0) return;
+
+ while (l--) {
+ /* send data with RS enabled */
+ // drv_HD_I2C_byte (controller, *(string++), SIGNAL_RS);
+ }
+}
+
+
+static int drv_HD_I2C_start (const char *section)
+{
+ return 0;
+}
+
+
+static void drv_HD_I2C_stop (void)
+{
+ /* clear all signals */
+ // drv_generic_i2c_data (0);
+ /* slose port */
+ // drv_generic_i2c_close();
+}
+
+
+
+/****************************************/
+/*** display dependant functions ***/
+/****************************************/
+
static void drv_HD_clear (void)
{
drv_HD_command (allControllers, 0x01, T_CLEAR); /* clear *both* displays */
@@ -632,7 +786,7 @@ static void drv_HD_setGPO (const int bits)
static int drv_HD_start (const char *section, const int quiet)
{
- char *model, *strsize;
+ char *model, *size, *bus;
int rows=-1, cols=-1, gpos=-1;
model=cfg_get(section, "Model", "generic");
@@ -650,22 +804,23 @@ static int drv_HD_start (const char *section, const int quiet)
info ("%s: using model '%s'", Name, Models[Model].name);
} else {
error ("%s: empty '%s.Model' entry from %s", Name, section, cfg_source());
+ if (model) free (model);
return -1;
}
free(model);
- strsize=cfg_get(section, "Size", NULL);
- if (strsize==NULL || *strsize=='\0') {
+ size=cfg_get(section, "Size", NULL);
+ if (size==NULL || *size=='\0') {
error ("%s: no '%s.Size' entry from %s", Name, section, cfg_source());
- free(strsize);
+ free(size);
return -1;
}
- if (sscanf(strsize,"%dx%d",&cols,&rows)!=2 || rows<1 || cols<1) {
- error ("%s: bad %s.Size '%s' from %s", Name, section, strsize, cfg_source());
- free(strsize);
+ if (sscanf(size,"%dx%d",&cols,&rows)!=2 || rows<1 || cols<1) {
+ error ("%s: bad %s.Size '%s' from %s", Name, section, size, cfg_source());
+ free(size);
return -1;
}
- free(strsize);
+ free(size);
if (cfg_number(section, "GPOs", 0, 0, 8, &gpos)<0) return -1;
info ("%s: controlling %d GPO's", Name, gpos);
@@ -683,74 +838,39 @@ static int drv_HD_start (const char *section, const int quiet)
DCOLS = cols;
GPOS = gpos;
- if (cfg_number(section, "Bits", 8, 4, 8, &Bits)<0) return -1;
- if (Bits!=4 && Bits!=8) {
- error ("%s: bad %s.Bits '%d' from %s, should be '4' or '8'", Name, section, Bits, cfg_source());
- return -1;
- }
- info ("%s: using %d bit mode", Name, Bits);
-
- if (drv_generic_parport_open(section, Name) != 0) {
- error ("%s: could not initialize parallel port!", Name);
+ bus=cfg_get(section, "Bus", "parport");
+ if (bus==NULL && *bus=='\0') {
+ error ("%s: empty '%s.Bus' entry from %s", Name, section, cfg_source());
+ if (bus) free (bus);
return -1;
}
- if (Bits==8) {
- if ((SIGNAL_RS = drv_generic_parport_wire_ctrl ("RS", "AUTOFD"))==0xff) return -1;
- if ((SIGNAL_RW = drv_generic_parport_wire_ctrl ("RW", "GND" ))==0xff) return -1;
- if ((SIGNAL_ENABLE = drv_generic_parport_wire_ctrl ("ENABLE", "STROBE"))==0xff) return -1;
- if ((SIGNAL_ENABLE2 = drv_generic_parport_wire_ctrl ("ENABLE2", "GND" ))==0xff) return -1;
- if ((SIGNAL_GPO = drv_generic_parport_wire_ctrl ("GPO", "GND" ))==0xff) return -1;
- } else {
- if ((SIGNAL_RS = drv_generic_parport_wire_data ("RS", "DB4"))==0xff) return -1;
- if ((SIGNAL_RW = drv_generic_parport_wire_data ("RW", "DB5"))==0xff) return -1;
- if ((SIGNAL_ENABLE = drv_generic_parport_wire_data ("ENABLE", "DB6"))==0xff) return -1;
- if ((SIGNAL_ENABLE2 = drv_generic_parport_wire_data ("ENABLE2", "GND"))==0xff) return -1;
- if ((SIGNAL_GPO = drv_generic_parport_wire_data ("GPO", "GND"))==0xff) return -1;
- }
-
- /* clear all signals */
- if (Bits==8) {
- drv_generic_parport_control (SIGNAL_RS|SIGNAL_RW|SIGNAL_ENABLE|SIGNAL_ENABLE2|SIGNAL_GPO, 0);
- } else {
- drv_generic_parport_data (0);
- }
-
- /* set direction: write */
- drv_generic_parport_direction (0);
-
- /* initialize *both* displays */
- if (Bits==8) {
- 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 (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 */
- }
-
- /* maybe use busy-flag from now on */
- /* (we can't use the busy flag during the init sequence) */
- cfg_number(section, "UseBusy", 0, 0, 1, &UseBusy);
-
- /* make sure we don't use the busy flag with RW wired to GND */
- if (UseBusy && !SIGNAL_RW) {
- error("%s: Busyflag is to be used, but RW is wired to GND", Name);
- UseBusy=0;
- }
+ if (strcasecmp(bus, "parport") == 0) {
+ info ("%s: using parallel port", Name);
+ if (drv_HD_PP_start(section) < 0) {
+ free (bus);
+ return -1;
+ }
+ drv_HD_command = drv_HD_PP_command;
+ drv_HD_data = drv_HD_PP_data;
+ drv_HD_stop = drv_HD_PP_stop;
+
+ } else if (strcasecmp(bus, "i2c") == 0) {
+ info ("%s: using I2C bus", Name);
+ if (drv_HD_I2C_start(section) < 0) {
+ free (bus);
+ return -1;
+ }
+ drv_HD_command = drv_HD_I2C_command;
+ drv_HD_data = drv_HD_I2C_data;
+ drv_HD_stop = drv_HD_I2C_stop;
- /* make sure the display supports busy-flag checking in 4-Bit-Mode */
- /* at the moment this is inly possible with Martin Hejl's gpio driver, */
- /* which allows to use 4 bits as input and 4 bits as output */
- if (UseBusy && Bits==4 && !(Capabilities&CAP_BUSY4BIT)) {
- error("%s: Model '%s' does not support busy-flag checking in 4-bit-mode", Name, Models[Model].name);
- UseBusy=0;
+ } else {
+ error ("%s: bad %s.Bus '%s' from %s, should be 'parport' or 'i2c'", Name, section, bus, cfg_source());
+ free (bus);
+ return -1;
}
-
- info("%s: %susing busy-flag checking", Name, UseBusy?"":"not ");
+ free(bus);
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 */
@@ -910,14 +1030,7 @@ int drv_HD_quit (const int quiet) {
drv_generic_text_greet ("goodbye!", NULL);
}
- /* clear all signals */
- if (Bits==8) {
- drv_generic_parport_control (SIGNAL_RS|SIGNAL_RW|SIGNAL_ENABLE|SIGNAL_ENABLE2|SIGNAL_GPO, 0);
- } else {
- drv_generic_parport_data (0);
- }
-
- drv_generic_parport_close();
+ drv_HD_stop();
return (0);
}
diff --git a/drv_generic_parport.c b/drv_generic_parport.c
index f008c46..72e5423 100644
--- a/drv_generic_parport.c
+++ b/drv_generic_parport.c
@@ -1,4 +1,4 @@
-/* $Id: drv_generic_parport.c,v 1.9 2004/09/18 08:22:59 reinelt Exp $
+/* $Id: drv_generic_parport.c,v 1.10 2004/09/18 09:48:29 reinelt Exp $
*
* generic driver helper for serial and parport access
*
@@ -23,6 +23,10 @@
*
*
* $Log: drv_generic_parport.c,v $
+ * Revision 1.10 2004/09/18 09:48:29 reinelt
+ * HD44780 cleanup and prepararation for I2C backend
+ * LCM-162 submodel framework
+ *
* Revision 1.9 2004/09/18 08:22:59 reinelt
* drv_generic_parport_status() to read status lines
*
@@ -170,7 +174,7 @@ int drv_generic_parport_open (const char *section, const char *driver)
#ifdef WITH_PPDEV
if (PPdev) {
- info ("using ppdev %s", PPdev);
+ info ("%s: using ppdev %s", Driver, PPdev);
PPfd=open(PPdev, O_RDWR);
if (PPfd==-1) {
error ("%s: open(%s) failed: %s", Driver, PPdev, strerror(errno));
diff --git a/lcd4linux.conf.sample b/lcd4linux.conf.sample
index e1e00b7..12a5891 100644
--- a/lcd4linux.conf.sample
+++ b/lcd4linux.conf.sample
@@ -95,6 +95,7 @@ Display SC1602D {
Display LCM-162 {
Driver 'HD44780'
+ Model 'LCM-162'
Port '/dev/parports/0'
Bits '8'
Size '16x2'
diff --git a/udelay.c b/udelay.c
index bfbdf00..f3a222c 100644
--- a/udelay.c
+++ b/udelay.c
@@ -1,4 +1,4 @@
-/* $Id: udelay.c,v 1.17 2004/06/20 10:09:56 reinelt Exp $
+/* $Id: udelay.c,v 1.18 2004/09/18 09:48:29 reinelt Exp $
*
* short delays
*
@@ -22,6 +22,10 @@
*
*
* $Log: udelay.c,v $
+ * Revision 1.18 2004/09/18 09:48:29 reinelt
+ * HD44780 cleanup and prepararation for I2C backend
+ * LCM-162 submodel framework
+ *
* Revision 1.17 2004/06/20 10:09:56 reinelt
*
* 'const'ified the whole source
@@ -205,11 +209,11 @@ static void getCPUinfo (int *hasTSC, double *MHz)
fd=open("/proc/cpuinfo", O_RDONLY);
if (fd==-1) {
- error ("open(/proc/cpuinfo) failed: %s", strerror(errno));
+ error ("udelay: open(/proc/cpuinfo) failed: %s", strerror(errno));
return;
}
if (read (fd, &buffer, sizeof(buffer)-1)==-1) {
- error ("read(/proc/cpuinfo) failed: %s", strerror(errno));
+ error ("udelay: read(/proc/cpuinfo) failed: %s", strerror(errno));
close (fd);
return;
}
@@ -217,26 +221,26 @@ static void getCPUinfo (int *hasTSC, double *MHz)
p=strstr(buffer, "flags");
if (p==NULL) {
- info ("/proc/cpuinfo has no 'flags' line");
+ info ("udelay: /proc/cpuinfo has no 'flags' line");
} else {
p=strstr(p, "tsc");
if (p==NULL) {
- info ("CPU does not support Time Stamp Counter");
+ info ("udelay: CPU does not support Time Stamp Counter");
} else {
- info ("CPU supports Time Stamp Counter");
+ info ("udelay: CPU supports Time Stamp Counter");
*hasTSC=1;
}
}
p=strstr(buffer, "cpu MHz");
if (p==NULL) {
- info ("/proc/cpuinfo has no 'cpu MHz' line");
+ info ("udelay: /proc/cpuinfo has no 'cpu MHz' line");
} else {
if (sscanf(p+7, " : %lf", MHz)!=1) {
- error ("parse(/proc/cpuinfo) failed: unknown 'cpu MHz' format");
+ error ("udelay: parse(/proc/cpuinfo) failed: unknown 'cpu MHz' format");
*MHz=-1;
} else {
- info ("CPU runs at %f MHz", *MHz);
+ info ("udelay: CPU runs at %f MHz", *MHz);
}
}
@@ -254,17 +258,17 @@ void udelay_init (void)
if (tsc && mhz>0.0) {
ticks_per_usec=ceil(mhz);
- info ("using TSC delay loop, %u ticks per microsecond", ticks_per_usec);
+ info ("udelay: using TSC delay loop, %u ticks per microsecond", ticks_per_usec);
} else
#else
- error ("The file 'include/asm/msr.h' was missing at compile time.");
- error ("Even if your CPU supports TSC, it will not be used!");
- error ("You *really* should install msr.h and recompile LCD4linux!");
+ error ("udelay: The file 'include/asm/msr.h' was missing at compile time.");
+ 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 ("using gettimeofday() delay loop");
+ info ("udelay: using gettimeofday() delay loop");
}
}