User | Revision | Line number | New contents of line |
Wimpie |
0:9218cf335f9b
|
1
|
/* mbed I2CTextLCD Library
|
Wimpie |
0:9218cf335f9b
|
2
|
* Copyright (c) 2007-2009 sford
|
Wimpie |
0:9218cf335f9b
|
3
|
* Copyright (c) 2010 Wim De Roeve changed to work with I2C PCF8575
|
Wimpie |
0:9218cf335f9b
|
4
|
* Released under the MIT License: http://mbed.org/license/mit
|
Wimpie |
0:9218cf335f9b
|
5
|
*/
|
Wimpie |
0:9218cf335f9b
|
6
|
|
Wimpie |
0:9218cf335f9b
|
7
|
#include "I2CTextLCD.h"
|
Wimpie |
0:9218cf335f9b
|
8
|
#include "mbed.h"
|
Wimpie |
0:9218cf335f9b
|
9
|
#include "error.h"
|
Wimpie |
0:9218cf335f9b
|
10
|
|
Wimpie |
0:9218cf335f9b
|
11
|
using namespace mbed;
|
Wimpie |
0:9218cf335f9b
|
12
|
|
Wimpie |
0:9218cf335f9b
|
13
|
/*
|
Wimpie |
0:9218cf335f9b
|
14
|
* useful info found at http://www.a-netz.de/lcd.en.php
|
Wimpie |
0:9218cf335f9b
|
15
|
*
|
Wimpie |
0:9218cf335f9b
|
16
|
*
|
Wimpie |
0:9218cf335f9b
|
17
|
* Initialisation
|
Wimpie |
0:9218cf335f9b
|
18
|
* ==============
|
Wimpie |
0:9218cf335f9b
|
19
|
*
|
Wimpie |
0:9218cf335f9b
|
20
|
* After attaching the supply voltage/after a reset, the display needs to be brought in to a defined state
|
Wimpie |
0:9218cf335f9b
|
21
|
*
|
Wimpie |
0:9218cf335f9b
|
22
|
* - wait approximately 15 ms so the display is ready to execute commands
|
Wimpie |
0:9218cf335f9b
|
23
|
* - Execute the command 0x30 ("Display Settings") three times (wait 1,64ms after each command, the busy flag cannot be queried now).
|
Wimpie |
0:9218cf335f9b
|
24
|
* - The display is in 8 bit mode, so if you have only connected 4 data pins you should only transmit the higher nibble of each command.
|
Wimpie |
0:9218cf335f9b
|
25
|
* - If you want to use the 4 bit mode, now you can execute the command to switch over to this mode now.
|
Wimpie |
0:9218cf335f9b
|
26
|
* - Execute the "clear display" command
|
Wimpie |
0:9218cf335f9b
|
27
|
*
|
Wimpie |
0:9218cf335f9b
|
28
|
* Timing
|
Wimpie |
0:9218cf335f9b
|
29
|
* ======
|
Wimpie |
0:9218cf335f9b
|
30
|
*
|
Wimpie |
0:9218cf335f9b
|
31
|
* Nearly all commands transmitted to the display need 40us for execution.
|
Wimpie |
0:9218cf335f9b
|
32
|
* Exceptions are the commands "Clear Display and Reset" and "Set Cursor to Start Position"
|
Wimpie |
0:9218cf335f9b
|
33
|
* These commands need 1.64ms for execution. These timings are valid for all displays working with an
|
Wimpie |
0:9218cf335f9b
|
34
|
* internal clock of 250kHz. But I do not know any displays that use other frequencies. Any time you
|
Wimpie |
0:9218cf335f9b
|
35
|
* can use the busy flag to test if the display is ready to accept the next command.
|
Wimpie |
0:9218cf335f9b
|
36
|
*
|
Wimpie |
0:9218cf335f9b
|
37
|
*/
|
Wimpie |
0:9218cf335f9b
|
38
|
|
Wimpie |
0:9218cf335f9b
|
39
|
I2CTextLCD::I2CTextLCD(PinName sda, PinName scl, int i2cAddress , int columns, int rows) :
|
Wimpie |
0:9218cf335f9b
|
40
|
_i2c(sda, scl) {
|
Wimpie |
0:9218cf335f9b
|
41
|
|
Wimpie |
0:9218cf335f9b
|
42
|
_i2cAddress = i2cAddress;
|
Wimpie |
0:9218cf335f9b
|
43
|
_columns = columns;
|
Wimpie |
0:9218cf335f9b
|
44
|
_rows = rows;
|
Wimpie |
1:0eb3365ec819
|
45
|
_backlight=true;
|
Wimpie |
0:9218cf335f9b
|
46
|
|
Wimpie |
0:9218cf335f9b
|
47
|
// Should theoretically wait 15ms, but most things will be powered up pre-reset
|
Wimpie |
0:9218cf335f9b
|
48
|
// so i'll disable that for the minute. If implemented, could wait 15ms post reset
|
Wimpie |
0:9218cf335f9b
|
49
|
// instead
|
Wimpie |
0:9218cf335f9b
|
50
|
// wait(0.015);
|
Wimpie |
0:9218cf335f9b
|
51
|
|
Wimpie |
0:9218cf335f9b
|
52
|
// send "Display Settings" 3 times (Only top nibble of 0x30 as we've got 4-bit bus)
|
Wimpie |
0:9218cf335f9b
|
53
|
|
Wimpie |
0:9218cf335f9b
|
54
|
for (int i=0; i<3; i++) {
|
Wimpie |
0:9218cf335f9b
|
55
|
writeNibble(0x3,false);
|
Wimpie |
0:9218cf335f9b
|
56
|
wait(0.00164); // this command takes 1.64ms, so wait for it
|
Wimpie |
0:9218cf335f9b
|
57
|
}
|
Wimpie |
0:9218cf335f9b
|
58
|
writeNibble(0x2,false); // 4-bit mode
|
Wimpie |
0:9218cf335f9b
|
59
|
|
Wimpie |
0:9218cf335f9b
|
60
|
writeCommand(0x28); // Function set 001 BW N F - -
|
Wimpie |
0:9218cf335f9b
|
61
|
writeCommand(0x0C);
|
Wimpie |
0:9218cf335f9b
|
62
|
writeCommand(0x6); // Cursor Direction and Display Shift : 0000 01 CD S (CD 0-left, 1-right S(hift) 0-no, 1-yes
|
Wimpie |
0:9218cf335f9b
|
63
|
|
Wimpie |
0:9218cf335f9b
|
64
|
cls();
|
Wimpie |
0:9218cf335f9b
|
65
|
}
|
Wimpie |
0:9218cf335f9b
|
66
|
|
Wimpie |
0:9218cf335f9b
|
67
|
int I2CTextLCD::_putc(int value) {
|
Wimpie |
0:9218cf335f9b
|
68
|
if (value == '\n') {
|
Wimpie |
0:9218cf335f9b
|
69
|
newline();
|
Wimpie |
0:9218cf335f9b
|
70
|
} else {
|
Wimpie |
0:9218cf335f9b
|
71
|
writeData(value);
|
Wimpie |
0:9218cf335f9b
|
72
|
}
|
Wimpie |
0:9218cf335f9b
|
73
|
return value;
|
Wimpie |
0:9218cf335f9b
|
74
|
}
|
Wimpie |
0:9218cf335f9b
|
75
|
|
Wimpie |
0:9218cf335f9b
|
76
|
int I2CTextLCD::_getc() {
|
Wimpie |
0:9218cf335f9b
|
77
|
return 0;
|
Wimpie |
0:9218cf335f9b
|
78
|
}
|
Wimpie |
0:9218cf335f9b
|
79
|
|
Wimpie |
1:0eb3365ec819
|
80
|
void I2CTextLCD::backlight(bool on) {
|
Wimpie |
1:0eb3365ec819
|
81
|
_backlight=on;
|
Wimpie |
1:0eb3365ec819
|
82
|
}
|
Wimpie |
1:0eb3365ec819
|
83
|
|
Wimpie |
1:0eb3365ec819
|
84
|
|
Wimpie |
0:9218cf335f9b
|
85
|
void I2CTextLCD::newline() {
|
Wimpie |
0:9218cf335f9b
|
86
|
_column = 0;
|
Wimpie |
0:9218cf335f9b
|
87
|
_row++;
|
Wimpie |
0:9218cf335f9b
|
88
|
if (_row >= _rows) {
|
Wimpie |
0:9218cf335f9b
|
89
|
_row = 0;
|
Wimpie |
0:9218cf335f9b
|
90
|
}
|
Wimpie |
0:9218cf335f9b
|
91
|
locate(_column, _row);
|
Wimpie |
0:9218cf335f9b
|
92
|
}
|
Wimpie |
0:9218cf335f9b
|
93
|
|
Wimpie |
0:9218cf335f9b
|
94
|
void I2CTextLCD::locate(int column, int row) {
|
Wimpie |
0:9218cf335f9b
|
95
|
if (column < 0 || column >= _columns || row < 0 || row >= _rows) {
|
Wimpie |
0:9218cf335f9b
|
96
|
error("locate(%d,%d) out of range on %dx%d display", column, row, _columns, _rows);
|
Wimpie |
0:9218cf335f9b
|
97
|
return;
|
Wimpie |
0:9218cf335f9b
|
98
|
}
|
Wimpie |
0:9218cf335f9b
|
99
|
|
Wimpie |
0:9218cf335f9b
|
100
|
_row = row;
|
Wimpie |
0:9218cf335f9b
|
101
|
_column = column;
|
Wimpie |
0:9218cf335f9b
|
102
|
int address = 0x80 + (_row * 40) + _column; // memory starts at 0x80, and is 40 chars long per row
|
Wimpie |
0:9218cf335f9b
|
103
|
// pc_LCD.traceOut("locate %dx%d\r\n", column, row);
|
Wimpie |
0:9218cf335f9b
|
104
|
writeCommand(address);
|
Wimpie |
0:9218cf335f9b
|
105
|
}
|
Wimpie |
0:9218cf335f9b
|
106
|
|
Wimpie |
0:9218cf335f9b
|
107
|
void I2CTextLCD::cls() {
|
Wimpie |
0:9218cf335f9b
|
108
|
writeCommand(0x01); // Clear Display
|
Wimpie |
0:9218cf335f9b
|
109
|
wait(0.00164f); // This command takes 1.64 ms
|
Wimpie |
0:9218cf335f9b
|
110
|
locate(0, 0);
|
Wimpie |
0:9218cf335f9b
|
111
|
}
|
Wimpie |
0:9218cf335f9b
|
112
|
|
Wimpie |
0:9218cf335f9b
|
113
|
void I2CTextLCD::reset() {
|
Wimpie |
0:9218cf335f9b
|
114
|
cls();
|
Wimpie |
0:9218cf335f9b
|
115
|
}
|
Wimpie |
0:9218cf335f9b
|
116
|
|
Wimpie |
0:9218cf335f9b
|
117
|
void I2CTextLCD::writeNibble(int data, bool rs) {
|
Wimpie |
0:9218cf335f9b
|
118
|
|
Wimpie |
0:9218cf335f9b
|
119
|
data = (data & 0xF);
|
Wimpie |
0:9218cf335f9b
|
120
|
|
Wimpie |
1:0eb3365ec819
|
121
|
|
Wimpie |
1:0eb3365ec819
|
122
|
if (_backlight)
|
Wimpie |
1:0eb3365ec819
|
123
|
data= data | BACKLIGHT_ON;
|
Wimpie |
1:0eb3365ec819
|
124
|
|
Wimpie |
0:9218cf335f9b
|
125
|
if (rs) {
|
Wimpie |
0:9218cf335f9b
|
126
|
data = data | RS_ON; // set rs bit
|
Wimpie |
0:9218cf335f9b
|
127
|
}
|
Wimpie |
0:9218cf335f9b
|
128
|
|
Wimpie |
0:9218cf335f9b
|
129
|
writeI2CByte(data | E_ON); // E=1
|
Wimpie |
0:9218cf335f9b
|
130
|
|
Wimpie |
0:9218cf335f9b
|
131
|
wait(0.000040f);
|
Wimpie |
0:9218cf335f9b
|
132
|
writeI2CByte(data ); // E=0
|
Wimpie |
0:9218cf335f9b
|
133
|
|
Wimpie |
0:9218cf335f9b
|
134
|
wait(0.000040f);
|
Wimpie |
0:9218cf335f9b
|
135
|
writeI2CByte(data | E_ON); // E=1
|
Wimpie |
0:9218cf335f9b
|
136
|
}
|
Wimpie |
0:9218cf335f9b
|
137
|
|
Wimpie |
0:9218cf335f9b
|
138
|
void I2CTextLCD::writeByte(int data, bool rs) {
|
Wimpie |
0:9218cf335f9b
|
139
|
writeNibble(data >> 4 , rs);
|
Wimpie |
0:9218cf335f9b
|
140
|
writeNibble(data >> 0 , rs);
|
Wimpie |
0:9218cf335f9b
|
141
|
}
|
Wimpie |
0:9218cf335f9b
|
142
|
|
Wimpie |
0:9218cf335f9b
|
143
|
void I2CTextLCD::writeCommand(int command) {
|
Wimpie |
0:9218cf335f9b
|
144
|
//command ^= RS_ON; // RS = 0;
|
Wimpie |
0:9218cf335f9b
|
145
|
writeByte(command,false);
|
Wimpie |
0:9218cf335f9b
|
146
|
}
|
Wimpie |
0:9218cf335f9b
|
147
|
|
Wimpie |
0:9218cf335f9b
|
148
|
void I2CTextLCD::writeData(int data) {
|
Wimpie |
0:9218cf335f9b
|
149
|
// data = data | RS_ON; //RS = 1
|
Wimpie |
0:9218cf335f9b
|
150
|
writeByte(data,true);
|
Wimpie |
0:9218cf335f9b
|
151
|
|
Wimpie |
0:9218cf335f9b
|
152
|
_column++;
|
Wimpie |
0:9218cf335f9b
|
153
|
if (_column >= _columns) {
|
Wimpie |
0:9218cf335f9b
|
154
|
newline();
|
Wimpie |
0:9218cf335f9b
|
155
|
}
|
Wimpie |
0:9218cf335f9b
|
156
|
}
|
Wimpie |
0:9218cf335f9b
|
157
|
|
Wimpie |
0:9218cf335f9b
|
158
|
void I2CTextLCD::writeI2CByte(int data) {
|
Wimpie |
0:9218cf335f9b
|
159
|
char cmd[2];
|
Wimpie |
0:9218cf335f9b
|
160
|
cmd[0] = (data & 0xFF);
|
Wimpie |
0:9218cf335f9b
|
161
|
cmd[1] = (data >> 8);
|
Wimpie |
0:9218cf335f9b
|
162
|
_i2c.write(_i2cAddress, cmd, 2);
|
Wimpie |
0:9218cf335f9b
|
163
|
}
|
Wimpie |
1:0eb3365ec819
|
164
|
|
Wimpie |
1:0eb3365ec819
|
165
|
|