correct logic hazard in latch and load nybble; was transitioning control lines at the same time as enable, causing spurious behaviour on less-tolerant displays

improve timing parameters in init sequences for better display compatibility

correct (row,col) -> address calculation; affects 4-line displays

update comments in header and readme
This commit is contained in:
ziggurat29 2016-05-29 11:09:00 -05:00
parent 4cc722aa1a
commit 4643fcdfd8
3 changed files with 43 additions and 21 deletions

View File

@ -63,9 +63,9 @@
/* timing characteristics of the LCD interface */
#define DELAY_US_NYBBLE0 200
#define DELAY_US_NYBBLE1 100
#define DELAY_US_WRITE 35
#define DELAY_US_NYBBLE0 20
#define DELAY_US_NYBBLE1 10
#define DELAY_US_WRITE 40
#define DELAY_US_HOMECLEAR 1500
/* HD44780 commands */
@ -259,7 +259,7 @@ static inline uint8_t rc2addr(FAR struct pcf8574_lcd_dev_s *priv,
* of first line, and fourth line is a continuation of second.
*/
return (row - 2) * 0x40 + (col - priv->cfg.cols);
return (row - 2) * 0x40 + (col + priv->cfg.cols);
}
}
@ -383,9 +383,14 @@ static void latch_nybble(FAR struct pcf8574_lcd_dev_s *priv, uint8_t nybble,
en_bit = 1 << priv->cfg.en;
rs_bit = rs ? (1 << priv->cfg.rs) : 0;
/* Put the nybble, preserving backlight, reset R/~W and set EN and maybe RS */
/* Put the nybble, preserving backlight, reset R/~W and maybe RS */
lcddata = prepare_nybble(priv, nybble) | priv->bl_bit | en_bit | rs_bit;
lcddata = prepare_nybble(priv, nybble) | priv->bl_bit | rs_bit;
pca8574_write(priv, lcddata);
/* Now set EN */
lcddata |= en_bit;
pca8574_write(priv, lcddata);
up_udelay(DELAY_US_NYBBLE0); /* setup */
@ -419,9 +424,14 @@ static uint8_t load_nybble(FAR struct pcf8574_lcd_dev_s *priv, bool rs)
rs_bit = rs ? (1 << priv->cfg.rs) : 0;
rw_bit = 1 << priv->cfg.rw;
/* Put highs on the data lines, preserve, set R/~W and set EN and maybe RS */
/* Put highs on the data lines, preserve, set R/~W and maybe RS */
lcddata = prepare_nybble(priv, 0x0f) | priv->bl_bit | en_bit | rw_bit | rs_bit;
lcddata = prepare_nybble(priv, 0x0f) | priv->bl_bit | rw_bit | rs_bit;
pca8574_write(priv, lcddata);
/* Now set EN */
lcddata |= en_bit;
pca8574_write(priv, lcddata);
up_udelay(DELAY_US_NYBBLE0); /* setup */
@ -538,7 +548,7 @@ static void lcd_init(FAR struct pcf8574_lcd_dev_s *priv)
{
/* Wait for more than 15 ms after Vcc for the LCD to stabilize */
usleep(20000);
usleep(50000);
/* Perform the init sequence. This sequence of commands is constructed so
* that it will get the device into nybble mode irrespective of what state
@ -548,7 +558,7 @@ static void lcd_init(FAR struct pcf8574_lcd_dev_s *priv)
* the remainder of operations.
*/
/* Send Command 0x30, set 8-bit mode, and wait > 4.1 ms*/
/* Send Command 0x30, set 8-bit mode, and wait > 4.1 ms */
latch_nybble(priv, 0x30>>4, false);
usleep(5000);
@ -556,15 +566,17 @@ static void lcd_init(FAR struct pcf8574_lcd_dev_s *priv)
/* Send Command 0x30, set 8-bit mode, and wait > 100 us */
latch_nybble(priv, 0x30>>4, false);
usleep(200);
usleep(5000);
/* Send Command 0x30, set 8-bit mode */
latch_nybble(priv, 0x30>>4, false);
usleep(200);
/* now Function set: Set interface to be 4 bits long (only 1 cycle write for the first time). */
latch_nybble(priv, 0x20>>4, false);
usleep(5000);
/* Function set: DL=0;Interface is 4 bits, N=1 (2 Lines), F=0 (5x8 dots font) */

View File

@ -225,7 +225,7 @@ Example of programming a character image:
Now character '\x04' will display as an 'up arrow'.
Note, you might consider avoiding the use of code point 0x00 unless
absolutely needed, because the embedded nul character can cause
you absolutely need it, because the embedded nul character can cause
problems. The driver, and write() apis are binary, and unaffected,
but things like printf() and puts() assume C-style strings, and are
affected.
@ -237,9 +237,16 @@ Troubleshooting
bus timeouts that suggest a non-responsive slave.
* Check your board wiring and configuration specification. Buzz
out the lines if you have to.
* Con't forget to check the 'contrast' potentiometer. The voltage
at the central wiper should be approximately 0.29 V. The useful
range of voltages at this pin is very narrow, and outside that
range there will be nothing visible on the display, so most of the
turn range of the pot is non-useful. Much of human life has been
wasted in the rediscovery of this farcically idiotic
* Remember to set the (ros,cols) geometry in pcf8574_lcd_backpack_config_s
before registration of the driver, since this cannot be determined
programmatically.
* If the driver registration step seems to 'hang' it could be the I2C
driver performing retries due to no response from the LCD backpack. Check
the address. Turning on debug output for I2C can help make this visible.
* Don't forget to check the 'contrast' potentiometer. The voltage at the
central wiper should be approximately 0.3 V - 2.4 V, but the actual value
is is dependent on the physics of the attached LCD module. The useful
range of voltages at this pin for any given LCD is quite narrow, and
outside that range there will be nothing visible on the display, so most
of the turn range of the pot is non-useful. It's less 'contrast' and
more 'LCD segment drive bias'.

View File

@ -58,12 +58,15 @@
* Pretty much anything on the market except 4x40, which really consists of two
* separate 2x40 controllers, and the I2C backpack doesn't support those due
* to the second 'E' line being needed.
* Additionally, you still need to set the (row,col) geometry explicitly, since
* there is not a means of determining this dynamically.
* Consider these 'informative'.
* XXX Note, actual testing has been done on LCD_I2C_BACKPACK_CFG_MJKDZ only,
* the others come from online research.
* XXX Note, actual testing has been done on LCD_I2C_BACKPACK_CFG_MJKDZ
* and LCD_I2C_BACKPACK_CFG_SAINSMART only, the others come from online
* research.
*/
/* board marked 'mjkdz' */
/* board marked 'mjkdz' and Arduino-IIC-LCD GY-LCD-V1 */
#define LCD_I2C_BACKPACK_CFG_MJKDZ {0x20,4,5,6,0,1,2,3,7,false,0,0}