mirror of
https://github.com/netfun2000/lcd4linux.git
synced 2026-02-27 09:44:34 +08:00
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
This commit is contained in:
+64
-15
@@ -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 */
|
||||
|
||||
+25
-9
@@ -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) {
|
||||
|
||||
Reference in New Issue
Block a user