From: Michael R. <mi...@re...> - 2015-06-18 17:12:12
|
Patch has been applied an checked in. Thanks a lot! Am 2015-06-18 um 18:00 schrieb Michael Grzeschik: > From: Michael Grzeschik <m.g...@pe...> > > This patch adds support for dual i2c io-expander > based 8bit support for HD44780. It multiplexes the > switch between the data and databits. > > Signed-off-by: Michael Grzeschik <m.g...@pe...> > --- > drv_HD44780.c | 82 ++++++++++++++++++++++++++++++++++++++----------------- > drv_generic_i2c.c | 65 +++++++++++++++++++++++++++++++++---------- > drv_generic_i2c.h | 2 +- > 3 files changed, 109 insertions(+), 40 deletions(-) > > diff --git a/drv_HD44780.c b/drv_HD44780.c > index 26f0bc9..7f4a56a 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..1bee16f 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,49 @@ 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 +188,29 @@ 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; > + } > + > + 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) > +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..bd68e44 100644 > --- a/drv_generic_i2c.h > +++ b/drv_generic_i2c.h > @@ -57,6 +57,6 @@ 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 > -- Michael Reinelt <mi...@re...> http://home.pages.at/reinelt GPG-Key 0xDF13BA50 ICQ #288386781 |