From d38b3dc0f50ff5049f07fbeac284fcd17f3cae30 Mon Sep 17 00:00:00 2001 From: michael Date: Thu, 18 Jun 2015 16:44:09 +0000 Subject: drv_HD44780: add 8bit i2c mode for HD44780 by Michael Grzeschik git-svn-id: https://ssl.bulix.org/svn/lcd4linux/trunk@1202 3ae390bd-cb1e-0410-b409-cd5a39f66f1f --- drv_HD44780.c | 82 ++++++++++++++++++++++++++++++++++++++----------------- drv_generic_i2c.c | 67 +++++++++++++++++++++++++++++++++++---------- drv_generic_i2c.h | 3 +- 3 files changed, 112 insertions(+), 40 deletions(-) diff --git a/drv_HD44780.c b/drv_HD44780.c index 26f0bc9..7ca979c 100644 --- a/drv_HD44780.c +++ b/drv_HD44780.c @@ -706,10 +706,10 @@ static void drv_HD_PP_stop(void) */ -static void drv_HD_I2C_nibble(unsigned char controller, unsigned char nibble) +static void drv_HD_I2C(unsigned char controller, unsigned char byte, int rs, int rw) { unsigned char enable; - unsigned char command; /* this is actually the first data byte on the PCF8574 */ + unsigned char command = 0; /* this is actually the first data byte on the PCF8574 */ unsigned char data_block[2]; /* enable signal: 'controller' is a bitmask */ /* bit n .. send to controller #n */ @@ -738,28 +738,51 @@ static void drv_HD_I2C_nibble(unsigned char controller, unsigned char nibble) The main advantage we see is that we do 2 less IOCTL's from our driver. */ - command = nibble; - data_block[0] = nibble | enable; - data_block[1] = nibble; + if (Bits == 4) { + if (rw) + byte |= SIGNAL_RW; + if (rs) + byte |= SIGNAL_RS; + command = byte; + data_block[0] = byte | enable; + data_block[1] = byte; + + } else if (Bits == 8) { + if (rw) + command |= SIGNAL_RW; + if (rs) + command |= SIGNAL_RS; + + data_block[0] = byte; + data_block[1] = enable; + } - drv_generic_i2c_command(command, data_block, 2); + drv_generic_i2c_command(command, data_block, 2, Bits); } static void drv_HD_I2C_byte(const unsigned char controller, const unsigned char data) { /* send data with RS enabled */ - drv_HD_I2C_nibble(controller, ((data >> 4) & 0x0f) | SIGNAL_RS); - drv_HD_I2C_nibble(controller, (data & 0x0f) | SIGNAL_RS); + if (Bits == 4) { + drv_HD_I2C(controller, ((data >> 4) & 0x0f), 1, 0); + drv_HD_I2C(controller, (data & 0x0f), 1, 0); + } else if (Bits == 8) { + drv_HD_I2C(controller, data, 1, 0); + } } static void drv_HD_I2C_command(const unsigned char controller, const unsigned char cmd, __attribute__ ((unused)) const unsigned long delay) { - /* send data with RS disabled */ - drv_HD_I2C_nibble(controller, ((cmd >> 4) & 0x0f)); - drv_HD_I2C_nibble(controller, ((cmd) & 0x0f)); + /* send command data with RS disabled */ + if (Bits == 4) { + drv_HD_I2C(controller, ((cmd >> 4) & 0x0f), 0, 0); + drv_HD_I2C(controller, ((cmd) & 0x0f), 0, 0); + } else if (Bits == 8) { + drv_HD_I2C(controller, cmd, 0, 0); + } } static void drv_HD_I2C_data(const unsigned char controller, const char *string, const int len, __attribute__ ((unused)) @@ -781,13 +804,14 @@ static int drv_HD_I2C_load(const char *section) { if (cfg_number(section, "Bits", 8, 4, 8, &Bits) < 0) return -1; - if (Bits != 4) { - error("%s: bad %s.Bits '%d' from %s, should be '4'", Name, section, Bits, cfg_source()); - return -1; - } info("%s: using %d bit mode", Name, Bits); + 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; + } + if (drv_generic_i2c_open(section, Name) != 0) { error("%s: could not initialize i2c attached device!", Name); return -1; @@ -804,16 +828,24 @@ static int drv_HD_I2C_load(const char *section) if ((SIGNAL_GPO = drv_generic_i2c_wire("GPO", "GND")) == 0xff) return -1; - /* initialize display */ - drv_HD_I2C_nibble(allControllers, 0x03); - udelay(T_INIT1); /* 4 Bit mode, wait 4.1 ms */ - drv_HD_I2C_nibble(allControllers, 0x03); - udelay(T_INIT2); /* 4 Bit mode, wait 100 us */ - drv_HD_I2C_nibble(allControllers, 0x03); - udelay(T_INIT1); /* 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 */ + if (Bits == 4) { + /* initialize display */ + drv_HD_I2C(allControllers, 0x02, 0, 0); + udelay(T_INIT1); /* 4 Bit mode, wait 4.1 ms */ + drv_HD_I2C(allControllers, 0x03, 0, 0); + udelay(T_INIT2); /* 4 Bit mode, wait 100 us */ + drv_HD_I2C(allControllers, 0x03, 0, 0); + udelay(T_INIT1); /* 4 Bit mode, wait 4.1 ms */ + drv_HD_I2C(allControllers, 0x02, 0, 0); + 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 */ + } else if (Bits == 8) { + drv_HD_I2C(allControllers, 0x30, 0, 0); /* 8 Bit mode, wait 4.1 ms */ + udelay(T_INIT1); /* 8 Bit mode, wait 4.1 ms */ + drv_HD_I2C(allControllers, 0x30, 0, 0); /* 8 Bit mode, wait 100 us */ + udelay(T_INIT2); /* 8 Bit mode, wait 4.1 ms */ + drv_HD_I2C_command(allControllers, 0x38, T_EXEC); /* 8 Bit mode, 1/16 duty cycle, 5x8 font */ + } info("%s: I2C initialization done", Name); diff --git a/drv_generic_i2c.c b/drv_generic_i2c.c index 2170b0c..0976bc6 100644 --- a/drv_generic_i2c.c +++ b/drv_generic_i2c.c @@ -62,7 +62,8 @@ static char *Driver = ""; static char *Section = ""; static int i2c_device; - +static int ctrldev; +static int datadev; static void my_i2c_smbus_write_byte_data(const int device, const unsigned char val) { @@ -91,34 +92,50 @@ static void my_i2c_smbus_read_byte_data(const int device, const unsigned char da } #endif +int drv_generic_i2c_pre_write(int dev) +{ + + info("%s: selecting slave device 0x%x", Driver, dev); + if (ioctl(i2c_device, I2C_SLAVE, dev) < 0) { + error("%s: error selecting slave device 0x%x\n", Driver, dev); + return -EPIPE; + } + + info("%s: initializing I2C slave device 0x%x for output", Driver, dev); + if (i2c_smbus_write_byte_data(i2c_device, 3, 0) < 0) { + error("%s: error initializing device 0x%x\n", Driver, dev); + close(i2c_device); + } + + return 0; +} int drv_generic_i2c_open(const char *section, const char *driver) { - int dev; char *bus, *device; udelay_init(); Section = (char *) section; Driver = (char *) driver; bus = cfg_get(Section, "Port", NULL); device = cfg_get(Section, "Device", NULL); - dev = atoi(device); + ctrldev = atoi(device); + device = cfg_get(Section, "DDevice", NULL); + datadev = atoi(device); + info("%s: initializing I2C bus %s", Driver, bus); if ((i2c_device = open(bus, O_WRONLY)) < 0) { error("%s: I2C bus %s open failed !\n", Driver, bus); goto exit_error; } - info("%s: selecting slave device 0x%x", Driver, dev); - if (ioctl(i2c_device, I2C_SLAVE, dev) < 0) { - error("%s: error selecting slave device 0x%x\n", Driver, dev); - goto exit_error; - } - info("%s: initializing I2C slave device 0x%x", Driver, dev); - if (i2c_smbus_write_quick(i2c_device, I2C_SMBUS_WRITE) < 0) { - error("%s: error initializing device 0x%x\n", Driver, dev); - close(i2c_device); + if (datadev) { + if (drv_generic_i2c_pre_write(datadev) < 0) + goto exit_error; } + if (drv_generic_i2c_pre_write(ctrldev) < 0) + goto exit_error; + return 0; exit_error: @@ -172,8 +189,30 @@ void drv_generic_i2c_data(const unsigned char data) my_i2c_smbus_write_byte_data(i2c_device, data); } +static void i2c_out(int dev, unsigned char val) +{ + info("%s: initializing I2C slave device 0x%x", Driver, dev); + if (ioctl(i2c_device, I2C_SLAVE, dev) < 0) { + error("%s: error selecting slave device 0x%x\n", Driver, dev); + return; + } -void drv_generic_i2c_command(const unsigned char command, /*const */ unsigned char *data, const unsigned char length) + i2c_smbus_write_byte_data(i2c_device, 1, val); +} + +void drv_generic_i2c_command(const unsigned char command, /*const */ unsigned char *data, const unsigned char length, + int bits) { - i2c_smbus_write_block_data(i2c_device, command, length, data); + if (bits == 4) { + i2c_smbus_write_block_data(i2c_device, command, length, data); + } else if (bits == 8 && datadev) { + /* set data on pins */ + info("cmd: %08x, data0: %08x, data1: %08x\n", command, data[0], data[1]); + i2c_out(datadev, data[0]); + /* set enable pin including optional rs and rw */ + i2c_out(ctrldev, command | data[1]); + /* unset enable pin including optional rs and rw */ + i2c_out(ctrldev, command); + } + } diff --git a/drv_generic_i2c.h b/drv_generic_i2c.h index 2cc6a02..da7347d 100644 --- a/drv_generic_i2c.h +++ b/drv_generic_i2c.h @@ -57,6 +57,7 @@ int drv_generic_i2c_close(void); unsigned char drv_generic_i2c_wire(const char *name, const char *deflt); void drv_generic_i2c_byte(const unsigned char data); void drv_generic_i2c_data(const unsigned char data); -void drv_generic_i2c_command(const unsigned char command, /*const */ unsigned char *data, const unsigned char length); +void drv_generic_i2c_command(const unsigned char command, /*const */ unsigned char *data, const unsigned char length, + int bits); #endif -- cgit v1.2.3