aboutsummaryrefslogtreecommitdiffstats
path: root/drv_HD44780.c
diff options
context:
space:
mode:
Diffstat (limited to 'drv_HD44780.c')
-rw-r--r--drv_HD44780.c121
1 files changed, 102 insertions, 19 deletions
diff --git a/drv_HD44780.c b/drv_HD44780.c
index 93faa83..fcc0c27 100644
--- a/drv_HD44780.c
+++ b/drv_HD44780.c
@@ -1,9 +1,9 @@
-/* $Id: drv_HD44780.c 773 2007-02-25 12:39:09Z michael $
- * $URL: https://ssl.bulix.org/svn/lcd4linux/branches/0.10.1/drv_HD44780.c $
+/* $Id: drv_HD44780.c 1066 2009-11-19 04:32:13Z edman007 $
+ * $URL: https://ssl.bulix.org/svn/lcd4linux/trunk/drv_HD44780.c $
*
* new style driver for HD44780-based displays
*
- * Copyright (C) 2003 Michael Reinelt <reinelt@eunet.at>
+ * Copyright (C) 2003 Michael Reinelt <michael@reinelt.co.at>
* Copyright (C) 2004 The LCD4Linux Team <lcd4linux-devel@users.sourceforge.net>
*
* Support for I2C bus
@@ -63,12 +63,15 @@
#include "widget_text.h"
#include "widget_icon.h"
#include "widget_bar.h"
+#include "widget_keypad.h"
#include "drv.h"
#include "drv_generic_text.h"
#include "drv_generic_gpio.h"
#ifdef WITH_PARPORT
#include "drv_generic_parport.h"
+#include "drv_generic_keypad.h"
+#include "widget_keypad.h"
#endif
#ifdef WITH_I2C
@@ -109,6 +112,7 @@ static unsigned char SIGNAL_ENABLE4;
static unsigned char SIGNAL_GPO;
#ifdef WITH_PARPORT
+static unsigned char SIGNAL_GPI;
static unsigned char SIGNAL_BACKLIGHT;
static unsigned char SIGNAL_POWER;
#endif
@@ -124,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
@@ -143,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},
@@ -218,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 */
@@ -228,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;
@@ -284,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 */
@@ -317,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);
}
@@ -369,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);
@@ -435,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);
@@ -538,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;
}
@@ -549,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 */
@@ -598,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 */
@@ -664,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);
}
@@ -962,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);
@@ -974,11 +987,38 @@ 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
#ifdef WITH_PARPORT
+
+static int drv_HD_LCM162_keypad_handler(const int num)
+{
+ return num;
+}
+
static void drv_HD_LCM162_timer(void __attribute__ ((unused)) * notused)
{
static unsigned char data = 0x00;
@@ -1000,8 +1040,28 @@ static void drv_HD_LCM162_timer(void __attribute__ ((unused)) * notused)
if (data != temp) {
data = temp;
+ int KEYPAD_VAL = 0;
keynum = (data & mask3 ? 1 : 0) + (data & mask5 ? 2 : 0);
+ switch (keynum) {
+ default:
+ case 0:
+ KEYPAD_VAL = WIDGET_KEY_CANCEL;
+ break;
+ case 1:
+ KEYPAD_VAL = WIDGET_KEY_UP;
+ break;
+ case 2:
+ KEYPAD_VAL = WIDGET_KEY_CONFIRM;
+ break;
+ case 3:
+ KEYPAD_VAL = WIDGET_KEY_DOWN;
+ break;
+ }
+
updown = (data & mask6 ? 1 : 0);
+ KEYPAD_VAL += updown ? WIDGET_KEY_PRESSED : WIDGET_KEY_RELEASED;
+
+ drv_generic_keypad_press(KEYPAD_VAL);
debug("key %d press %d", keynum, updown);
}
@@ -1013,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;
@@ -1170,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;
@@ -1212,6 +1289,7 @@ static int drv_HD_start(const char *section, const int quiet)
#ifdef WITH_PARPORT
if (Capabilities & CAP_LCM162) {
timer_add(drv_HD_LCM162_timer, NULL, 10, 0);
+ drv_generic_keypad_real_press = drv_HD_LCM162_keypad_handler;
}
#endif
@@ -1287,7 +1365,7 @@ int drv_HD_init(const char *section, const int quiet)
int asc255bug;
int ret;
- info("%s: %s", Name, "$Rev: 773 $");
+ info("%s: %s", Name, "$Rev: 1066 $");
/* display preferences */
XRES = 5; /* pixel width of one char */
@@ -1301,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 */
@@ -1332,6 +1411,10 @@ int drv_HD_init(const char *section, const int quiet)
if ((ret = drv_generic_gpio_init(section, Name)) != 0)
return ret;
+#ifdef WITH_PARPORT
+ if ((ret = drv_generic_keypad_init(section, Name)) != 0)
+ return ret;
+#endif
/* register text widget */
wc = Widget_Text;
wc.draw = drv_generic_text_draw;