Very nice. I like it.
It now compiles and runs using existing Liquidcrystal code on 0022, and 1.0rc2
I've tested this on this shield: http://emartee.com/product/42054/Arduino%20Keypad%20LCD%20Shield%20V2.0
Unfortunately, I can't tell you which LCD it is as it is soldered on the shield.
I think the challenge will be for things like I2c and trying to be compatible with other i2c
implementations and to not break other lcd libraries.
For example, your i2c backpack and backpacks
like this: https://www.adafruit.com/products/292
or this: http://emartee.com/product/42098/Wrobot%20IIC/I2C%20LCD%201602%20Shield%20%20B
don't use the same pinout for the bits from the i2c register output going into the hd44780 interface.
Many Arduino users are quite hardware ignorant and may really struggle with these types of differences.
I'm not sure how to best support these different hd44780 I2C backpacks and yet make it easy for the Arduino user.
Its a real tough challenge.
Some vendors use a separate lcd library for their board. This is quite simple and avoids any compatibility
or library collisions as it is a separate library and the user simply copies
over the .cpp and .h files into the libraries directory and thats it. They include the vendors "xxx_i2c.h" header
and then it all works just like the LiquidCrystal library.
While adafruit has a seperate custom i2c lcd library for their backpack: https://github.com/adafruit/MCP23008-library
Adafruit also now has released a multi headed LiquidCrystal library that works for both 4 bit parallel and their
own i2c or SPI: https://github.com/adafruit/LiquidCrystal
Their implementation is slower than a real i2c implementation as it uses an "arduino like" interface across the i2c. i.e. they
do pinMode(), DigitalWrite() type operations through the i2c to control the lcd pins.
So it does independent i2c operations for setting every single individual hd44780 signal.
It does have the advantage that if they would update their i2c constructor they could configure which
i2c output register bit controls which lcd signal. Today they have it hard coded to their own i2c backpack
but this could allow it work with any backpack.
I like your implementation as it can be made to support any hd4480 backpack.
I think the challenge is how to deal with all these different interfaces when replacing the LiquidCrystal library.
i.e. Your library cannot coexist with the latest AdaFruit library. Both want to replace the LiquidCrystal library
and both have hardcoded i2c implementations that are incompatible with each other.
From an end users perspective, it gets tricky at best and more than likely frustrating with the current state
of libraries in that if you have different i2c backpacks, it may or may not be possible to control them with just
sketch changes. You may have to replace LiquidCrystal libraries between sketch builds for the different
boards. And that is pretty ugly/painful.
As it is today, the i2c lcd libraries look a bit problematic and painful to use if you have more than a single
vendor's i2c lcd backpack.
I think with your library model, it can be resolved.
It could be through either adding additional supported "boards", or by updating the i2c constructors to support
the ability to configure which hd44780 pin is connected to which i2c register bit. kind of the way the
existing LiquidCrystal constructors work with the 4 bit interface. In the case of i2c, the i2c register bit number
would be specified rather than an arduino pin number.
I think the latter, while not the absolute fastest way to run the interface, offers the greatest flexibility and
ease of use for the users especially those that want/need to support different i2c/spi lcd backpacks
that are wired up differently.
On performance tuning, I would caution you to be careful when using some of the techniques that the code is
currently using. For example, in functions like pulseEnable() some of the delays have been removed.
This is making an assumption about a particular API implementation [ digitalWrite() ] that
offers no such guarantee. ie. digital does not promise to take any particular amount of time.
So it theoretically could take zero time. While 0 really isn't reality, much smaller than 1us or even
the needed 450ns is a potential reality. Consider if this library is to be ported to say the chipKit or the Maple
then you may have issues. Also if the arduino code is compiled differently by compiling all the code together
vs seperately and building core libraries you can get optimizations that can dramatically affect
the timing. If you replace the poor Arduino core code with smarter code, then it could
potentially optimize the digitalWrite() functions down to single cycle instructions which on a standard arduino board
is only 62.5ns
If you still want to go down the path of trying to squeeze out the performance by removing or reducing delays like this,
I'd encourage using some sort of ifdef that can turn them back on to insert the proper delays for environments
that have faster digitalWrite() implementations.
BTW, if you want to step just a bit outside of the Arduino core library functions, there are other delay functions
that can offer shorter than 1us delays with much better accuracy than the Arduino delayMicroseconds() function
which has terrible accuracy.