-
Notifications
You must be signed in to change notification settings - Fork 28
/
lcd.go
182 lines (154 loc) · 4.47 KB
/
lcd.go
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
package i2c
// i2c LCD adapter
// Adapted from http://think-bowl.com/raspberry-pi/installing-the-think-bowl-i2c-libraries-for-python/
import "time"
const (
// Commands
CMD_Clear_Display = 0x01
CMD_Return_Home = 0x02
CMD_Entry_Mode = 0x04
CMD_Display_Control = 0x08
CMD_Cursor_Display_Shift = 0x10
CMD_Function_Set = 0x20
CMD_DDRAM_Set = 0x80
// Options
OPT_Increment = 0x02 // CMD_Entry_Mode
// OPT_Display_Shift = 0x01 // CMD_Entry_Mode
OPT_Enable_Display = 0x04 // CMD_Display_Control
OPT_Enable_Cursor = 0x02 // CMD_Display_Control
OPT_Enable_Blink = 0x01 // CMD_Display_Control
OPT_Display_Shift = 0x08 // CMD_Cursor_Display_Shift
OPT_Shift_Right = 0x04 // CMD_Cursor_Display_Shift 0 = Left
OPT_2_Lines = 0x08 // CMD_Function_Set 0 = 1 line
OPT_5x10_Dots = 0x04 // CMD_Function_Set 0 = 5x7 dots
)
type Lcd struct {
i2c *I2C
en, rw, rs, d4, d5, d6, d7, backlight byte
backlight_state bool
}
func NewLcd(i2c *I2C, en, rw, rs, d4, d5, d6, d7, backlight byte) (*Lcd, error) {
lcd := Lcd{
i2c: i2c,
en: en,
rw: rw,
rs: rs,
d4: d4,
d5: d5,
d6: d6,
d7: d7,
backlight: backlight,
}
// Activate LCD
var data byte
data = pinInterpret(lcd.d4, data, true)
data = pinInterpret(lcd.d5, data, true)
lcd.enable(data)
time.Sleep(200 * time.Millisecond)
lcd.enable(data)
time.Sleep(100 * time.Millisecond)
lcd.enable(data)
time.Sleep(100 * time.Millisecond)
// Initialize 4-bit mode
data = pinInterpret(lcd.d4, data, false)
lcd.enable(data)
time.Sleep(10 * time.Millisecond)
lcd.command(CMD_Function_Set | OPT_2_Lines)
lcd.command(CMD_Display_Control | OPT_Enable_Display | OPT_Enable_Cursor)
lcd.command(CMD_Clear_Display)
lcd.command(CMD_Entry_Mode | OPT_Increment | OPT_Display_Shift)
return &lcd, nil
}
func (lcd *Lcd) enable(data byte) {
// Determine if black light is on and insure it does not turn off or on
if lcd.backlight_state {
data = pinInterpret(lcd.backlight, data, true)
} else {
data = pinInterpret(lcd.backlight, data, false)
}
lcd.i2c.WriteByte(data)
lcd.i2c.WriteByte(pinInterpret(lcd.en, data, true))
lcd.i2c.WriteByte(data)
}
func (lcd *Lcd) command(data byte) {
lcd.write(data, true)
}
func (lcd *Lcd) write(data byte, command bool) {
var i2c_data byte
// Add data for high nibble
hi_nibble := data >> 4
i2c_data = pinInterpret(lcd.d4, i2c_data, (hi_nibble&0x01 == 0x01))
i2c_data = pinInterpret(lcd.d5, i2c_data, ((hi_nibble>>1)&0x01 == 0x01))
i2c_data = pinInterpret(lcd.d6, i2c_data, ((hi_nibble>>2)&0x01 == 0x01))
i2c_data = pinInterpret(lcd.d7, i2c_data, ((hi_nibble>>3)&0x01 == 0x01))
// # Set the register selector to 1 if this is data
if !command {
i2c_data = pinInterpret(lcd.rs, i2c_data, true)
}
// Toggle Enable
lcd.enable(i2c_data)
i2c_data = 0x00
// Add data for high nibble
low_nibble := data & 0x0F
i2c_data = pinInterpret(lcd.d4, i2c_data, (low_nibble&0x01 == 0x01))
i2c_data = pinInterpret(lcd.d5, i2c_data, ((low_nibble>>1)&0x01 == 0x01))
i2c_data = pinInterpret(lcd.d6, i2c_data, ((low_nibble>>2)&0x01 == 0x01))
i2c_data = pinInterpret(lcd.d7, i2c_data, ((low_nibble>>3)&0x01 == 0x01))
// Set the register selector to 1 if this is data
if !command {
i2c_data = pinInterpret(lcd.rs, i2c_data, true)
}
lcd.enable(i2c_data)
}
func (lcd *Lcd) BacklightOn() {
lcd.i2c.WriteByte(pinInterpret(lcd.backlight, 0x00, true))
lcd.backlight_state = true
}
func (lcd *Lcd) BacklightOff() {
lcd.i2c.WriteByte(pinInterpret(lcd.backlight, 0x00, false))
lcd.backlight_state = false
}
func (lcd *Lcd) Clear() {
lcd.command(CMD_Clear_Display)
}
func (lcd *Lcd) Home() {
lcd.command(CMD_Return_Home)
}
func (lcd *Lcd) SetPosition(line, pos byte) {
var address byte
switch line {
case 1:
address = pos
case 2:
address = 0x40 + pos
case 3:
address = 0x10 + pos
case 4:
address = 0x50 + pos
}
lcd.command(CMD_DDRAM_Set + address)
}
func (lcd *Lcd) Command(cmd byte) {
lcd.command(cmd)
}
func (lcd *Lcd) writeChar(char byte) {
lcd.write(char, false)
}
func (lcd *Lcd) Write(buf []byte) (int, error) {
for _, c := range buf {
lcd.writeChar(c)
}
return len(buf), nil
}
func pinInterpret(pin, data byte, value bool) byte {
if value {
// Construct mask using pin
var mask byte = 0x01 << (pin)
data = data | mask
} else {
// Construct mask using pin
var mask byte = 0x01<<(pin) ^ 0xFF
data = data & mask
}
return data
}