From 8b185a53fc6c35d570987ab9ff2c194dcaa24cd2 Mon Sep 17 00:00:00 2001 From: michael Date: Tue, 23 Dec 2008 13:37:07 +0000 Subject: patch from a.nielsen: inverted parport signals, support GPI on HD44780 git-svn-id: https://ssl.bulix.org/svn/lcd4linux/trunk@905 3ae390bd-cb1e-0410-b409-cd5a39f66f1f --- drv_HD44780.c | 79 +++++++++++++++++++++++++++++++++++++++++---------- drv_generic_parport.c | 34 ++++++++++++++++------ 2 files changed, 89 insertions(+), 24 deletions(-) diff --git a/drv_HD44780.c b/drv_HD44780.c index 5b8a4ad..9550f8d 100644 --- a/drv_HD44780.c +++ b/drv_HD44780.c @@ -111,6 +111,7 @@ static unsigned char SIGNAL_ENABLE3; static unsigned char SIGNAL_ENABLE4; static unsigned char SIGNAL_GPO; +static unsigned char SIGNAL_GPI; #ifdef WITH_PARPORT static unsigned char SIGNAL_BACKLIGHT; static unsigned char SIGNAL_POWER; @@ -127,7 +128,10 @@ static unsigned char SIGNAL_POWER; static int UseBusy = 0; #endif -/* buffer holding the GPO state */ +/* which data bits should have their logic inverted */ +static int invert_data_bits = 0; + +/* buffer holding the GPIO state */ #ifdef WITH_PARPORT static unsigned char GPO = 0; #endif @@ -146,13 +150,14 @@ typedef struct { #define CAP_BUSY4BIT (1<<5) #define CAP_HD66712 (1<<6) #define CAP_LCM162 (1<<7) +#define CAP_GPI (1<<8) #define BUS_PP CAP_PARPORT #define BUS_I2C CAP_I2C static MODEL Models[] = { - {0x01, "generic", CAP_PARPORT | CAP_I2C | CAP_GPO | CAP_BACKLIGHT}, + {0x01, "generic", CAP_PARPORT | CAP_I2C | CAP_GPO | CAP_GPI | CAP_BACKLIGHT}, {0x02, "Noritake", CAP_PARPORT | CAP_I2C | CAP_GPO | CAP_BRIGHTNESS}, {0x03, "Soekris", CAP_PARPORT | CAP_BUSY4BIT}, {0x04, "HD66712", CAP_PARPORT | CAP_I2C | CAP_GPO | CAP_BACKLIGHT | CAP_HD66712}, @@ -221,7 +226,7 @@ static void drv_HD_PP_busy(const int controller) /* 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 ^ invert_data_bits); } /* Address set-up time */ @@ -231,7 +236,7 @@ static void drv_HD_PP_busy(const int controller) if (Bits == 8) { drv_generic_parport_control(enable, enable); } else { - drv_generic_parport_data(SIGNAL_RW | enable); + drv_generic_parport_data((SIGNAL_RW | enable) ^ invert_data_bits); } counter = 0; @@ -287,9 +292,9 @@ static void drv_HD_PP_busy(const int controller) drv_generic_parport_control(SIGNAL_RW | SIGNAL_RS, 0); } else { /* Lower EN */ - drv_generic_parport_data(SIGNAL_RW); + drv_generic_parport_data(SIGNAL_RW ^ invert_data_bits); ndelay(T_AH); - drv_generic_parport_data(0); + drv_generic_parport_data(0 ^ invert_data_bits); } /* set data-lines to output */ @@ -320,19 +325,19 @@ static void drv_HD_PP_nibble(const unsigned char controller, const unsigned char /* clear ENABLE */ /* put data on DB1..DB4 */ /* nibble already contains RS bit! */ - drv_generic_parport_data(nibble); + drv_generic_parport_data(nibble ^ invert_data_bits); /* Address set-up time */ ndelay(T_AS); /* rise ENABLE */ - drv_generic_parport_data(nibble | enable); + drv_generic_parport_data((nibble | enable) ^ invert_data_bits); /* Enable pulse width */ ndelay(T_PW); /* lower ENABLE */ - drv_generic_parport_data(nibble); + drv_generic_parport_data(nibble ^ invert_data_bits); } @@ -372,7 +377,7 @@ static void drv_HD_PP_command(const unsigned char controller, const unsigned cha enable |= SIGNAL_ENABLE4; /* put data on DB1..DB8 */ - drv_generic_parport_data(cmd); + drv_generic_parport_data(cmd ^ invert_data_bits); /* clear RW and RS */ drv_generic_parport_control(SIGNAL_RW | SIGNAL_RS, 0); @@ -438,7 +443,7 @@ static void drv_HD_PP_data(const unsigned char controller, const char *string, c } /* put data on DB1..DB8 */ - drv_generic_parport_data(*(string++)); + drv_generic_parport_data((*(string++)) ^ invert_data_bits); /* send command */ drv_generic_parport_toggle(enable, 1, T_PW); @@ -541,6 +546,8 @@ static int drv_HD_PP_load(const char *section) return -1; if ((SIGNAL_GPO = drv_generic_parport_wire_ctrl("GPO", "GND")) == 0xff) return -1; + if ((SIGNAL_GPI = drv_generic_parport_wire_ctrl("GPI", "GND")) == 0xff) + return -1; if ((SIGNAL_POWER = drv_generic_parport_wire_ctrl("POWER", "GND")) == 0xff) return -1; } @@ -552,6 +559,9 @@ static int drv_HD_PP_load(const char *section) if (SIGNAL_GPO == 0) { Capabilities &= ~CAP_GPO; } + if (SIGNAL_GPI == 0) { + Capabilities &= ~CAP_GPI; + } /* Timings */ @@ -601,7 +611,7 @@ static int drv_HD_PP_load(const char *section) SIGNAL_BACKLIGHT | SIGNAL_GPO | SIGNAL_POWER, 0); } else { drv_generic_parport_control(SIGNAL_BACKLIGHT | SIGNAL_GPO | SIGNAL_POWER, 0); - drv_generic_parport_data(0); + drv_generic_parport_data(0 ^ invert_data_bits); } /* set direction: write */ @@ -667,7 +677,7 @@ static void drv_HD_PP_stop(void) SIGNAL_RW | SIGNAL_ENABLE | SIGNAL_ENABLE2 | SIGNAL_ENABLE3 | SIGNAL_ENABLE4 | SIGNAL_BACKLIGHT | SIGNAL_GPO, 0); } else { - drv_generic_parport_data(0); + drv_generic_parport_data(0 ^ invert_data_bits); drv_generic_parport_control(SIGNAL_BACKLIGHT | SIGNAL_GPO | SIGNAL_POWER, 0); } @@ -965,7 +975,7 @@ static int drv_HD_GPO(const int num, const int val) } /* put data on DB1..DB8 */ - drv_generic_parport_data(GPO); + drv_generic_parport_data(GPO ^ invert_data_bits); /* 74HCT573 set-up time */ ndelay(T_GPO_ST); @@ -977,6 +987,27 @@ static int drv_HD_GPO(const int num, const int val) return v; } +static int drv_HD_GPI(const int num) +{ + int v; + + /* switch to read mode */ + drv_generic_parport_direction(1); + drv_generic_parport_control(SIGNAL_GPI, SIGNAL_GPI); + + /* 74HCT573 set-up time + enable pulse width */ + ndelay(T_GPO_ST + T_GPO_PW); + + /* read data from DB1..DB8 */ + v = drv_generic_parport_read() ^ invert_data_bits; + + /* switch back to write mode */ + drv_generic_parport_control(SIGNAL_GPI, 0); + drv_generic_parport_direction(0); + + return (v >> num) & 1; +} + #endif @@ -1042,7 +1073,7 @@ 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, i; + int rows = -1, cols = -1, gpos = -1, gpis = -1, i; int size_defined = 0; int size_missing = 0; @@ -1199,6 +1230,23 @@ static int drv_HD_start(const char *section, const int quiet) info("%s: using %d GPO's", Name, GPOS); } + if (cfg_number(section, "GPIs", 0, 0, 8, &gpis) < 0) + return -1; + if (gpis > 0 && !(Capabilities & CAP_GPI)) { + error("%s: Model '%s' does not support GPI's!", Name, Models[Model].name); + gpis = 0; + } + GPIS = gpis; + if (GPIS > 0) { + info("%s: using %d GPI's", Name, GPIS); + } + + if (cfg_number(section, "InvertDataBits", 0, 0, 256, &invert_data_bits) < 0) + return -1; + if (invert_data_bits) { + info("%s: inverting data bits (mask %02X)", Name, invert_data_bits); + } + if (drv_HD_load(section) < 0) { error("%s: start display failed!", Name); return -1; @@ -1331,6 +1379,7 @@ int drv_HD_init(const char *section, const int quiet) drv_generic_text_real_defchar = drv_HD_defchar; #ifdef WITH_PARPORT drv_generic_gpio_real_set = drv_HD_GPO; + drv_generic_gpio_real_get = drv_HD_GPI; #endif /* start display */ diff --git a/drv_generic_parport.c b/drv_generic_parport.c index e501ef0..457a6bd 100644 --- a/drv_generic_parport.c +++ b/drv_generic_parport.c @@ -65,6 +65,9 @@ #define PARPORT_STATUS_BUSY 0x80 #endif +/* these signals are inverted by hardware on the parallel port */ +#define PARPORT_CONTROL_INVERTED (PARPORT_CONTROL_STROBE | PARPORT_CONTROL_SELECT | PARPORT_CONTROL_AUTOFD) + #if !defined(WITH_OUTB) && !defined(WITH_PPDEV) #error neither outb() nor ppdev() possible #error cannot compile parallel port driver @@ -82,6 +85,9 @@ static char *Section = ""; static unsigned short Port = 0; static char *PPdev = NULL; +/* Any bits set here will have their logic inverted at the parallel port */ +static unsigned char inverted_control_bits = 0; + /* initial value taken from linux/parport_pc.c */ static unsigned char ctr = 0xc; @@ -205,23 +211,30 @@ int drv_generic_parport_close(void) static unsigned char drv_generic_parport_signal_ctrl(const char *name, const char *signal) { unsigned char wire; + int invert = 0; + + /* Prefixing a signal name with '-' inverts the logic */ + if (signal[0] == '-') { + invert = 1; + signal++; + } if (strcasecmp(signal, "STROBE") == 0) { wire = PARPORT_CONTROL_STROBE; - info("%s: wiring: DISPLAY:%-9s - PARPORT:STROBE (Pin 1)", Driver, name); + info("%s: wiring: DISPLAY:%-9s - PARPORT:STROBE (Pin 1)%s", Driver, name, invert ? " [inverted]" : ""); } else if (strcasecmp(signal, "AUTOFD") == 0) { wire = PARPORT_CONTROL_AUTOFD; - info("%s: wiring: DISPLAY:%-9s - PARPORT:AUTOFD (Pin 14)", Driver, name); + info("%s: wiring: DISPLAY:%-9s - PARPORT:AUTOFD (Pin 14)%s", Driver, name, invert ? " [inverted]" : ""); } else if (strcasecmp(signal, "INIT") == 0) { wire = PARPORT_CONTROL_INIT; - info("%s: wiring: DISPLAY:%-9s - PARPORT:INIT (Pin 16)", Driver, name); + info("%s: wiring: DISPLAY:%-9s - PARPORT:INIT (Pin 16)%s", Driver, name, invert ? " [inverted]" : ""); } else if (strcasecmp(signal, "SLCTIN") == 0) { wire = PARPORT_CONTROL_SELECT; - info("%s: wiring: DISPLAY:%-9s - PARPORT:SLCTIN (Pin 17)", Driver, name); + info("%s: wiring: DISPLAY:%-9s - PARPORT:SLCTIN (Pin 17)%s", Driver, name, invert ? " [inverted]" : ""); } else if (strcasecmp(signal, "SELECT") == 0) { wire = PARPORT_CONTROL_SELECT; error("%s: SELECT is deprecated. Please use SLCTIN instead!", Driver); - info("%s: wiring: DISPLAY:%-9s - PARPORT:SLCTIN (Pin 17)", Driver, name); + info("%s: wiring: DISPLAY:%-9s - PARPORT:SLCTIN (Pin 17)%s", Driver, name, invert ? " [inverted]" : ""); } else if (strcasecmp(signal, "GND") == 0) { wire = 0; info("%s: wiring: DISPLAY:%-9s - PARPORT:GND", Driver, name); @@ -231,6 +244,10 @@ static unsigned char drv_generic_parport_signal_ctrl(const char *name, const cha return 0xff; } + if (invert) { + inverted_control_bits |= wire; + } + return wire; } @@ -401,7 +418,7 @@ void drv_generic_parport_control(const unsigned char mask, const unsigned char v return; /* Strobe, Select and AutoFeed are inverted! */ - val = mask & (value ^ (PARPORT_CONTROL_STROBE | PARPORT_CONTROL_SELECT | PARPORT_CONTROL_AUTOFD)); + val = mask & (value ^ PARPORT_CONTROL_INVERTED ^ inverted_control_bits); #ifdef WITH_PPDEV if (PPdev) { @@ -433,9 +450,8 @@ void drv_generic_parport_toggle(const unsigned char bits, const int level, const value2 = level ? 0 : bits; /* Strobe, Select and AutoFeed are inverted! */ - value1 = bits & (value1 ^ (PARPORT_CONTROL_STROBE | PARPORT_CONTROL_SELECT | PARPORT_CONTROL_AUTOFD)); - value2 = bits & (value2 ^ (PARPORT_CONTROL_STROBE | PARPORT_CONTROL_SELECT | PARPORT_CONTROL_AUTOFD)); - + value1 = bits & (value1 ^ PARPORT_CONTROL_INVERTED ^ inverted_control_bits); + value2 = bits & (value2 ^ PARPORT_CONTROL_INVERTED ^ inverted_control_bits); #ifdef WITH_PPDEV if (PPdev) { -- cgit v1.2.3