Updated for more display types. Fixed memoryaddress confusion in address() method. Added new getAddress() method. Added support for UDCs, Backlight control and other features such as control through I2C and SPI port expanders and controllers with native I2C and SPI interfaces. Refactored to fix issue with pins that are default declared as NC.

Dependents:   GPSDevice TestTextLCD SD to Flash Data Transfer DrumMachine ... more

Fork of TextLCD by Simon Ford

Example

Hello World! for the TextLCD

#include "mbed.h"
#include "TextLCD.h"
 
// Host PC Communication channels
Serial pc(USBTX, USBRX); // tx, rx
 
// I2C Communication
I2C i2c_lcd(p28,p27); // SDA, SCL
 
// SPI Communication
SPI spi_lcd(p5, NC, p7); // MOSI, MISO, SCLK

//TextLCD lcd(p15, p16, p17, p18, p19, p20);                // RS, E, D4-D7, LCDType=LCD16x2, BL=NC, E2=NC, LCDTCtrl=HD44780
//TextLCD_SPI lcd(&spi_lcd, p8, TextLCD::LCD40x4);   // SPI bus, 74595 expander, CS pin, LCD Type  
TextLCD_I2C lcd(&i2c_lcd, 0x42, TextLCD::LCD20x4);  // I2C bus, PCF8574 Slaveaddress, LCD Type
//TextLCD_I2C lcd(&i2c_lcd, 0x42, TextLCD::LCD16x2, TextLCD::WS0010); // I2C bus, PCF8574 Slaveaddress, LCD Type, Device Type
//TextLCD_SPI_N lcd(&spi_lcd, p8, p9);               // SPI bus, CS pin, RS pin, LCDType=LCD16x2, BL=NC, LCDTCtrl=ST7032_3V3   
//TextLCD_I2C_N lcd(&i2c_lcd, ST7032_SA, TextLCD::LCD16x2, NC, TextLCD::ST7032_3V3); // I2C bus, Slaveaddress, LCD Type, BL=NC, LCDTCtrl=ST7032_3V3  

int main() {
    pc.printf("LCD Test. Columns=%d, Rows=%d\n\r", lcd.columns(), lcd.rows());
    
    for (int row=0; row<lcd.rows(); row++) {
      int col=0;
      
      pc.printf("MemAddr(Col=%d, Row=%d)=0x%02X\n\r", col, row, lcd.getAddress(col, row));      
//      lcd.putc('-');
      lcd.putc('0' + row);      
      
      for (col=1; col<lcd.columns()-1; col++) {    
        lcd.putc('*');
      }
 
      pc.printf("MemAddr(Col=%d, Row=%d)=0x%02X\n\r", col, row, lcd.getAddress(col, row));      
      lcd.putc('+');
        
    }    
    
// Show cursor as blinking character
    lcd.setCursor(TextLCD::CurOff_BlkOn);
 
// Set and show user defined characters. A maximum of 8 UDCs are supported by the HD44780.
// They are defined by a 5x7 bitpattern. 
    lcd.setUDC(0, (char *) udc_0);  // Show |>
    lcd.putc(0);    
    lcd.setUDC(1, (char *) udc_1);  // Show <|
    lcd.putc(1);    

}

Handbook page

More info is here

Revision:
17:652ab113bc2e
Parent:
16:c276b75e6585
Child:
18:bd65dc10f27f
--- a/TextLCD.cpp	Wed Feb 20 19:37:53 2013 +0000
+++ b/TextLCD.cpp	Sat Mar 02 16:51:01 2013 +0000
@@ -3,6 +3,7 @@
  *               2013, v01: WH, Added LCD types, fixed LCD address issues, added Cursor and UDCs 
  *               2013, v02: WH, Added I2C and SPI bus interfaces  
  *               2013, v03: WH, Added support for LCD40x4 which uses 2 controllers 
+ *               2013, v04: WH, Added support for Display On/Off, improved 4bit bootprocess 
  *
  * Permission is hereby granted, free of charge, to any person obtaining a copy
  * of this software and associated documentation files (the "Software"), to deal
@@ -151,6 +152,18 @@
     
     wait_ms(20);        // Wait 20ms to ensure powered up
 
+#if(1)
+    // send "Display Settings" 3 times (Only top nibble of 0x30 as we've got 4-bit bus)    
+    for (int i=0; i<3; i++) {
+        _writeNibble(0x3);
+        wait_ms(15);     // this command takes 1.64ms, so wait for it 
+    }
+    _writeNibble(0x2);   // 4-bit mode
+    wait_us(40);         // most instructions take 40us
+#else
+//Original code. Does not comply with specification and causes problems
+//unless used right after power-on.
+
     // send "Display Settings" 3 times (Only top nibble of 0x30 as we've got 4-bit bus)
     for (int i=0; i<3; i++) {
         _writeByte(0x3);
@@ -158,6 +171,7 @@
     }
     _writeByte(0x2);     // 4-bit mode
     wait_us(40);         // most instructions take 40us
+#endif
     
     // Display is now in 4-bit mode
     switch (_type) {
@@ -214,9 +228,9 @@
                          //   S=0  (No display shift)                        
 
 //    _writeCommand(0x0C); // Display Ctrl 0000 1 D C B
-//                         //   Display On, Cursor Off, Blink Off
+//                         //   Display On, Cursor Off, Blink Off   
     setCursor(TextLCD::CurOff_BlkOff);     
-
+    setMode(TextLCD::DispOn);     
 }
 
 
@@ -228,7 +242,7 @@
     _ctrl=TextLCD::_LCDCtrl_1; // Select 2nd controller
 
     // Second LCD controller Cursor always Off
-    _setCursor(TextLCD::CurOff_BlkOff);
+    _setCursorAndDisplayMode(_currentMode, TextLCD::CurOff_BlkOff);
 
     // Second LCD controller Clearscreen
     _writeCommand(0x01); // cls, and set cursor to 0    
@@ -248,7 +262,7 @@
 
   // Restore cursormode on primary LCD controller when needed
   if(_type==LCD40x4) {
-    _setCursor(_currentCursor);
+    _setCursorAndDisplayMode(_currentMode,_currentCursor);     
   }
                    
   _row=0;          // Reset Cursor location
@@ -499,6 +513,22 @@
 }
 
 
+// Write a nibble using the 4-bit interface
+// Used for mbed pins, I2C bus expander or SPI shifregister
+void TextLCD::_writeNibble(int value) {
+
+// Enable is Low
+    _setEnable(true);        
+    _setData(value & 0x0F);   // Low nibble
+    wait_us(1); // Data setup time        
+    _setEnable(false);    
+    wait_us(1); // Datahold time
+
+// Enable is Low
+
+}
+
+
 // Write a byte using the 4-bit interface
 // Used for mbed pins, I2C bus expander or SPI shifregister
 void TextLCD::_writeByte(int value) {
@@ -656,14 +686,15 @@
           if (row<2) { 
             // Test to see if we need to switch between controllers  
             if (_ctrl != _LCDCtrl_0) {
+
               // Second LCD controller Cursor Off
-              _setCursor(TextLCD::CurOff_BlkOff);
+              _setCursorAndDisplayMode(_currentMode, TextLCD::CurOff_BlkOff);    
 
               // Select primary controller
               _ctrl = _LCDCtrl_0;
 
               // Restore cursormode on primary LCD controller
-              _setCursor(_currentCursor);
+              _setCursorAndDisplayMode(_currentMode, _currentCursor);    
             }           
             
             return 0x00 + (row * 0x40) + column;          
@@ -673,13 +704,13 @@
             // Test to see if we need to switch between controllers  
             if (_ctrl != _LCDCtrl_1) {
               // Primary LCD controller Cursor Off
-              _setCursor(TextLCD::CurOff_BlkOff);
+              _setCursorAndDisplayMode(_currentMode, TextLCD::CurOff_BlkOff);    
 
               // Select secondary controller
               _ctrl = _LCDCtrl_1;
 
               // Restore cursormode on secondary LCD controller
-              _setCursor(_currentCursor);
+              _setCursorAndDisplayMode(_currentMode, _currentCursor);    
             }           
                                    
             return 0x00 + ((row-2) * 0x40) + column;          
@@ -784,37 +815,66 @@
 }
 
 
-void TextLCD::setCursor(TextLCD::LCDCursor show) { 
+// Set the Cursor Mode (Cursor Off & Blink Off, Cursor On & Blink Off, Cursor Off & Blink On, Cursor On & Blink On
+void TextLCD::setCursor(TextLCD::LCDCursor cursorMode) { 
 
-  // Save new cursor mode, needed when 2 controllers are in use
-  _currentCursor = show;
+  // Save new cursor mode, needed when 2 controllers are in use or when display is switched off/on
+  _currentCursor = cursorMode;
     
-  // Configure current LCD controller
-  _setCursor(_currentCursor);
+  // Configure only current LCD controller
+  _setCursorAndDisplayMode(_currentMode, _currentCursor);
     
 }
 
-void TextLCD::_setCursor(TextLCD::LCDCursor show) { 
+// Set the Displaymode (On/Off)
+void TextLCD::setMode(TextLCD::LCDMode displayMode) { 
+
+  // Save new displayMode, needed when 2 controllers are in use or when cursor is changed
+  _currentMode = displayMode;
     
-    // Configure current LCD controller    
-    switch (show) {
-      case CurOff_BlkOff : _writeCommand(0x0C); // Cursor off and Blink Off
-                           break;
+  // Select and configure second LCD controller when needed
+  if(_type==LCD40x4) {
+    if (_ctrl==TextLCD::_LCDCtrl_0) {
+      // Configure primary LCD controller
+      _setCursorAndDisplayMode(_currentMode, _currentCursor);
 
-      case CurOn_BlkOff :  _writeCommand(0x0E); // Cursor on and Blink Off
-                           break;
+      // Select 2nd controller
+      _ctrl=TextLCD::_LCDCtrl_1;
+  
+      // Configure secondary LCD controller    
+      _setCursorAndDisplayMode(_currentMode, TextLCD::CurOff_BlkOff);
 
-      case CurOff_BlkOn :  _writeCommand(0x0D); // Cursor off and Blink On
-                           break;
+      // Restore current controller
+      _ctrl=TextLCD::_LCDCtrl_0;       
+    }
+    else {
+      // Select primary controller
+      _ctrl=TextLCD::_LCDCtrl_0;
+    
+      // Configure primary LCD controller
+      _setCursorAndDisplayMode(_currentMode, TextLCD::CurOff_BlkOff);
+       
+      // Restore current controller
+      _ctrl=TextLCD::_LCDCtrl_1;
 
-      case CurOn_BlkOn  :  _writeCommand(0x0F); // Cursor on and Blink char
-                           break;
+      // Configure secondary LCD controller    
+      _setCursorAndDisplayMode(_currentMode, _currentCursor);
 
-// Should never get here.
-      default : 
-                           break;
-                     
     }
+  }
+  else {
+    // Configure primary LCD controller
+    _setCursorAndDisplayMode(_currentMode, _currentCursor);
+  }   
+    
+}
+
+
+// Set the Displaymode (On/Off) and Cursortype for current controller
+void TextLCD::_setCursorAndDisplayMode(TextLCD::LCDMode displayMode, TextLCD::LCDCursor cursorType) { 
+    
+    // Configure current LCD controller       
+    _writeCommand(0x08 | displayMode | cursorType);
 }