1 /*
2  * SPDX-License-Identifier: Apache-2.0
3  */
4 
5 /**
6  * @file Display text strings on HD44780 based 20x4 LCD controller
7  * using GPIO for parallel interface on Arduino Due.
8  *
9  * Datasheet: http://lcd-linux.sourceforge.net/pdfdocs/hd44780.pdf
10  *
11  * LCD Wiring
12  * ----------
13  *
14  * The wiring for the LCD is as follows:
15  * 1 : GND
16  * 2 : 5V
17  * 3 : Contrast (0-5V)*
18  * 4 : RS (Register Select)
19  * 5 : R/W (Read Write)       - GROUND THIS PIN
20  * 6 : Enable or Strobe
21  * 7 : Data Bit 0             - NOT USED
22  * 8 : Data Bit 1             - NOT USED
23  * 9 : Data Bit 2             - NOT USED
24  * 10: Data Bit 3             - NOT USED
25  * 11: Data Bit 4
26  * 12: Data Bit 5
27  * 13: Data Bit 6
28  * 14: Data Bit 7
29  * 15: LCD Backlight +5V**
30  * 16: LCD Backlight GND
31  *
32  *
33  * Arduino Due
34  * -----------
35  *
36  * On Arduino Due:
37  * 1. IO_3 is PC28
38  * 2. IO_5 is PC25
39  * 3. IO_6 is PC24
40  * 4. IO_7 is PC23
41  * 5. IO_8 is PC22
42  * 6. IO_9 is PC21
43  *
44  * The gpio_atmel_sam3 driver is being used.
45  *
46  * This sample app display text strings per line & page wise.
47  *
48  * Every 3 second you should see this repeatedly
49  * on display:
50  * "
51  *     *********************
52  *     Arduino Due
53  *     20x4 LCD Display
54  *     *********************
55  *
56  *      ------------------
57  *     - Zephyr Rocks!
58  *     - My super RTOS
59  *      ------------------
60  *
61  *     --------HOME--------
62  *     I am home!
63  *
64  *	--------------------
65  */
66 
67 #include <zephyr/kernel.h>
68 
69 #include <zephyr/sys/printk.h>
70 #include <zephyr/drivers/gpio.h>
71 #include <string.h>
72 
73 #if defined(CONFIG_SOC_SAM3X8E)
74 #define GPIO_NODE DT_NODELABEL(pioc)
75 #else
76 #error "Unsupported GPIO driver"
77 #endif
78 
79 #if defined(CONFIG_SOC_SAM3X8E)
80 /* Define GPIO OUT to LCD */
81 #define GPIO_PIN_PC12_D0		12	/* PC12 - pin 51 */
82 #define GPIO_PIN_PC13_D1		13	/* PC13 - pin 50 */
83 #define GPIO_PIN_PC14_D2		14	/* PC14 - pin 49 */
84 #define GPIO_PIN_PC15_D3		15	/* PC15 - pin 48 */
85 #define GPIO_PIN_PC24_D4		24	/* PC24 - pin 6 */
86 #define GPIO_PIN_PC23_D5		23	/* PC23 - pin 7 */
87 #define GPIO_PIN_PC22_D6		22	/* PC22 - pin 8 */
88 #define GPIO_PIN_PC21_D7		21	/* PC21 - pin 9 */
89 #define GPIO_PIN_PC28_RS		28	/* PC28 - pin 3 */
90 #define GPIO_PIN_PC25_E			25	/* PC25 - pin 5 */
91 #define GPIO_NAME			"GPIO_"
92 #endif
93 
94 /* Commands */
95 #define LCD_CLEAR_DISPLAY		0x01
96 #define LCD_RETURN_HOME			0x02
97 #define LCD_ENTRY_MODE_SET		0x04
98 #define LCD_DISPLAY_CONTROL		0x08
99 #define LCD_CURSOR_SHIFT		0x10
100 #define LCD_FUNCTION_SET		0x20
101 #define LCD_SET_CGRAM_ADDR		0x40
102 #define LCD_SET_DDRAM_ADDR		0x80
103 
104 /* Display entry mode */
105 #define LCD_ENTRY_RIGHT			0x00
106 #define LCD_ENTRY_LEFT			0x02
107 #define LCD_ENTRY_SHIFT_INCREMENT	0x01
108 #define LCD_ENTRY_SHIFT_DECREMENT	0x00
109 
110 /* Display on/off control */
111 #define LCD_DISPLAY_ON			0x04
112 #define LCD_DISPLAY_OFF			0x00
113 #define LCD_CURSOR_ON			0x02
114 #define LCD_CURSOR_OFF			0x00
115 #define LCD_BLINK_ON			0x01
116 #define LCD_BLINK_OFF			0x00
117 
118 /* Display/cursor shift */
119 #define LCD_DISPLAY_MOVE		0x08
120 #define LCD_CURSOR_MOVE			0x00
121 #define LCD_MOVE_RIGHT			0x04
122 #define LCD_MOVE_LEFT			0x00
123 
124 /* Function set */
125 #define LCD_8BIT_MODE			0x10
126 #define LCD_4BIT_MODE			0x00
127 #define LCD_2_LINE			0x08
128 #define LCD_1_LINE			0x00
129 #define LCD_5x10_DOTS			0x04
130 #define LCD_5x8_DOTS			0x00
131 
132 /* Define some device constants */
133 #define LCD_WIDTH			20	/* Max char per line */
134 #define HIGH				1
135 #define LOW				0
136 /* in millisecond */
137 #define	ENABLE_DELAY			10
138 
139 
140 #define GPIO_PIN_WR(dev, pin, bit)						\
141 	do {									\
142 		if (gpio_pin_set_raw((dev), (pin), (bit))) {			\
143 			printk("Err set " GPIO_NAME "%d! %x\n", (pin), (bit));	\
144 		}								\
145 	} while (0)								\
146 
147 
148 #define GPIO_PIN_CFG(dev, pin, dir)						\
149 	do {									\
150 		if (gpio_pin_configure((dev), (pin), (dir))) {			\
151 			printk("Err cfg " GPIO_NAME "%d! %x\n", (pin), (dir));	\
152 		}								\
153 	} while (0)
154 
155 
156 struct pi_lcd_data {
157 	uint8_t	disp_func;	/* Display Function */
158 	uint8_t	disp_cntl;	/* Display Control */
159 	uint8_t disp_mode;	/* Display Mode */
160 	uint8_t	cfg_rows;
161 	uint8_t	row_offsets[4];
162 };
163 
164 /* Default Configuration - User can update */
165 struct pi_lcd_data lcd_data = {
166 	.disp_func = LCD_4BIT_MODE | LCD_1_LINE | LCD_5x8_DOTS,
167 	.disp_cntl = 0,
168 	.disp_mode = 0,
169 	.cfg_rows = 0,
170 	.row_offsets = {0x00, 0x00, 0x00, 0x00}
171 };
172 
_set_row_offsets(int8_t row0,int8_t row1,int8_t row2,int8_t row3)173 void _set_row_offsets(int8_t row0, int8_t row1, int8_t row2, int8_t row3)
174 {
175 	lcd_data.row_offsets[0] = row0;
176 	lcd_data.row_offsets[1] = row1;
177 	lcd_data.row_offsets[2] = row2;
178 	lcd_data.row_offsets[3] = row3;
179 }
180 
181 
_pi_lcd_toggle_enable(const struct device * gpio_dev)182 void _pi_lcd_toggle_enable(const struct device *gpio_dev)
183 {
184 	GPIO_PIN_WR(gpio_dev, GPIO_PIN_PC25_E, LOW);
185 	k_msleep(ENABLE_DELAY);
186 	GPIO_PIN_WR(gpio_dev, GPIO_PIN_PC25_E, HIGH);
187 	k_msleep(ENABLE_DELAY);
188 	GPIO_PIN_WR(gpio_dev, GPIO_PIN_PC25_E, LOW);
189 	k_msleep(ENABLE_DELAY);
190 }
191 
192 
_pi_lcd_4bits_wr(const struct device * gpio_dev,uint8_t bits)193 void _pi_lcd_4bits_wr(const struct device *gpio_dev, uint8_t bits)
194 {
195 	/* High bits */
196 	GPIO_PIN_WR(gpio_dev, GPIO_PIN_PC24_D4, LOW);
197 	GPIO_PIN_WR(gpio_dev, GPIO_PIN_PC23_D5, LOW);
198 	GPIO_PIN_WR(gpio_dev, GPIO_PIN_PC22_D6, LOW);
199 	GPIO_PIN_WR(gpio_dev, GPIO_PIN_PC21_D7, LOW);
200 	if ((bits & BIT(4)) == BIT(4)) {
201 		GPIO_PIN_WR(gpio_dev, GPIO_PIN_PC24_D4, HIGH);
202 	}
203 	if ((bits & BIT(5)) == BIT(5)) {
204 		GPIO_PIN_WR(gpio_dev, GPIO_PIN_PC23_D5, HIGH);
205 	}
206 	if ((bits & BIT(6)) == BIT(6)) {
207 		GPIO_PIN_WR(gpio_dev, GPIO_PIN_PC22_D6, HIGH);
208 	}
209 	if ((bits & BIT(7)) == BIT(7)) {
210 		GPIO_PIN_WR(gpio_dev, GPIO_PIN_PC21_D7, HIGH);
211 	}
212 
213 	/* Toggle 'Enable' pin */
214 	_pi_lcd_toggle_enable(gpio_dev);
215 
216 	/* Low bits */
217 	GPIO_PIN_WR(gpio_dev, GPIO_PIN_PC24_D4, LOW);
218 	GPIO_PIN_WR(gpio_dev, GPIO_PIN_PC23_D5, LOW);
219 	GPIO_PIN_WR(gpio_dev, GPIO_PIN_PC22_D6, LOW);
220 	GPIO_PIN_WR(gpio_dev, GPIO_PIN_PC21_D7, LOW);
221 	if ((bits & BIT(0)) == BIT(0)) {
222 		GPIO_PIN_WR(gpio_dev, GPIO_PIN_PC24_D4, HIGH);
223 	}
224 	if ((bits & BIT(1)) == BIT(1)) {
225 		GPIO_PIN_WR(gpio_dev, GPIO_PIN_PC23_D5, HIGH);
226 	}
227 	if ((bits & BIT(2)) == BIT(2)) {
228 		GPIO_PIN_WR(gpio_dev, GPIO_PIN_PC22_D6, HIGH);
229 	}
230 	if ((bits & BIT(3)) == BIT(3)) {
231 		GPIO_PIN_WR(gpio_dev, GPIO_PIN_PC21_D7, HIGH);
232 	}
233 
234 	/* Toggle 'Enable' pin */
235 	_pi_lcd_toggle_enable(gpio_dev);
236 }
237 
_pi_lcd_8bits_wr(const struct device * gpio_dev,uint8_t bits)238 void _pi_lcd_8bits_wr(const struct device *gpio_dev, uint8_t bits)
239 {
240 	/* High bits */
241 	GPIO_PIN_WR(gpio_dev, GPIO_PIN_PC21_D7, LOW);
242 	GPIO_PIN_WR(gpio_dev, GPIO_PIN_PC22_D6, LOW);
243 	GPIO_PIN_WR(gpio_dev, GPIO_PIN_PC23_D5, LOW);
244 	GPIO_PIN_WR(gpio_dev, GPIO_PIN_PC24_D4, LOW);
245 	GPIO_PIN_WR(gpio_dev, GPIO_PIN_PC15_D3, LOW);
246 	GPIO_PIN_WR(gpio_dev, GPIO_PIN_PC14_D2, LOW);
247 	GPIO_PIN_WR(gpio_dev, GPIO_PIN_PC13_D1, LOW);
248 	GPIO_PIN_WR(gpio_dev, GPIO_PIN_PC12_D0, LOW);
249 
250 	/* Low bits */
251 	if ((bits & BIT(0)) == BIT(0)) {
252 		GPIO_PIN_WR(gpio_dev, GPIO_PIN_PC12_D0, HIGH);
253 	}
254 	if ((bits & BIT(1)) == BIT(1)) {
255 		GPIO_PIN_WR(gpio_dev, GPIO_PIN_PC13_D1, HIGH);
256 	}
257 	if ((bits & BIT(2)) == BIT(2)) {
258 		GPIO_PIN_WR(gpio_dev, GPIO_PIN_PC14_D2, HIGH);
259 	}
260 	if ((bits & BIT(3)) == BIT(3)) {
261 		GPIO_PIN_WR(gpio_dev, GPIO_PIN_PC15_D3, HIGH);
262 	}
263 	if ((bits & BIT(4)) == BIT(4)) {
264 		GPIO_PIN_WR(gpio_dev, GPIO_PIN_PC24_D4, HIGH);
265 	}
266 	if ((bits & BIT(5)) == BIT(5)) {
267 		GPIO_PIN_WR(gpio_dev, GPIO_PIN_PC23_D5, HIGH);
268 	}
269 	if ((bits & BIT(6)) == BIT(6)) {
270 		GPIO_PIN_WR(gpio_dev, GPIO_PIN_PC22_D6, HIGH);
271 	}
272 	if ((bits & BIT(7)) == BIT(7)) {
273 		GPIO_PIN_WR(gpio_dev, GPIO_PIN_PC21_D7, HIGH);
274 	}
275 
276 	/* Toggle 'Enable' pin */
277 	_pi_lcd_toggle_enable(gpio_dev);
278 }
279 
_pi_lcd_data(const struct device * gpio_dev,uint8_t bits)280 void _pi_lcd_data(const struct device *gpio_dev, uint8_t bits)
281 {
282 	if (lcd_data.disp_func & LCD_8BIT_MODE) {
283 		_pi_lcd_8bits_wr(gpio_dev, bits);
284 	} else {
285 		_pi_lcd_4bits_wr(gpio_dev, bits);
286 	}
287 }
288 
_pi_lcd_command(const struct device * gpio_dev,uint8_t bits)289 void _pi_lcd_command(const struct device *gpio_dev, uint8_t bits)
290 {
291 	/* mode = False for command */
292 	GPIO_PIN_WR(gpio_dev, GPIO_PIN_PC28_RS, LOW);
293 	_pi_lcd_data(gpio_dev, bits);
294 }
295 
_pi_lcd_write(const struct device * gpio_dev,uint8_t bits)296 void _pi_lcd_write(const struct device *gpio_dev, uint8_t bits)
297 {
298 	/* mode = True for character */
299 	GPIO_PIN_WR(gpio_dev, GPIO_PIN_PC28_RS, HIGH);
300 	_pi_lcd_data(gpio_dev, bits);
301 }
302 
303 
304 /*************************
305  * USER can use these APIs
306  *************************/
307 /** Home */
pi_lcd_home(const struct device * gpio_dev)308 void pi_lcd_home(const struct device *gpio_dev)
309 {
310 	_pi_lcd_command(gpio_dev, LCD_RETURN_HOME);
311 	k_sleep(K_MSEC(2));			/* wait for 2ms */
312 }
313 
314 /** Set cursor position */
pi_lcd_set_cursor(const struct device * gpio_dev,uint8_t col,uint8_t row)315 void pi_lcd_set_cursor(const struct device *gpio_dev, uint8_t col,
316 		       uint8_t row)
317 {
318 	size_t max_lines;
319 
320 	max_lines = ARRAY_SIZE(lcd_data.row_offsets);
321 	if (row >= max_lines) {
322 		row = max_lines - 1;	/* Count rows starting w/0 */
323 	}
324 	if (row >= lcd_data.cfg_rows) {
325 		row = lcd_data.cfg_rows - 1;    /* Count rows starting w/0 */
326 	}
327 	_pi_lcd_command(gpio_dev, (LCD_SET_DDRAM_ADDR | (col + lcd_data.row_offsets[row])));
328 }
329 
330 
331 /** Clear display */
pi_lcd_clear(const struct device * gpio_dev)332 void pi_lcd_clear(const struct device *gpio_dev)
333 {
334 	_pi_lcd_command(gpio_dev, LCD_CLEAR_DISPLAY);
335 	k_sleep(K_MSEC(2));			/* wait for 2ms */
336 }
337 
338 
339 /** Display ON */
pi_lcd_display_on(const struct device * gpio_dev)340 void pi_lcd_display_on(const struct device *gpio_dev)
341 {
342 	lcd_data.disp_cntl |= LCD_DISPLAY_ON;
343 	_pi_lcd_command(gpio_dev,
344 			LCD_DISPLAY_CONTROL | lcd_data.disp_cntl);
345 }
346 
347 /** Display OFF */
pi_lcd_display_off(const struct device * gpio_dev)348 void pi_lcd_display_off(const struct device *gpio_dev)
349 {
350 	lcd_data.disp_cntl &= ~LCD_DISPLAY_ON;
351 	_pi_lcd_command(gpio_dev,
352 			LCD_DISPLAY_CONTROL | lcd_data.disp_cntl);
353 }
354 
355 
356 /** Turns cursor off */
pi_lcd_cursor_off(const struct device * gpio_dev)357 void pi_lcd_cursor_off(const struct device *gpio_dev)
358 {
359 	lcd_data.disp_cntl &= ~LCD_CURSOR_ON;
360 	_pi_lcd_command(gpio_dev,
361 			LCD_DISPLAY_CONTROL | lcd_data.disp_cntl);
362 }
363 
364 /** Turn cursor on */
pi_lcd_cursor_on(const struct device * gpio_dev)365 void pi_lcd_cursor_on(const struct device *gpio_dev)
366 {
367 	lcd_data.disp_cntl |= LCD_CURSOR_ON;
368 	_pi_lcd_command(gpio_dev,
369 			LCD_DISPLAY_CONTROL | lcd_data.disp_cntl);
370 }
371 
372 
373 /** Turn off the blinking cursor */
pi_lcd_blink_off(const struct device * gpio_dev)374 void pi_lcd_blink_off(const struct device *gpio_dev)
375 {
376 	lcd_data.disp_cntl &= ~LCD_BLINK_ON;
377 	_pi_lcd_command(gpio_dev,
378 			LCD_DISPLAY_CONTROL | lcd_data.disp_cntl);
379 }
380 
381 /** Turn on the blinking cursor */
pi_lcd_blink_on(const struct device * gpio_dev)382 void pi_lcd_blink_on(const struct device *gpio_dev)
383 {
384 	lcd_data.disp_cntl |= LCD_BLINK_ON;
385 	_pi_lcd_command(gpio_dev,
386 			LCD_DISPLAY_CONTROL | lcd_data.disp_cntl);
387 }
388 
389 /** Scroll the display left without changing the RAM */
pi_lcd_scroll_left(const struct device * gpio_dev)390 void pi_lcd_scroll_left(const struct device *gpio_dev)
391 {
392 	_pi_lcd_command(gpio_dev, LCD_CURSOR_SHIFT |
393 			LCD_DISPLAY_MOVE | LCD_MOVE_LEFT);
394 }
395 
396 /** Scroll the display right without changing the RAM */
pi_lcd_scroll_right(const struct device * gpio_dev)397 void pi_lcd_scroll_right(const struct device *gpio_dev)
398 {
399 	_pi_lcd_command(gpio_dev, LCD_CURSOR_SHIFT |
400 			LCD_DISPLAY_MOVE | LCD_MOVE_RIGHT);
401 }
402 
403 /** Text that flows from left to right */
pi_lcd_left_to_right(const struct device * gpio_dev)404 void pi_lcd_left_to_right(const struct device *gpio_dev)
405 {
406 	lcd_data.disp_mode |= LCD_ENTRY_LEFT;
407 	_pi_lcd_command(gpio_dev,
408 			LCD_ENTRY_MODE_SET | lcd_data.disp_cntl);
409 }
410 
411 /** Text that flows from right to left */
pi_lcd_right_to_left(const struct device * gpio_dev)412 void pi_lcd_right_to_left(const struct device *gpio_dev)
413 {
414 	lcd_data.disp_mode &= ~LCD_ENTRY_LEFT;
415 	_pi_lcd_command(gpio_dev,
416 			LCD_ENTRY_MODE_SET | lcd_data.disp_cntl);
417 }
418 
419 /** Right justify text from the cursor location */
pi_lcd_auto_scroll_right(const struct device * gpio_dev)420 void pi_lcd_auto_scroll_right(const struct device *gpio_dev)
421 {
422 	lcd_data.disp_mode |= LCD_ENTRY_SHIFT_INCREMENT;
423 	_pi_lcd_command(gpio_dev,
424 			LCD_ENTRY_MODE_SET | lcd_data.disp_cntl);
425 }
426 
427 /** Left justify text from the cursor location */
pi_lcd_auto_scroll_left(const struct device * gpio_dev)428 void pi_lcd_auto_scroll_left(const struct device *gpio_dev)
429 {
430 	lcd_data.disp_mode &= ~LCD_ENTRY_SHIFT_INCREMENT;
431 	_pi_lcd_command(gpio_dev,
432 			LCD_ENTRY_MODE_SET | lcd_data.disp_cntl);
433 }
434 
pi_lcd_string(const struct device * gpio_dev,char * msg)435 void pi_lcd_string(const struct device *gpio_dev, char *msg)
436 {
437 	int i;
438 	int len = 0;
439 	uint8_t data;
440 
441 	len = strlen(msg);
442 	if (len > LCD_WIDTH) {
443 		printk("Too long message! len %d %s\n", len, msg);
444 	}
445 
446 	for (i = 0; i < len; i++) {
447 		data = msg[i];
448 		_pi_lcd_write(gpio_dev, data);
449 	}
450 }
451 
452 
453 /** LCD initialization function */
pi_lcd_init(const struct device * gpio_dev,uint8_t cols,uint8_t rows,uint8_t dotsize)454 void pi_lcd_init(const struct device *gpio_dev, uint8_t cols, uint8_t rows,
455 		 uint8_t dotsize)
456 {
457 	if (rows > 1) {
458 		lcd_data.disp_func |= LCD_2_LINE;
459 	}
460 	lcd_data.cfg_rows = rows;
461 
462 	_set_row_offsets(0x00, 0x40, 0x00 + cols, 0x40 + cols);
463 
464 	/* For 1 line displays, a 10 pixel high font looks OK */
465 	if ((dotsize != LCD_5x8_DOTS) && (rows == 1U)) {
466 		lcd_data.disp_func |= LCD_5x10_DOTS;
467 	}
468 
469 	/* SEE PAGE 45/46 FOR INITIALIZATION SPECIFICATION!
470 	 * according to datasheet, we need at least 40ms after power rises
471 	 * above 2.7V before sending commands. Arduino can turn on way
472 	 * before 4.5V so we'll wait 50
473 	 */
474 	k_sleep(K_MSEC(50));
475 
476 	/* this is according to the hitachi HD44780 datasheet
477 	 * figure 23/24, pg 45/46 try to set 4/8 bits mode
478 	 */
479 	if (lcd_data.disp_func & LCD_8BIT_MODE) {
480 		/* 1st try */
481 		_pi_lcd_command(gpio_dev, 0x30);
482 		k_sleep(K_MSEC(5));			/* wait for 5ms */
483 
484 		/* 2nd try */
485 		_pi_lcd_command(gpio_dev, 0x30);
486 		k_sleep(K_MSEC(5));			/* wait for 5ms */
487 
488 		/* 3rd try */
489 		_pi_lcd_command(gpio_dev, 0x30);
490 		k_sleep(K_MSEC(1));			/* wait for 1ms */
491 
492 		/* Set 4bit interface */
493 		_pi_lcd_command(gpio_dev, 0x30);
494 	} else {
495 		/* 1st try */
496 		_pi_lcd_command(gpio_dev, 0x03);
497 		k_sleep(K_MSEC(5));			/* wait for 5ms */
498 
499 		/* 2nd try */
500 		_pi_lcd_command(gpio_dev, 0x03);
501 		k_sleep(K_MSEC(5));			/* wait for 5ms */
502 
503 		/* 3rd try */
504 		_pi_lcd_command(gpio_dev, 0x03);
505 		k_sleep(K_MSEC(1));			/* wait for 1ms */
506 
507 		/* Set 4bit interface */
508 		_pi_lcd_command(gpio_dev, 0x02);
509 	}
510 
511 	/* finally, set # lines, font size, etc. */
512 	_pi_lcd_command(gpio_dev, (LCD_FUNCTION_SET | lcd_data.disp_func));
513 
514 	/* turn the display on with no cursor or blinking default */
515 	lcd_data.disp_cntl = LCD_DISPLAY_ON | LCD_CURSOR_OFF | LCD_BLINK_OFF;
516 	pi_lcd_display_on(gpio_dev);
517 
518 	/* clear it off */
519 	pi_lcd_clear(gpio_dev);
520 
521 	/* Initialize to default text direction */
522 	lcd_data.disp_mode = LCD_ENTRY_LEFT | LCD_ENTRY_SHIFT_DECREMENT;
523 	/* set the entry mode */
524 	_pi_lcd_command(gpio_dev, LCD_ENTRY_MODE_SET | lcd_data.disp_mode);
525 }
526 
main(void)527 int main(void)
528 {
529 	const struct device *const gpio_dev = DEVICE_DT_GET(GPIO_NODE);
530 
531 	if (!device_is_ready(gpio_dev)) {
532 		printk("Device %s not ready!\n", gpio_dev->name);
533 		return 0;
534 	}
535 
536 	/* Setup GPIO output */
537 	GPIO_PIN_CFG(gpio_dev, GPIO_PIN_PC25_E, GPIO_OUTPUT);
538 	GPIO_PIN_CFG(gpio_dev, GPIO_PIN_PC28_RS, GPIO_OUTPUT);
539 	GPIO_PIN_CFG(gpio_dev, GPIO_PIN_PC12_D0, GPIO_OUTPUT);
540 	GPIO_PIN_CFG(gpio_dev, GPIO_PIN_PC13_D1, GPIO_OUTPUT);
541 	GPIO_PIN_CFG(gpio_dev, GPIO_PIN_PC14_D2, GPIO_OUTPUT);
542 	GPIO_PIN_CFG(gpio_dev, GPIO_PIN_PC15_D3, GPIO_OUTPUT);
543 	GPIO_PIN_CFG(gpio_dev, GPIO_PIN_PC24_D4, GPIO_OUTPUT);
544 	GPIO_PIN_CFG(gpio_dev, GPIO_PIN_PC23_D5, GPIO_OUTPUT);
545 	GPIO_PIN_CFG(gpio_dev, GPIO_PIN_PC22_D6, GPIO_OUTPUT);
546 	GPIO_PIN_CFG(gpio_dev, GPIO_PIN_PC21_D7, GPIO_OUTPUT);
547 
548 	printk("LCD Init\n");
549 	pi_lcd_init(gpio_dev, 20, 4, LCD_5x8_DOTS);
550 
551 	/* Clear display */
552 	pi_lcd_clear(gpio_dev);
553 
554 	while (1) {
555 		printk("Page 1: message\n");
556 
557 		pi_lcd_string(gpio_dev, "********************");
558 		pi_lcd_set_cursor(gpio_dev, 0, 1);
559 		pi_lcd_string(gpio_dev, "Arduino Due");
560 		pi_lcd_right_to_left(gpio_dev);
561 		pi_lcd_set_cursor(gpio_dev, 15, 2);
562 		pi_lcd_string(gpio_dev, "yalpsiD DCL 4x02");
563 		pi_lcd_set_cursor(gpio_dev, 19, 3);
564 		pi_lcd_left_to_right(gpio_dev);
565 		pi_lcd_string(gpio_dev, "********************");
566 		k_msleep(MSEC_PER_SEC * 3U);
567 
568 		/* Clear display */
569 		pi_lcd_clear(gpio_dev);
570 
571 		printk("Page 2: message\n");
572 
573 		pi_lcd_scroll_right(gpio_dev);
574 		pi_lcd_string(gpio_dev, "-------------------");
575 		pi_lcd_set_cursor(gpio_dev, 0, 1);
576 		pi_lcd_scroll_right(gpio_dev);
577 		pi_lcd_string(gpio_dev, "Zephyr Rocks!");
578 		pi_lcd_set_cursor(gpio_dev, 0, 2);
579 		pi_lcd_string(gpio_dev, "My super RTOS");
580 		pi_lcd_set_cursor(gpio_dev, 0, 3);
581 		pi_lcd_string(gpio_dev, "-------------------");
582 		k_msleep(MSEC_PER_SEC * 3U);
583 
584 		/* Clear display */
585 		pi_lcd_clear(gpio_dev);
586 
587 		printk("Page 3: message\n");
588 
589 		pi_lcd_set_cursor(gpio_dev, 0, 3);
590 		pi_lcd_string(gpio_dev, "--------------------");
591 		pi_lcd_home(gpio_dev);
592 		pi_lcd_string(gpio_dev, "--------HOME--------");
593 		pi_lcd_set_cursor(gpio_dev, 0, 1);
594 		pi_lcd_string(gpio_dev, "I am home!");
595 		pi_lcd_set_cursor(gpio_dev, 0, 2);
596 		pi_lcd_string(gpio_dev, "");
597 		k_msleep(MSEC_PER_SEC * 3U);
598 
599 		/* Clear display */
600 		pi_lcd_clear(gpio_dev);
601 	}
602 	return 0;
603 }
604