| /* |
| * 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) |