From b7d7e66c6ef570ea8dd690caa9f0a4dcf6118ead Mon Sep 17 00:00:00 2001 From: Jan Kuliga Date: Fri, 13 Sep 2024 23:50:56 +0200 Subject: [PATCH] drivers: auxdisplay: hd44780: rework the initialization procedure If proper power supply is used to power the hd44780, it initializes correctly on a reset condition all by itself. However, if the power supply is below its expectations (e.g. some 3.3V Nucleo board), it won't initialize properly on its own, and the MCU has to carry out the initialization as listed in the reference manual. Since we cannot determine it properly in the runtime, always carry out the initialization procedure. Signed-off-by: Jan Kuliga --- drivers/auxdisplay/auxdisplay_hd44780.c | 73 +++++++++++++++++-------- 1 file changed, 50 insertions(+), 23 deletions(-) diff --git a/drivers/auxdisplay/auxdisplay_hd44780.c b/drivers/auxdisplay/auxdisplay_hd44780.c index 6c095dc82c991e..e5b8fd868321af 100644 --- a/drivers/auxdisplay/auxdisplay_hd44780.c +++ b/drivers/auxdisplay/auxdisplay_hd44780.c @@ -109,13 +109,61 @@ static void auxdisplay_hd44780_command(const struct device *dev, bool rs, uint8_ } } +static void hd44780_ic_initialize(const struct device *dev) +{ + const struct auxdisplay_hd44780_config *config = dev->config; + uint8_t cmd; + + /* + * If proper power supply is used to power the hd44780, it initializes correctly + * on a reset condition all by itself. However, if the power supply is below + * its expectations (e.g. supplying it with some 3.3V Nucleo board), + * it won't initialize properly on its own, and the MCU has to carry out + * the initialization as listed in the reference manual. + * Since we cannot determine it properly in the runtime, + * always carry out the initialization procedure. + */ + cmd = AUXDISPLAY_HD44780_CMD_SETUP | AUXDISPLAY_HD44780_8_BIT_CONFIG; + auxdisplay_hd44780_command(dev, false, cmd, AUXDISPLAY_HD44780_MODE_4_BIT_ONCE); + k_sleep(K_USEC(4100)); + auxdisplay_hd44780_command(dev, false, cmd, AUXDISPLAY_HD44780_MODE_4_BIT_ONCE); + k_sleep(K_USEC(100)); + auxdisplay_hd44780_command(dev, false, cmd, AUXDISPLAY_HD44780_MODE_4_BIT_ONCE); + k_sleep(K_USEC(100)); + + if (config->capabilities.mode == AUXDISPLAY_HD44780_MODE_4_BIT) { + /* Put display into 4-bit mode */ + cmd = AUXDISPLAY_HD44780_CMD_SETUP; + auxdisplay_hd44780_command(dev, false, cmd, AUXDISPLAY_HD44780_MODE_4_BIT_ONCE); + } + + if (config->capabilities.rows > 1) { + cmd |= AUXDISPLAY_HD44780_2_LINE_CONFIG; + } + auxdisplay_hd44780_command(dev, false, cmd, config->capabilities.mode); + + cmd = AUXDISPLAY_HD44780_CMD_DISPLAY_MODE; + auxdisplay_hd44780_command(dev, false, cmd, config->capabilities.mode); + + cmd = AUXDISPLAY_HD44780_CMD_CLEAR; + auxdisplay_hd44780_command(dev, false, cmd, config->capabilities.mode); + + auxdisplay_hd44780_set_entry_mode(dev); + + /* Configure display */ + auxdisplay_hd44780_set_display_mode(dev, true); + auxdisplay_hd44780_command(dev, false, AUXDISPLAY_HD44780_CMD_CLEAR, + config->capabilities.mode); + + k_sleep(K_USEC(config->clear_delay)); +} + static int auxdisplay_hd44780_init(const struct device *dev) { const struct auxdisplay_hd44780_config *config = dev->config; struct auxdisplay_hd44780_data *data = dev->data; int rc; uint8_t i = 0; - uint8_t cmd = AUXDISPLAY_HD44780_CMD_SETUP | AUXDISPLAY_HD44780_8_BIT_CONFIG; if (config->capabilities.mode > AUXDISPLAY_HD44780_MODE_8_BIT) { /* This index is reserved for internal driver usage */ @@ -199,28 +247,7 @@ static int auxdisplay_hd44780_init(const struct device *dev) k_sleep(K_MSEC(config->boot_delay)); } - if (config->capabilities.mode == AUXDISPLAY_HD44780_MODE_4_BIT) { - /* Reset display to known state in 8-bit mode */ - auxdisplay_hd44780_command(dev, false, cmd, AUXDISPLAY_HD44780_MODE_4_BIT_ONCE); - auxdisplay_hd44780_command(dev, false, cmd, AUXDISPLAY_HD44780_MODE_4_BIT_ONCE); - - /* Put display into 4-bit mode */ - cmd = AUXDISPLAY_HD44780_CMD_SETUP; - auxdisplay_hd44780_command(dev, false, cmd, AUXDISPLAY_HD44780_MODE_4_BIT_ONCE); - } - - if (config->capabilities.rows > 1) { - cmd |= AUXDISPLAY_HD44780_2_LINE_CONFIG; - } - - /* Configure display */ - auxdisplay_hd44780_command(dev, false, cmd, config->capabilities.mode); - auxdisplay_hd44780_set_display_mode(dev, true); - auxdisplay_hd44780_set_entry_mode(dev); - auxdisplay_hd44780_command(dev, false, AUXDISPLAY_HD44780_CMD_CLEAR, - config->capabilities.mode); - - k_sleep(K_USEC(config->clear_delay)); + hd44780_ic_initialize(dev); return 0; }