aboutsummaryrefslogtreecommitdiffstats
path: root/drv_HD44780.c
diff options
context:
space:
mode:
Diffstat (limited to 'drv_HD44780.c')
-rw-r--r--drv_HD44780.c596
1 files changed, 346 insertions, 250 deletions
diff --git a/drv_HD44780.c b/drv_HD44780.c
index 0771aa2..c47370a 100644
--- a/drv_HD44780.c
+++ b/drv_HD44780.c
@@ -1,4 +1,4 @@
-/* $Id: drv_HD44780.c,v 1.46 2005/03/28 19:39:23 reinelt Exp $
+/* $Id: drv_HD44780.c,v 1.47 2005/03/28 22:29:23 reinelt Exp $
*
* new style driver for HD44780-based displays
*
@@ -32,6 +32,9 @@
*
*
* $Log: drv_HD44780.c,v $
+ * Revision 1.47 2005/03/28 22:29:23 reinelt
+ * HD44780 multiple displays patch from geronet
+ *
* Revision 1.46 2005/03/28 19:39:23 reinelt
* HD44780/I2C patch from Luis merged (still does not work for me)
*
@@ -287,7 +290,7 @@ static int Capabilities;
#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 1680 /* Clear Display */
+#define T_CLEAR 2250 /* Clear Display */
static int Bits=0;
@@ -295,10 +298,16 @@ static int numControllers = 0;
static int allControllers = 0;
static int currController = 0;
+/* size of every single controller */
+static int CROWS[4];
+static int CCOLS[4];
+
static unsigned char SIGNAL_RW;
static unsigned char SIGNAL_RS;
static unsigned char SIGNAL_ENABLE;
static unsigned char SIGNAL_ENABLE2;
+static unsigned char SIGNAL_ENABLE3;
+static unsigned char SIGNAL_ENABLE4;
static unsigned char SIGNAL_BACKLIGHT;
static unsigned char SIGNAL_GPO;
@@ -361,17 +370,17 @@ static void (*drv_HD_stop) (void);
/*** parport dependant functions ***/
/****************************************/
-static void drv_HD_PP_busy(const int controller)
+static void drv_HD_PP_busy (const int controller)
{
static unsigned int errors = 0;
-
+
unsigned char enable;
unsigned char data=0xFF;
unsigned char busymask;
unsigned char ctrlmask;
unsigned int counter;
- if (Bits==8) {
+ if (Bits == 8) {
busymask = 0x80;
} else {
/* Since in 4-Bit mode DB0 on the parport is mapped to DB4 on the LCD
@@ -380,93 +389,96 @@ static void drv_HD_PP_busy(const int controller)
*/
busymask = 0x08;
}
-
- ctrlmask = 0x02;
- while (ctrlmask > 0 ) {
+
+ ctrlmask = 0x08;
+ while (ctrlmask > 0) {
if (controller & ctrlmask) {
-
+
enable = 0;
- if (ctrlmask & 0x01) enable = SIGNAL_ENABLE;
+ if (ctrlmask & 0x01) enable = SIGNAL_ENABLE;
else if (ctrlmask & 0x02) enable = SIGNAL_ENABLE2;
+ else if (ctrlmask & 0x04) enable = SIGNAL_ENABLE3;
+ else if (ctrlmask & 0x08) enable = SIGNAL_ENABLE4;
/* 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);
+ if (Bits == 8) {
+ /* Set RW, clear RS */
+ drv_generic_parport_control(SIGNAL_RW|SIGNAL_RS, SIGNAL_RW);
} else {
- drv_generic_parport_data(SIGNAL_RW);
+ drv_generic_parport_data(SIGNAL_RW);
}
/* Address set-up time */
ndelay(T_AS);
/* rise ENABLE */
- if (Bits==8) {
- drv_generic_parport_control(enable,enable);
+ if (Bits == 8) {
+ drv_generic_parport_control(enable,enable);
} else {
- drv_generic_parport_data(SIGNAL_RW|enable);
+ drv_generic_parport_data(SIGNAL_RW|enable);
}
-
+
counter=0;
while (1) {
- /* read the busy flag */
- data = drv_generic_parport_read();
- if ((data & busymask) == 0) {
+ /* read the busy flag */
+ data = drv_generic_parport_read();
+ if ((data & busymask) == 0) {
errors = 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 ("%s: timeout waiting for busy flag on controller %x (%x)", Name, ctrlmask, data);
+
+ /* 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 ("%s: timeout waiting for busy flag on controller %x (%x)", Name, ctrlmask, data);
if (++errors >= MAX_BUSYFLAG_ERRORS) {
error ("%s: too many busy flag failures, turning off busy flag checking.", Name);
UseBusy = 0;
}
- break;
- }
- }
+ 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);
+ /* 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);
+ /* 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);
}
@@ -475,23 +487,24 @@ static void drv_HD_PP_busy(const int controller)
}
-static void drv_HD_PP_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;
-
+
/* enable signal: 'controller' is a bitmask */
- /* bit 0 .. send to controller #0 */
- /* bit 1 .. send to controller #1 */
- /* so we can send a byte to both controllers at the same time! */
+ /* bit n .. send to controller #n */
+ /* so we can send a byte to more controllers at the same time! */
enable=0;
- if (controller&0x01) enable|=SIGNAL_ENABLE;
- if (controller&0x02) enable|=SIGNAL_ENABLE2;
+ if (controller & 0x01) enable |= SIGNAL_ENABLE;
+ if (controller & 0x02) enable |= SIGNAL_ENABLE2;
+ if (controller & 0x04) enable |= SIGNAL_ENABLE3;
+ if (controller & 0x08) enable |= SIGNAL_ENABLE4;
/* clear ENABLE */
/* put data on DB1..DB4 */
/* nibble already contains RS bit! */
drv_generic_parport_data(nibble);
-
+
/* Address set-up time */
ndelay(T_AS);
@@ -500,7 +513,7 @@ static void drv_HD_PP_nibble(const unsigned char controller, const unsigned char
/* Enable pulse width */
ndelay(T_PW);
-
+
/* lower ENABLE */
drv_generic_parport_data(nibble);
}
@@ -509,53 +522,54 @@ static void drv_HD_PP_nibble(const unsigned char controller, const unsigned char
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_PP_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_PP_nibble(controller, (data&0x0f)|RS);
+ drv_HD_PP_nibble (controller, (data & 0x0f) | RS);
}
static void drv_HD_PP_command (const unsigned char controller, const unsigned char cmd, const int delay)
{
unsigned char enable;
-
- if (UseBusy) drv_HD_PP_busy(controller);
-
- if (Bits==8) {
+
+ if (UseBusy) drv_HD_PP_busy (controller);
+
+ if (Bits == 8) {
/* enable signal: 'controller' is a bitmask */
- /* bit 0 .. send to controller #0 */
- /* bit 1 .. send to controller #1 */
- /* so we can send a byte to both controllers at the same time! */
+ /* bit n .. send to controller #n */
+ /* so we can send a byte to more controllers at the same time! */
enable=0;
- if (controller&0x01) enable|=SIGNAL_ENABLE;
- if (controller&0x02) enable|=SIGNAL_ENABLE2;
+ if (controller & 0x01) enable |= SIGNAL_ENABLE;
+ if (controller & 0x02) enable |= SIGNAL_ENABLE2;
+ if (controller & 0x04) enable |= SIGNAL_ENABLE3;
+ if (controller & 0x08) enable |= SIGNAL_ENABLE4;
/* put data on DB1..DB8 */
drv_generic_parport_data (cmd);
-
+
/* clear RW and RS */
drv_generic_parport_control (SIGNAL_RW | SIGNAL_RS, 0);
/* Address set-up time */
ndelay(T_AS);
-
+
/* send command */
drv_generic_parport_toggle (enable, 1, T_PW);
} else {
-
+
drv_HD_PP_byte (controller, cmd, 0);
-
+
}
/* wait for command completion */
- if (!UseBusy) udelay(delay);
-
+ if (!UseBusy) udelay (delay);
+
}
@@ -563,19 +577,20 @@ static void drv_HD_PP_data (const unsigned char controller, const char *string,
{
int l = len;
unsigned char enable;
-
+
/* sanity check */
- if (len<=0) return;
-
- if (Bits==8) {
-
+ if (len <= 0) return;
+
+ if (Bits == 8) {
+
/* enable signal: 'controller' is a bitmask */
- /* bit 0 .. send to controller #0 */
- /* bit 1 .. send to controller #1 */
- /* so we can send a byte to both controllers at the same time! */
+ /* bit n .. send to controller #n */
+ /* so we can send a byte to more controllers at the same time! */
enable=0;
- if (controller&0x01) enable|=SIGNAL_ENABLE;
- if (controller&0x02) enable|=SIGNAL_ENABLE2;
+ if (controller & 0x01) enable |= SIGNAL_ENABLE;
+ if (controller & 0x02) enable |= SIGNAL_ENABLE2;
+ if (controller & 0x04) enable |= SIGNAL_ENABLE3;
+ if (controller & 0x08) enable |= SIGNAL_ENABLE4;
if (!UseBusy) {
/* clear RW, set RS */
@@ -585,9 +600,9 @@ static void drv_HD_PP_data (const unsigned char controller, const char *string,
}
while (l--) {
-
+
if (UseBusy) {
- drv_HD_PP_busy(controller);
+ drv_HD_PP_busy (controller);
/* clear RW, set RS */
drv_generic_parport_control (SIGNAL_RW | SIGNAL_RS, SIGNAL_RS);
/* Address set-up time */
@@ -601,19 +616,19 @@ static void drv_HD_PP_data (const unsigned char controller, const char *string,
drv_generic_parport_toggle (enable, 1, T_PW);
/* wait for command completion */
- if (!UseBusy) udelay(delay);
+ if (!UseBusy) udelay (delay);
}
} else { /* 4 bit mode */
while (l--) {
- if (UseBusy) drv_HD_PP_busy(controller);
-
+ if (UseBusy) drv_HD_PP_busy (controller);
+
/* send data with RS enabled */
drv_HD_PP_byte (controller, *(string++), SIGNAL_RS);
/* wait for command completion */
- if (!UseBusy) udelay(delay);
+ if (!UseBusy) udelay (delay);
}
}
}
@@ -621,8 +636,9 @@ static void drv_HD_PP_data (const unsigned char controller, const char *string,
static int drv_HD_PP_load (const char *section)
{
- if (cfg_number(section, "Bits", 8, 4, 8, &Bits)<0) return -1;
- if (Bits!=4 && Bits!=8) {
+ 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;
}
@@ -634,11 +650,11 @@ static int drv_HD_PP_load (const char *section)
}
info ("%s: using %d bit mode", Name, Bits);
- if (drv_generic_parport_open(section, Name) != 0) {
+ if (drv_generic_parport_open (section, Name) != 0) {
error ("%s: could not initialize parallel port!", Name);
return -1;
}
-
+
/* Soft-Wiring */
if (Capabilities & CAP_LCM162) {
/* the LCM-162 is hardwired */
@@ -646,25 +662,31 @@ static int drv_HD_PP_load (const char *section)
if ((SIGNAL_RW = drv_generic_parport_hardwire_ctrl ("RW", "INIT" )) == 0xff) return -1;
if ((SIGNAL_ENABLE = drv_generic_parport_hardwire_ctrl ("ENABLE", "AUTOFD")) == 0xff) return -1;
if ((SIGNAL_ENABLE2 = drv_generic_parport_hardwire_ctrl ("ENABLE2", "GND" )) == 0xff) return -1;
+ if ((SIGNAL_ENABLE3 = drv_generic_parport_hardwire_ctrl ("ENABLE3", "GND" )) == 0xff) return -1;
+ if ((SIGNAL_ENABLE4 = drv_generic_parport_hardwire_ctrl ("ENABLE4", "GND" )) == 0xff) return -1;
if ((SIGNAL_BACKLIGHT = drv_generic_parport_hardwire_ctrl ("BACKLIGHT", "GND" )) == 0xff) return -1;
if ((SIGNAL_GPO = drv_generic_parport_hardwire_ctrl ("GPO", "GND" )) == 0xff) return -1;
} else {
- 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 (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_ENABLE3 = drv_generic_parport_wire_ctrl ("ENABLE3", "GND" )) == 0xff) return -1;
+ if ((SIGNAL_ENABLE4 = drv_generic_parport_wire_ctrl ("ENABLE4", "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_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_ENABLE3 = drv_generic_parport_wire_data ("ENABLE3", "GND")) == 0xff) return -1;
+ if ((SIGNAL_ENABLE4 = drv_generic_parport_wire_data ("ENABLE4", "GND")) == 0xff) return -1;
}
/* backlight and GPO are always control signals */
- if ((SIGNAL_BACKLIGHT = drv_generic_parport_wire_ctrl ("BACKLIGHT", "GND" )) == 0xff) return -1;
- if ((SIGNAL_GPO = drv_generic_parport_wire_ctrl ("GPO", "GND" )) == 0xff) return -1;
+ if ((SIGNAL_BACKLIGHT = drv_generic_parport_wire_ctrl ("BACKLIGHT", "GND")) == 0xff) return -1;
+ if ((SIGNAL_GPO = drv_generic_parport_wire_ctrl ("GPO", "GND")) == 0xff) return -1;
}
-
+
/* clear capabilities if corresponding signal is GND */
if (SIGNAL_BACKLIGHT == 0) {
Capabilities &= ~CAP_BACKLIGHT;
@@ -672,11 +694,18 @@ static int drv_HD_PP_load (const char *section)
if (SIGNAL_GPO == 0) {
Capabilities &= ~CAP_GPO;
}
-
-
+
+
/* clear all signals */
if (Bits == 8) {
- drv_generic_parport_control (SIGNAL_RS|SIGNAL_RW|SIGNAL_ENABLE|SIGNAL_ENABLE2|SIGNAL_BACKLIGHT|SIGNAL_GPO, 0);
+ drv_generic_parport_control (SIGNAL_RS |
+ SIGNAL_RW |
+ SIGNAL_ENABLE |
+ SIGNAL_ENABLE2 |
+ SIGNAL_ENABLE3 |
+ SIGNAL_ENABLE4 |
+ SIGNAL_BACKLIGHT |
+ SIGNAL_GPO, 0);
} else {
drv_generic_parport_data (0);
}
@@ -684,41 +713,41 @@ static int drv_HD_PP_load (const char *section)
/* set direction: write */
drv_generic_parport_direction (0);
- /* initialize *both* displays */
- if (Bits==8) {
+ /* initialize *all* controllers */
+ 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 */
+ 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) {
+ if (UseBusy && !SIGNAL_RW) {
error("%s: busy-flag checking is impossible with RW 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)) {
+ 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 ");
-
+
/* The LCM-162 should really use BusyFlag checking */
- if (!UseBusy && (Capabilities & CAP_LCM162)) {
+ if (!UseBusy && (Capabilities & CAP_LCM162)) {
error("%s: Model '%s' should definitely use busy-flag checking!", Name, Models[Model].name);
}
@@ -729,12 +758,19 @@ static int drv_HD_PP_load (const char *section)
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_BACKLIGHT|SIGNAL_GPO, 0);
+ if (Bits == 8) {
+ drv_generic_parport_control (SIGNAL_RS |
+ SIGNAL_RW |
+ SIGNAL_ENABLE |
+ SIGNAL_ENABLE2 |
+ SIGNAL_ENABLE3 |
+ SIGNAL_ENABLE4 |
+ SIGNAL_BACKLIGHT |
+ SIGNAL_GPO, 0);
} else {
drv_generic_parport_data (0);
}
-
+
drv_generic_parport_close();
}
@@ -750,16 +786,17 @@ static void drv_HD_PP_stop (void)
static void drv_HD_I2C_nibble (unsigned char controller, unsigned char nibble)
{
unsigned char enable;
-
+
/* enable signal: 'controller' is a bitmask */
- /* bit 0 .. send to controller #0 */
- /* bit 1 .. send to controller #1 */
- /* so we can send a byte to both controllers at the same time! */
+ /* bit n .. send to controller #n */
+ /* so we can send a byte to more controllers at the same time! */
enable = 0;
if (controller & 0x01) enable |= SIGNAL_ENABLE;
if (controller & 0x02) enable |= SIGNAL_ENABLE2;
+ if (controller & 0x04) enable |= SIGNAL_ENABLE3;
+ if (controller & 0x08) enable |= SIGNAL_ENABLE4;
+
-
/* clear ENABLE */
/* put data on DB1..DB4 */
/* nibble already contains RS bit! */
@@ -769,13 +806,13 @@ static void drv_HD_I2C_nibble (unsigned char controller, unsigned char nibble)
ndelay(T_AS);
/* rise ENABLE */
- drv_generic_i2c_data(nibble | enable);
+ drv_generic_i2c_data(nibble | enable);
/* Enable pulse width */
ndelay(T_PW);
/* lower ENABLE */
- drv_generic_i2c_data(nibble);
+ drv_generic_i2c_data(nibble);
/* Address hold time */
ndelay(T_H);
@@ -787,10 +824,10 @@ static void drv_HD_I2C_byte (const unsigned char controller, const unsigned char
/* send data with RS disabled */
/* send high nibble of the data */
drv_HD_I2C_nibble (controller, ((data>>4)&0x0f)|SIGNAL_RS);
-
+
/* Make sure we honour T_CYCLE */
ndelay(T_CYCLE-T_AS-T_PW);
-
+
/* send low nibble of the data */
drv_HD_I2C_nibble(controller, (data&0x0f)|SIGNAL_RS);
}
@@ -800,11 +837,11 @@ static void drv_HD_I2C_command (const unsigned char controller, const unsigned c
{
/* send data with RS disabled */
drv_HD_I2C_nibble (controller, ((cmd>>4)&0x0f));
-
+
ndelay(T_CYCLE-T_AS-T_PW);
-
+
drv_HD_I2C_nibble (controller, ((cmd)&0x0f));
-
+
/* wait for command completion */
udelay(delay);
}
@@ -812,14 +849,14 @@ static void drv_HD_I2C_command (const unsigned char controller, const unsigned c
static void drv_HD_I2C_data (const unsigned char controller, const char *string, const int len, const int delay)
{
int l = len;
-
+
/* sanity check */
if (len<=0) return;
-
+
while (l--) {
/* send data with RS enabled */
drv_HD_I2C_byte (controller, *(string++));
-
+
/* wait for command completion */
udelay(delay);
}
@@ -840,7 +877,7 @@ static int drv_HD_I2C_load (const char *section)
error ("%s: could not initialize i2c attached device!", Name);
return -1;
}
-
+
if ((SIGNAL_RS = drv_generic_i2c_wire ("RS", "DB4"))==0xff) return -1;
if ((SIGNAL_RW = drv_generic_i2c_wire ("RW", "DB5"))==0xff) return -1;
if ((SIGNAL_ENABLE = drv_generic_i2c_wire ("ENABLE", "DB6"))==0xff) return -1;
@@ -853,9 +890,9 @@ static int drv_HD_I2C_load (const char *section)
drv_HD_I2C_nibble (allControllers, 0x03); udelay(T_INIT2); /* 4 Bit mode, wait 4.1 ms */
drv_HD_I2C_nibble (allControllers, 0x02); udelay(T_INIT2); /* 4 Bit mode, wait 100 us */
drv_HD_I2C_command (allControllers, 0x28, T_EXEC); /* 4 Bit mode, 1/16 duty cycle, 5x8 font */
-
+
info("%s: I2C initialization done", Name);
-
+
return 0;
}
@@ -864,7 +901,7 @@ static void drv_HD_I2C_stop (void)
{
/* clear all signals */
drv_generic_i2c_data (0);
-
+
/* close port */
drv_generic_i2c_close();
}
@@ -878,24 +915,34 @@ static void drv_HD_I2C_stop (void)
static void drv_HD_clear (void)
{
- drv_HD_command (allControllers, 0x01, T_CLEAR); /* clear *both* displays */
+ drv_HD_command (allControllers, 0x01, T_CLEAR); /* clear *all* displays */
}
-static void drv_HD_goto (int row, int col)
+static int drv_HD_goto (int row, int col)
{
- int pos;
-
- /* handle multiple displays/controllers */
- if (numControllers > 1 && row >= DROWS/2) {
- row -= DROWS/2;
- currController = 2;
- } else {
- currController = 1;
+ int pos, controller;
+
+ /* handle multiple controllers */
+ for (pos = 0, controller = 0; controller < numControllers; controller++) {
+ pos += CROWS[controller];
+ if (row < pos) {
+ currController = (1 << controller);
+ break;
+ }
+ row -= CROWS[controller];
+ }
+
+ /* column outside of current display's width */
+ if (col >= CCOLS[controller]) return -1;
+
+ if (0) {
+ debug ("goto: [%d,%d] mask=%d, controller=%d, size:%dx%d",
+ row, col, currController, controller, CROWS[controller], CCOLS[controller]);
}
-
+
/* 16x1 Displays are organized as 8x2 :-( */
- if (DCOLS == 16 && DROWS == 1 && col > 7) {
+ if (CCOLS[controller] == 16 && CROWS[controller] == 1 && col > 7) {
row++;
col -= 8;
}
@@ -904,21 +951,27 @@ static void drv_HD_goto (int row, int col)
/* the HD66712 doesn't have a braindamadged RAM layout */
pos = row*32 + col;
} else {
- /* 16x4 Displays use a slightly different layout */
- if (DCOLS == 16 && DROWS == 4) {
+ /* 16x4 Controllers use a slightly different layout */
+ if (CCOLS[controller] == 16 && CROWS[controller] == 4) {
pos = (row%2)*64 + (row/2)*16 + col;
- } else {
+ } else {
pos = (row%2)*64 + (row/2)*20 + col;
}
}
- drv_HD_command (currController, (0x80|pos), T_EXEC);
+ drv_HD_command (currController, (0x80 | pos), T_EXEC);
+
+ /* return columns left on current display */
+ return CCOLS[controller] - col;
+
}
static void drv_HD_write (const int row, const int col, const char *data, const int len)
{
- drv_HD_goto (row, col);
- drv_HD_data (currController, data, len, T_EXEC);
+ int space = drv_HD_goto (row, col);
+ if (space > 0) {
+ drv_HD_data (currController, data, len > space ? space : len, T_EXEC);
+ }
}
@@ -926,13 +979,13 @@ static void drv_HD_defchar (const int ascii, const unsigned char *matrix)
{
int i;
char buffer[8];
-
+
for (i = 0; i < 8; i++) {
buffer[i] = matrix[i] & 0x1f;
}
- /* define chars on *both* controllers! */
- drv_HD_command (allControllers, 0x40|8*ascii, T_EXEC);
+ /* define chars on *all* controllers! */
+ drv_HD_command (allControllers, 0x40 | 8 * ascii, T_EXEC);
drv_HD_data (allControllers, buffer, 8, T_WRCG);
}
@@ -940,39 +993,39 @@ static void drv_HD_defchar (const int ascii, const unsigned char *matrix)
static int drv_HD_backlight (int backlight)
{
if (!(Capabilities & CAP_BACKLIGHT)) return -1;
-
+
if (backlight < 0) backlight = 0;
if (backlight > 1) backlight = 1;
-
+
drv_generic_parport_control (SIGNAL_BACKLIGHT, backlight ? SIGNAL_BACKLIGHT : 0);
-
+
return backlight;
}
-
+
static int drv_HD_brightness (int brightness)
{
char cmd;
if (!(Capabilities & CAP_BRIGHTNESS)) return -1;
-
- if (brightness<0) brightness=0;
- if (brightness>3) brightness=3;
-
+
+ if (brightness < 0) brightness = 0;
+ if (brightness > 3) brightness = 3;
+
cmd='0'+brightness;
drv_HD_command (allControllers, 0x38, T_EXEC); /* enable function */
drv_HD_data (allControllers, &cmd, 1, T_WRCG); /* set brightness */
-
+
return brightness;
}
-
+
/* Fixme: GPO's */
#if 0
static void drv_HD_setGPO (const int bits)
{
- if (Lcd.gpos>0) {
+ if (Lcd.gpos > 0) {
/* put data on DB1..DB8 */
drv_generic_parport_data (bits);
@@ -991,27 +1044,27 @@ static void drv_HD_setGPO (const int bits)
static void drv_HD_LCM162_timer (void __attribute__((unused)) *notused)
{
static unsigned char data = 0x00;
-
+
/* Bit 3+5 : key number */
/* Bit 6 : key press/release */
unsigned char mask3 = 1<<3;
unsigned char mask5 = 1<<5;
unsigned char mask6 = 1<<6;
unsigned char mask = mask3 | mask5 | mask6;
-
+
int keynum;
int updown;
unsigned char temp;
temp = drv_generic_parport_status() & mask;
-
+
if (data != temp) {
data = temp;
-
+
keynum = (data & mask3 ? 1 : 0) + (data & mask5 ? 2 : 0);
updown = (data & mask6 ? 1 : 0);
-
+
debug ("key %d press %d", keynum, updown);
}
}
@@ -1020,15 +1073,17 @@ static void drv_HD_LCM162_timer (void __attribute__((unused)) *notused)
static int drv_HD_start (const char *section, const int quiet)
{
char *model, *size, *bus;
- int rows=-1, cols=-1, gpos=-1;
-
+ int rows = -1, cols = -1, gpos = -1, i;
+ int size_defined = 0;
+ int size_missing = 0;
+
model=cfg_get(section, "Model", "generic");
- if (model!=NULL && *model!='\0') {
+ if (model != NULL && *model != '\0') {
int i;
- for (i=0; Models[i].type!=0xff; i++) {
- if (strcasecmp(Models[i].name, model)==0) break;
+ for (i = 0; Models[i].type != 0xff; i++) {
+ if (strcasecmp (Models[i].name, model) == 0) break;
}
- if (Models[i].type==0xff) {
+ if (Models[i].type == 0xff) {
error ("%s: %s.Model '%s' is unknown from %s", Name, section, model, cfg_source());
return -1;
}
@@ -1041,15 +1096,15 @@ static int drv_HD_start (const char *section, const int quiet)
return -1;
}
free (model);
-
+
bus=cfg_get(section, "Bus", "parport");
- if (bus==NULL && *bus=='\0') {
+ if (bus == NULL && *bus == '\0') {
error ("%s: empty '%s.Bus' entry from %s", Name, section, cfg_source());
if (bus) free (bus);
return -1;
}
-
- if (strcasecmp(bus, "parport") == 0) {
+
+ if (strcasecmp (bus, "parport") == 0) {
info ("%s: using parallel port", Name);
Bus = BUS_PP;
drv_HD_load = drv_HD_PP_load;
@@ -1071,13 +1126,13 @@ static int drv_HD_start (const char *section, const int quiet)
free (bus);
return -1;
#endif
-
+
} else {
error ("%s: bad %s.Bus '%s' from %s, should be 'parport' or 'i2c'", Name, section, bus, cfg_source());
free (bus);
return -1;
}
-
+
/* sanity check: Model can use bus */
if (!(Capabilities & Bus)) {
error ("%s: Model '%s' cannot be used on the %s bus!", Name, Models[Model].name, bus);
@@ -1086,31 +1141,73 @@ static int drv_HD_start (const char *section, const int quiet)
}
free(bus);
- size=cfg_get(section, "Size", NULL);
- if (size==NULL || *size=='\0') {
- error ("%s: no '%s.Size' entry from %s", Name, section, cfg_source());
+ if (cfg_number (section, "Controllers", 1, 1, 4, (int *) &numControllers) < 0) return -1;
+ info ("%s: using %d Controller(s)", Name, numControllers);
+
+ /* current Controller */
+ currController = 1;
+
+ /* Bitmask for *all* Controllers */
+ allControllers = (1 << numControllers) - 1;
+
+
+ DCOLS = 0;
+ DROWS = 0;
+
+ for (i = 0; i < numControllers; i++) {
+ char key[6];
+ qprintf(key, sizeof(key), "Size%d", i+1);
+ size = cfg_get (section, key, NULL);
+ if (size == NULL || *size == '\0') {
+ size_missing++;
+ free(size);
+ continue;
+ }
+ if (sscanf (size, "%dx%d", &cols, &rows) != 2 || rows < 1 || cols < 1) {
+ error ("%s: bad %s.%s '%s' from %s", Name, section, key, size, cfg_source ());
+ free(size);
+ return -1;
+ }
free(size);
- return -1;
+ CCOLS[i] = cols;
+ CROWS[i] = rows;
+ size_defined++;
+ info ("%s: Controller %d: %dx%d", Name, i+1, cols, rows);
+ /* grow the size */
+ if (cols > DCOLS) DCOLS = cols;
+ DROWS += rows;
}
- 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);
+ if (size_defined && size_missing) {
+ error ("%s: bad %s.Size* definition in %s:", Name, section, cfg_source());
+ error ("%s: either you specify the size for *all* controllers or for none.", Name);
return -1;
}
- free(size);
- DROWS = rows;
- DCOLS = cols;
-
- if (cfg_number(section, "Controllers", 1, 1, 2, &numControllers)<0) return -1;
- info ("%s: using %d controller(s)", Name, numControllers);
- /* current controller */
- currController=1;
+ size = cfg_get(section, "Size", NULL);
+ if (size != NULL && *size != '\0') {
+ 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;
+ }
+ if (DCOLS == 0 && DROWS == 0) {
+ for (i = 0; i < numControllers; i++) {
+ CCOLS[i] = cols;
+ CROWS[i] = rows/numControllers;
+ DCOLS = CCOLS[i];
+ DROWS += CROWS[i];
+ }
+ }
+ if (rows != DROWS || cols != DCOLS) {
+ error ("%s: bad %s.Size definition in %s:", Name, section, cfg_source());
+ error ("%s: Size %dx%d should be %dx%d", Name, cols, rows, DCOLS, DROWS);
+ return -1;
+ }
+ }
+ free(size);
- /* Bitmask for *all* Controllers */
- allControllers = numControllers==2 ? 3 : 1;
- if (cfg_number(section, "GPOs", 0, 0, 8, &gpos)<0) return -1;
+ if (cfg_number (section, "GPOs", 0, 0, 8, &gpos) < 0) return -1;
if (gpos > 0 && !(Capabilities & CAP_GPO)) {
error ("%s: Model '%s' does not support GPO's!", Name, Models[Model].name);
gpos = 0;
@@ -1120,42 +1217,42 @@ static int drv_HD_start (const char *section, const int quiet)
info ("%s: using %d GPO's", Name, GPOS);
}
- if (drv_HD_load(section) < 0) {
+ if (drv_HD_load (section) < 0) {
error ("%s: start display failed!", Name);
return -1;
}
- drv_HD_command (allControllers, 0x08, T_EXEC); /* Display off, cursor off, blink off */
+ 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, 0x06, T_EXEC); /* curser moves to right, no shift */
-
+
if ((Capabilities & CAP_HD66712) && DROWS > 2) {
- drv_HD_command (allControllers, Bits==8?0x3c:0x2c, T_EXEC); /* set extended register enable bit */
- drv_HD_command (allControllers, 0x09, T_EXEC); /* set 4-line mode */
- drv_HD_command (allControllers, Bits==8?0x38:0x28, T_EXEC); /* clear extended register enable bit */
+ drv_HD_command (allControllers, Bits == 8 ? 0x3c : 0x2c, T_EXEC); /* set extended register enable bit */
+ drv_HD_command (allControllers, 0x09, T_EXEC); /* set 4-line mode */
+ drv_HD_command (allControllers, Bits == 8 ? 0x38 : 0x28, T_EXEC); /* clear extended register enable bit */
}
-
- drv_HD_clear(); /* clear *both* displays */
+
+ drv_HD_clear(); /* clear *all* displays */
drv_HD_command (allControllers, 0x03, T_CLEAR); /* return home */
/* maybe set backlight */
if (Capabilities & CAP_BACKLIGHT) {
int backlight;
- if (cfg_number(section, "Backlight", 0, 0, 1, &backlight) > 0) {
+ if (cfg_number (section, "Backlight", 0, 0, 1, &backlight) > 0) {
info ("%s: backlight %s", Name, backlight ? "enabled" : "disabled");
drv_HD_backlight(backlight);
}
}
-
+
/* maybe set brightness */
if (Capabilities & CAP_BRIGHTNESS) {
int brightness;
- if (cfg_number(section, "Brightness", 0, 0, 3, &brightness) > 0) {
+ if (cfg_number (section, "Brightness", 0, 0, 3, &brightness) > 0) {
info ("%s: brightness level %d", Name, brightness);
drv_HD_brightness(brightness);
}
}
-
+
/* install keypad polling timer for LCM-162 */
if (Capabilities & CAP_LCM162) {
timer_add (drv_HD_LCM162_timer, NULL, 10, 0);
@@ -1169,7 +1266,7 @@ static int drv_HD_start (const char *section, const int quiet)
drv_HD_clear();
}
}
-
+
return 0;
}
@@ -1217,7 +1314,7 @@ int drv_HD_list (void)
{
int i;
- for (i=0; Models[i].type!=0xff; i++) {
+ for (i = 0; Models[i].type != 0xff; i++) {
printf ("%s ", Models[i].name);
}
return 0;
@@ -1241,8 +1338,8 @@ int drv_HD_init (const char *section, const int quiet)
/* real worker functions */
drv_generic_text_real_write = drv_HD_write;
drv_generic_text_real_defchar = drv_HD_defchar;
-
-
+
+
/* start display */
if ((ret=drv_HD_start (section, quiet))!=0)
return ret;
@@ -1250,7 +1347,7 @@ int drv_HD_init (const char *section, const int quiet)
/* initialize generic text driver */
if ((ret=drv_generic_text_init(section, Name))!=0)
return ret;
-
+
/* initialize generic icon driver */
if ((ret=drv_generic_text_icon_init())!=0)
return ret;
@@ -1296,13 +1393,14 @@ int drv_HD_init (const char *section, const int quiet)
/* close driver & display */
-int drv_HD_quit (const int quiet) {
-
+int drv_HD_quit (const int quiet)
+{
+
info("%s: shutting down.", Name);
-
+
drv_generic_text_quit();
-
- /* clear *both* displays */
+
+ /* clear display */
drv_HD_clear();
/* say goodbye... */
@@ -1322,5 +1420,3 @@ DRIVER drv_HD44780 = {
init: drv_HD_init,
quit: drv_HD_quit,
};
-
-