-
-
Notifications
You must be signed in to change notification settings - Fork 1
/
Copy pathTwiLiquidCrystal.cpp
260 lines (210 loc) · 7.17 KB
/
TwiLiquidCrystal.cpp
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
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
/*
Library created in February 2021
by Arnaud Ouvrier (http://www.arnaudouvrier.fr)
This is free and unencumbered software released into the public domain.
For more information, see http://unlicense.org/ or
the accompanying (un)LICENSE file
https://github.com/arnakazim/TwiLiquidCrystal-library
*/
#include "Arduino.h"
#include "Wire.h"
#include "TwiLiquidCrystal.h"
TwiLiquidCrystal::TwiLiquidCrystal(uint8_t address) {
_i2cLcdAddress = address;
}
void TwiLiquidCrystal::setRowOffsets(int row1, int row2, int row3, int row4) {
_rowOffsets[0] = row1;
_rowOffsets[1] = row2;
_rowOffsets[2] = row3;
_rowOffsets[3] = row4;
}
// write a byte to the I2C bus
size_t TwiLiquidCrystal::write(uint8_t byte) {
_ctrlRegister |= RS_BIT; // Set register to DATA
sendCmd(byte);
_ctrlRegister &= ~RS_BIT; // Reset register to INSTRUCTION
return 1;
}
void TwiLiquidCrystal::send(uint8_t byte) {
Wire.beginTransmission(_i2cLcdAddress);
Wire.write(byte);
Wire.endTransmission();
}
// Set the state of a bit in the Control register
void TwiLiquidCrystal::setCtrlRegisterBit(uint8_t bit, bool state) {
if(state) _ctrlRegister |= bit;
else _ctrlRegister &= ~bit;
}
void TwiLiquidCrystal::setDsplRegisterBit(uint8_t bit, bool state) {
if(state) _dsplRegister |= bit;
else _dsplRegister &= ~bit;
}
void TwiLiquidCrystal::setEntryModeBit(uint8_t bit, bool state) {
if(state) _modeRegister |= bit;
else _modeRegister &= ~bit;
}
// Merge the command quartet with the control command (BL EN RW RS)
void TwiLiquidCrystal::sendQuartet(uint8_t data) {
data |= _ctrlRegister;
send(data);
send(data | EN_BIT); // pulse enable
delayMicroseconds(1);
send(data);
delayMicroseconds(42);
}
// Take a command byte and split it in two quartets (LCD in 4 bit mode)
void TwiLiquidCrystal::sendCmd(uint8_t data) {
sendQuartet(data & DATA_PORTION);
sendQuartet((data << 4) & DATA_PORTION);
}
// Initialization routine to set the LCD to 4 bit mode
void TwiLiquidCrystal::initializationRoutine() {
// Init in 8-bit
// LiquidCrystal was outputing 0x30 4500µs - 0x30 4500µs 0x30 150µs
// The datasheet for the HD44780 says 0x30 4100µs - 0x30 100µs 0x30 no delay...
// (HD44780U datasheet, page 45)
// It also may be optionnal, useful only when "the power supply conditions for correctly operating the internal reset circuit are not met"
sendQuartet(LCD_FUNCTIONSET | LCD_FUNCTIONSET_DL_BIT);
delayMicroseconds(4200);
sendQuartet(LCD_FUNCTIONSET | LCD_FUNCTIONSET_DL_BIT);
delayMicroseconds(110);
sendQuartet(LCD_FUNCTIONSET | LCD_FUNCTIONSET_DL_BIT);
// set in 4-bit mode (Function set)
sendQuartet(LCD_FUNCTIONSET);
}
void TwiLiquidCrystal::setBacklight(bool state) {
setCtrlRegisterBit(BL_BIT, state);
send(_ctrlRegister);
}
// set the function register
// bytemode = 0 -> 4-bit mode; twoLines = 1 -> 2 lines; font = 0 -> 5x8 dots, 1 = 5x10
void TwiLiquidCrystal::setFctnRegister(uint8_t bytemode, uint8_t twoLines, uint8_t font) {
_fctnRegister = 0 | (bytemode << 4) | (twoLines << 3) | (font << 2);
sendCmd(LCD_FUNCTIONSET | _fctnRegister);
}
void TwiLiquidCrystal::setDsplControl(uint8_t display, uint8_t cursor, uint8_t blink) {
_dsplRegister = 0 | (display << 2) | (cursor << 1) | blink;
sendCmd(LCD_DISPLAYCONTROL | _dsplRegister);
}
void TwiLiquidCrystal::setEntryMode(uint8_t increment, uint8_t shift) {
_modeRegister = 0 | (increment << 1) | shift;
sendCmd(LCD_ENTRYMODESET | _modeRegister);
}
void TwiLiquidCrystal::setCursor(uint8_t col, uint8_t row) {
if ((row >= _rows) | (row >= 4)) {
row = _rows - 1;
}
sendCmd(LCD_SETDDRAMADDR | (col + _rowOffsets[row]));
}
// Clear the display
void TwiLiquidCrystal::clear() {
sendCmd(LCD_CLEARDISPLAY);
delay(2);
}
// Set cursor to 0;0 position
void TwiLiquidCrystal::home() {
sendCmd(LCD_RETURNHOME);
delay(2);
}
// Setting up and initializig the LCD
void TwiLiquidCrystal::begin(uint8_t cols, uint8_t rows, uint8_t font) {
Wire.begin();
_cols = cols;
_rows = rows;
_font = font;
// set rows start address
// On a 16x2:
// line 1, screen 1 [0x00 ; 0x0F]
// line 2, screen 1 [0x40 ; 0x4F]
// line 1, screen 2 [0x10 ; 0x1F]
// line 2, screen 2 [0x50 ; 0x5F]
// On a 20x4 (only one screen, HD44780 can only store 80 characters):
// (Remark: on a 20x4, incrementing the cursor col give this result:
// Line 1 -> Line 3 -> Line 2 -> Line 4)
// line 1, screen 1 [0x00 ; 0x13]
// line 2, screen 1 [0x40 ; 0x53]
// line 3, screen 1 [0x14 ; 0x27]
// line 4, screen 1 [0x54 ; 0x67]
setRowOffsets(0x00, 0x40, 0x00 + cols, 0x40 + cols);
delay(1000); // LCD power up time
send(0x00); // clear data line
initializationRoutine();
// first params(byte) = 0 -> Always 4bit
setFctnRegister(0, (rows != 1), font);
clear();
setDsplControl(1, 0, 0);
setEntryMode(1, 0);
home();
}
void TwiLiquidCrystal::createChar(uint8_t index, uint8_t character[]) {
index &= 0x7; // 7 editable characters
sendCmd(LCD_SETCGRAMADDR | (index << 3));
_ctrlRegister |= RS_BIT; // Set register to DATA
for (uint8_t i=0; i<8; i++) {
sendCmd(character[i]);
}
_ctrlRegister &= ~RS_BIT; // Reset register to INSTRUCTION
}
void TwiLiquidCrystal::selectScreen(uint8_t index) {
home();
for (uint8_t i = 0; i < index * _cols; i++) {
sendCmd(LCD_CURSORSHIFT | LCD_CURSORSHIFT_SC_BIT);
}
}
void TwiLiquidCrystal::backlight() {
setBacklight(true);
}
void TwiLiquidCrystal::noBacklight() {
setBacklight(false);
}
void TwiLiquidCrystal::display() {
setDsplRegisterBit(LCD_DISPLAYCONTROL_D_BIT, true);
sendCmd(LCD_DISPLAYCONTROL | _dsplRegister);
}
void TwiLiquidCrystal::noDisplay() {
setDsplRegisterBit(LCD_DISPLAYCONTROL_D_BIT, false);
sendCmd(LCD_DISPLAYCONTROL | _dsplRegister);
}
void TwiLiquidCrystal::blink(){
setDsplRegisterBit(LCD_DISPLAYCONTROL_B_BIT, true);
sendCmd(LCD_DISPLAYCONTROL | _dsplRegister);
}
void TwiLiquidCrystal::noBlink() {
setDsplRegisterBit(LCD_DISPLAYCONTROL_B_BIT, false);
sendCmd(LCD_DISPLAYCONTROL | _dsplRegister);
}
void TwiLiquidCrystal::cursor() {
setDsplRegisterBit(LCD_DISPLAYCONTROL_C_BIT, true);
sendCmd(LCD_DISPLAYCONTROL | _dsplRegister);
}
void TwiLiquidCrystal::noCursor() {
setDsplRegisterBit(LCD_DISPLAYCONTROL_C_BIT, false);
sendCmd(LCD_DISPLAYCONTROL | _dsplRegister);
}
void TwiLiquidCrystal::leftToRight() {
setEntryModeBit(LCD_ENTRYMODESET_ID_BIT, true);
sendCmd(LCD_ENTRYMODESET | _modeRegister);
}
// This is for text that flows Right to Left
void TwiLiquidCrystal::rightToLeft() {
setEntryModeBit(LCD_ENTRYMODESET_ID_BIT, false);
sendCmd(LCD_ENTRYMODESET | _modeRegister);
}
void TwiLiquidCrystal::autoscroll(void) {
setEntryModeBit(LCD_ENTRYMODESET_S_BIT, true);
sendCmd(LCD_ENTRYMODESET | _modeRegister);
}
// This will 'left justify' text from the cursor
void TwiLiquidCrystal::noAutoscroll(void) {
setEntryModeBit(LCD_ENTRYMODESET_S_BIT, false);
sendCmd(LCD_ENTRYMODESET | _modeRegister);
}
void TwiLiquidCrystal::scrollDisplayLeft(void) {
sendCmd(LCD_CURSORSHIFT | LCD_CURSORSHIFT_SC_BIT);
}
void TwiLiquidCrystal::scrollDisplayRight(void) {
sendCmd(LCD_CURSORSHIFT | LCD_CURSORSHIFT_RL_BIT | LCD_CURSORSHIFT_SC_BIT);
}
void TwiLiquidCrystal::command(uint8_t value) {
sendCmd(value);
}