1 /*
2 * Copyright (c) 2023 Jamie McCrae
3 *
4 * SPDX-License-Identifier: Apache-2.0
5 */
6
7 #define DT_DRV_COMPAT hit_hd44780
8
9 #include <string.h>
10 #include <zephyr/device.h>
11 #include <zephyr/devicetree.h>
12 #include <zephyr/drivers/auxdisplay.h>
13 #include <zephyr/drivers/gpio.h>
14 #include <zephyr/pm/device.h>
15 #include <zephyr/sys/byteorder.h>
16 #include <zephyr/logging/log.h>
17
18 LOG_MODULE_REGISTER(auxdisplay_hd44780, CONFIG_AUXDISPLAY_LOG_LEVEL);
19
20 #define AUXDISPLAY_HD44780_BACKLIGHT_MIN 0
21 #define AUXDISPLAY_HD44780_BACKLIGHT_MAX 1
22
23 #define AUXDISPLAY_HD44780_CUSTOM_CHARACTERS 8
24 #define AUXDISPLAY_HD44780_CUSTOM_CHARACTER_WIDTH 5
25 #define AUXDISPLAY_HD44780_CUSTOM_CHARACTER_HEIGHT 8
26
27 enum {
28 AUXDISPLAY_HD44780_MODE_4_BIT = 0,
29 AUXDISPLAY_HD44780_MODE_8_BIT = 1,
30
31 /* Reserved for internal driver use only */
32 AUXDISPLAY_HD44780_MODE_4_BIT_ONCE,
33 };
34
35 /* Display commands */
36 #define AUXDISPLAY_HD44780_CMD_CLEAR 0x01
37 #define AUXDISPLAY_HD44780_CMD_ENTRY_MODE 0x04
38 #define AUXDISPLAY_HD44780_CMD_DISPLAY_MODE 0x08
39 #define AUXDISPLAY_HD44780_CMD_CGRAM_SET 0x40
40 #define AUXDISPLAY_HD44780_CMD_POSITION_SET 0x80
41 #define AUXDISPLAY_HD44780_CMD_SETUP 0x20
42
43 #define AUXDISPLAY_HD44780_8_BIT_CONFIG 0x10
44 #define AUXDISPLAY_HD44780_2_LINE_CONFIG 0x08
45
46 #define AUXDISPLAY_HD44780_POSITION_BLINK_ENABLED 0x01
47 #define AUXDISPLAY_HD44780_CURSOR_ENABLED 0x02
48 #define AUXDISPLAY_HD44780_DISPLAY_ENABLED 0x04
49
50 #define AUXDISPLAY_HD44780_DISPLAY_SHIFT 0x01
51 #define AUXDISPLAY_HD44780_CURSOR_MOVE_RIGHT 0x02
52
53 struct auxdisplay_hd44780_data {
54 uint16_t character_x;
55 uint16_t character_y;
56 bool cursor_enabled;
57 bool position_blink_enabled;
58 uint8_t direction;
59 bool display_shift;
60 bool backlight_state;
61 };
62
63 struct auxdisplay_hd44780_config {
64 struct auxdisplay_capabilities capabilities;
65 struct gpio_dt_spec rs_gpio;
66 struct gpio_dt_spec rw_gpio;
67 struct gpio_dt_spec e_gpio;
68 struct gpio_dt_spec db_gpios[8];
69 struct gpio_dt_spec backlight_gpio;
70 uint8_t line_addresses[4];
71 uint16_t enable_line_rise_delay;
72 uint16_t enable_line_fall_delay;
73 uint16_t clear_delay;
74 uint16_t boot_delay;
75 };
76
77 static void auxdisplay_hd44780_set_entry_mode(const struct device *dev);
78 static void auxdisplay_hd44780_set_display_mode(const struct device *dev, bool enabled);
79
auxdisplay_hd44780_command(const struct device * dev,bool rs,uint8_t cmd,uint8_t mode)80 static void auxdisplay_hd44780_command(const struct device *dev, bool rs, uint8_t cmd,
81 uint8_t mode)
82 {
83 const struct auxdisplay_hd44780_config *config = dev->config;
84 int8_t i = 7;
85
86 if (mode == AUXDISPLAY_HD44780_MODE_8_BIT) {
87 while (i >= 0) {
88 gpio_pin_set_dt(&config->db_gpios[i], ((cmd & BIT(i)) ? 1 : 0));
89 --i;
90 }
91 } else {
92 while (i >= 4) {
93 gpio_pin_set_dt(&config->db_gpios[i], ((cmd & BIT(i)) ? 1 : 0));
94 --i;
95 }
96 }
97
98 gpio_pin_set_dt(&config->rs_gpio, rs);
99
100 if (config->rw_gpio.port) {
101 gpio_pin_set_dt(&config->rw_gpio, 0);
102 }
103
104 gpio_pin_set_dt(&config->e_gpio, 1);
105 k_sleep(K_USEC(config->enable_line_rise_delay));
106 gpio_pin_set_dt(&config->e_gpio, 0);
107 k_sleep(K_USEC(config->enable_line_fall_delay));
108
109 if (mode == AUXDISPLAY_HD44780_MODE_4_BIT) {
110 while (i >= 0) {
111 gpio_pin_set_dt(&config->db_gpios[(i + 4)], ((cmd & BIT(i)) ? 1 : 0));
112 --i;
113 }
114
115 gpio_pin_set_dt(&config->e_gpio, 1);
116 k_sleep(K_USEC(config->enable_line_rise_delay));
117 gpio_pin_set_dt(&config->e_gpio, 0);
118 k_sleep(K_USEC(config->enable_line_fall_delay));
119 }
120 }
121
auxdisplay_hd44780_init(const struct device * dev)122 static int auxdisplay_hd44780_init(const struct device *dev)
123 {
124 const struct auxdisplay_hd44780_config *config = dev->config;
125 struct auxdisplay_hd44780_data *data = dev->data;
126 int rc;
127 uint8_t i = 0;
128 uint8_t cmd = AUXDISPLAY_HD44780_CMD_SETUP | AUXDISPLAY_HD44780_8_BIT_CONFIG;
129
130 if (config->capabilities.mode > AUXDISPLAY_HD44780_MODE_8_BIT) {
131 /* This index is reserved for internal driver usage */
132 LOG_ERR("HD44780 mode must be 4 or 8-bit");
133 return -EINVAL;
134 }
135
136 /* Configure and set GPIOs */
137 rc = gpio_pin_configure_dt(&config->rs_gpio, GPIO_OUTPUT);
138
139 if (rc < 0) {
140 LOG_ERR("Configuration of RS GPIO failed: %d", rc);
141 return rc;
142 }
143
144 if (config->rw_gpio.port) {
145 rc = gpio_pin_configure_dt(&config->rw_gpio, GPIO_OUTPUT);
146
147 if (rc < 0) {
148 LOG_ERR("Configuration of RW GPIO failed: %d", rc);
149 return rc;
150 }
151 }
152
153 rc = gpio_pin_configure_dt(&config->e_gpio, GPIO_OUTPUT);
154
155 if (rc < 0) {
156 LOG_ERR("Configuration of E GPIO failed: %d", rc);
157 return rc;
158 }
159
160 if (config->capabilities.mode == AUXDISPLAY_HD44780_MODE_4_BIT) {
161 i = 4;
162 }
163
164 while (i < 8) {
165 if (config->db_gpios[i].port) {
166 rc = gpio_pin_configure_dt(&config->db_gpios[i], GPIO_OUTPUT);
167
168 if (rc < 0) {
169 LOG_ERR("Configuration of DB%d GPIO failed: %d", i, rc);
170 return rc;
171 }
172 } else if (config->capabilities.mode == AUXDISPLAY_HD44780_MODE_4_BIT && i > 3) {
173 /* Required pin missing */
174 LOG_ERR("Required DB%d pin missing (DB4-DB7 needed for 4-bit mode)", i);
175 return -EINVAL;
176 } else if (config->capabilities.mode == AUXDISPLAY_HD44780_MODE_8_BIT) {
177 /* Required pin missing */
178 LOG_ERR("Required DB%d pin missing", i);
179 return -EINVAL;
180 }
181
182 ++i;
183 }
184
185 if (config->backlight_gpio.port) {
186 rc = gpio_pin_configure_dt(&config->backlight_gpio, GPIO_OUTPUT);
187
188 if (rc < 0) {
189 LOG_ERR("Configuration of backlight GPIO failed: %d", rc);
190 return rc;
191 }
192
193 gpio_pin_set_dt(&config->backlight_gpio, 0);
194 }
195
196 data->character_x = 0;
197 data->character_y = 0;
198 data->backlight_state = false;
199 data->cursor_enabled = false;
200 data->position_blink_enabled = false;
201 data->direction = AUXDISPLAY_DIRECTION_RIGHT;
202
203 if (config->boot_delay != 0) {
204 /* Boot delay is set, wait for a period of time for the LCD to become ready to
205 * accept commands
206 */
207 k_sleep(K_MSEC(config->boot_delay));
208 }
209
210 if (config->capabilities.mode == AUXDISPLAY_HD44780_MODE_4_BIT) {
211 /* Reset display to known state in 8-bit mode */
212 auxdisplay_hd44780_command(dev, false, cmd, AUXDISPLAY_HD44780_MODE_4_BIT_ONCE);
213 auxdisplay_hd44780_command(dev, false, cmd, AUXDISPLAY_HD44780_MODE_4_BIT_ONCE);
214
215 /* Put display into 4-bit mode */
216 cmd = AUXDISPLAY_HD44780_CMD_SETUP;
217 auxdisplay_hd44780_command(dev, false, cmd, AUXDISPLAY_HD44780_MODE_4_BIT_ONCE);
218 }
219
220 if (config->capabilities.rows > 1) {
221 cmd |= AUXDISPLAY_HD44780_2_LINE_CONFIG;
222 }
223
224 /* Configure display */
225 auxdisplay_hd44780_command(dev, false, cmd, config->capabilities.mode);
226 auxdisplay_hd44780_set_display_mode(dev, true);
227 auxdisplay_hd44780_set_entry_mode(dev);
228 auxdisplay_hd44780_command(dev, false, AUXDISPLAY_HD44780_CMD_CLEAR,
229 config->capabilities.mode);
230
231 k_sleep(K_USEC(config->clear_delay));
232
233 return 0;
234 }
235
auxdisplay_hd44780_capabilities_get(const struct device * dev,struct auxdisplay_capabilities * capabilities)236 static int auxdisplay_hd44780_capabilities_get(const struct device *dev,
237 struct auxdisplay_capabilities *capabilities)
238 {
239 const struct auxdisplay_hd44780_config *config = dev->config;
240
241 memcpy(capabilities, &config->capabilities, sizeof(struct auxdisplay_capabilities));
242
243 return 0;
244 }
245
auxdisplay_hd44780_clear(const struct device * dev)246 static int auxdisplay_hd44780_clear(const struct device *dev)
247 {
248 const struct auxdisplay_hd44780_config *config = dev->config;
249 struct auxdisplay_hd44780_data *data = dev->data;
250
251 auxdisplay_hd44780_command(dev, false, AUXDISPLAY_HD44780_CMD_CLEAR,
252 config->capabilities.mode);
253
254 data->character_x = 0;
255 data->character_y = 0;
256
257 k_sleep(K_USEC(config->clear_delay));
258
259 return 0;
260 }
261
auxdisplay_hd44780_set_entry_mode(const struct device * dev)262 static void auxdisplay_hd44780_set_entry_mode(const struct device *dev)
263 {
264 const struct auxdisplay_hd44780_config *config = dev->config;
265 struct auxdisplay_hd44780_data *data = dev->data;
266 uint8_t cmd = AUXDISPLAY_HD44780_CMD_ENTRY_MODE;
267
268 if (data->direction == AUXDISPLAY_DIRECTION_RIGHT) {
269 cmd |= AUXDISPLAY_HD44780_CURSOR_MOVE_RIGHT;
270 }
271
272 if (data->display_shift) {
273 cmd |= AUXDISPLAY_HD44780_DISPLAY_SHIFT;
274 }
275
276 auxdisplay_hd44780_command(dev, false, cmd, config->capabilities.mode);
277 }
278
auxdisplay_hd44780_set_display_mode(const struct device * dev,bool enabled)279 static void auxdisplay_hd44780_set_display_mode(const struct device *dev, bool enabled)
280 {
281 const struct auxdisplay_hd44780_config *config = dev->config;
282 struct auxdisplay_hd44780_data *data = dev->data;
283 uint8_t cmd = AUXDISPLAY_HD44780_CMD_DISPLAY_MODE;
284
285 if (data->cursor_enabled) {
286 cmd |= AUXDISPLAY_HD44780_CURSOR_ENABLED;
287 }
288
289 if (data->position_blink_enabled) {
290 cmd |= AUXDISPLAY_HD44780_POSITION_BLINK_ENABLED;
291 }
292
293 if (enabled) {
294 cmd |= AUXDISPLAY_HD44780_DISPLAY_ENABLED;
295 }
296
297 auxdisplay_hd44780_command(dev, false, cmd, config->capabilities.mode);
298 }
299
auxdisplay_hd44780_display_on(const struct device * dev)300 static int auxdisplay_hd44780_display_on(const struct device *dev)
301 {
302 auxdisplay_hd44780_set_display_mode(dev, true);
303 return 0;
304 }
305
auxdisplay_hd44780_display_off(const struct device * dev)306 static int auxdisplay_hd44780_display_off(const struct device *dev)
307 {
308 auxdisplay_hd44780_set_display_mode(dev, false);
309 return 0;
310 }
311
auxdisplay_hd44780_cursor_set_enabled(const struct device * dev,bool enabled)312 static int auxdisplay_hd44780_cursor_set_enabled(const struct device *dev, bool enabled)
313 {
314 struct auxdisplay_hd44780_data *data = dev->data;
315
316 data->cursor_enabled = enabled;
317
318 auxdisplay_hd44780_set_display_mode(dev, true);
319
320 return 0;
321 }
322
auxdisplay_hd44780_position_blinking_set_enabled(const struct device * dev,bool enabled)323 static int auxdisplay_hd44780_position_blinking_set_enabled(const struct device *dev, bool enabled)
324 {
325 struct auxdisplay_hd44780_data *data = dev->data;
326
327 data->position_blink_enabled = enabled;
328
329 auxdisplay_hd44780_set_display_mode(dev, true);
330
331 return 0;
332 }
333
auxdisplay_hd44780_cursor_shift_set(const struct device * dev,uint8_t direction,bool display_shift)334 static int auxdisplay_hd44780_cursor_shift_set(const struct device *dev, uint8_t direction,
335 bool display_shift)
336 {
337 struct auxdisplay_hd44780_data *data = dev->data;
338
339 if (display_shift) {
340 /* Not currently supported */
341 return -EINVAL;
342 }
343
344 data->direction = direction;
345 data->display_shift = (display_shift ? true : false);
346
347 auxdisplay_hd44780_set_entry_mode(dev);
348
349 return 0;
350 }
351
auxdisplay_hd44780_cursor_position_set(const struct device * dev,enum auxdisplay_position type,int16_t x,int16_t y)352 static int auxdisplay_hd44780_cursor_position_set(const struct device *dev,
353 enum auxdisplay_position type, int16_t x,
354 int16_t y)
355 {
356 const struct auxdisplay_hd44780_config *config = dev->config;
357 struct auxdisplay_hd44780_data *data = dev->data;
358 uint8_t cmd = AUXDISPLAY_HD44780_CMD_POSITION_SET;
359
360 if (type == AUXDISPLAY_POSITION_RELATIVE) {
361 x += (int16_t)data->character_x;
362 y += (int16_t)data->character_y;
363 } else if (type == AUXDISPLAY_POSITION_RELATIVE_DIRECTION) {
364 if (data->direction == AUXDISPLAY_DIRECTION_RIGHT) {
365 x += (int16_t)data->character_x;
366 y += (int16_t)data->character_y;
367 } else {
368 x -= (int16_t)data->character_x;
369 y -= (int16_t)data->character_y;
370 }
371 }
372
373 /* Check position is valid before applying */
374 if (x < 0 || y < 0) {
375 return -EINVAL;
376 } else if (x >= config->capabilities.columns || y >= config->capabilities.rows) {
377 return -EINVAL;
378 }
379
380 data->character_x = (uint16_t)x;
381 data->character_y = (uint16_t)y;
382 cmd |= config->line_addresses[data->character_y] + data->character_x;
383
384 auxdisplay_hd44780_command(dev, false, cmd, config->capabilities.mode);
385
386 return 0;
387 }
388
auxdisplay_hd44780_cursor_position_get(const struct device * dev,int16_t * x,int16_t * y)389 static int auxdisplay_hd44780_cursor_position_get(const struct device *dev, int16_t *x, int16_t *y)
390 {
391 struct auxdisplay_hd44780_data *data = dev->data;
392
393 *x = (int16_t)data->character_x;
394 *y = (int16_t)data->character_y;
395
396 return 0;
397 }
398
auxdisplay_hd44780_backlight_get(const struct device * dev,uint8_t * backlight)399 static int auxdisplay_hd44780_backlight_get(const struct device *dev, uint8_t *backlight)
400 {
401 const struct auxdisplay_hd44780_config *config = dev->config;
402 struct auxdisplay_hd44780_data *data = dev->data;
403
404 if (!config->backlight_gpio.port) {
405 return -ENOTSUP;
406 }
407
408 *backlight = (data->backlight_state == true ? 1 : 0);
409
410 return 0;
411 }
412
auxdisplay_hd44780_backlight_set(const struct device * dev,uint8_t backlight)413 static int auxdisplay_hd44780_backlight_set(const struct device *dev, uint8_t backlight)
414 {
415 const struct auxdisplay_hd44780_config *config = dev->config;
416 struct auxdisplay_hd44780_data *data = dev->data;
417
418 if (!config->backlight_gpio.port) {
419 return -ENOTSUP;
420 }
421
422 data->backlight_state = (bool)backlight;
423
424 gpio_pin_set_dt(&config->backlight_gpio, (uint8_t)data->backlight_state);
425
426 return 0;
427 }
428
auxdisplay_hd44780_custom_character_set(const struct device * dev,struct auxdisplay_character * character)429 static int auxdisplay_hd44780_custom_character_set(const struct device *dev,
430 struct auxdisplay_character *character)
431 {
432 const struct auxdisplay_hd44780_config *config = dev->config;
433 struct auxdisplay_hd44780_data *data = dev->data;
434 uint8_t i = 0;
435 uint8_t cmd = AUXDISPLAY_HD44780_CMD_CGRAM_SET | (character->index << 3);
436
437 auxdisplay_hd44780_command(dev, false, cmd, config->capabilities.mode);
438
439 /* HD44780 accepts 5x8 font but needs 8x8 data to be sent, mask off top 3 bits
440 * for each line sent
441 */
442 while (i < 8) {
443 uint8_t l = 0;
444
445 cmd = 0;
446
447 while (l < 5) {
448 if (character->data[(i * 5) + (4 - l)]) {
449 cmd |= BIT(l);
450 }
451
452 ++l;
453 }
454
455 auxdisplay_hd44780_command(dev, true, cmd, config->capabilities.mode);
456
457 ++i;
458 }
459
460 character->character_code = character->index;
461
462 /* Send last known address to switch back to DDRAM entry mode */
463 cmd = AUXDISPLAY_HD44780_CMD_POSITION_SET |
464 (config->line_addresses[data->character_y] +
465 data->character_x);
466
467 auxdisplay_hd44780_command(dev, false, cmd, config->capabilities.mode);
468
469 return 0;
470 }
471
auxdisplay_hd44780_write(const struct device * dev,const uint8_t * text,uint16_t len)472 static int auxdisplay_hd44780_write(const struct device *dev, const uint8_t *text, uint16_t len)
473 {
474 const struct auxdisplay_hd44780_config *config = dev->config;
475 struct auxdisplay_hd44780_data *data = dev->data;
476 uint16_t i = 0;
477
478 while (i < len) {
479 auxdisplay_hd44780_command(dev, true, text[i], config->capabilities.mode);
480 ++i;
481
482 if (data->direction == AUXDISPLAY_DIRECTION_RIGHT) {
483 /* Increment */
484 ++data->character_x;
485
486 if (data->character_x == config->capabilities.columns) {
487 data->character_x = 0;
488 ++data->character_y;
489
490 if (data->character_y == config->capabilities.rows) {
491 data->character_y = 0;
492 }
493
494 /* Send command to set position */
495 uint8_t cmd = AUXDISPLAY_HD44780_CMD_POSITION_SET |
496 config->line_addresses[data->character_y];
497 auxdisplay_hd44780_command(dev, false, cmd,
498 config->capabilities.mode);
499 }
500 } else {
501 /* Decrement */
502 if (data->character_x == 0) {
503 data->character_x = config->capabilities.columns - 1;
504
505 if (data->character_y == 0) {
506 data->character_y = config->capabilities.rows - 1;
507 } else {
508 --data->character_y;
509 }
510
511 /* Send command to set position */
512 uint8_t cmd = AUXDISPLAY_HD44780_CMD_POSITION_SET |
513 (config->line_addresses[data->character_y] +
514 data->character_x);
515 auxdisplay_hd44780_command(dev, false, cmd,
516 config->capabilities.mode);
517 } else {
518 --data->character_x;
519 }
520 }
521 }
522
523 return 0;
524 }
525
526 static const struct auxdisplay_driver_api auxdisplay_hd44780_auxdisplay_api = {
527 .display_on = auxdisplay_hd44780_display_on,
528 .display_off = auxdisplay_hd44780_display_off,
529 .cursor_set_enabled = auxdisplay_hd44780_cursor_set_enabled,
530 .position_blinking_set_enabled = auxdisplay_hd44780_position_blinking_set_enabled,
531 .cursor_shift_set = auxdisplay_hd44780_cursor_shift_set,
532 .cursor_position_set = auxdisplay_hd44780_cursor_position_set,
533 .cursor_position_get = auxdisplay_hd44780_cursor_position_get,
534 .capabilities_get = auxdisplay_hd44780_capabilities_get,
535 .clear = auxdisplay_hd44780_clear,
536 .backlight_get = auxdisplay_hd44780_backlight_get,
537 .backlight_set = auxdisplay_hd44780_backlight_set,
538 .custom_character_set = auxdisplay_hd44780_custom_character_set,
539 .write = auxdisplay_hd44780_write,
540 };
541
542 /* Returns desired value if backlight is enabled, otherwise returns not supported value */
543 #define BACKLIGHT_CHECK(inst, value) \
544 COND_CODE_1(DT_PROP_HAS_IDX(DT_DRV_INST(inst), backlight_gpios, 0), (value), \
545 (AUXDISPLAY_LIGHT_NOT_SUPPORTED))
546
547 #define AUXDISPLAY_HD44780_DEVICE(inst) \
548 static struct auxdisplay_hd44780_data auxdisplay_hd44780_data_##inst; \
549 static const struct auxdisplay_hd44780_config auxdisplay_hd44780_config_##inst = { \
550 .capabilities = { \
551 .columns = DT_INST_PROP(inst, columns), \
552 .rows = DT_INST_PROP(inst, rows), \
553 .mode = DT_INST_ENUM_IDX(inst, mode), \
554 .brightness.minimum = AUXDISPLAY_LIGHT_NOT_SUPPORTED, \
555 .brightness.maximum = AUXDISPLAY_LIGHT_NOT_SUPPORTED, \
556 .backlight.minimum = BACKLIGHT_CHECK(inst, \
557 AUXDISPLAY_HD44780_BACKLIGHT_MIN), \
558 .backlight.maximum = BACKLIGHT_CHECK(inst, \
559 AUXDISPLAY_HD44780_BACKLIGHT_MAX), \
560 .custom_characters = AUXDISPLAY_HD44780_CUSTOM_CHARACTERS, \
561 .custom_character_width = AUXDISPLAY_HD44780_CUSTOM_CHARACTER_WIDTH, \
562 .custom_character_height = AUXDISPLAY_HD44780_CUSTOM_CHARACTER_HEIGHT, \
563 }, \
564 .rs_gpio = GPIO_DT_SPEC_INST_GET(inst, register_select_gpios), \
565 .rw_gpio = GPIO_DT_SPEC_INST_GET_OR(inst, read_write_gpios, {0}), \
566 .e_gpio = GPIO_DT_SPEC_INST_GET(inst, enable_gpios), \
567 .db_gpios[0] = GPIO_DT_SPEC_INST_GET_BY_IDX_OR(inst, data_bus_gpios, 0, {0}), \
568 .db_gpios[1] = GPIO_DT_SPEC_INST_GET_BY_IDX_OR(inst, data_bus_gpios, 1, {0}), \
569 .db_gpios[2] = GPIO_DT_SPEC_INST_GET_BY_IDX_OR(inst, data_bus_gpios, 2, {0}), \
570 .db_gpios[3] = GPIO_DT_SPEC_INST_GET_BY_IDX_OR(inst, data_bus_gpios, 3, {0}), \
571 .db_gpios[4] = GPIO_DT_SPEC_INST_GET_BY_IDX(inst, data_bus_gpios, 4), \
572 .db_gpios[5] = GPIO_DT_SPEC_INST_GET_BY_IDX(inst, data_bus_gpios, 5), \
573 .db_gpios[6] = GPIO_DT_SPEC_INST_GET_BY_IDX(inst, data_bus_gpios, 6), \
574 .db_gpios[7] = GPIO_DT_SPEC_INST_GET_BY_IDX(inst, data_bus_gpios, 7), \
575 .line_addresses[0] = DT_INST_PROP_BY_IDX(inst, line_addresses, 0), \
576 .line_addresses[1] = DT_INST_PROP_BY_IDX(inst, line_addresses, 1), \
577 .line_addresses[2] = DT_INST_PROP_BY_IDX(inst, line_addresses, 2), \
578 .line_addresses[3] = DT_INST_PROP_BY_IDX(inst, line_addresses, 3), \
579 .backlight_gpio = GPIO_DT_SPEC_INST_GET_OR(inst, backlight_gpios, {0}), \
580 .enable_line_rise_delay = DT_INST_PROP(inst, enable_line_rise_delay_us), \
581 .enable_line_fall_delay = DT_INST_PROP(inst, enable_line_fall_delay_us), \
582 .clear_delay = DT_INST_PROP(inst, clear_command_delay_us), \
583 .boot_delay = DT_INST_PROP(inst, boot_delay_ms), \
584 }; \
585 DEVICE_DT_INST_DEFINE(inst, \
586 &auxdisplay_hd44780_init, \
587 NULL, \
588 &auxdisplay_hd44780_data_##inst, \
589 &auxdisplay_hd44780_config_##inst, \
590 POST_KERNEL, \
591 CONFIG_AUXDISPLAY_INIT_PRIORITY, \
592 &auxdisplay_hd44780_auxdisplay_api);
593
594 DT_INST_FOREACH_STATUS_OKAY(AUXDISPLAY_HD44780_DEVICE)
595