1// --------------------------------------------------------------------------- 2// Created by Francisco Malpartida on 20/08/11. 3// Copyright 2011 - Under creative commons license 3.0: 4// Attribution-ShareAlike CC BY-SA 5// 6// This software is furnished "as is", without technical support, and with no 7// warranty, express or implied, as to its usefulness for any purpose. 8// 9// Thread Safe: No 10// Extendable: Yes 11// 12// @file LCD.cpp 13// This file implements a basic liquid crystal library that comes as standard 14// in the Arduino SDK. 15// 16// @brief 17// This is a basic implementation of the HD44780 library of the 18// Arduino SDK. This library is a refactored version of the one supplied 19// in the Arduino SDK in such a way that it simplifies its extension 20// to support other mechanism to communicate to LCDs such as I2C, Serial, SR, ... 21// The original library has been reworked in such a way that this will be 22// the base class implementing all generic methods to command an LCD based 23// on the Hitachi HD44780 and compatible chipsets. 24// 25// This base class is a pure abstract class and needs to be extended. As reference, 26// it has been extended to drive 4 and 8 bit mode control, LCDs and I2C extension 27// backpacks such as the I2CLCDextraIO using the PCF8574* I2C IO Expander ASIC. 28// 29// 30// @version API 1.1.0 31// 32// 2012.03.29 bperrybap - changed comparision to use LCD_5x8DOTS rather than 0 33// @author F. Malpartida - fmalpartida@gmail.com 34// --------------------------------------------------------------------------- 35#include <stdio.h> 36#include <string.h> 37#include <inttypes.h> 38 39#if (ARDUINO < 100) 40#include <WProgram.h> 41#else 42#include <Arduino.h> 43#endif 44#include"Visuino_LCD.h" 45 46// CLASS CONSTRUCTORS 47// --------------------------------------------------------------------------- 48// Constructor 49LCD::LCD() 50{ 51 52} 53 54// PUBLIC METHODS 55// --------------------------------------------------------------------------- 56// When the display powers up, it is configured as follows: 57// 58// 1. Display clear 59// 2. Function set: 60// DL = 1; 8-bit interface data 61// N = 0; 1-line display 62// F = 0; 5x8 dot character font 63// 3. Display on/off control: 64// D = 0; Display off 65// C = 0; Cursor off 66// B = 0; Blinking off 67// 4. Entry mode set: 68// I/D = 1; Increment by 1 69// S = 0; No shift 70// 71// Note, however, that resetting the Arduino doesn't reset the LCD, so we 72// can't assume that its in that state when a sketch starts (and the 73// LiquidCrystal constructor is called). 74// A call to begin() will reinitialize the LCD. 75// 76voidLCD::begin(uint8_t cols,uint8_t lines,uint8_t dotsize) 77{ 78if(lines >1) 79{ 80 _displayfunction |= LCD_2LINE; 81} 82 _numlines = lines; 83 _cols = cols; 84 85// for some 1 line displays you can select a 10 pixel high font 86// ------------------------------------------------------------ 87if((dotsize != LCD_5x8DOTS) && (lines ==1)) 88{ 89 _displayfunction |= LCD_5x10DOTS; 90} 91 92// SEE PAGE 45/46 FOR INITIALIZATION SPECIFICATION! 93// according to datasheet, we need at least 40ms after power rises above 2.7V 94// before sending commands. Arduino can turn on way before 4.5V so we'll wait 95// 50 96// --------------------------------------------------------------------------- 97delay(100);// 100ms delay 98 99//put the LCD into 4 bit or 8 bit mode 100// ------------------------------------- 101if(! (_displayfunction & LCD_8BITMODE)) 102{ 103// this is according to the hitachi HD44780 datasheet 104// figure 24, pg 46 105 106// we start in 8bit mode, try to set 4 bit mode 107send(0x03, FOUR_BITS); 108delayMicroseconds(4500);// wait min 4.1ms 109 110// second try 111send(0x03, FOUR_BITS ); 112delayMicroseconds(4500);// wait min 4.1ms 113 114// third go! 115send(0x03, FOUR_BITS ); 116delayMicroseconds(150); 117 118// finally, set to 4-bit interface 119send(0x02, FOUR_BITS ); 120} 121else 122{ 123// this is according to the hitachi HD44780 datasheet 124// page 45 figure 23 125 126// Send function set command sequence 127command(LCD_FUNCTIONSET | _displayfunction); 128delayMicroseconds(4500);// wait more than 4.1ms 129 130// second try 131command(LCD_FUNCTIONSET | _displayfunction); 132delayMicroseconds(150); 133 134// third go 135command(LCD_FUNCTIONSET | _displayfunction); 136} 137 138// finally, set # lines, font size, etc. 139command(LCD_FUNCTIONSET | _displayfunction); 140 141// turn the display on with no cursor or blinking default 142 _displaycontrol = LCD_DISPLAYON | LCD_CURSOROFF | LCD_BLINKOFF; 143display(); 144 145// clear the LCD 146clear(); 147 148// Initialize to default text direction (for romance languages) 149 _displaymode = LCD_ENTRYLEFT | LCD_ENTRYSHIFTDECREMENT; 150// set the entry mode 151command(LCD_ENTRYMODESET | _displaymode); 152 153backlight(); 154 155} 156 157// Common LCD Commands 158// --------------------------------------------------------------------------- 159voidLCD::clear() 160{ 161command(LCD_CLEARDISPLAY);// clear display, set cursor position to zero 162delayMicroseconds(HOME_CLEAR_EXEC);// this command is time consuming 163} 164 165voidLCD::home() 166{ 167command(LCD_RETURNHOME);// set cursor position to zero 168delayMicroseconds(HOME_CLEAR_EXEC);// This command is time consuming 169} 170 171voidLCD::setCursor(uint8_t col,uint8_t row) 172{ 173const byte row_offsetsDef[] = {0x00,0x40,0x14,0x54};// For regular LCDs 174const byte row_offsetsLarge[] = {0x00,0x40,0x10,0x50};// For 16x4 LCDs 175 176if( row >= _numlines ) 177{ 178 row = _numlines-1;// rows start at 0 179} 180 181// 16x4 LCDs have special memory map layout 182// ---------------------------------------- 183if( _cols ==16&& _numlines ==4) 184{ 185command(LCD_SETDDRAMADDR | (col + row_offsetsLarge[row])); 186} 187else 188{ 189command(LCD_SETDDRAMADDR | (col + row_offsetsDef[row])); 190} 191 192} 193 194// Turn the display on/off 195voidLCD::noDisplay() 196{ 197 _displaycontrol &= ~LCD_DISPLAYON; 198command(LCD_DISPLAYCONTROL | _displaycontrol); 199} 200 201voidLCD::display() 202{ 203 _displaycontrol |= LCD_DISPLAYON; 204command(LCD_DISPLAYCONTROL | _displaycontrol); 205} 206 207// Turns the underline cursor on/off 208voidLCD::noCursor() 209{ 210 _displaycontrol &= ~LCD_CURSORON; 211command(LCD_DISPLAYCONTROL | _displaycontrol); 212} 213voidLCD::cursor() 214{ 215 _displaycontrol |= LCD_CURSORON; 216command(LCD_DISPLAYCONTROL | _displaycontrol); 217} 218 219// Turns on/off the blinking cursor 220voidLCD::noBlink() 221{ 222 _displaycontrol &= ~LCD_BLINKON; 223command(LCD_DISPLAYCONTROL | _displaycontrol); 224} 225 226voidLCD::blink() 227{ 228 _displaycontrol |= LCD_BLINKON; 229command(LCD_DISPLAYCONTROL | _displaycontrol); 230} 231 232// These commands scroll the display without changing the RAM 233voidLCD::scrollDisplayLeft(void) 234{ 235command(LCD_CURSORSHIFT | LCD_DISPLAYMOVE | LCD_MOVELEFT); 236} 237 238voidLCD::scrollDisplayRight(void) 239{ 240command(LCD_CURSORSHIFT | LCD_DISPLAYMOVE | LCD_MOVERIGHT); 241} 242 243// This is for text that flows Left to Right 244voidLCD::leftToRight(void) 245{ 246 _displaymode |= LCD_ENTRYLEFT; 247command(LCD_ENTRYMODESET | _displaymode); 248} 249 250// This is for text that flows Right to Left 251voidLCD::rightToLeft(void) 252{ 253 _displaymode &= ~LCD_ENTRYLEFT; 254command(LCD_ENTRYMODESET | _displaymode); 255} 256 257// This method moves the cursor one space to the right 258voidLCD::moveCursorRight(void) 259{ 260command(LCD_CURSORSHIFT | LCD_CURSORMOVE | LCD_MOVERIGHT); 261} 262 263// This method moves the cursor one space to the left 264voidLCD::moveCursorLeft(void) 265{ 266command(LCD_CURSORSHIFT | LCD_CURSORMOVE | LCD_MOVELEFT); 267} 268 269 270// This will 'right justify' text from the cursor 271voidLCD::autoscroll(void) 272{ 273 _displaymode |= LCD_ENTRYSHIFTINCREMENT; 274command(LCD_ENTRYMODESET | _displaymode); 275} 276 277// This will 'left justify' text from the cursor 278voidLCD::noAutoscroll(void) 279{ 280 _displaymode &= ~LCD_ENTRYSHIFTINCREMENT; 281command(LCD_ENTRYMODESET | _displaymode); 282} 283 284// Write to CGRAM of new characters 285voidLCD::createChar(uint8_t location,uint8_t charmap[]) 286{ 287 location &=0x7;// we only have 8 locations 0-7 288 289command(LCD_SETCGRAMADDR | (location <<3)); 290delayMicroseconds(30); 291 292for(int i=0; i<8; i++) 293{ 294write(charmap[i]);// call the virtual write method 295delayMicroseconds(40); 296} 297} 298 299// 300// Switch on the backlight 301voidLCD::backlight(void) 302{ 303setBacklight(255); 304} 305 306// 307// Switch off the backlight 308voidLCD::noBacklight(void) 309{ 310setBacklight(0); 311} 312 313// 314// Switch fully on the LCD (backlight and LCD) 315voidLCD::on(void) 316{ 317display(); 318backlight(); 319} 320 321// 322// Switch fully off the LCD (backlight and LCD) 323voidLCD::off(void) 324{ 325noBacklight(); 326noDisplay(); 327} 328 329// General LCD commands - generic methods used by the rest of the commands 330// --------------------------------------------------------------------------- 331voidLCD::command(uint8_t value) 332{ 333send(value, COMMAND); 334} 335 336#if (ARDUINO < 100) 337voidLCD::write(uint8_t value) 338{ 339send(value, DATA); 340} 341#else 342size_tLCD::write(uint8_t value) 343{ 344send(value, DATA); 345return1;// assume OK 346} 347#endif