Statistics
| Revision:

root / Ports / PortsLCD.cpp

History | View | Annotate | Download (10.2 KB)

1 7763 jcw
//>>> The latest version of this code can be found at https://github.com/jcw/ !!
2 7763 jcw
3 4727 jcw
#include "PortsLCD.h"
4 4727 jcw
#include <stdio.h>
5 4727 jcw
#include <string.h>
6 4727 jcw
#include <inttypes.h>
7 4727 jcw
#include "WProgram.h"
8 4727 jcw
9 4727 jcw
void LiquidCrystalBase::begin(byte cols, byte lines, byte dotsize) {
10 4727 jcw
  if (lines > 1) {
11 4727 jcw
    _displayfunction |= LCD_2LINE;
12 4727 jcw
  }
13 4727 jcw
  _numlines = lines;
14 4727 jcw
  _currline = 0;
15 4727 jcw
16 4727 jcw
  // for some 1 line displays you can select a 10 pixel high font
17 4727 jcw
  if ((dotsize != 0) && (lines == 1)) {
18 4727 jcw
    _displayfunction |= LCD_5x10DOTS;
19 4727 jcw
  }
20 4727 jcw
21 4727 jcw
  // SEE PAGE 45/46 FOR INITIALIZATION SPECIFICATION!
22 4727 jcw
  // according to datasheet, we need at least 40ms after power rises above 2.7V
23 4727 jcw
  // before sending commands. Arduino can turn on way befer 4.5V so we'll wait 50
24 4727 jcw
  delayMicroseconds(50000); // can't use delay, may get called before main!
25 4727 jcw
26 4727 jcw
  // Now we pull both RS and R/W low to begin commands
27 4727 jcw
  config();
28 4727 jcw
29 4727 jcw
  //put the LCD into 4 bit or 8 bit mode
30 4727 jcw
  if (! (_displayfunction & LCD_8BITMODE)) {
31 4727 jcw
    // this is according to the hitachi HD44780 datasheet
32 4727 jcw
    // figure 24, pg 46
33 4727 jcw
34 4727 jcw
    // we start in 8bit mode, try to set 4 bit mode
35 4727 jcw
    write4bits(0x03);
36 4727 jcw
    delayMicroseconds(4500); // wait min 4.1ms
37 4727 jcw
38 4727 jcw
    // second try
39 4727 jcw
    write4bits(0x03);
40 4727 jcw
    delayMicroseconds(4500); // wait min 4.1ms
41 4727 jcw
42 4727 jcw
    // third go!
43 4727 jcw
    write4bits(0x03);
44 4727 jcw
    delayMicroseconds(150);
45 4727 jcw
46 4727 jcw
    // finally, set to 8-bit interface
47 4727 jcw
    write4bits(0x02);
48 4727 jcw
  } else {
49 4727 jcw
    // this is according to the hitachi HD44780 datasheet
50 4727 jcw
    // page 45 figure 23
51 4727 jcw
52 4727 jcw
    // Send function set command sequence
53 4727 jcw
    command(LCD_FUNCTIONSET | _displayfunction);
54 4727 jcw
    delayMicroseconds(4500);  // wait more than 4.1ms
55 4727 jcw
56 4727 jcw
    // second try
57 4727 jcw
    command(LCD_FUNCTIONSET | _displayfunction);
58 4727 jcw
    delayMicroseconds(150);
59 4727 jcw
60 4727 jcw
    // third go
61 4727 jcw
    command(LCD_FUNCTIONSET | _displayfunction);
62 4727 jcw
  }
63 4727 jcw
64 4727 jcw
  // finally, set # lines, font size, etc.
65 4727 jcw
  command(LCD_FUNCTIONSET | _displayfunction);
66 4727 jcw
67 4727 jcw
  // turn the display on with no cursor or blinking default
68 4727 jcw
  _displaycontrol = LCD_DISPLAYON | LCD_CURSOROFF | LCD_BLINKOFF;
69 4727 jcw
  display();
70 4727 jcw
71 4727 jcw
  // clear it off
72 4727 jcw
  clear();
73 4727 jcw
74 4727 jcw
  // Initialize to default text direction (for romance languages)
75 4727 jcw
  _displaymode = LCD_ENTRYLEFT | LCD_ENTRYSHIFTDECREMENT;
76 4727 jcw
  // set the entry mode
77 4727 jcw
  command(LCD_ENTRYMODESET | _displaymode);
78 4727 jcw
79 4727 jcw
}
80 4727 jcw
81 4727 jcw
/********** high level commands, for the user! */
82 4727 jcw
void LiquidCrystalBase::clear()
83 4727 jcw
{
84 4727 jcw
  command(LCD_CLEARDISPLAY);  // clear display, set cursor position to zero
85 4727 jcw
  delayMicroseconds(2000);  // this command takes a long time!
86 4727 jcw
}
87 4727 jcw
88 4727 jcw
void LiquidCrystalBase::home()
89 4727 jcw
{
90 4727 jcw
  command(LCD_RETURNHOME);  // set cursor position to zero
91 4727 jcw
  delayMicroseconds(2000);  // this command takes a long time!
92 4727 jcw
}
93 4727 jcw
94 4727 jcw
void LiquidCrystalBase::setCursor(byte col, byte row)
95 4727 jcw
{
96 4727 jcw
  int row_offsets[] = { 0x00, 0x40, 0x14, 0x54 };
97 4727 jcw
  if ( row > _numlines ) {
98 4727 jcw
    row = _numlines-1;    // we count rows starting w/0
99 4727 jcw
  }
100 4727 jcw
101 4727 jcw
  command(LCD_SETDDRAMADDR | (col + row_offsets[row]));
102 4727 jcw
}
103 4727 jcw
104 4727 jcw
// Turn the display on/off (quickly)
105 4727 jcw
void LiquidCrystalBase::noDisplay() {
106 4727 jcw
  _displaycontrol &= ~LCD_DISPLAYON;
107 4727 jcw
  command(LCD_DISPLAYCONTROL | _displaycontrol);
108 4727 jcw
}
109 4727 jcw
void LiquidCrystalBase::display() {
110 4727 jcw
  _displaycontrol |= LCD_DISPLAYON;
111 4727 jcw
  command(LCD_DISPLAYCONTROL | _displaycontrol);
112 4727 jcw
}
113 4727 jcw
114 4727 jcw
// Turns the underline cursor on/off
115 4727 jcw
void LiquidCrystalBase::noCursor() {
116 4727 jcw
  _displaycontrol &= ~LCD_CURSORON;
117 4727 jcw
  command(LCD_DISPLAYCONTROL | _displaycontrol);
118 4727 jcw
}
119 4727 jcw
void LiquidCrystalBase::cursor() {
120 4727 jcw
  _displaycontrol |= LCD_CURSORON;
121 4727 jcw
  command(LCD_DISPLAYCONTROL | _displaycontrol);
122 4727 jcw
}
123 4727 jcw
124 4727 jcw
// Turn on and off the blinking cursor
125 4727 jcw
void LiquidCrystalBase::noBlink() {
126 4727 jcw
  _displaycontrol &= ~LCD_BLINKON;
127 4727 jcw
  command(LCD_DISPLAYCONTROL | _displaycontrol);
128 4727 jcw
}
129 4727 jcw
void LiquidCrystalBase::blink() {
130 4727 jcw
  _displaycontrol |= LCD_BLINKON;
131 4727 jcw
  command(LCD_DISPLAYCONTROL | _displaycontrol);
132 4727 jcw
}
133 4727 jcw
134 4727 jcw
// These commands scroll the display without changing the RAM
135 4727 jcw
void LiquidCrystalBase::scrollDisplayLeft(void) {
136 4727 jcw
  command(LCD_CURSORSHIFT | LCD_DISPLAYMOVE | LCD_MOVELEFT);
137 4727 jcw
}
138 4727 jcw
void LiquidCrystalBase::scrollDisplayRight(void) {
139 4727 jcw
  command(LCD_CURSORSHIFT | LCD_DISPLAYMOVE | LCD_MOVERIGHT);
140 4727 jcw
}
141 4727 jcw
142 4727 jcw
// This is for text that flows Left to Right
143 4727 jcw
void LiquidCrystalBase::leftToRight(void) {
144 4727 jcw
  _displaymode |= LCD_ENTRYLEFT;
145 4727 jcw
  command(LCD_ENTRYMODESET | _displaymode);
146 4727 jcw
}
147 4727 jcw
148 4727 jcw
// This is for text that flows Right to Left
149 4727 jcw
void LiquidCrystalBase::rightToLeft(void) {
150 4727 jcw
  _displaymode &= ~LCD_ENTRYLEFT;
151 4727 jcw
  command(LCD_ENTRYMODESET | _displaymode);
152 4727 jcw
}
153 4727 jcw
154 4727 jcw
// This will 'right justify' text from the cursor
155 4727 jcw
void LiquidCrystalBase::autoscroll(void) {
156 4727 jcw
  _displaymode |= LCD_ENTRYSHIFTINCREMENT;
157 4727 jcw
  command(LCD_ENTRYMODESET | _displaymode);
158 4727 jcw
}
159 4727 jcw
160 4727 jcw
// This will 'left justify' text from the cursor
161 4727 jcw
void LiquidCrystalBase::noAutoscroll(void) {
162 4727 jcw
  _displaymode &= ~LCD_ENTRYSHIFTINCREMENT;
163 4727 jcw
  command(LCD_ENTRYMODESET | _displaymode);
164 4727 jcw
}
165 4727 jcw
166 4727 jcw
// Allows us to fill the first 8 CGRAM locations
167 4727 jcw
// with custom characters
168 4727 jcw
void LiquidCrystalBase::createChar(byte location, byte charmap[]) {
169 4727 jcw
  location &= 0x7; // we only have 8 locations 0-7
170 4727 jcw
  command(LCD_SETCGRAMADDR | (location << 3));
171 4727 jcw
  for (int i=0; i<8; i++) {
172 4727 jcw
    write(charmap[i]);
173 4727 jcw
  }
174 4727 jcw
}
175 4727 jcw
176 4727 jcw
/*********** mid level commands, for sending data/cmds */
177 4727 jcw
178 4727 jcw
inline void LiquidCrystalBase::command(byte value) {
179 4727 jcw
  send(value, LOW);
180 4727 jcw
}
181 4727 jcw
182 4727 jcw
inline void LiquidCrystalBase::write(byte value) {
183 4727 jcw
  send(value, HIGH);
184 4727 jcw
}
185 4727 jcw
186 4727 jcw
// When the display powers up, it is configured as follows:
187 4727 jcw
//
188 4727 jcw
// 1. Display clear
189 4727 jcw
// 2. Function set:
190 4727 jcw
//    DL = 1; 8-bit interface data
191 4727 jcw
//    N = 0; 1-line display
192 4727 jcw
//    F = 0; 5x8 dot character font
193 4727 jcw
// 3. Display on/off control:
194 4727 jcw
//    D = 0; Display off
195 4727 jcw
//    C = 0; Cursor off
196 4727 jcw
//    B = 0; Blinking off
197 4727 jcw
// 4. Entry mode set:
198 4727 jcw
//    I/D = 1; Increment by 1
199 4727 jcw
//    S = 0; No shift
200 4727 jcw
//
201 4727 jcw
// Note, however, that resetting the Arduino doesn't reset the LCD, so we
202 4727 jcw
// can't assume that its in that state when a sketch starts (and the
203 4727 jcw
// LiquidCrystal constructor is called).
204 4727 jcw
205 4727 jcw
LiquidCrystal::LiquidCrystal(byte rs, byte rw, byte enable,
206 4727 jcw
             byte d0, byte d1, byte d2, byte d3, byte d4, byte d5, byte d6, byte d7)
207 4727 jcw
{
208 4727 jcw
  init(0, rs, rw, enable, d0, d1, d2, d3, d4, d5, d6, d7);
209 4727 jcw
}
210 4727 jcw
211 4727 jcw
LiquidCrystal::LiquidCrystal(byte rs, byte enable,
212 4727 jcw
             byte d0, byte d1, byte d2, byte d3, byte d4, byte d5, byte d6, byte d7)
213 4727 jcw
{
214 4727 jcw
  init(0, rs, -1, enable, d0, d1, d2, d3, d4, d5, d6, d7);
215 4727 jcw
}
216 4727 jcw
217 4727 jcw
LiquidCrystal::LiquidCrystal(byte rs, byte rw, byte enable,
218 4727 jcw
             byte d0, byte d1, byte d2, byte d3)
219 4727 jcw
{
220 4727 jcw
  init(1, rs, rw, enable, d0, d1, d2, d3, 0, 0, 0, 0);
221 4727 jcw
}
222 4727 jcw
223 4727 jcw
LiquidCrystal::LiquidCrystal(byte rs,  byte enable,
224 4727 jcw
             byte d0, byte d1, byte d2, byte d3)
225 4727 jcw
{
226 4727 jcw
  init(1, rs, -1, enable, d0, d1, d2, d3, 0, 0, 0, 0);
227 4727 jcw
}
228 4727 jcw
229 4727 jcw
void LiquidCrystal::init(byte fourbitmode, byte rs, byte rw, byte enable,
230 4727 jcw
                         byte d0, byte d1, byte d2, byte d3, byte d4, byte d5, byte d6, byte d7)
231 4727 jcw
{
232 4727 jcw
  _rs_pin = rs;
233 4727 jcw
  _rw_pin = rw;
234 4727 jcw
  _enable_pin = enable;
235 4727 jcw
236 4727 jcw
  _data_pins[0] = d0;
237 4727 jcw
  _data_pins[1] = d1;
238 4727 jcw
  _data_pins[2] = d2;
239 4727 jcw
  _data_pins[3] = d3;
240 4727 jcw
  _data_pins[4] = d4;
241 4727 jcw
  _data_pins[5] = d5;
242 4727 jcw
  _data_pins[6] = d6;
243 4727 jcw
  _data_pins[7] = d7;
244 4727 jcw
245 4727 jcw
  pinMode(_rs_pin, OUTPUT);
246 4727 jcw
  // we can save 1 pin by not using RW. Indicate by passing -1 instead of pin#
247 4727 jcw
  if (_rw_pin != -1) {
248 4727 jcw
    pinMode(_rw_pin, OUTPUT);
249 4727 jcw
  }
250 4727 jcw
  pinMode(_enable_pin, OUTPUT);
251 4727 jcw
252 4727 jcw
  if (fourbitmode)
253 4727 jcw
    _displayfunction = LCD_4BITMODE | LCD_1LINE | LCD_5x8DOTS;
254 4727 jcw
  else
255 4727 jcw
    _displayfunction = LCD_8BITMODE | LCD_1LINE | LCD_5x8DOTS;
256 4727 jcw
257 4727 jcw
  begin(16, 1);
258 4727 jcw
}
259 4727 jcw
260 4727 jcw
/************ low level data pushing commands **********/
261 4727 jcw
262 4727 jcw
void LiquidCrystal::config() {
263 4727 jcw
  // SEE PAGE 45/46 FOR INITIALIZATION SPECIFICATION!
264 4727 jcw
  // according to datasheet, we need at least 40ms after power rises above 2.7V
265 4727 jcw
  // before sending commands. Arduino can turn on way befer 4.5V so we'll wait 50
266 4727 jcw
  delayMicroseconds(50000);
267 4727 jcw
  // Now we pull both RS and R/W low to begin commands
268 4727 jcw
  digitalWrite(_rs_pin, LOW);
269 4727 jcw
  digitalWrite(_enable_pin, LOW);
270 4727 jcw
  if (_rw_pin != -1) {
271 4727 jcw
    digitalWrite(_rw_pin, LOW);
272 4727 jcw
  }
273 4727 jcw
}
274 4727 jcw
275 4727 jcw
// write either command or data, with automatic 4/8-bit selection
276 4727 jcw
void LiquidCrystal::send(byte value, byte mode) {
277 4727 jcw
  digitalWrite(_rs_pin, mode);
278 4727 jcw
279 4727 jcw
  // if there is a RW pin indicated, set it low to Write
280 4727 jcw
  if (_rw_pin != -1) {
281 4727 jcw
    digitalWrite(_rw_pin, LOW);
282 4727 jcw
  }
283 4727 jcw
284 4727 jcw
  if (_displayfunction & LCD_8BITMODE) {
285 4727 jcw
    write8bits(value);
286 4727 jcw
  } else {
287 4727 jcw
    write4bits(value>>4);
288 4727 jcw
    write4bits(value);
289 4727 jcw
  }
290 4727 jcw
}
291 4727 jcw
292 4727 jcw
void LiquidCrystal::pulseEnable(void) {
293 4727 jcw
  digitalWrite(_enable_pin, LOW);
294 4727 jcw
  delayMicroseconds(1);
295 4727 jcw
  digitalWrite(_enable_pin, HIGH);
296 4727 jcw
  delayMicroseconds(1);    // enable pulse must be >450ns
297 4727 jcw
  digitalWrite(_enable_pin, LOW);
298 4727 jcw
  delayMicroseconds(100);   // commands need > 37us to settle
299 4727 jcw
}
300 4727 jcw
301 4727 jcw
void LiquidCrystal::write4bits(byte value) {
302 4727 jcw
  for (int i = 0; i < 4; i++) {
303 4727 jcw
    pinMode(_data_pins[i], OUTPUT);
304 4727 jcw
    digitalWrite(_data_pins[i], (value >> i) & 0x01);
305 4727 jcw
  }
306 4727 jcw
307 4727 jcw
  pulseEnable();
308 4727 jcw
}
309 4727 jcw
310 4727 jcw
void LiquidCrystal::write8bits(byte value) {
311 4727 jcw
  for (int i = 0; i < 8; i++) {
312 4727 jcw
    pinMode(_data_pins[i], OUTPUT);
313 4727 jcw
    digitalWrite(_data_pins[i], (value >> i) & 0x01);
314 4727 jcw
  }
315 4727 jcw
316 4727 jcw
  pulseEnable();
317 4727 jcw
}
318 4727 jcw
319 4727 jcw
enum {
320 4727 jcw
  MCP_IODIR, MCP_IPOL, MCP_GPINTEN, MCP_DEFVAL, MCP_INTCON, MCP_IOCON,
321 4727 jcw
  MCP_GPPU, MCP_INTF, MCP_INTCAP, MCP_GPIO, MCP_OLAT
322 4727 jcw
};
323 4727 jcw
324 4727 jcw
// bits 0..3 and D4..D7, the rest is connected as follows
325 4727 jcw
#define MCP_BACKLIGHT   0x80
326 4727 jcw
#define MCP_ENABLE      0x40
327 4727 jcw
#define MCP_OTHER       0x20
328 4727 jcw
#define MCP_REGSEL      0x10
329 4727 jcw
330 4769 jcw
LiquidCrystalI2C::LiquidCrystalI2C (const PortI2C& p, byte addr)
331 4769 jcw
    : device (p, addr) {
332 4769 jcw
  _displayfunction = LCD_4BITMODE | LCD_1LINE | LCD_5x8DOTS;
333 4769 jcw
  begin(16, 2);
334 4769 jcw
}
335 4769 jcw
336 4769 jcw
void LiquidCrystalI2C::backlight() {
337 4769 jcw
    device.send();
338 4769 jcw
    device.write(MCP_IODIR);
339 4769 jcw
    device.write(0); // IODIR: all outputs
340 4769 jcw
    device.stop();
341 4769 jcw
}
342 4769 jcw
343 4769 jcw
void LiquidCrystalI2C::noBacklight() {
344 4769 jcw
    device.send();
345 4769 jcw
    device.write(MCP_IODIR);
346 4769 jcw
    device.write(MCP_BACKLIGHT); // IODIR: all outputs, except backlight
347 4769 jcw
    device.stop();
348 4769 jcw
}
349 4769 jcw
350 4769 jcw
/************ low level data pushing commands **********/
351 4769 jcw
352 4727 jcw
void LiquidCrystalI2C::config() {
353 4727 jcw
  // IOCON: SEQOP = 1, ODR = 1, rest zero
354 4727 jcw
  device.send();
355 4727 jcw
  device.write(MCP_IOCON);
356 4727 jcw
  device.write(0x24);
357 4727 jcw
  device.stop();
358 4770 jcw
  backlight(); // start with backlight on
359 4727 jcw
}
360 4727 jcw
361 4727 jcw
// write either command or data, with automatic 4/8-bit selection
362 4727 jcw
void LiquidCrystalI2C::send(byte value, byte mode) {
363 4727 jcw
  if (mode != 0)
364 4727 jcw
    mode = MCP_REGSEL;
365 4727 jcw
  write4bits((value >> 4) | mode);
366 4727 jcw
  write4bits((value & 0x0F) | mode);
367 4727 jcw
}
368 4727 jcw
369 4727 jcw
void LiquidCrystalI2C::write4bits(byte value) {
370 4727 jcw
  value |= MCP_BACKLIGHT | MCP_ENABLE;
371 4727 jcw
  device.send();
372 4727 jcw
  device.write(MCP_GPIO);
373 4727 jcw
  device.write(value);
374 4727 jcw
  device.write(value ^ MCP_ENABLE);
375 4727 jcw
  device.write(value);
376 4727 jcw
  device.stop();
377 4727 jcw
}