blob: d33fa670d71377a58ced798d290124b9422423ae [file] [log] [blame]
Steve Jeong8a774592023-06-01 18:36:00 +09001/*
2 * i2c_lcd.c:
3 * Standard "i2c_lcd" program in wiringPi.
4 * Supports 16x2 and 20x4 screens.
5 * reference: lcd_i2c.py (https://bitbucket.org/MattHawkinsUK/rpispy-misc/raw/master/python/lcd_i2c.py)
6 *
7 * Copyright (C) 2023 Steve Jeong
8 *
9 * This program is free software: you can redistribute it and/or modify
10 * it under the terms of the GNU General Public License as published by
11 * the Free Software Foundation, either version 3 of the License, or
12 * (at your option) any later version.
13 *
14 * This program is distributed in the hope that it will be useful,
15 * but WITHOUT ANY WARRANTY; without even the implied warranty of
16 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
17 * GNU General Public License for more details.
18 *
19 * You should have received a copy of the GNU General Public License
20 * along with this program. If not, see <http://www.gnu.org/licenses/>.
21 */
22
23#include <wiringPiI2C.h>
24#include <wiringPi.h>
25#include <stdlib.h>
26#include <string.h>
27#include <stdio.h>
28
29// Define some device parameters
30#define I2C_ADDR 0x3f // I2C device address
Steve Jeong8a774592023-06-01 18:36:00 +090031
32// Define some device constants
33#define LCD_CHR 1 // Mode - Sending data
34#define LCD_CMD 0 // Mode - Sending command
35
36#define LINE1 0x80 // 1st line
37#define LINE2 0xC0 // 2nd line
38#define LINE3 0x94 // 3rd line
39#define LINE4 0xD4 // 4th line
40
41#define LCD_BACKLIGHT 0x08 // On
Steve Jeong18668e82023-06-02 11:43:29 +090042// #define LCD_BACKLIGHT 0x00 // Off
Steve Jeong8a774592023-06-01 18:36:00 +090043
44#define ENABLE 0b00000100 // Enable bit
45
46void lcd_init(void);
47void lcd_byte(int bits, int mode);
48void lcd_toggle_enable(int bits);
49void display_string(const char *string, int line);
50
51int fd;
Steve Jeong18668e82023-06-02 11:43:29 +090052char *bus = "0"; /* /dev/i2c-0 ~ /dev/i2c-9 */
53int address = 0x3f;
Steve Jeong8a774592023-06-01 18:36:00 +090054
55int main(int argc, char *argv[]) {
56
Steve Jeong18668e82023-06-02 11:43:29 +090057 char device[12];
Steve Jeong8a774592023-06-01 18:36:00 +090058
59 if (wiringPiSetup () == -1)
60 exit (1);
61
62 if (argc > 1)
63 address = strtoul(argv[1], NULL, 16);
64
65 if (argc > 2) {
66 bus = argv[1];
67 address = strtoul(argv[2], NULL, 16);
68 }
69
Steve Jeong18668e82023-06-02 11:43:29 +090070 snprintf(device, 11, "%s%s", "/dev/i2c-", bus);
Steve Jeong8a774592023-06-01 18:36:00 +090071 fd = wiringPiI2CSetupInterface(device, address);
72
73 lcd_init(); // setup LCD
74
75 while (1) {
Steve Jeong18668e82023-06-02 11:43:29 +090076 display_string("HardKernel", LINE1);
Steve Jeong8a774592023-06-01 18:36:00 +090077 display_string("Hello ODROID", LINE2);
78 }
79
80 return 0;
Steve Jeong8a774592023-06-01 18:36:00 +090081}
82
83void display_string(const char *string, int line) {
84 // go to location on LCD
85 lcd_byte(line, LCD_CMD);
86
Steve Jeong18668e82023-06-02 11:43:29 +090087 while (*string) {
88 lcd_byte(*(string++), LCD_CHR);
Steve Jeong8a774592023-06-01 18:36:00 +090089 }
90
Steve Jeong8a774592023-06-01 18:36:00 +090091}
92
93void lcd_byte(int bits, int mode) {
94
95 //Send byte to data pins
96 // bits = the data
97 // mode = 1 for data, 0 for command
98 int bits_high;
99 int bits_low;
100 // uses the two half byte writes to LCD
Steve Jeong18668e82023-06-02 11:43:29 +0900101 bits_high = mode | (bits & 0xf0) | LCD_BACKLIGHT;
102 bits_low = mode | ((bits << 4) & 0xf0) | LCD_BACKLIGHT;
Steve Jeong8a774592023-06-01 18:36:00 +0900103
104 // High bits
105 wiringPiI2CReadReg8(fd, bits_high);
106 lcd_toggle_enable(bits_high);
107
108 // Low bits
109 wiringPiI2CReadReg8(fd, bits_low);
110 lcd_toggle_enable(bits_low);
111}
112
Steve Jeong18668e82023-06-02 11:43:29 +0900113void lcd_toggle_enable(int bits) {
Steve Jeong8a774592023-06-01 18:36:00 +0900114 // Toggle enable pin on LCD display
115 delayMicroseconds(500);
116 wiringPiI2CReadReg8(fd, (bits | ENABLE));
117 delayMicroseconds(500);
118 wiringPiI2CReadReg8(fd, (bits & ~ENABLE));
119 delayMicroseconds(500);
120}
121
Steve Jeong18668e82023-06-02 11:43:29 +0900122void lcd_init() {
Steve Jeong8a774592023-06-01 18:36:00 +0900123 // Initialise display
124 lcd_byte(0x33, LCD_CMD); // Initialise
125 lcd_byte(0x32, LCD_CMD); // Initialise
126 lcd_byte(0x06, LCD_CMD); // Cursor move direction
127 lcd_byte(0x0C, LCD_CMD); // 0x0F On, Blink Off
128 lcd_byte(0x28, LCD_CMD); // Data length, number of lines, font size
129 lcd_byte(0x01, LCD_CMD); // Clear display
130 delayMicroseconds(1000);
131}