Skip to content

Commit

Permalink
drivers: auxdisplay: hd44780: implement busy-flag polling mechanism
Browse files Browse the repository at this point in the history
HD44780 controller can indicate via busy flag whether it's finished
processing current command. This allows for faster completion of HD44780
commands as seen from MCU perspective, as the MCU doesn't have to wait
for fixed long period of time. Implement this functionality.

Signed-off-by: Jan Kuliga <jtkuliga@gmail.com>
  • Loading branch information
kuliga committed Sep 17, 2024
1 parent b7d7e66 commit 70b77c4
Showing 1 changed file with 79 additions and 15 deletions.
94 changes: 79 additions & 15 deletions drivers/auxdisplay/auxdisplay_hd44780.c
Original file line number Diff line number Diff line change
Expand Up @@ -88,17 +88,76 @@ static void hd44780_pulse_enable_line(const struct device *dev)
k_sleep(K_NSEC(config->enable_line_fall_delay));
}

static void auxdisplay_hd44780_command(const struct device *dev, bool rs, uint8_t cmd,
uint8_t mode)
static inline void hd44780_set_rs_rw_lines(const struct device *dev, bool rs, bool rw)
{
const struct auxdisplay_hd44780_config *const config = dev->config;

gpio_pin_set_dt(&config->rs_gpio, rs);
if (config->rw_gpio.port) {
gpio_pin_set_dt(&config->rw_gpio, rw);
}

k_sleep(K_NSEC(config->rs_line_delay));
}

static int hd44780_db_gpios_configure(const struct device *dev, uint8_t lsb_line,
gpio_flags_t flags)
{
const struct auxdisplay_hd44780_config *config = dev->config;
int rc;

for (int line = 7; line >= lsb_line; --line) {
rc = gpio_pin_configure_dt(&config->db_gpios[line], flags);
if (rc < 0) {
return rc;
}
}

return 0;
}

static void auxdisplay_hd44780_command(const struct device *dev, bool rs,
uint8_t cmd, uint8_t mode)
{
int rc;
const struct auxdisplay_hd44780_config *config = dev->config;
int8_t i = 7;
const int lsb_line = (mode == AUXDISPLAY_HD44780_MODE_8_BIT) ? 0 : 4;
int ncommands = (mode == AUXDISPLAY_HD44780_MODE_4_BIT) ? 2 : 1;
const bool check_busy_flag = (!config->rw_gpio.port ||
(mode == AUXDISPLAY_HD44780_MODE_4_BIT_ONCE)) ?
false : true;

Check notice on line 130 in drivers/auxdisplay/auxdisplay_hd44780.c

View workflow job for this annotation

GitHub Actions / Run compliance checks on patch series (PR)

You may want to run clang-format on this change

drivers/auxdisplay/auxdisplay_hd44780.c:130 -static void auxdisplay_hd44780_command(const struct device *dev, bool rs, - uint8_t cmd, uint8_t mode) +static void auxdisplay_hd44780_command(const struct device *dev, bool rs, uint8_t cmd, uint8_t mode) { int rc; const struct auxdisplay_hd44780_config *config = dev->config; int8_t i = 7; const int lsb_line = (mode == AUXDISPLAY_HD44780_MODE_8_BIT) ? 0 : 4; int ncommands = (mode == AUXDISPLAY_HD44780_MODE_4_BIT) ? 2 : 1; - const bool check_busy_flag = (!config->rw_gpio.port || - (mode == AUXDISPLAY_HD44780_MODE_4_BIT_ONCE)) ? - false : true; + const bool check_busy_flag = + (!config->rw_gpio.port || (mode == AUXDISPLAY_HD44780_MODE_4_BIT_ONCE)) ? false + : true;
gpio_pin_set_dt(&config->rs_gpio, rs);
k_sleep(K_NSEC(config->rs_line_delay));
if (check_busy_flag) {
bool busy;

rc = hd44780_db_gpios_configure(dev, lsb_line, GPIO_INPUT | GPIO_PULL_DOWN);
if (rc < 0) {
LOG_ERR("configuration of db-gpios as inputs failed: %d", rc);
return;
}

hd44780_set_rs_rw_lines(dev, 0, 1);
do {
hd44780_pulse_enable_line(dev);

/* We don't care about the other pins. */
busy = gpio_pin_get_dt(&config->db_gpios[7]);

if (config->capabilities.mode == AUXDISPLAY_HD44780_MODE_4_BIT) {
/* In this mode we have to initiate two separate readbacks. */
hd44780_pulse_enable_line(dev);
}
} while (busy);

rc = hd44780_db_gpios_configure(dev, lsb_line, GPIO_OUTPUT);
if (rc < 0) {
LOG_ERR("configuration of db-gpios as outputs failed: %d", rc);
return;
}
}

hd44780_set_rs_rw_lines(dev, rs, 0);
while (ncommands--) {
for (int line = 7; line >= lsb_line; --line) {
gpio_pin_set_dt(&config->db_gpios[line], ((cmd & BIT(i)) ? 1 : 0));
Expand All @@ -107,6 +166,13 @@ static void auxdisplay_hd44780_command(const struct device *dev, bool rs, uint8_

hd44780_pulse_enable_line(dev);
}

if (!check_busy_flag) {
/* Sleep for a max execution time for a given instruction. */
uint16_t cmd_delay_us = (cmd == AUXDISPLAY_HD44780_CMD_CLEAR) ? 1520 : 37;

k_sleep(K_USEC(cmd_delay_us));
}
}

static void hd44780_ic_initialize(const struct device *dev)
Expand Down Expand Up @@ -179,17 +245,6 @@ static int auxdisplay_hd44780_init(const struct device *dev)
return rc;
}

if (config->rw_gpio.port) {
rc = gpio_pin_configure_dt(&config->rw_gpio, GPIO_OUTPUT);

if (rc < 0) {
LOG_ERR("Configuration of RW GPIO failed: %d", rc);
return rc;
}

gpio_pin_set_dt(&config->rw_gpio, 0);
}

rc = gpio_pin_configure_dt(&config->e_gpio, GPIO_OUTPUT);

if (rc < 0) {
Expand Down Expand Up @@ -222,6 +277,15 @@ static int auxdisplay_hd44780_init(const struct device *dev)
++i;
}

if (config->rw_gpio.port) {
rc = gpio_pin_configure_dt(&config->rw_gpio, GPIO_OUTPUT);

if (rc < 0) {
LOG_ERR("Configuration of RW GPIO failed: %d", rc);
return rc;
}
}

if (config->backlight_gpio.port) {
rc = gpio_pin_configure_dt(&config->backlight_gpio, GPIO_OUTPUT);

Expand Down

0 comments on commit 70b77c4

Please sign in to comment.