diff --git a/drivers/lcd/pcf8574_lcd_backpack.c b/drivers/lcd/pcf8574_lcd_backpack.c index 09ccdfcd2b..c06a0951dd 100644 --- a/drivers/lcd/pcf8574_lcd_backpack.c +++ b/drivers/lcd/pcf8574_lcd_backpack.c @@ -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) */ diff --git a/drivers/lcd/pcf8574_lcd_backpack_readme.txt b/drivers/lcd/pcf8574_lcd_backpack_readme.txt index d5573ea377..edae94e0b6 100644 --- a/drivers/lcd/pcf8574_lcd_backpack_readme.txt +++ b/drivers/lcd/pcf8574_lcd_backpack_readme.txt @@ -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'. diff --git a/include/nuttx/lcd/pcf8574_lcd_backpack.h b/include/nuttx/lcd/pcf8574_lcd_backpack.h index 437d71d64f..abbe6f9701 100644 --- a/include/nuttx/lcd/pcf8574_lcd_backpack.h +++ b/include/nuttx/lcd/pcf8574_lcd_backpack.h @@ -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}