drivers: auxdisplay: Add Hitachi HD44780 driver

Adds an auxiliary display driver for Hitachi HD44780-based (and
compatible) LCD displays.

Signed-off-by: Jamie McCrae <spam@helper3000.net>
This commit is contained in:
Jamie McCrae 2023-01-15 11:49:03 +00:00 committed by Carles Cufí
parent 71c727e92e
commit 212a4857ba
5 changed files with 693 additions and 0 deletions

View file

@ -1,5 +1,6 @@
# SPDX-License-Identifier: Apache-2.0 # SPDX-License-Identifier: Apache-2.0
zephyr_library() zephyr_library()
zephyr_library_sources_ifdef(CONFIG_AUXDISPLAY_HD44780 auxdisplay_hd44780.c)
zephyr_library_sources_ifdef(CONFIG_AUXDISPLAY_ITRON auxdisplay_itron.c) zephyr_library_sources_ifdef(CONFIG_AUXDISPLAY_ITRON auxdisplay_itron.c)
zephyr_library_sources_ifdef(CONFIG_AUXDISPLAY_JHD1313 auxdisplay_jhd1313.c) zephyr_library_sources_ifdef(CONFIG_AUXDISPLAY_JHD1313 auxdisplay_jhd1313.c)

View file

@ -20,6 +20,7 @@ module = AUXDISPLAY
module-str = auxdisplay module-str = auxdisplay
source "subsys/logging/Kconfig.template.log_config" source "subsys/logging/Kconfig.template.log_config"
source "drivers/auxdisplay/Kconfig.hd44780"
source "drivers/auxdisplay/Kconfig.itron" source "drivers/auxdisplay/Kconfig.itron"
source "drivers/auxdisplay/Kconfig.jhd1313" source "drivers/auxdisplay/Kconfig.jhd1313"

View file

@ -0,0 +1,9 @@
# Copyright (c) 2023 Jamie McCrae
# SPDX-License-Identifier: Apache-2.0
config AUXDISPLAY_HD44780
bool "Hitachi HD44780 LCD driver"
default y
depends on DT_HAS_HIT_HD44780_ENABLED
help
Enable driver for Hitachi HD44780 and compatible LCDs.

View file

@ -0,0 +1,594 @@
/*
* Copyright (c) 2023 Jamie McCrae
*
* SPDX-License-Identifier: Apache-2.0
*/
#define DT_DRV_COMPAT hit_hd44780
#include <string.h>
#include <zephyr/device.h>
#include <zephyr/devicetree.h>
#include <zephyr/drivers/auxdisplay.h>
#include <zephyr/drivers/gpio.h>
#include <zephyr/pm/device.h>
#include <zephyr/sys/byteorder.h>
#include <zephyr/logging/log.h>
LOG_MODULE_REGISTER(auxdisplay_hd44780, CONFIG_AUXDISPLAY_LOG_LEVEL);
#define AUXDISPLAY_HD44780_BACKLIGHT_MIN 0
#define AUXDISPLAY_HD44780_BACKLIGHT_MAX 1
#define AUXDISPLAY_HD44780_CUSTOM_CHARACTERS 8
#define AUXDISPLAY_HD44780_CUSTOM_CHARACTER_WIDTH 5
#define AUXDISPLAY_HD44780_CUSTOM_CHARACTER_HEIGHT 8
enum {
AUXDISPLAY_HD44780_MODE_4_BIT = 0,
AUXDISPLAY_HD44780_MODE_8_BIT = 1,
/* Reserved for internal driver use only */
AUXDISPLAY_HD44780_MODE_4_BIT_ONCE,
};
/* Display commands */
#define AUXDISPLAY_HD44780_CMD_CLEAR 0x01
#define AUXDISPLAY_HD44780_CMD_ENTRY_MODE 0x04
#define AUXDISPLAY_HD44780_CMD_DISPLAY_MODE 0x08
#define AUXDISPLAY_HD44780_CMD_CGRAM_SET 0x40
#define AUXDISPLAY_HD44780_CMD_POSITION_SET 0x80
#define AUXDISPLAY_HD44780_CMD_SETUP 0x20
#define AUXDISPLAY_HD44780_8_BIT_CONFIG 0x10
#define AUXDISPLAY_HD44780_2_LINE_CONFIG 0x08
#define AUXDISPLAY_HD44780_POSITION_BLINK_ENABLED 0x01
#define AUXDISPLAY_HD44780_CURSOR_ENABLED 0x02
#define AUXDISPLAY_HD44780_DISPLAY_ENABLED 0x04
#define AUXDISPLAY_HD44780_DISPLAY_SHIFT 0x01
#define AUXDISPLAY_HD44780_CURSOR_MOVE_RIGHT 0x02
struct auxdisplay_hd44780_data {
uint16_t character_x;
uint16_t character_y;
bool cursor_enabled;
bool position_blink_enabled;
uint8_t direction;
bool display_shift;
bool backlight_state;
};
struct auxdisplay_hd44780_config {
struct auxdisplay_capabilities capabilities;
struct gpio_dt_spec rs_gpio;
struct gpio_dt_spec rw_gpio;
struct gpio_dt_spec e_gpio;
struct gpio_dt_spec db_gpios[8];
struct gpio_dt_spec backlight_gpio;
uint8_t line_addresses[4];
uint16_t enable_line_rise_delay;
uint16_t enable_line_fall_delay;
uint16_t clear_delay;
uint16_t boot_delay;
};
static void auxdisplay_hd44780_set_entry_mode(const struct device *dev);
static void auxdisplay_hd44780_set_display_mode(const struct device *dev, bool enabled);
static void auxdisplay_hd44780_command(const struct device *dev, bool rs, uint8_t cmd,
uint8_t mode)
{
const struct auxdisplay_hd44780_config *config = dev->config;
int8_t i = 7;
if (mode == AUXDISPLAY_HD44780_MODE_8_BIT) {
while (i >= 0) {
gpio_pin_set_dt(&config->db_gpios[i], ((cmd & BIT(i)) ? 1 : 0));
--i;
}
} else {
while (i >= 4) {
gpio_pin_set_dt(&config->db_gpios[i], ((cmd & BIT(i)) ? 1 : 0));
--i;
}
}
gpio_pin_set_dt(&config->rs_gpio, rs);
if (config->rw_gpio.port) {
gpio_pin_set_dt(&config->rw_gpio, 0);
}
gpio_pin_set_dt(&config->e_gpio, 1);
k_sleep(K_USEC(config->enable_line_rise_delay));
gpio_pin_set_dt(&config->e_gpio, 0);
k_sleep(K_USEC(config->enable_line_fall_delay));
if (mode == AUXDISPLAY_HD44780_MODE_4_BIT) {
while (i >= 0) {
gpio_pin_set_dt(&config->db_gpios[(i + 4)], ((cmd & BIT(i)) ? 1 : 0));
--i;
}
gpio_pin_set_dt(&config->e_gpio, 1);
k_sleep(K_USEC(config->enable_line_rise_delay));
gpio_pin_set_dt(&config->e_gpio, 0);
k_sleep(K_USEC(config->enable_line_fall_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 */
LOG_ERR("HD44780 mode must be 4 or 8-bit");
return -EINVAL;
}
/* Configure and set GPIOs */
rc = gpio_pin_configure_dt(&config->rs_gpio, GPIO_OUTPUT);
if (rc < 0) {
LOG_ERR("Configuration of RS GPIO failed: %d", rc);
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;
}
}
rc = gpio_pin_configure_dt(&config->e_gpio, GPIO_OUTPUT);
if (rc < 0) {
LOG_ERR("Configuration of E GPIO failed: %d", rc);
return rc;
}
if (config->capabilities.mode == AUXDISPLAY_HD44780_MODE_4_BIT) {
i = 4;
}
while (i < 8) {
if (config->db_gpios[i].port) {
rc = gpio_pin_configure_dt(&config->db_gpios[i], GPIO_OUTPUT);
if (rc < 0) {
LOG_ERR("Configuration of DB%d GPIO failed: %d", i, rc);
return rc;
}
} else if (config->capabilities.mode == AUXDISPLAY_HD44780_MODE_4_BIT && i > 3) {
/* Required pin missing */
LOG_ERR("Required DB%d pin missing (DB4-DB7 needed for 4-bit mode)", i);
return -EINVAL;
} else if (config->capabilities.mode == AUXDISPLAY_HD44780_MODE_8_BIT) {
/* Required pin missing */
LOG_ERR("Required DB%d pin missing", i);
return -EINVAL;
}
++i;
}
if (config->backlight_gpio.port) {
rc = gpio_pin_configure_dt(&config->backlight_gpio, GPIO_OUTPUT);
if (rc < 0) {
LOG_ERR("Configuration of backlight GPIO failed: %d", rc);
return rc;
}
gpio_pin_set_dt(&config->backlight_gpio, 0);
}
data->character_x = 0;
data->character_y = 0;
data->backlight_state = false;
data->cursor_enabled = false;
data->position_blink_enabled = false;
data->direction = AUXDISPLAY_DIRECTION_RIGHT;
if (config->boot_delay != 0) {
/* Boot delay is set, wait for a period of time for the LCD to become ready to
* accept commands
*/
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));
return 0;
}
static int auxdisplay_hd44780_capabilities_get(const struct device *dev,
struct auxdisplay_capabilities *capabilities)
{
const struct auxdisplay_hd44780_config *config = dev->config;
memcpy(capabilities, &config->capabilities, sizeof(struct auxdisplay_capabilities));
return 0;
}
static int auxdisplay_hd44780_clear(const struct device *dev)
{
const struct auxdisplay_hd44780_config *config = dev->config;
struct auxdisplay_hd44780_data *data = dev->data;
auxdisplay_hd44780_command(dev, false, AUXDISPLAY_HD44780_CMD_CLEAR,
config->capabilities.mode);
data->character_x = 0;
data->character_y = 0;
k_sleep(K_USEC(config->clear_delay));
return 0;
}
static void auxdisplay_hd44780_set_entry_mode(const struct device *dev)
{
const struct auxdisplay_hd44780_config *config = dev->config;
struct auxdisplay_hd44780_data *data = dev->data;
uint8_t cmd = AUXDISPLAY_HD44780_CMD_ENTRY_MODE;
if (data->direction == AUXDISPLAY_DIRECTION_RIGHT) {
cmd |= AUXDISPLAY_HD44780_CURSOR_MOVE_RIGHT;
}
if (data->display_shift) {
cmd |= AUXDISPLAY_HD44780_DISPLAY_SHIFT;
}
auxdisplay_hd44780_command(dev, false, cmd, config->capabilities.mode);
}
static void auxdisplay_hd44780_set_display_mode(const struct device *dev, bool enabled)
{
const struct auxdisplay_hd44780_config *config = dev->config;
struct auxdisplay_hd44780_data *data = dev->data;
uint8_t cmd = AUXDISPLAY_HD44780_CMD_DISPLAY_MODE;
if (data->cursor_enabled) {
cmd |= AUXDISPLAY_HD44780_CURSOR_ENABLED;
}
if (data->position_blink_enabled) {
cmd |= AUXDISPLAY_HD44780_POSITION_BLINK_ENABLED;
}
if (enabled) {
cmd |= AUXDISPLAY_HD44780_DISPLAY_ENABLED;
}
auxdisplay_hd44780_command(dev, false, cmd, config->capabilities.mode);
}
static int auxdisplay_hd44780_display_on(const struct device *dev)
{
auxdisplay_hd44780_set_display_mode(dev, true);
return 0;
}
static int auxdisplay_hd44780_display_off(const struct device *dev)
{
auxdisplay_hd44780_set_display_mode(dev, false);
return 0;
}
static int auxdisplay_hd44780_cursor_set_enabled(const struct device *dev, bool enabled)
{
struct auxdisplay_hd44780_data *data = dev->data;
data->cursor_enabled = enabled;
auxdisplay_hd44780_set_display_mode(dev, true);
return 0;
}
static int auxdisplay_hd44780_position_blinking_set_enabled(const struct device *dev, bool enabled)
{
struct auxdisplay_hd44780_data *data = dev->data;
data->position_blink_enabled = enabled;
auxdisplay_hd44780_set_display_mode(dev, true);
return 0;
}
static int auxdisplay_hd44780_cursor_shift_set(const struct device *dev, uint8_t direction,
bool display_shift)
{
struct auxdisplay_hd44780_data *data = dev->data;
if (display_shift) {
/* Not currently supported */
return -EINVAL;
}
data->direction = direction;
data->display_shift = (display_shift ? true : false);
auxdisplay_hd44780_set_entry_mode(dev);
return 0;
}
static int auxdisplay_hd44780_cursor_position_set(const struct device *dev,
enum auxdisplay_position type, int16_t x,
int16_t y)
{
const struct auxdisplay_hd44780_config *config = dev->config;
struct auxdisplay_hd44780_data *data = dev->data;
uint8_t cmd = AUXDISPLAY_HD44780_CMD_POSITION_SET;
if (type == AUXDISPLAY_POSITION_RELATIVE) {
x += (int16_t)data->character_x;
y += (int16_t)data->character_y;
} else if (type == AUXDISPLAY_POSITION_RELATIVE_DIRECTION) {
if (data->direction == AUXDISPLAY_DIRECTION_RIGHT) {
x += (int16_t)data->character_x;
y += (int16_t)data->character_y;
} else {
x -= (int16_t)data->character_x;
y -= (int16_t)data->character_y;
}
}
/* Check position is valid before applying */
if (x < 0 || y < 0) {
return -EINVAL;
} else if (x >= config->capabilities.columns || y >= config->capabilities.rows) {
return -EINVAL;
}
data->character_x = (uint16_t)x;
data->character_y = (uint16_t)y;
cmd |= config->line_addresses[data->character_y] + data->character_x;
auxdisplay_hd44780_command(dev, false, cmd, config->capabilities.mode);
return 0;
}
static int auxdisplay_hd44780_cursor_position_get(const struct device *dev, int16_t *x, int16_t *y)
{
struct auxdisplay_hd44780_data *data = dev->data;
*x = (int16_t)data->character_x;
*y = (int16_t)data->character_y;
return 0;
}
static int auxdisplay_hd44780_backlight_get(const struct device *dev, uint8_t *backlight)
{
const struct auxdisplay_hd44780_config *config = dev->config;
struct auxdisplay_hd44780_data *data = dev->data;
if (!config->backlight_gpio.port) {
return -ENOTSUP;
}
*backlight = (data->backlight_state == true ? 1 : 0);
return 0;
}
static int auxdisplay_hd44780_backlight_set(const struct device *dev, uint8_t backlight)
{
const struct auxdisplay_hd44780_config *config = dev->config;
struct auxdisplay_hd44780_data *data = dev->data;
if (!config->backlight_gpio.port) {
return -ENOTSUP;
}
data->backlight_state = (bool)backlight;
gpio_pin_set_dt(&config->backlight_gpio, (uint8_t)data->backlight_state);
return 0;
}
static int auxdisplay_hd44780_custom_character_set(const struct device *dev,
struct auxdisplay_character *character)
{
const struct auxdisplay_hd44780_config *config = dev->config;
struct auxdisplay_hd44780_data *data = dev->data;
uint8_t i = 0;
uint8_t cmd = AUXDISPLAY_HD44780_CMD_CGRAM_SET | (character->index << 3);
auxdisplay_hd44780_command(dev, false, cmd, config->capabilities.mode);
/* HD44780 accepts 5x8 font but needs 8x8 data to be sent, mask off top 3 bits
* for each line sent
*/
while (i < 8) {
uint8_t l = 0;
cmd = 0;
while (l < 5) {
if (character->data[(i * 5) + (4 - l)]) {
cmd |= BIT(l);
}
++l;
}
auxdisplay_hd44780_command(dev, true, cmd, config->capabilities.mode);
++i;
}
character->character_code = character->index;
/* Send last known address to switch back to DDRAM entry mode */
cmd = AUXDISPLAY_HD44780_CMD_POSITION_SET |
(config->line_addresses[data->character_y] +
data->character_x);
auxdisplay_hd44780_command(dev, false, cmd, config->capabilities.mode);
return 0;
}
static int auxdisplay_hd44780_write(const struct device *dev, const uint8_t *text, uint16_t len)
{
const struct auxdisplay_hd44780_config *config = dev->config;
struct auxdisplay_hd44780_data *data = dev->data;
uint16_t i = 0;
while (i < len) {
auxdisplay_hd44780_command(dev, true, text[i], config->capabilities.mode);
++i;
if (data->direction == AUXDISPLAY_DIRECTION_RIGHT) {
/* Increment */
++data->character_x;
if (data->character_x == config->capabilities.columns) {
data->character_x = 0;
++data->character_y;
if (data->character_y == config->capabilities.rows) {
data->character_y = 0;
}
/* Send command to set position */
uint8_t cmd = AUXDISPLAY_HD44780_CMD_POSITION_SET |
config->line_addresses[data->character_y];
auxdisplay_hd44780_command(dev, false, cmd,
config->capabilities.mode);
}
} else {
/* Decrement */
if (data->character_x == 0) {
data->character_x = config->capabilities.columns - 1;
if (data->character_y == 0) {
data->character_y = config->capabilities.rows - 1;
} else {
--data->character_y;
}
/* Send command to set position */
uint8_t cmd = AUXDISPLAY_HD44780_CMD_POSITION_SET |
(config->line_addresses[data->character_y] +
data->character_x);
auxdisplay_hd44780_command(dev, false, cmd,
config->capabilities.mode);
} else {
--data->character_x;
}
}
}
return 0;
}
static const struct auxdisplay_driver_api auxdisplay_hd44780_auxdisplay_api = {
.display_on = auxdisplay_hd44780_display_on,
.display_off = auxdisplay_hd44780_display_off,
.cursor_set_enabled = auxdisplay_hd44780_cursor_set_enabled,
.position_blinking_set_enabled = auxdisplay_hd44780_position_blinking_set_enabled,
.cursor_shift_set = auxdisplay_hd44780_cursor_shift_set,
.cursor_position_set = auxdisplay_hd44780_cursor_position_set,
.cursor_position_get = auxdisplay_hd44780_cursor_position_get,
.capabilities_get = auxdisplay_hd44780_capabilities_get,
.clear = auxdisplay_hd44780_clear,
.backlight_get = auxdisplay_hd44780_backlight_get,
.backlight_set = auxdisplay_hd44780_backlight_set,
.custom_character_set = auxdisplay_hd44780_custom_character_set,
.write = auxdisplay_hd44780_write,
};
/* Returns desired value if backlight is enabled, otherwise returns not supported value */
#define BACKLIGHT_CHECK(inst, value) \
COND_CODE_1(DT_PROP_HAS_IDX(DT_DRV_INST(inst), backlight_gpios, 0), (value), \
(AUXDISPLAY_LIGHT_NOT_SUPPORTED))
#define AUXDISPLAY_HD44780_DEVICE(inst) \
static struct auxdisplay_hd44780_data auxdisplay_hd44780_data_##inst; \
static const struct auxdisplay_hd44780_config auxdisplay_hd44780_config_##inst = { \
.capabilities = { \
.columns = DT_INST_PROP(inst, columns), \
.rows = DT_INST_PROP(inst, rows), \
.mode = DT_INST_ENUM_IDX(inst, mode), \
.brightness.minimum = AUXDISPLAY_LIGHT_NOT_SUPPORTED, \
.brightness.maximum = AUXDISPLAY_LIGHT_NOT_SUPPORTED, \
.backlight.minimum = BACKLIGHT_CHECK(inst, \
AUXDISPLAY_HD44780_BACKLIGHT_MIN), \
.backlight.maximum = BACKLIGHT_CHECK(inst, \
AUXDISPLAY_HD44780_BACKLIGHT_MAX), \
.custom_characters = AUXDISPLAY_HD44780_CUSTOM_CHARACTERS, \
.custom_character_width = AUXDISPLAY_HD44780_CUSTOM_CHARACTER_WIDTH, \
.custom_character_height = AUXDISPLAY_HD44780_CUSTOM_CHARACTER_HEIGHT, \
}, \
.rs_gpio = GPIO_DT_SPEC_INST_GET(inst, register_select_gpios), \
.rw_gpio = GPIO_DT_SPEC_INST_GET_OR(inst, read_write_gpios, {0}), \
.e_gpio = GPIO_DT_SPEC_INST_GET(inst, enable_gpios), \
.db_gpios[0] = GPIO_DT_SPEC_INST_GET_BY_IDX_OR(inst, data_bus_gpios, 0, {0}), \
.db_gpios[1] = GPIO_DT_SPEC_INST_GET_BY_IDX_OR(inst, data_bus_gpios, 1, {0}), \
.db_gpios[2] = GPIO_DT_SPEC_INST_GET_BY_IDX_OR(inst, data_bus_gpios, 2, {0}), \
.db_gpios[3] = GPIO_DT_SPEC_INST_GET_BY_IDX_OR(inst, data_bus_gpios, 3, {0}), \
.db_gpios[4] = GPIO_DT_SPEC_INST_GET_BY_IDX(inst, data_bus_gpios, 4), \
.db_gpios[5] = GPIO_DT_SPEC_INST_GET_BY_IDX(inst, data_bus_gpios, 5), \
.db_gpios[6] = GPIO_DT_SPEC_INST_GET_BY_IDX(inst, data_bus_gpios, 6), \
.db_gpios[7] = GPIO_DT_SPEC_INST_GET_BY_IDX(inst, data_bus_gpios, 7), \
.line_addresses[0] = DT_INST_PROP_BY_IDX(inst, line_addresses, 0), \
.line_addresses[1] = DT_INST_PROP_BY_IDX(inst, line_addresses, 1), \
.line_addresses[2] = DT_INST_PROP_BY_IDX(inst, line_addresses, 2), \
.line_addresses[3] = DT_INST_PROP_BY_IDX(inst, line_addresses, 3), \
.backlight_gpio = GPIO_DT_SPEC_INST_GET_OR(inst, backlight_gpios, {0}), \
.enable_line_rise_delay = DT_INST_PROP(inst, enable_line_rise_delay_us), \
.enable_line_fall_delay = DT_INST_PROP(inst, enable_line_fall_delay_us), \
.clear_delay = DT_INST_PROP(inst, clear_command_delay_us), \
.boot_delay = DT_INST_PROP(inst, boot_delay_ms), \
}; \
DEVICE_DT_INST_DEFINE(inst, \
&auxdisplay_hd44780_init, \
NULL, \
&auxdisplay_hd44780_data_##inst, \
&auxdisplay_hd44780_config_##inst, \
POST_KERNEL, \
CONFIG_AUXDISPLAY_INIT_PRIORITY, \
&auxdisplay_hd44780_auxdisplay_api);
DT_INST_FOREACH_STATUS_OKAY(AUXDISPLAY_HD44780_DEVICE)

View file

@ -0,0 +1,88 @@
#
# Copyright (c) 2023 Jamie McCrae
#
# SPDX-License-Identifier: Apache-2.0
#
description: Hitachi HD44780 LCD
compatible: "hit,hd44780"
include: [auxdisplay-device.yaml]
properties:
mode:
type: int
required: true
description: Operating mode of display, 8-bit or 4 for 4-bit mode
enum:
- 4
- 8
register-select-gpios:
type: phandle-array
required: true
description: GPIO connected to Register Select (RS) of LCD
read-write-gpios:
type: phandle-array
description: Optional GPIO used for selecting read or write mode
enable-gpios:
type: phandle-array
required: true
description: GPIO used for enabling commands to be sent
data-bus-gpios:
type: phandle-array
required: true
description: |
Array of GPIOs connected to the DB lines of the display, this must
contain 8 entries ascending from DB0 to DB7, for 4-bit interface
displays, the first 4 must be set as `<0>`
brightness-gpios:
type: phandle-array
description: Optional GPIO used for controlling the brightness (contrast)
backlight-gpios:
type: phandle-array
description: Optional GPIO used for enabling the backlight
line-addresses:
type: uint8-array
default: [0x00, 0x40, 0x14, 0x54]
description: |
Array of addresses for each row, will use defaults if not provided.
Default is as per Hitachi HD44780 specification.
enable-line-rise-delay-us:
type: int
default: 800
description: |
Delay time (in us) to wait after enable line rises before setting low.
Default is as per Hitachi HD44780 specification.
enable-line-fall-delay-us:
type: int
default: 100
description: |
Delay time (in us) to wait after enable line falls before sending
another command. Default is as per Hitachi HD44780 specification.
clear-command-delay-us:
type: int
default: 5000
description: |
Delay time (in us) to wait after issuing a clear command before sending
another command. Default is as per Hitachi HD44780 specification.
boot-delay-ms:
type: int
default: 0
description: |
Delay time (in ms) to wait at boot time before sending a command (note:
this will delay startup of the whole application by this time, this
should only be used when time is needed for the display device to be
ready before it can be configured which without any delay would cause
the display to not function properly).