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:
29:a3663151aa65
Parent:
28:30fa94f7341c
Child:
30:033048611c01
--- a/TextLCD.cpp	Sat Jun 14 17:04:25 2014 +0000
+++ b/TextLCD.cpp	Tue Jun 17 17:41:47 2014 +0000
@@ -10,6 +10,7 @@
  *               2014, v08: WH, Refactored in Base and Derived Classes to deal with mbed lib change regarding 'NC' defined pins 
  *               2014, v09: WH/EO, Added Class for Native SPI controllers such as ST7032 
  *               2014, v10: WH, Added Class for Native I2C controllers such as ST7032i, Added support for MCP23008 I2C portexpander, Added support for Adafruit module  
+ *               2014, v11: WH, Added support for native I2C controllers such as PCF21XX, improved the _initCtrl() method to deal with differences between all supported controllers  
  *
  * Permission is hereby granted, free of charge, to any person obtaining a copy
  * of this software and associated documentation files (the "Software"), to deal
@@ -33,6 +34,11 @@
 #include "TextLCD.h"
 #include "mbed.h"
 
+
+DigitalOut led1(LED1);
+DigitalOut led2(LED2);
+
+
 /** Create a TextLCD_Base interface
   *
   * @param type  Sets the panel size/addressing mode (default = LCD16x2)
@@ -86,76 +92,281 @@
     // Display is now in 4-bit mode
     // Note: 4 bit mode is ignored for native SPI and I2C devices
    
-    // Device specific initialisations for DC/DC converter to generate VLCD or VLED
+    // Device specific initialisations: DC/DC converter to generate VLCD or VLED, number of lines etc
     switch (_ctrl) {
-      case ST7036:
-          // ST7036 controller: Initialise Voltage booster for VLCD. VDD=5V
-          // Note: supports 1,2 or 3 lines
-          _writeCommand(0x29);    // 4-bit Databus, 2 Lines, Select Instruction Set = 1
-          wait_ms(30);            // > 26,3ms 
-          _writeCommand(0x14);    // Bias: 1/5, 2-Lines LCD 
-//          _writeCommand(0x15);    // Bias: 1/5, 3-Lines LCD           
-          wait_ms(30);            // > 26,3ms
-          _writeCommand(0x55);    // Icon off, Booster on, Set Contrast C5, C4
-          wait_ms(30);            // > 26,3ms
-          _writeCommand(0x6D);    // Voltagefollower On, Ampl ratio Rab2, Rab1, Rab0
-          wait_ms(200);           // > 200ms!
-          _writeCommand(0x78);    // Set Contrast C3, C2, C1, C0
-          wait_ms(30);            // > 26,3ms
-          _writeCommand(0x28);    // Return to Instruction Set = 0
-          wait_ms(50);      
-          break;
-          
+      case KS0078:
+
+          // Initialise Display configuration
+          switch (_type) {
+            case LCD8x1:         //8x1 is a regular 1 line display
+            case LCD8x2B:        //8x2B is a special case of 16x1
+//            case LCD12x1:                                
+            case LCD16x1:                                            
+            case LCD24x1:
+//@TODO check config
+              _writeCommand(0x20); // Function set 001 DL N F - -
+                                   //  DL=0 (4 bits bus)             
+                                   //   N=0 (1 line)
+                                   //   F=0 (5x7 dots font)
+              break;                                
+
+            case LCD24x4B:
+              // Special mode for KS0078
+              _writeCommand(0x2A); // Function set 001 DL N RE DH REV
+                                   //   DL=0  (4 bits bus)             
+                                   //    N=1  (Dont care for KS0078)
+                                   //   RE=0  (Dis. Extended Regs, special mode for KS0078)
+                                   //   DH=1  (Disp shift, special mode for KS0078)                                
+                                   //   REV=0 (Reverse, special mode for KS0078)
+
+              _writeCommand(0x2E); // Function set 001 DL N RE DH REV
+                                   //   DL=0  (4 bits bus)             
+                                   //    N=1  (Dont care for KS0078)
+                                   //   RE=1  (Ena Extended Regs, special mode for KS0078)
+                                   //   DH=1  (Disp shift, special mode for KS0078)                                
+                                   //   REV=0 (Reverse, special mode for KS0078)
+
+              _writeCommand(0x09); // Ext Function set 0000 1 FW BW NW
+                                   //   FW=0  (5-dot font, special mode for KS0078)
+                                   //   BW=0  (Cur BW invert disable, special mode for KS0078)
+                                   //   NW=1  (4 Line, special mode for KS0078)                                
+
+              _writeCommand(0x2A); // Function set 001 DL N RE DH REV
+                                   //   DL=0  (4 bits bus)             
+                                   //    N=1  (Dont care for KS0078)
+                                   //   RE=0  (Dis. Extended Regs, special mode for KS0078)
+                                   //   DH=1  (Disp shift, special mode for KS0078)                                
+                                   //   REV=0 (Reverse, special mode for KS0078)
+                                                  
+            // All other LCD types are initialised as 2 Line displays (including LCD40x4)
+            default:
+//@TODO check config            
+              _writeCommand(0x28); // Function set 001 DL N F - -
+                                   //  DL=0 (4 bits bus)
+                                   //  Note: 4 bit mode is ignored for native SPI and I2C devices                                 
+                                   //   N=1 (2 lines)
+                                   //   F=0 (5x7 dots font, only option for 2 line display)
+                                   //    -  (Don't care)                                
+            
+              break;
+          } // switch type
+
+          break; // case KS0078 Controller
+              
       case ST7032_3V3:
           // ST7032 controller: Initialise Voltage booster for VLCD. VDD=3V3
 
-//          _writeCommand(0x39);    //FUNCTION SET 8 bit,N=1 2-line display mode,5*7dot, Select Instruction Set = 1
-          _writeCommand(0x29);    //FUNCTION SET 4 bit, N=1 2-line display mode, 5*7dot, Select Instruction Set = 1
-                                  //Note: 4 bit mode is ignored for native SPI and I2C devices
+          // Initialise Display configuration
+          switch (_type) {
+            case LCD8x1:         //8x1 is a regular 1 line display
+            case LCD8x2B:        //8x2B is a special case of 16x1
+//            case LCD12x1:                                
+            case LCD16x1:                                            
+            case LCD24x1:                    
 
-          _writeCommand(0x1C);    //Internal OSC frequency adjustment Framefreq=183HZ, bias will be 1/4 
+//              _writeCommand(0x31);    //FUNCTION SET 8 bit,N=0 1-line display mode,5*7dot, Select Instruction Set = 1
+              _writeCommand(0x21);    //FUNCTION SET 4 bit, N=0 1-line display mode, 5*7dot, Select Instruction Set = 1
+                                      //Note: 4 bit mode is ignored for native SPI and I2C devices
+
+              _writeCommand(0x1C);    //Internal OSC frequency adjustment Framefreq=183HZ, bias will be 1/4 
 
-          _writeCommand(0x73);    //Contrast control low byte
+              _writeCommand(0x73);    //Contrast control low byte
 
-          _writeCommand(0x57);    //booster circuit is turned on. /ICON display off. /Contrast control high byte
-          wait_ms(10);            // Wait 10ms to ensure powered up
+              _writeCommand(0x57);    //booster circuit is turned on. /ICON display off. /Contrast control high byte
+              wait_ms(10);            // Wait 10ms to ensure powered up
+          
+              _writeCommand(0x6C);    //Follower control
+              wait_ms(10);            // Wait 10ms to ensure powered up
           
-          _writeCommand(0x6C);    //Follower control
-          wait_ms(10);            // Wait 10ms to ensure powered up
+//              _writeCommand(0x30);    //FUNCTION SET 8 bit,N=0 1-line display mode,5*7dot, Return to Instruction Set = 0        
+              _writeCommand(0x20);    //FUNCTION SET 4 bit, N=0 1-line display mode, 5*7dot, Return to Instruction Set = 0                  
+                                      //Note: 4 bit mode is ignored for native SPI and I2C devices                                                                          
+
+              break;  
+
+            default:
+              // All other LCD types are initialised as 2 Line displays        
+                                    
+//              _writeCommand(0x39);    //FUNCTION SET 8 bit,N=1 2-line display mode,5*7dot, Select Instruction Set = 1
+              _writeCommand(0x29);    //FUNCTION SET 4 bit, N=1 2-line display mode, 5*7dot, Select Instruction Set = 1
+                                      //Note: 4 bit mode is ignored for native SPI and I2C devices
+
+              _writeCommand(0x1C);    //Internal OSC frequency adjustment Framefreq=183HZ, bias will be 1/4 
+
+              _writeCommand(0x73);    //Contrast control low byte
+
+              _writeCommand(0x57);    //booster circuit is turned on. /ICON display off. /Contrast control high byte
+              wait_ms(10);            // Wait 10ms to ensure powered up
           
-//          _writeCommand(0x38);    //FUNCTION SET 8 bit,N=1 2-line display mode,5*7dot, Return to Instruction Set = 0        
-          _writeCommand(0x28);    //FUNCTION SET 4 bit, N=1 2-line display mode, 5*7dot, Return to Instruction Set = 0                  
-                                  //Note: 4 bit mode is ignored for native SPI and I2C devices    
-                                  
-          _writeCommand(0x14);    // Cursor or Display shift 0001 S/C R/L x x 
-                                  //   S/C=0 Cursor moves
-                                  //   R/L=1 Right
-                                  //    
-          break;
+              _writeCommand(0x6C);    //Follower control
+              wait_ms(10);            // Wait 10ms to ensure powered up
+          
+//              _writeCommand(0x38);    //FUNCTION SET 8 bit,N=1 2-line display mode,5*7dot, Return to Instruction Set = 0        
+              _writeCommand(0x28);    //FUNCTION SET 4 bit, N=1 2-line display mode, 5*7dot, Return to Instruction Set = 0                  
+                                      //Note: 4 bit mode is ignored for native SPI and I2C devices                                                                          
+          } // switch type    
+                                     
+          break; // case ST7032_3V3 Controller
 
 
       case ST7032_5V:
           // ST7032 controller: Disable Voltage booster for VLCD. VDD=5V      
-//          _writeCommand(0x39);    //FUNCTION SET 8 bit,N=1 2-line display mode,5*7dot, Instruction Set = 1
-          _writeCommand(0x29);    //FUNCTION SET 4 bit, N=1 2-line display mode, 5*7dot, Select Instruction Set = 1
-                                  //Note: 4 bit mode is ignored for native SPI and I2C devices         
+
+          // Initialise Display configuration
+          switch (_type) {
+            case LCD8x1:         //8x1 is a regular 1 line display
+            case LCD8x2B:        //8x2B is a special case of 16x1
+//            case LCD12x1:                                
+            case LCD16x1:                                            
+            case LCD24x1:                    
+
+//              _writeCommand(0x31);    //FUNCTION SET 8 bit,N=0 1-line display mode,5*7dot, Select Instruction Set = 1
+              _writeCommand(0x21);    //FUNCTION SET 4 bit, N=0 1-line display mode, 5*7dot, Select Instruction Set = 1
+                                      //Note: 4 bit mode is ignored for native SPI and I2C devices
+
+              _writeCommand(0x1C);    //Internal OSC frequency adjustment Framefreq=183HZ, bias will be 1/4 
+
+              _writeCommand(0x73);    //Contrast control low byte
 
-          _writeCommand(0x1C);    //Internal OSC frequency adjustment 183HZ, bias will be 1/4 
+              _writeCommand(0x53);    //booster circuit is turned off. /ICON display off. /Contrast control high byte
+              wait_ms(10);            // Wait 10ms to ensure powered up
+          
+              _writeCommand(0x6C);    //Follower control
+              wait_ms(10);            // Wait 10ms to ensure powered up
+          
+//              _writeCommand(0x30);    //FUNCTION SET 8 bit,N=0 1-line display mode,5*7dot, Return to Instruction Set = 0        
+              _writeCommand(0x20);    //FUNCTION SET 4 bit, N=0 1-line display mode, 5*7dot, Return to Instruction Set = 0                  
+                                      //Note: 4 bit mode is ignored for native SPI and I2C devices                                                                          
+
+              break;  
 
-          _writeCommand(0x73);    //Contrast control low byte
+            default:
+              // All other LCD types are initialised as 2 Line displays        
+                                    
+//              _writeCommand(0x39);    //FUNCTION SET 8 bit,N=1 2-line display mode,5*7dot, Select Instruction Set = 1
+              _writeCommand(0x29);    //FUNCTION SET 4 bit, N=1 2-line display mode, 5*7dot, Select Instruction Set = 1
+                                      //Note: 4 bit mode is ignored for native SPI and I2C devices
+
+              _writeCommand(0x1C);    //Internal OSC frequency adjustment Framefreq=183HZ, bias will be 1/4 
+
+              _writeCommand(0x73);    //Contrast control low byte
+
+              _writeCommand(0x53);    //booster circuit is turned off. /ICON display off. /Contrast control high byte
+              wait_ms(10);            // Wait 10ms to ensure powered up
+          
+              _writeCommand(0x6C);    //Follower control
+              wait_ms(10);            // Wait 10ms to ensure powered up
+          
+//              _writeCommand(0x38);    //FUNCTION SET 8 bit,N=1 2-line display mode,5*7dot, Return to Instruction Set = 0        
+              _writeCommand(0x28);    //FUNCTION SET 4 bit, N=1 2-line display mode, 5*7dot, Return to Instruction Set = 0                  
+                                      //Note: 4 bit mode is ignored for native SPI and I2C devices                                                                          
+          } // switch type    
+                                    
+          break; // case ST7032_5V Controller
 
-          _writeCommand(0x53);    //booster circuit is turned off. /ICON display off. /Contrast control high byte
-          wait_ms(10);            // Wait 10ms to ensure powered up
-          
-          _writeCommand(0x6C);    //Follower control
-          wait_ms(10);            // Wait 10ms to ensure powered up
+      case ST7036:
+          // ST7036 controller: Initialise Voltage booster for VLCD. VDD=5V
+          // Note: supports 1,2 or 3 lines
           
-//          _writeCommand(0x38);    //FUNCTION SET 8 bit,N=1 2-line display mode,5*7dot, Instruction Set = 0                  
-          _writeCommand(0x28);    //FUNCTION SET 4 bit, N=1 2-line display mode, 5*7dot, Return to Instruction Set = 0                            
-                                  //Note: 4 bit mode is ignored for native SPI and I2C devices                   
+          // Initialise Display configuration
+          switch (_type) {
+            case LCD8x1:         //8x1 is a regular 1 line display
+            case LCD8x2B:        //8x2B is a special case of 16x1
+//            case LCD12x1:                                
+            case LCD16x1:   
+            case LCD24x1:                                                                         
+              _writeCommand(0x21);    // 4-bit Databus, N=0 1 Line, DH=0 5x7font, IS2,IS1 = 01 Select Instruction Set = 1
+              wait_ms(30);            // > 26,3ms 
+              _writeCommand(0x14);    // Bias: 1/5, 1 or 2-Lines LCD 
+//              _writeCommand(0x15);    // Bias: 1/5, 3-Lines LCD           
+              wait_ms(30);            // > 26,3ms
+              _writeCommand(0x55);    // Icon off, Booster on, Set Contrast C5, C4
+              wait_ms(30);            // > 26,3ms
+              _writeCommand(0x6D);    // Voltagefollower On, Ampl ratio Rab2, Rab1, Rab0
+              wait_ms(200);           // > 200ms!
+              _writeCommand(0x78);    // Set Contrast C3, C2, C1, C0
+              wait_ms(30);            // > 26,3ms
+              _writeCommand(0x20);    // Return to Instruction Set = 0
+              wait_ms(50);      
+              break;  
+#if(0)
+//            case LCD12x3:                                            
+            case LCD16x3:                                            
+              _writeCommand(0x29);    // 4-bit Databus, N=1 2 Line, DH=0 5x7font, IS2,IS1 = 01 Select Instruction Set = 1
+              wait_ms(30);            // > 26,3ms 
+//              _writeCommand(0x14);    // Bias: 1/5, 1 or 2-Lines LCD 
+              _writeCommand(0x15);    // Bias: 1/5, 3-Lines LCD           
+              wait_ms(30);            // > 26,3ms
+              _writeCommand(0x55);    // Icon off, Booster on, Set Contrast C5, C4
+              wait_ms(30);            // > 26,3ms
+              _writeCommand(0x6D);    // Voltagefollower On, Ampl ratio Rab2, Rab1, Rab0
+              wait_ms(200);           // > 200ms!
+              _writeCommand(0x78);    // Set Contrast C3, C2, C1, C0
+              wait_ms(30);            // > 26,3ms
+              _writeCommand(0x28);    // Return to Instruction Set = 0
+              wait_ms(50);      
+              break;  
+#endif
+            default:
+              // All other LCD types are initialised as 2 Line displays        
+              _writeCommand(0x29);    // 4-bit Databus, N=1 2 Line, DH=0 5x7font, IS2,IS1 = 01 Select Instruction Set = 1              
+              wait_ms(30);            // > 26,3ms 
+              _writeCommand(0x14);    // Bias: 1/5, 2-Lines LCD 
+//             _writeCommand(0x15);    // Bias: 1/5, 3-Lines LCD           
+              wait_ms(30);            // > 26,3ms
+              _writeCommand(0x55);    // Icon off, Booster on, Set Contrast C5, C4
+              wait_ms(30);            // > 26,3ms
+              _writeCommand(0x6D);    // Voltagefollower On, Ampl ratio Rab2, Rab1, Rab0
+              wait_ms(200);           // > 200ms!
+              _writeCommand(0x78);    // Set Contrast C3, C2, C1, C0
+              wait_ms(30);            // > 26,3ms
+              _writeCommand(0x28);    // Return to Instruction Set = 0
+              wait_ms(50);      
+          } // switch type
+          
+          break; // case ST7036 Controller
+          
+      case PCF21XX_3V3:
+          // PCF21XX controller: Initialise Voltage booster for VLCD. VDD=3V3
 
-          break;
-          
+          // Initialise Display configuration
+          switch (_type) {
+            case LCD8x1:         //8x1 is a regular 1 line display
+            case LCD8x2B:        //8x2B is a special case of 16x1
+//            case LCD12x1:                                
+            case LCD16x1:                                            
+            case LCD24x1:                    
+              _writeCommand(0x22);    //FUNCTION SET 4 bit, N=0/M=0 1-line/24 chars display mode, G=1 Booster on                               
+                                      //Note: 4 bit mode is ignored for I2C mode
+              wait_ms(10);            // Wait 10ms to ensure powered up                                                    
+              break;  
+
+            case LCD12x3B:                    
+            case LCD12x4B:                                
+              _writeCommand(0x2E);    //FUNCTION SET 4 bit, N=1/M=1 4-line/12 chars display mode, G=1 Booster on                               
+                                      //Note: 4 bit mode is ignored for I2C mode              
+              wait_ms(10);            // Wait 10ms to ensure powered up                                                    
+              break;  
+              
+            default:
+              // All other LCD types are initialised as 2 Line displays        
+              _writeCommand(0x2A);    //FUNCTION SET 4 bit, N=1/M=0 2-line/24 chars display mode, G=1 Booster on
+                                      //Note: 4 bit mode is ignored for I2C mode
+
+              wait_ms(10);            // Wait 10ms to ensure powered up   
+              
+              
+              led1=!led1;
+          } // switch type    
+
+
+          break; // case PCF21XX_3V3 Controller
+
+
+//      case PCF21XX_5V:
+          // PCF21XX controller: No Voltage booster for VLCD. VDD=5V
+                              
+
       case WS0010:         
           // WS0010 OLED controller: Initialise DC/DC Voltage converter for LEDs
           // Note: supports 1 or 2 lines (and 16x100 graphics)
@@ -170,66 +381,68 @@
           _writeCommand(0x17);   // DC/DC on        
           wait_ms(10);           // Wait 10ms to ensure powered up
           
-          break;
-        
+
+          // Initialise Display configuration
+          switch (_type) {                    
+            case LCD8x1:         //8x1 is a regular 1 line display
+            case LCD8x2B:        //8x2B is a special case of 16x1
+//            case LCD12x1:                                
+            case LCD16x1:                                            
+//            case LCD24x1:
+              _writeCommand(0x20); // Function set 001 DL N F - -
+                                   //  DL=0 (4 bits bus)             
+                                   //   N=0 (1 line)
+                                   //   F=0 (5x7 dots font)
+              break;  
+
+            default:
+              // All other LCD types are initialised as 2 Line displays (including LCD40x4)       
+              _writeCommand(0x28); // Function set 001 DL N F - -
+                                   //  DL=0 (4 bits bus)
+                                   //   N=1 (2 lines)
+                                   //   F=0 (5x7 dots font, only option for 2 line display)
+                                   //    -  (Don't care)                                
+          
+              break;
+           } // switch type
+           
+           break; // case WS0100 Controller
+           
         default:
-          // Devices that do not use DC/DC Voltage converters but external VLCD
-          break;                  
-    }
-    
-    // Initialise Display configuration
-    switch (_type) {
-        case LCD8x1:
-        case LCD8x2B:        
-            //8x1 is a regular 1 line display
-            //8x2B is a special case of 16x1
-            _writeCommand(0x20); // Function set 001 DL N F - -
-                                 //  DL=0 (4 bits bus)             
-                                 //   N=0 (1 line)
-                                 //   F=0 (5x7 dots font)
-            break;                                
-            
-        case LCD24x4:
-            // Special mode for KS0078
-            _writeCommand(0x2A); // Function set 001 DL N RE DH REV
-                                 //   DL=0  (4 bits bus)             
-                                 //    N=1  (Dont care for KS0078)
-                                 //   RE=0  (Extended Regs, special mode for KS0078)
-                                 //   DH=1  (Disp shift, special mode for KS0078)                                
-                                 //   REV=0 (Reverse, special mode for KS0078)
+          // Devices fully compatible to HD44780 that do not use any DC/DC Voltage converters but external VLCD
 
-            _writeCommand(0x2E); // Function set 001 DL N RE DH REV
-                                 //   DL=0  (4 bits bus)             
-                                 //    N=1  (Dont care for KS0078)
-                                 //   RE=1  (Ena Extended Regs, special mode for KS0078)
-                                 //   DH=1  (Disp shift, special mode for KS0078)                                
-                                 //   REV=0 (Reverse, special mode for KS0078)
-
-            _writeCommand(0x09); // Ext Function set 0000 1 FW BW NW
-                                 //   FW=0  (5-dot font, special mode for KS0078)
-                                 //   BW=0  (Cur BW invert disable, special mode for KS0078)
-                                 //   NW=1  (4 Line, special mode for KS0078)                                
+          // Initialise Display configuration
+          switch (_type) {
+            case LCD8x1:         //8x1 is a regular 1 line display
+            case LCD8x2B:        //8x2B is a special case of 16x1
+//            case LCD12x1:                                
+            case LCD16x1:                                            
+            case LCD24x1:
+              _writeCommand(0x20); // Function set 001 DL N F - -
+                                   //  DL=0 (4 bits bus)             
+                                   //   N=0 (1 line)
+                                   //   F=0 (5x7 dots font)
+              break;                                
+                                                  
+            // All other LCD types are initialised as 2 Line displays (including LCD40x4)
+            default:
+              _writeCommand(0x28); // Function set 001 DL N F - -
+                                   //  DL=0 (4 bits bus)
+                                   //  Note: 4 bit mode is ignored for native SPI and I2C devices                                 
+                                   //   N=1 (2 lines)
+                                   //   F=0 (5x7 dots font, only option for 2 line display)
+                                   //    -  (Don't care)                                
+            
+              break;
+          } // switch type
 
-            _writeCommand(0x2A); // Function set 001 DL N RE DH REV
-                                 //   DL=0  (4 bits bus)             
-                                 //    N=1  (Dont care for KS0078)
-                                 //   RE=0  (Dis. Extended Regs, special mode for KS0078)
-                                 //   DH=1  (Disp shift, special mode for KS0078)                                
-                                 //   REV=0 (Reverse, special mode for KS0078)
-            break;
-                                            
-// All other LCD types are initialised as 2 Line displays (including LCD40x4)
-        default:
-            _writeCommand(0x28); // Function set 001 DL N F - -
-                                 //  DL=0 (4 bits bus)
-                                 //  Note: 4 bit mode is ignored for native SPI and I2C devices                                 
-                                 //   N=1 (2 lines)
-                                 //   F=0 (5x7 dots font, only option for 2 line display)
-                                 //    -  (Don't care)                                
-            
-            break;
-    }
+          break; // case default Controller
+          
+    } // switch Controller specific initialisations 
+    
 
+    // Controller general initialisations
+                                           
     _writeCommand(0x01); // cls, and set cursor to 0
     wait_ms(10);         // The CLS command takes 1.64 ms.
                          // Since we are not using the Busy flag, Lets be safe and take 10 ms  
@@ -242,10 +455,17 @@
                          //   I/D=1 (Cur incr)
                          //     S=0 (No display shift)                        
 
+    _writeCommand(0x14); // Cursor or Display shift 0001 S/C R/L x x 
+                         //   S/C=0 Cursor moves
+                         //   R/L=1 Right
+                         // 
+
+
 //    _writeCommand(0x0C); // Display Ctrl 0000 1 D C B
 //                         //   Display On, Cursor Off, Blink Off   
     setCursor(CurOff_BlkOff);     
     setMode(DispOn);     
+    led2=!led2;    
 }
 
 
@@ -262,28 +482,31 @@
 
     // Second LCD controller Clearscreen
     _writeCommand(0x01);  // cls, and set cursor to 0    
-    wait_ms(10);     // The CLS command takes 1.64 ms.
-                     // Since we are not using the Busy flag, Lets be safe and take 10 ms
+    wait_ms(10);          // The CLS command takes 1.64 ms.
+                          // Since we are not using the Busy flag, Lets be safe and take 10 ms
   
     _ctrl_idx=_LCDCtrl_0; // Select primary controller
   }
   
   // Primary LCD controller Clearscreen
   _writeCommand(0x01);    // cls, and set cursor to 0
-  wait_ms(10);     // The CLS command takes 1.64 ms.
-                   // Since we are not using the Busy flag, Lets be safe and take 10 ms
+  wait_ms(10);            // The CLS command takes 1.64 ms.
+                          // Since we are not using the Busy flag, Lets be safe and take 10 ms
 
   // Restore cursormode on primary LCD controller when needed
   if(_type==LCD40x4) {
     _setCursorAndDisplayMode(_currentMode,_currentCursor);     
   }
                    
-  _row=0;          // Reset Cursor location
-  _column=0;
+  setAddress(0, 0);  // Reset Cursor location
+                     // Note: this is needed because some rare displays (eg PCF21XX) don't use line 0 in the '3 Line' mode.   
 }
 
-/** Move cursor to selected row and column
-  */
+/** Locate cursor to a screen column and row
+  *
+  * @param column  The horizontal position from the left, indexed from 0
+  * @param row     The vertical position from the top, indexed from 0
+  */ 
 void TextLCD_Base::locate(int column, int row) {
     
    // setAddress() does all the heavy lifting:
@@ -433,12 +656,26 @@
 
 // This is new method to return the memory address based on row, column and displaytype.
 //
+/** Return the memoryaddress of screen column and row location
+   *
+   * @param column  The horizontal position from the left, indexed from 0
+   * @param row     The vertical position from the top, indexed from 0
+   * @param return  The memoryaddress of screen column and row location
+   */
 int TextLCD_Base::getAddress(int column, int row) {
 
     switch (_type) {
         case LCD8x1:
+        case LCD24x1:        
             return 0x00 + column;                        
 
+        case LCD16x1:
+            // LCD16x1 is a special layout of LCD8x2
+            if (column<8) 
+              return 0x00 + column;                        
+            else   
+              return 0x40 + (column - 8);                        
+
         case LCD8x2B:
             // LCD8x2B is a special layout of LCD16x1
             if (row==0) 
@@ -446,26 +683,44 @@
             else   
               return 0x08 + column;                        
 
-        case LCD16x1:
-            // LCD16x1 is a special layout of LCD8x2
-            if (column<8) 
-              return 0x00 + column;                        
-            else   
-              return 0x40 + (column - 8);                        
+        case LCD8x2:               
+        case LCD12x2:                
+        case LCD16x2:
+        case LCD20x2:
+        case LCD24x2:        
+        case LCD40x2:                
+            return 0x00 + (row * 0x40) + column;
 
-#if(0)
+// Not sure about this one, seems wrong.
+// Left in for compatibility with original library
+        case LCD16x2B:      
+            return 0x00 + (row * 40) + column;
+    
+
 // Special mode for ST7036 
 //        case LCD16x3:
 
-// Special mode for PCF2116 (and KS0078) 
-        case LCD12x3:
+// Special mode for PCF2116 
+        case LCD12x3B:
+            switch (row) {
+                case 0:
+                    return 0x20 + column;
+                case 1:
+                    return 0x40 + column;
+                case 2:
+                    return 0x60 + column;
+            }
+
+        case LCD12x4:
             switch (row) {
                 case 0:
                     return 0x00 + column;
                 case 1:
-                    return 0x20 + column;
+                    return 0x40 + column;
                 case 2:
-                    return 0x40 + column;
+                    return 0x0C + column;
+                case 3:
+                    return 0x4C + column;
             }
 
 // Special mode for PCF2116 (and KS0078) 
@@ -481,20 +736,6 @@
                     return 0x60 + column;                   
             }
 
-#endif
-
-        case LCD12x4:
-            switch (row) {
-                case 0:
-                    return 0x00 + column;
-                case 1:
-                    return 0x40 + column;
-                case 2:
-                    return 0x0C + column;
-                case 3:
-                    return 0x4C + column;
-            }
-
         case LCD16x4:
             switch (row) {
                 case 0:
@@ -520,7 +761,7 @@
             }
 
 // Special mode for KS0078
-        case LCD24x4:
+        case LCD24x4B:
             switch (row) {
                 case 0:
                     return 0x00 + column;
@@ -532,19 +773,6 @@
                     return 0x60 + column;
             }
 
-// Not sure about this one, seems wrong.
-// Left in for compatibility with original library
-        case LCD16x2B:      
-            return 0x00 + (row * 40) + column;
-      
-        case LCD8x2:               
-        case LCD12x2:                
-        case LCD16x2:
-        case LCD20x2:
-        case LCD24x2:        
-        case LCD40x2:                
-            return 0x00 + (row * 0x40) + column;
-
         case LCD40x4:                
           // LCD40x4 is a special case since it has 2 controllers
           // Each controller is configured as 40x2
@@ -588,8 +816,11 @@
 }
 
 
-// Set row, column and update memoryaddress.
-//
+/** Set the memoryaddress of screen column and row location
+  *
+  * @param column  The horizontal position from the left, indexed from 0
+  * @param row     The vertical position from the top, indexed from 0
+  */
 void TextLCD_Base::setAddress(int column, int row) {
    
 // Sanity Check column
@@ -617,6 +848,11 @@
     _writeCommand(0x80 | addr);
 }
 
+
+/** Return the number of columns
+  *
+  * @param return  The number of columns
+  */   
 int TextLCD_Base::columns() {
     switch (_type) {
         case LCD8x1:
@@ -625,9 +861,9 @@
             return 8;
         
         case LCD12x2:        
-//        case LCD12x3:                
+        case LCD12x3B:                
         case LCD12x4:        
-//        case LCD12x4B:                
+        case LCD12x4B:                
             return 12;        
 
         case LCD16x1:        
@@ -641,8 +877,9 @@
         case LCD20x4:
             return 20;
 
+        case LCD24x1:
         case LCD24x2:
-        case LCD24x4:        
+        case LCD24x4B:        
             return 24;        
 
         case LCD40x2:
@@ -655,10 +892,15 @@
     }
 }
 
+/** Return the number of rows
+  *
+  * @param return  The number of rows
+  */
 int TextLCD_Base::rows() {
     switch (_type) {
         case LCD8x1: 
         case LCD16x1:         
+        case LCD24x1:                 
             return 1;           
 
         case LCD8x2:  
@@ -671,15 +913,15 @@
         case LCD40x2:                
             return 2;
 
-//        case LCD12x3:                
+        case LCD12x3B:                
 //        case LCD16x3:                
-//            return 3;
+            return 3;
                     
         case LCD12x4:        
-//        case LCD12x4B:                
+        case LCD12x4B:                
         case LCD16x4:
         case LCD20x4:
-        case LCD24x4:        
+        case LCD24x4B:        
         case LCD40x4:
             return 4;
 
@@ -689,8 +931,10 @@
     }
 }
 
-
-// Set the Cursor Mode (Cursor Off & Blink Off, Cursor On & Blink Off, Cursor Off & Blink On, Cursor On & Blink On
+/** Set the Cursormode
+  *
+  * @param cursorMode  The Cursor mode (CurOff_BlkOff, CurOn_BlkOff, CurOff_BlkOn, CurOn_BlkOn)
+  */
 void TextLCD_Base::setCursor(LCDCursor cursorMode) { 
 
   // Save new cursor mode, needed when 2 controllers are in use or when display is switched off/on
@@ -701,7 +945,10 @@
     
 }
 
-// Set the Displaymode (On/Off)
+/** Set the Displaymode
+  *
+  * @param displayMode The Display mode (DispOff, DispOn)
+  */
 void TextLCD_Base::setMode(LCDMode displayMode) { 
 
   // Save new displayMode, needed when 2 controllers are in use or when cursor is changed
@@ -745,14 +992,19 @@
 }
 
 
-// Set the Displaymode (On/Off) and Cursortype for current controller
+/** Low level method to restore the cursortype and display mode for current controller
+  */     
 void TextLCD_Base::_setCursorAndDisplayMode(LCDMode displayMode, LCDCursor cursorType) { 
     
     // Configure current LCD controller       
     _writeCommand(0x08 | displayMode | cursorType);
 }
 
-// Set the Backlight mode (Off/On)
+
+/** Set the Backlight mode
+  *
+  *  @param backlightMode The Backlight mode (LightOff, LightOn)
+  */
 void TextLCD_Base::setBacklight(LCDBacklight backlightMode) {
 
     if (backlightMode == LightOn) {
@@ -763,7 +1015,11 @@
     }
 } 
 
-
+/** Set User Defined Characters
+  *
+  * @param unsigned char c   The Index of the UDC (0..7)
+  * @param char *udc_data    The bitpatterns for the UDC (8 bytes of 5 significant bits)     
+  */
 void TextLCD_Base::setUDC(unsigned char c, char *udc_data) {
   
   // Select and configure second LCD controller when needed
@@ -792,6 +1048,8 @@
     
 }
 
+/** Low level method to store user defined characters for current controller
+  */     
 void TextLCD_Base::_setUDC(unsigned char c, char *udc_data) {
   
   // Select CG RAM for current LCD controller
@@ -854,6 +1112,18 @@
 
 }
 
+
+/** Destruct a TextLCD interface for using regular mbed pins
+  *
+  * @param  none
+  * @return none
+  */ 
+TextLCD::~TextLCD() {
+   if (_bl != NULL) {delete _bl;}  // BL pin
+   if (_e2 != NULL) {delete _e2;}  // E2 pin
+}
+
+
 /** Set E pin (or E2 pin)
   * Used for mbed pins, I2C bus expander or SPI shiftregister
   * Default PinName value for E2 is NC, must be used as pointer to avoid issues with mbed lib and DigitalOut pins
@@ -917,16 +1187,6 @@
   _d = value & 0x0F;   // Write Databits 
 }    
 
-/** Destruct a TextLCD interface for using regular mbed pins
-  *
-  * @param  none
-  * @return none
-  */ 
-TextLCD::~TextLCD() {
-   if (_bl != NULL) {delete _bl;}  // BL pin
-   if (_e2 != NULL) {delete _e2;}  // E2 pin
-}
-
     
 //----------- End TextLCD ---------------
 
@@ -1150,10 +1410,10 @@
                               
   _slaveAddress = deviceAddress & 0xFE;
   
-
   // Setup the I2C bus
-  // The max bitrate for ST7032 is 400kbit, 
-//  _i2c->frequency(100000);
+  // The max bitrate for ST7032i is 400kbit, lets stick to default here
+  _i2c->frequency(100000);
+//  _i2c->frequency(50000);
 
         
   // The hardware Backlight pin is optional. Test and make sure whether it exists or not to prevent illegal access.
@@ -1196,6 +1456,12 @@
     }    
 }    
 
+    
+// Not used in this mode
+void TextLCD_I2C_N::_setData(int value) {
+}    
+
+
 // Write a byte using I2C
 void TextLCD_I2C_N::_writeByte(int value) {
 
@@ -1204,10 +1470,6 @@
   _i2c->write(_slaveAddress, data, 2);
  
 }
-    
-// Not used in this mode
-void TextLCD_I2C_N::_setData(int value) {
-}    
 
 
 //-------- End TextLCD_I2C_N ------------
@@ -1313,7 +1575,6 @@
 }    
 
 
-
 // Place the 4bit data on the databus
 // Used for mbed pins, I2C bus expander or SPI shiftregister
 void TextLCD_SPI::_setData(int value) {
@@ -1429,6 +1690,11 @@
     }    
 }    
 
+// Not used in this mode
+void TextLCD_SPI_N::_setData(int value) {
+}    
+
+
 // Write a byte using SPI
 void TextLCD_SPI_N::_writeByte(int value) {
     _cs = 0;
@@ -1438,9 +1704,6 @@
     _cs = 1;
 }
     
-// Not used in this mode
-void TextLCD_SPI_N::_setData(int value) {
-}    
 
 
 //-------- End TextLCD_SPI_N ------------