Add module fc113 (PCF8574t)

Dependents:   Cassaforte Cassaforte2 Cassaforte5dic18 Cassaforte5_copy ... more

Fork of TextLCD by Wim Huiskamp

Files at this revision

API Documentation at this revision

Comitter:
wim
Date:
Sun Mar 29 13:08:03 2015 +0000
Parent:
36:9f5f86dfd44a
Child:
38:cbe275b0b647
Commit message:
Cleaned up low level command and data write operations to improve speed of I2C expander versions (PCF8574 and MCP23008). Added initial support for controllers with alternative fonttables.

Changed in this revision

TextLCD.cpp Show annotated file Show diff for this revision Revisions of this file
TextLCD.h Show annotated file Show diff for this revision Revisions of this file
TextLCD_Config.h Show annotated file Show diff for this revision Revisions of this file
TextLCD_UDC.h Show annotated file Show diff for this revision Revisions of this file
TextLCD_UDC.inc Show annotated file Show diff for this revision Revisions of this file
--- a/TextLCD.cpp	Tue Nov 25 19:21:18 2014 +0000
+++ b/TextLCD.cpp	Sun Mar 29 13:08:03 2015 +0000
@@ -1,4 +1,4 @@
-/* mbed TextLCD Library, for a 4-bit LCD based on HD44780
+/* mbed TextLCD Library, for LCDs based on HD44780 controllers
  * Copyright (c) 2007-2010, sford, http://mbed.org
  *               2013, v01: WH, Added LCD types, fixed LCD address issues, added Cursor and UDCs 
  *               2013, v02: WH, Added I2C and SPI bus interfaces  
@@ -17,6 +17,7 @@
  *                              added 16 UDCs for supported devices (eg PCF2103), moved UDC defines to TextLCD_UDC file, added TextLCD_Config.h for feature and footprint settings.
  *               2014, v15: WH, Added AC780 support, added I2C expander modules, fixed setBacklight() for inverted logic modules. Fixed bug in LCD_SPI_N define 
  *               2014, v16: WH, Added ST7070 and KS0073 support, added setIcon(), clrIcon() and setInvert() method for supported devices 
+ *               2015, v17: WH, Clean up low-level _writeCommand() and _writeData(), Added support for alternative fonttables (eg PCF21XX), Added ST7066_ACM controller for ACM1602 module 
  *
  * Permission is hereby granted, free of charge, to any person obtaining a copy
  * of this software and associated documentation files (the "Software"), to deal
@@ -57,6 +58,9 @@
 
   // Addressing mode encoded in b19..b16  
   _addr_mode = _type & LCD_T_ADR_MSK;
+  
+  // Font table, encoded in LCDCtrl  
+  _font = _type & LCD_C_FNT_MSK;
 }
 
 /**  Init the LCD Controller(s)
@@ -100,33 +104,35 @@
     
     wait_ms(20);         // Wait 20ms to ensure powered up
 
-    // The Controller could be in 8 bit mode (power-on reset) or in 4 bit mode (warm reboot) at this point.
-    // Follow this procedure to make sure the Controller enters the correct state. The hardware interface
-    // between the uP and the LCD can only write the 4 most significant bits (Most Significant Nibble, MSN).
-    // In 4 bit mode the LCD expects the MSN first, followed by the LSN.
-    //
-    //    Current state:               8 bit mode                |  4 bit mode, MSN is next      | 4 bit mode, LSN is next          
-                         //-------------------------------------------------------------------------------------------------                          
-    _writeNibble(0x3);   //  set 8 bit mode (MSN) and dummy LSN, |   set 8 bit mode (MSN),       |    set dummy LSN, 
-                         //  remains in 8 bit mode               |    change to 8 bit mode       |  remains in 4 bit mode
-    wait_ms(15);         //                           
+    if (dl == _LCD_DL_4) {
+      // The Controller could be in 8 bit mode (power-on reset) or in 4 bit mode (warm reboot) at this point.
+      // Follow this procedure to make sure the Controller enters the correct state. The hardware interface
+      // between the uP and the LCD can only write the 4 most significant bits (Most Significant Nibble, MSN).
+      // In 4 bit mode the LCD expects the MSN first, followed by the LSN.
+      //
+      //    Current state:               8 bit mode                |  4 bit mode, MSN is next      | 4 bit mode, LSN is next          
+                           //-------------------------------------------------------------------------------------------------                          
+      _writeNibble(0x3);   //  set 8 bit mode (MSN) and dummy LSN, |   set 8 bit mode (MSN),       |    set dummy LSN, 
+                           //  remains in 8 bit mode               |    change to 8 bit mode       |  remains in 4 bit mode
+      wait_ms(15);         //                           
+     
+      _writeNibble(0x3);   //  set 8 bit mode and dummy LSN,       | set 8 bit mode and dummy LSN, |    set 8bit mode (MSN), 
+                           //  remains in 8 bit mode               |   remains in 8 bit mode       |  remains in 4 bit mode
+      wait_ms(15);         // 
     
-    _writeNibble(0x3);   //  set 8 bit mode and dummy LSN,       | set 8 bit mode and dummy LSN, |    set 8bit mode (MSN), 
-                         //  remains in 8 bit mode               |   remains in 8 bit mode       |  remains in 4 bit mode
-    wait_ms(15);         // 
-    
-    _writeNibble(0x3);   //  set 8 bit mode and dummy LSN,       | set 8 bit mode and dummy LSN, |    set dummy LSN, 
-                         //  remains in 8 bit mode               |   remains in 8 bit mode       |  change to 8 bit mode
-    wait_ms(15);         // 
-
-    // Controller is now in 8 bit mode
-
-    _writeNibble(0x2);   // Change to 4-bit mode (MSN), the LSN is undefined dummy
-    wait_us(40);         // most instructions take 40us
-
-    // Display is now in 4-bit mode
-    // Note: 4/8 bit mode is ignored for most native SPI and I2C devices. They dont use the parallel bus.
-    //       However, _writeNibble() method is void anyway for native SPI and I2C devices.
+      _writeNibble(0x3);   //  set 8 bit mode and dummy LSN,       | set 8 bit mode and dummy LSN, |    set dummy LSN, 
+                           //  remains in 8 bit mode               |   remains in 8 bit mode       |  change to 8 bit mode
+      wait_ms(15);         // 
+
+      // Controller is now in 8 bit mode
+
+      _writeNibble(0x2);   // Change to 4-bit mode (MSN), the LSN is undefined dummy
+      wait_us(40);         // most instructions take 40us
+
+      // Controller is now in 4-bit mode
+      // Note: 4/8 bit mode is ignored for most native SPI and I2C devices. They dont use the parallel bus.
+      //       However, _writeNibble() method is void anyway for native SPI and I2C devices.
+    }      
    
     // Device specific initialisations: DC/DC converter to generate VLCD or VLED, number of lines etc
     switch (_ctrl) {
@@ -1193,6 +1199,7 @@
           _writeCommand(0x20 | _function | ((~_contrast) >> 4));        // Invert and shift to use 2 MSBs     
           break; // case PT6314 Controller (VFD)
            
+        case ST7066_ACM:                                                // ST7066 4/8 bit, I2C on ACM1602 using a PIC        
         default:
           // Devices fully compatible to HD44780 that do not use any DC/DC Voltage converters but external VLCD, no icons etc
 
@@ -1329,9 +1336,12 @@
       }      
     }
     else {
-      //Character to write      
-      _writeData(value); 
-              
+      //Character to write
+#if (LCD_DEFAULT_FONT == 1)      
+      _writeData(value);
+#else
+      _writeData(ASCII_2_LCD(value));
+#endif              
       //Update Cursor
       _column++;
       if (_column >= columns()) {
@@ -1356,6 +1366,30 @@
     return -1;
 }
 
+/** Convert ASCII character code to the LCD fonttable code
+  *
+  * @param c The character to write to the display
+  * @return The character code for the specific fonttable of the controller
+  */
+int TextLCD_Base::ASCII_2_LCD (int c) {
+    
+//LCD_C_FT0 is default for HD44780 and compatible series
+    if (_font == LCD_C_FT0) return c;
+
+//LCD_C_FT1 for PCF21XXC series    
+//Used code from Suga koubou library for PCF2119
+    if (((c >= ' ') && (c <= '?')) || ((c >= 'A') && (c <= 'Z')) || ((c >= 'a') && (c <= 'z'))) {
+        c |= 0x80;
+    } else if (c >= 0xf0 && c <= 0xff) {
+        c &= 0x0f;
+    }
+    return c;
+
+//LCD_C_FT2 ...
+//@TODO add more, eg cyrillic 
+//@TODO add method to switch between fonts for controllers that support this
+}
+
 
 #if(LCD_PRINTF != 1)
 /** Write a character to the LCD
@@ -1383,17 +1417,15 @@
 #endif    
 
 
-
 // Write a nibble using the 4-bit interface
 void TextLCD_Base::_writeNibble(int value) {
 
 // Enable is Low
     this->_setEnable(true);        
-    this->_setData(value & 0x0F);   // Low nibble
+    this->_setData(value);        // Low nibble
     wait_us(1); // Data setup time        
     this->_setEnable(false);    
     wait_us(1); // Datahold time
-
 // Enable is Low
 }
 
@@ -1408,7 +1440,7 @@
     wait_us(1); // Data hold time
     
     this->_setEnable(true);        
-    this->_setData(value >> 0);   // Low nibble
+    this->_setData(value);        // Low nibble
     wait_us(1); // Data setup time        
     this->_setEnable(false);    
     wait_us(1); // Datahold time
@@ -2644,8 +2676,8 @@
     // No Hardware Enable pin       
     _e2 = NULL;                 //Construct dummy pin     
   }  
-                                                                           
-  _init();
+
+  _init(_LCD_DL_4);   // Set Datalength to 4 bit for mbed bus interfaces
 }
 
 /** Destruct a TextLCD interface for using regular mbed pins
@@ -2742,23 +2774,27 @@
   
 #if (MCP23008==1)
   // MCP23008 portexpander Init
-  _write_register(IODIR,   0x00);  // All outputs
-  _write_register(IPOL,    0x00);  // No reverse polarity 
-  _write_register(GPINTEN, 0x00);  // No interrupt 
-  _write_register(DEFVAL,  0x00);  // Default value to compare against for interrupts
-  _write_register(INTCON,  0x00);  // No interrupt on changes 
-  _write_register(IOCON,   0x00);  // Interrupt polarity   
-  _write_register(GPPU,    0x00);  // No Pullup 
-  _write_register(INTF,    0x00);  //    
-  _write_register(INTCAP,  0x00);  //    
-  _write_register(GPIO,    0x00);  // Output/Input pins   
-  _write_register(OLAT,    0x00);  // Output Latch  
+  _writeRegister(IODIR,   0x00);  // All pins are outputs
+  _writeRegister(IPOL,    0x00);  // No reverse polarity on inputs
+  _writeRegister(GPINTEN, 0x00);  // No interrupt on change of input pins
+  _writeRegister(DEFVAL,  0x00);  // Default value to compare against for interrupts
+  _writeRegister(INTCON,  0x00);  // No interrupt on changes, compare against previous pin value 
+  _writeRegister(IOCON,   0x20);  // b1=0 - Interrupt polarity active low  
+                                  // b2=0 - Interrupt pin active driver output  
+                                  // b4=0 - Slew rate enable on SDA
+                                  // b5=0 - Auto-increment on registeraddress                                  
+                                  // b5=1 - No auto-increment on registeraddress => needed for performance improved I2C expander mode
+  _writeRegister(GPPU,    0x00);  // No Pullup 
+//               INTF             // Interrupt flags read (Read-Only)
+//               INTCAP           // Captured inputpins at time of interrupt (Read-Only)   
+//  _writeRegister(GPIO,    0x00);  // Output/Input pins   
+//  _writeRegister(OLAT,    0x00);  // Output Latch  
     
   // Init the portexpander bus
   _lcd_bus = D_LCD_BUS_DEF;
   
   // write the new data to the portexpander
-  _write_register(GPIO, _lcd_bus);      
+  _writeRegister(GPIO, _lcd_bus);      
 #else
   // PCF8574 of PCF8574A portexpander
 
@@ -2769,12 +2805,12 @@
   _i2c->write(_slaveAddress, &_lcd_bus, 1);    
 #endif
 
-  _init();    
+  _init(_LCD_DL_4);   // Set Datalength to 4 bit for all serial expander interfaces
 }
 
-// Set E pin (or E2 pin)
-// Used for mbed pins, I2C bus expander or SPI shiftregister
-void TextLCD_I2C::_setEnable(bool value) {
+// Set E bit (or E2 bit) in the databus shadowvalue
+// Used for mbed I2C bus expander
+void TextLCD_I2C::_setEnableBit(bool value) {
 
   if(_ctrl_idx==_LCDCtrl_0) {
     if (value) {
@@ -2792,12 +2828,20 @@
       _lcd_bus &= ~D_LCD_E2;   // Reset E2bit                     
     }  
   }    
+}    
+
+// Set E pin (or E2 pin)
+// Used for mbed pins, I2C bus expander or SPI shiftregister
+void TextLCD_I2C::_setEnable(bool value) {
+
+  // Place the E or E2 bit data on the databus shadowvalue
+  _setEnableBit(value);
 
 #if (MCP23008==1)
   // MCP23008 portexpander
   
   // write the new data to the portexpander
-  _write_register(GPIO, _lcd_bus);      
+  _writeRegister(GPIO, _lcd_bus);      
 #else
   // PCF8574 of PCF8574A portexpander
 
@@ -2806,6 +2850,7 @@
 #endif
 }    
 
+
 // Set RS pin
 // Used for mbed pins, I2C bus expander or SPI shiftregister
 void TextLCD_I2C::_setRS(bool value) {
@@ -2821,7 +2866,7 @@
   // MCP23008 portexpander
   
   // write the new data to the portexpander
-  _write_register(GPIO, _lcd_bus);      
+  _writeRegister(GPIO, _lcd_bus);      
 #else
   // PCF8574 of PCF8574A portexpander
 
@@ -2845,7 +2890,63 @@
   // MCP23008 portexpander
   
   // write the new data to the portexpander
-  _write_register(GPIO, _lcd_bus);      
+  _writeRegister(GPIO, _lcd_bus);      
+#else
+  // PCF8574 of PCF8574A portexpander
+
+  // write the new data to the I2C portexpander
+  _i2c->write(_slaveAddress, &_lcd_bus, 1);    
+#endif                 
+}    
+
+
+// Place the 4bit data in the databus shadowvalue
+// Used for mbed I2C bus expander
+void TextLCD_I2C::_setDataBits(int value) {
+
+  // Set bit by bit to support any mapping of expander portpins to LCD pins 
+  if (value & 0x01){
+    _lcd_bus |= D_LCD_D4;   // Set Databit 
+  }  
+  else { 
+    _lcd_bus &= ~D_LCD_D4;  // Reset Databit
+  }  
+
+  if (value & 0x02){
+    _lcd_bus |= D_LCD_D5;   // Set Databit 
+  }  
+  else {
+    _lcd_bus &= ~D_LCD_D5;  // Reset Databit
+  }  
+
+  if (value & 0x04) {
+    _lcd_bus |= D_LCD_D6;   // Set Databit 
+  }  
+  else {                    
+    _lcd_bus &= ~D_LCD_D6;  // Reset Databit
+  }  
+
+  if (value & 0x08) {
+    _lcd_bus |= D_LCD_D7;   // Set Databit 
+  }  
+  else {
+    _lcd_bus &= ~D_LCD_D7;  // Reset Databit
+  }                                      
+}    
+
+// Place the 4bit data on the databus
+// Used for mbed pins, I2C bus expander or SPI shifregister
+void TextLCD_I2C::_setData(int value) {
+
+  // Place the 4bit data on the databus shadowvalue
+  _setDataBits(value); 
+  
+  // Place the 4bit data on the databus
+#if (MCP23008==1)
+  // MCP23008 portexpander
+  
+  // write the new data to the portexpander
+  _writeRegister(GPIO, _lcd_bus);      
 #else
   // PCF8574 of PCF8574A portexpander
 
@@ -2854,65 +2955,207 @@
 #endif                 
 }    
 
+// Write data to MCP23008 I2C portexpander
+// Used for mbed I2C bus expander
+void TextLCD_I2C::_writeRegister (int reg, int value) {
+  char data[] = {reg, value};
+    
+  _i2c->write(_slaveAddress, data, 2); 
+}
+
+//New optimized
+//Test faster _writeByte 0.11s vs 0.27s for a 20x4 fillscreen (PCF8574)
+//Test faster _writeByte 0.14s vs 0.34s for a 20x4 fillscreen (MCP23008)
+
+// Write a byte using I2C
+void TextLCD_I2C::_writeByte(int value) {
+  char data[6];
+  
+#if (MCP23008==1)
+  // MCP23008 portexpander
+
+  data[0] = GPIO;                 // set registeraddres
+                                  // Note: auto-increment is disabled so all data will go to GPIO register
+  
+  _setEnableBit(true);            // set E 
+  _setDataBits(value >> 4);       // set data high  
+  data[1] = _lcd_bus;
+  
+  _setEnableBit(false);           // clear E   
+  data[2] = _lcd_bus;
+  
+  _setEnableBit(true);            // set E   
+  _setDataBits(value);            // set data low    
+  data[3] = _lcd_bus;
+  
+  _setEnableBit(false);           // clear E     
+  data[4] = _lcd_bus;
+  
+  // write the packed data to the I2C portexpander
+  _i2c->write(_slaveAddress, data, 5);    
+#else
+  // PCF8574 of PCF8574A portexpander
+  
+  _setEnableBit(true);            // set E 
+  _setDataBits(value >> 4);       // set data high  
+  data[0] = _lcd_bus;
+  
+  _setEnableBit(false);           // clear E   
+  data[1] = _lcd_bus;
+  
+  _setEnableBit(true);            // set E   
+  _setDataBits(value);            // set data low    
+  data[2] = _lcd_bus;
+  
+  _setEnableBit(false);           // clear E     
+  data[3] = _lcd_bus;
+  
+  // write the packed data to the I2C portexpander
+  _i2c->write(_slaveAddress, data, 4);    
+#endif
+}
+
+#endif /* I2C Expander PCF8574/MCP23008 */
+//---------- End TextLCD_I2C ------------
+
+
+//--------- Start TextLCD_SPI -----------
+#if(LCD_SPI == 1) /* SPI Expander SN74595          */
+
+ /** Create a TextLCD interface using an SPI 74595 portexpander
+   *
+   * @param spi             SPI Bus
+   * @param cs              chip select pin (active low)
+   * @param type            Sets the panel size/addressing mode (default = LCD16x2)
+   * @param ctrl            LCD controller (default = HD44780)      
+   */
+TextLCD_SPI::TextLCD_SPI(SPI *spi, PinName cs, LCDType type, LCDCtrl ctrl) :
+                         TextLCD_Base(type, ctrl), 
+                         _spi(spi),        
+                         _cs(cs) {      
+        
+  // Init cs
+  _cs = 1;  
+
+  // Setup the spi for 8 bit data, low steady state clock,
+  // rising edge capture, with a 500KHz or 1MHz clock rate  
+  _spi->format(8,0);
+  _spi->frequency(500000);    
+  //_spi.frequency(1000000);    
+
+  // Init the portexpander bus
+  _lcd_bus = D_LCD_BUS_DEF;
+  
+  // write the new data to the portexpander
+  _cs = 0;  
+  _spi->write(_lcd_bus);   
+  _cs = 1;  
+
+  _init(_LCD_DL_4);   // Set Datalength to 4 bit for all serial expander interfaces
+}
+
+// Set E pin (or E2 pin)
+// Used for mbed pins, I2C bus expander or SPI shiftregister
+void TextLCD_SPI::_setEnable(bool value) {
+
+  if(_ctrl_idx==_LCDCtrl_0) {
+    if (value) {
+      _lcd_bus |= D_LCD_E;     // Set E bit 
+    }  
+    else {                    
+      _lcd_bus &= ~D_LCD_E;    // Reset E bit                     
+    }  
+  }
+  else {
+    if (value) {
+      _lcd_bus |= D_LCD_E2;    // Set E2 bit 
+    }  
+    else {
+      _lcd_bus &= ~D_LCD_E2;   // Reset E2 bit                     
+    }  
+  }
+                  
+  // write the new data to the SPI portexpander
+  _cs = 0;  
+  _spi->write(_lcd_bus);   
+  _cs = 1;    
+}    
+
+// Set RS pin
+// Used for mbed pins, I2C bus expander or SPI shiftregister and SPI_N
+void TextLCD_SPI::_setRS(bool value) {
+
+  if (value) {
+    _lcd_bus |= D_LCD_RS;    // Set RS bit 
+  }  
+  else {                    
+    _lcd_bus &= ~D_LCD_RS;   // Reset RS bit                     
+  }
+     
+  // write the new data to the SPI portexpander
+  _cs = 0;  
+  _spi->write(_lcd_bus);   
+  _cs = 1;     
+}    
+
+// Set BL pin
+// Used for mbed pins, I2C bus expander or SPI shiftregister
+void TextLCD_SPI::_setBL(bool value) {
+
+  if (value) {
+    _lcd_bus |= D_LCD_BL;    // Set BL bit 
+  }  
+  else {
+    _lcd_bus &= ~D_LCD_BL;   // Reset BL bit                     
+  }
+      
+  // write the new data to the SPI portexpander
+  _cs = 0;  
+  _spi->write(_lcd_bus);   
+  _cs = 1;      
+}    
 
 // Place the 4bit data on the databus
-// Used for mbed pins, I2C bus expander or SPI shifregister
-void TextLCD_I2C::_setData(int value) {
-  int data;
+// Used for mbed pins, I2C bus expander or SPI shiftregister
+void TextLCD_SPI::_setData(int value) {
 
   // Set bit by bit to support any mapping of expander portpins to LCD pins
-  
-  data = value & 0x0F;
-  if (data & 0x01){
+  if (value & 0x01) {
     _lcd_bus |= D_LCD_D4;   // Set Databit 
   }  
-  else { 
-    _lcd_bus &= ~D_LCD_D4;  // Reset Databit
-  }  
-
-  if (data & 0x02){
+  else {                    
+    _lcd_bus &= ~D_LCD_D4;  // Reset Databit                     
+  }
+  
+  if (value & 0x02) {
     _lcd_bus |= D_LCD_D5;   // Set Databit 
   }  
   else {
-    _lcd_bus &= ~D_LCD_D5;  // Reset Databit
-  }  
-
-  if (data & 0x04) {
+    _lcd_bus &= ~D_LCD_D5;  // Reset Databit                     
+  }
+  
+  if (value & 0x04) {
     _lcd_bus |= D_LCD_D6;   // Set Databit 
   }  
-  else {                    
-    _lcd_bus &= ~D_LCD_D6;  // Reset Databit
-  }  
-
-  if (data & 0x08) {
+  else {
+    _lcd_bus &= ~D_LCD_D6;  // Reset Databit                     
+  }
+  
+  if (value & 0x08) {
     _lcd_bus |= D_LCD_D7;   // Set Databit 
   }  
   else {
     _lcd_bus &= ~D_LCD_D7;  // Reset Databit
   }  
                     
-#if (MCP23008==1)
-  // MCP23008 portexpander
-  
-  // write the new data to the portexpander
-  _write_register(GPIO, _lcd_bus);      
-#else
-  // PCF8574 of PCF8574A portexpander
-
-  // write the new data to the I2C portexpander
-  _i2c->write(_slaveAddress, &_lcd_bus, 1);    
-#endif
-                 
+  // write the new data to the SPI portexpander
+  _cs = 0;  
+  _spi->write(_lcd_bus);   
+  _cs = 1;       
 }    
 
-// Write data to MCP23008 I2C portexpander
-void TextLCD_I2C::_write_register (int reg, int value) {
-  char data[] = {reg, value};
-    
-  _i2c->write(_slaveAddress, data, 2); 
-}
-#endif /* I2C Expander PCF8574/MCP23008 */
-//---------- End TextLCD_I2C ------------
+#endif /* SPI Expander SN74595          */
+//---------- End TextLCD_SPI ------------
 
 
 //--------- Start TextLCD_I2C_N ---------
@@ -3015,6 +3258,7 @@
   _i2c->write(_slaveAddress, data, 2); 
 #else  
 //Controllers that dont support ACK
+//Note: This may be issue with some mbed platforms that dont fully/correctly support I2C byte operations.
   _i2c->start(); 
   _i2c->write(_slaveAddress);   
   _i2c->write(data[0]); 
@@ -3026,159 +3270,6 @@
 //-------- End TextLCD_I2C_N ------------
 
 
-//--------- Start TextLCD_SPI -----------
-#if(LCD_SPI == 1) /* SPI Expander SN74595          */
-
- /** Create a TextLCD interface using an SPI 74595 portexpander
-   *
-   * @param spi             SPI Bus
-   * @param cs              chip select pin (active low)
-   * @param type            Sets the panel size/addressing mode (default = LCD16x2)
-   * @param ctrl            LCD controller (default = HD44780)      
-   */
-TextLCD_SPI::TextLCD_SPI(SPI *spi, PinName cs, LCDType type, LCDCtrl ctrl) :
-                         TextLCD_Base(type, ctrl), 
-                         _spi(spi),        
-                         _cs(cs) {      
-        
-  // Init cs
-  _setCS(true);  
-
-  // Setup the spi for 8 bit data, low steady state clock,
-  // rising edge capture, with a 500KHz or 1MHz clock rate  
-  _spi->format(8,0);
-  _spi->frequency(500000);    
-  //_spi.frequency(1000000);    
-
-  // Init the portexpander bus
-  _lcd_bus = D_LCD_BUS_DEF;
-  
-  // write the new data to the portexpander
-  _setCS(false);  
-  _spi->write(_lcd_bus);   
-  _setCS(true);  
-
-  _init();   
-}
-
-// Set E pin (or E2 pin)
-// Used for mbed pins, I2C bus expander or SPI shiftregister
-void TextLCD_SPI::_setEnable(bool value) {
-
-  if(_ctrl_idx==_LCDCtrl_0) {
-    if (value) {
-      _lcd_bus |= D_LCD_E;     // Set E bit 
-    }  
-    else {                    
-      _lcd_bus &= ~D_LCD_E;    // Reset E bit                     
-    }  
-  }
-  else {
-    if (value) {
-      _lcd_bus |= D_LCD_E2;    // Set E2 bit 
-    }  
-    else {
-      _lcd_bus &= ~D_LCD_E2;   // Reset E2 bit                     
-    }  
-  }
-                  
-  // write the new data to the SPI portexpander
-  _setCS(false);  
-  _spi->write(_lcd_bus);   
-  _setCS(true);    
-}    
-
-// Set RS pin
-// Used for mbed pins, I2C bus expander or SPI shiftregister and SPI_N
-void TextLCD_SPI::_setRS(bool value) {
-
-  if (value) {
-    _lcd_bus |= D_LCD_RS;    // Set RS bit 
-  }  
-  else {                    
-    _lcd_bus &= ~D_LCD_RS;   // Reset RS bit                     
-  }
-     
-  // write the new data to the SPI portexpander
-  _setCS(false);  
-  _spi->write(_lcd_bus);   
-  _setCS(true);     
-}    
-
-// Set BL pin
-// Used for mbed pins, I2C bus expander or SPI shiftregister
-void TextLCD_SPI::_setBL(bool value) {
-
-  if (value) {
-    _lcd_bus |= D_LCD_BL;    // Set BL bit 
-  }  
-  else {
-    _lcd_bus &= ~D_LCD_BL;   // Reset BL bit                     
-  }
-      
-  // write the new data to the SPI portexpander
-  _setCS(false);  
-  _spi->write(_lcd_bus);   
-  _setCS(true);      
-}    
-
-// Place the 4bit data on the databus
-// Used for mbed pins, I2C bus expander or SPI shiftregister
-void TextLCD_SPI::_setData(int value) {
-  int data;
-
-  // Set bit by bit to support any mapping of expander portpins to LCD pins
-    
-  data = value & 0x0F;
-  if (data & 0x01) {
-    _lcd_bus |= D_LCD_D4;   // Set Databit 
-  }  
-  else {                    
-    _lcd_bus &= ~D_LCD_D4;  // Reset Databit                     
-  }
-  
-  if (data & 0x02) {
-    _lcd_bus |= D_LCD_D5;   // Set Databit 
-  }  
-  else {
-    _lcd_bus &= ~D_LCD_D5;  // Reset Databit                     
-  }
-  
-  if (data & 0x04) {
-    _lcd_bus |= D_LCD_D6;   // Set Databit 
-  }  
-  else {
-    _lcd_bus &= ~D_LCD_D6;  // Reset Databit                     
-  }
-  
-  if (data & 0x08) {
-    _lcd_bus |= D_LCD_D7;   // Set Databit 
-  }  
-  else {
-    _lcd_bus &= ~D_LCD_D7;  // Reset Databit
-  }  
-                    
-  // write the new data to the SPI portexpander
-  _setCS(false);  
-  _spi->write(_lcd_bus);   
-  _setCS(true);          
-}    
-
-// Set CS line.
-// Only used for SPI bus
-void TextLCD_SPI::_setCS(bool value) {
-
-  if (value) {   
-    _cs  = 1;    // Set CS pin 
-  }  
-  else {
-    _cs  = 0;    // Reset CS pin 
-  }
-}
-#endif /* SPI Expander SN74595          */
-//---------- End TextLCD_SPI ------------
-
-
 //--------- Start TextLCD_SPI_N ---------
 #if(LCD_SPI_N == 1) /* Native SPI bus     */
  /** Create a TextLCD interface using a controller with a native SPI4 interface
@@ -3202,12 +3293,12 @@
   // Setup the spi for 8 bit data, high steady state clock,
   // rising edge capture, with a 500KHz or 1MHz clock rate    
 //  _spi->format(8,3);  
+//  _spi->frequency(500000); 
 //  _spi->frequency(1000000);    
   
   // Setup the spi for 8 bit data, low steady state clock,
   // rising edge capture, with a 500KHz or 1MHz clock rate  
   _spi->format(8,0);
-//  _spi->frequency(300000);    
 //  _spi->frequency(500000); 
   _spi->frequency(1000000);    
     
@@ -3292,13 +3383,12 @@
   // Setup the spi for 8 bit data, high steady state clock,
   // rising edge capture, with a 500KHz or 1MHz clock rate  
 //  _spi->format(8,3);  
-//  _spi->frequency(300000);    
+//  _spi->frequency(500000);    
 //  _spi->frequency(1000000);    
 
   // Setup the spi for 8 bit data, low steady state clock,
   // rising edge capture, with a 500KHz or 1MHz clock rate  
   _spi->format(8,0);
-//  _spi->frequency(300000);    
 //  _spi->frequency(500000); 
   _spi->frequency(1000000);    
   
--- a/TextLCD.h	Tue Nov 25 19:21:18 2014 +0000
+++ b/TextLCD.h	Sun Mar 29 13:08:03 2015 +0000
@@ -1,4 +1,4 @@
-/* mbed TextLCD Library, for a 4-bit LCD based on HD44780
+/* mbed TextLCD Library, for LCDs based on HD44780 controllers
  * Copyright (c) 2007-2010, sford, http://mbed.org
  *               2013, v01: WH, Added LCD types, fixed LCD address issues, added Cursor and UDCs 
  *               2013, v02: WH, Added I2C and SPI bus interfaces
@@ -17,6 +17,7 @@
  *                              added 16 UDCs for supported devices (eg PCF2103), moved UDC defines to TextLCD_UDC file, added TextLCD_Config.h for feature and footprint settings.
  *               2014, v15: WH, Added AC780 support, added I2C expander modules, fixed setBacklight() for inverted logic modules. Fixed bug in LCD_SPI_N define 
  *               2014, v16: WH, Added ST7070 and KS0073 support, added setIcon(), clrIcon() and setInvert() method for supported devices  
+ *               2015, v17: WH, Clean up low-level _writeCommand() and _writeData(), Added support for alternative fonttables (eg PCF21XX), Added ST7066_ACM controller for ACM1602 module
  *
  * Permission is hereby granted, free of charge, to any person obtaining a copy
  * of this software and associated documentation files (the "Software"), to deal
@@ -130,21 +131,27 @@
 #define LCD_C_CTR      0x00020000  /*Contrast Control    */
 #define LCD_C_ICN      0x00040000  /*Icons               */
 #define LCD_C_PDN      0x00080000  /*Power Down          */
+// Fonttable encoded in b15..b12
+#define LCD_C_FNT_MSK  0x0000F000 
+#define LCD_C_FT0      0x00000000  /*Default             */
+#define LCD_C_FT1      0x00001000  /*Font1               */
+#define LCD_C_FT2      0x00002000  /*Font2               */
 
 /** A TextLCD interface for driving 4-bit HD44780-based LCDs
  *
  * @brief Currently supports 8x1, 8x2, 12x2, 12x3, 12x4, 16x1, 16x2, 16x3, 16x4, 20x2, 20x4, 24x2, 24x4, 40x2 and 40x4 panels
- *        Interface options include direct mbed pins, I2C portexpander (PCF8474/PCF8574A or MCP23008) or SPI bus shiftregister (74595) and some native I2C or SPI devices 
- *
+ *        Interface options include direct mbed pins, I2C portexpander (PCF8474/PCF8574A or MCP23008) or 
+ *        SPI bus shiftregister (74595) or native I2C or SPI interfaces for some supported devices. 
  */
 class TextLCD_Base : public Stream {
-//class TextLCD_Base{    
+//class TextLCD_Base {    
 
-//Unfortunately this #define selection breaks Doxygen !!!
+//Unfortunately the following #define selection breaks Doxygen !!!
+//Add it manually when you want to disable the Stream inheritance
 //#if (LCD_PRINTF == 1)
 //class TextLCD_Base : public Stream {
 //#else    
-//class TextLCD_Base{    
+//class TextLCD_Base {    
 //#endif
 
 public:
@@ -199,28 +206,32 @@
 
     /** LCD Controller Device */
     enum LCDCtrl {
-        HD44780     =  0 |  LCD_C_PAR,                                                                    /**<  HD44780 or full equivalent (default)         */    
-        WS0010      =  1 | (LCD_C_PAR | LCD_C_SPI3_10 | LCD_C_PDN),                                       /**<  WS0010/RS0010 OLED Controller, 4/8 bit, SPI3 */    
-        ST7036_3V3  =  2 | (LCD_C_PAR | LCD_C_SPI4    | LCD_C_I2C | LCD_C_BST | LCD_C_CTR),               /**<  ST7036  3V3 with Booster, 4/8 bit, SPI4, I2C */   
-        ST7036_5V   =  3 | (LCD_C_PAR | LCD_C_SPI4    | LCD_C_I2C | LCD_C_BST | LCD_C_CTR),               /**<  ST7036  5V no Booster, 4/8 bit, SPI4, I2C    */   
-        ST7032_3V3  =  4 | (LCD_C_PAR | LCD_C_SPI4    | LCD_C_I2C | LCD_C_BST | LCD_C_CTR),               /**<  ST7032  3V3 with Booster, 4/8 bit, SPI4, I2C */   
-        ST7032_5V   =  5 | (LCD_C_PAR | LCD_C_SPI4    | LCD_C_I2C | LCD_C_CTR),                           /**<  ST7032  5V no Booster, 4/8 bit, SPI4, I2C    */           
-        KS0078      =  6 | (LCD_C_PAR | LCD_C_SPI3_24 | LCD_C_PDN),                                       /**<  KS0078  24x4 support, 4/8 bit, SPI3          */                   
-        PCF2103_3V3 =  7 | (LCD_C_PAR | LCD_C_I2C),                                                       /**<  PCF2103 3V3 no Booster, 4/8 bit, I2C         */                                   
-        PCF2113_3V3 =  8 | (LCD_C_PAR | LCD_C_I2C     | LCD_C_BST | LCD_C_CTR),                           /**<  PCF2113 3V3 with Booster, 4/8 bit, I2C       */                           
-        PCF2116_3V3 =  9 | (LCD_C_PAR | LCD_C_I2C     | LCD_C_BST),                                       /**<  PCF2116 3V3 with Booster, 4/8 bit, I2C       */                           
-        PCF2116_5V  = 10 | (LCD_C_PAR | LCD_C_I2C),                                                       /**<  PCF2116 5V no Booster, 4/8 bit, I2C          */        
-        PCF2119_3V3 = 11 | (LCD_C_PAR | LCD_C_I2C     | LCD_C_BST | LCD_C_CTR),                           /**<  PCF2119 3V3 with Booster, 4/8 bit, I2C       */                           
-//        PCF2119_5V  = 12 | (LCD_C_PAR | LCD_C_I2C),                                                       /**<  PCF2119 5V no Booster, 4/8 bit, I2C          */
-        AIP31068    = 13 | (LCD_C_SPI3_9  | LCD_C_I2C | LCD_C_BST),                                       /**<  AIP31068 I2C, SPI3                           */                           
-        SSD1803_3V3 = 14 | (LCD_C_PAR | LCD_C_SPI3_24 | LCD_C_I2C | LCD_C_BST | LCD_C_CTR | LCD_C_PDN),   /**<  SSD1803 3V3 with Booster, 4/8 bit, I2C, SPI3 */
-//        SSD1803_5V  = 15 | (LCD_C_PAR | LCD_C_SPI3_24 | LCD_C_I2C | LCD_C_BST | LCD_C_CTR | LCD_C_PDN),   /**<  SSD1803 3V3 with Booster, 4/8 bit, I2C, SPI3 */
-        US2066_3V3  = 16 | (LCD_C_PAR | LCD_C_SPI3_24 | LCD_C_I2C | LCD_C_CTR | LCD_C_PDN),               /**<  US2066/SSD1311 3V3, 4/8 bit, I2C, SPI3 */
-        PT6314      = 17 | (LCD_C_PAR | LCD_C_SPI3_16 | LCD_C_CTR),                                       /**<  PT6314  VFD, 4/8 bit, SPI3                   */
-        AC780       = 18 | (LCD_C_PAR | LCD_C_SPI4 | LCD_C_I2C | LCD_C_PDN),                              /**<  AC780/KS0066i 4/8 bit, SPI, I2C              */
-//        WS0012      = 19 | (LCD_C_PAR | LCD_C_SPI3_10 | LCD_C_I2C | LCD_C_PDN),                           /**<  WS0012 4/8 bit, SPI, I2C                     */
-        ST7070      = 20 | (LCD_C_PAR | LCD_C_SPI3_8 | LCD_C_SPI4),                                       /**<  ST7070 4/8 bit, SPI3                         */
-        KS0073      = 21 | (LCD_C_PAR | LCD_C_SPI3_24 | LCD_C_PDN)                                        /**<  KS0073 4/8 bit, SPI3                         */
+        HD44780         =  0 |  LCD_C_PAR,                                                                    /**<  HD44780 or full equivalent (default)         */    
+        AC780           =  1 | (LCD_C_PAR | LCD_C_SPI4 | LCD_C_I2C | LCD_C_PDN),                              /**<  AC780/KS0066i 4/8 bit, SPI, I2C              */
+        AIP31068        =  2 | (LCD_C_SPI3_9  | LCD_C_I2C | LCD_C_BST),                                       /**<  AIP31068 I2C, SPI3                           */                           
+        KS0073          =  3 | (LCD_C_PAR | LCD_C_SPI3_24 | LCD_C_PDN),                                       /**<  KS0073 4/8 bit, SPI3                         */
+        KS0078          =  4 | (LCD_C_PAR | LCD_C_SPI3_24 | LCD_C_PDN),                                       /**<  KS0078  24x4 support, 4/8 bit, SPI3          */                   
+        PCF2103_3V3     =  5 | (LCD_C_PAR | LCD_C_I2C),                                                       /**<  PCF2103 3V3 no Booster, 4/8 bit, I2C         */                                   
+        PCF2113_3V3     =  6 | (LCD_C_PAR | LCD_C_I2C     | LCD_C_BST | LCD_C_CTR),                           /**<  PCF2113 3V3 with Booster, 4/8 bit, I2C       */                           
+        PCF2116_3V3     =  7 | (LCD_C_PAR | LCD_C_I2C     | LCD_C_BST),                                       /**<  PCF2116 3V3 with Booster, 4/8 bit, I2C       */                           
+        PCF2116_5V      =  8 | (LCD_C_PAR | LCD_C_I2C),                                                       /**<  PCF2116 5V no Booster, 4/8 bit, I2C          */        
+        PCF2116C_5V     =  9 | (LCD_C_PAR | LCD_C_I2C     | LCD_C_BST) | LCD_C_FT1,                           /**<  PCF2116C 3V3 with Booster, 4/8 bit, I2C       */                           
+        PCF2119_3V3     = 10 | (LCD_C_PAR | LCD_C_I2C     | LCD_C_BST | LCD_C_CTR),                           /**<  PCF2119 3V3 with Booster, 4/8 bit, I2C       */                           
+//        PCF2119C_3V3    = 11 | (LCD_C_PAR | LCD_C_I2C     | LCD_C_BST | LCD_C_CTR), LCD_C_FT1,                /**<  PCF2119K 3V3 with Booster, 4/8 bit, I2C       */                           
+//        PCF2119_5V      = 12 | (LCD_C_PAR | LCD_C_I2C),                                                       /**<  PCF2119 5V no Booster, 4/8 bit, I2C          */
+        PT6314          = 13 | (LCD_C_PAR | LCD_C_SPI3_16 | LCD_C_CTR),                                       /**<  PT6314  VFD, 4/8 bit, SPI3                   */
+        SSD1803_3V3     = 14 | (LCD_C_PAR | LCD_C_SPI3_24 | LCD_C_I2C | LCD_C_BST | LCD_C_CTR | LCD_C_PDN),   /**<  SSD1803 3V3 with Booster, 4/8 bit, I2C, SPI3 */
+//        SSD1803_5V      = 15 | (LCD_C_PAR | LCD_C_SPI3_24 | LCD_C_I2C | LCD_C_BST | LCD_C_CTR | LCD_C_PDN),   /**<  SSD1803 3V3 with Booster, 4/8 bit, I2C, SPI3 */
+        ST7032_3V3      = 16 | (LCD_C_PAR | LCD_C_SPI4    | LCD_C_I2C | LCD_C_BST | LCD_C_CTR),               /**<  ST7032  3V3 with Booster, 4/8 bit, SPI4, I2C */   
+        ST7032_5V       = 17 | (LCD_C_PAR | LCD_C_SPI4    | LCD_C_I2C | LCD_C_CTR),                           /**<  ST7032  5V no Booster, 4/8 bit, SPI4, I2C    */           
+        ST7036_3V3      = 18 | (LCD_C_PAR | LCD_C_SPI4    | LCD_C_I2C | LCD_C_BST | LCD_C_CTR),               /**<  ST7036  3V3 with Booster, 4/8 bit, SPI4, I2C */   
+        ST7036_5V       = 19 | (LCD_C_PAR | LCD_C_SPI4    | LCD_C_I2C | LCD_C_BST | LCD_C_CTR),               /**<  ST7036  5V no Booster, 4/8 bit, SPI4, I2C    */   
+        ST7066_ACM      = 20 | (LCD_C_PAR | LCD_C_I2C),                                                       /**<  ST7066 4/8 bit, I2C on ACM1602 using a PIC   */        
+        ST7070          = 21 | (LCD_C_PAR | LCD_C_SPI3_8 | LCD_C_SPI4),                                       /**<  ST7070 4/8 bit, SPI3                         */
+        US2066_3V3      = 22 | (LCD_C_PAR | LCD_C_SPI3_24 | LCD_C_I2C | LCD_C_CTR | LCD_C_PDN),               /**<  US2066/SSD1311 3V3, 4/8 bit, I2C, SPI3 */
+        WS0010          = 23 | (LCD_C_PAR | LCD_C_SPI3_10 | LCD_C_PDN)                                        /**<  WS0010/RS0010 OLED Controller, 4/8 bit, SPI3 */    
+//        WS0012          = 24 | (LCD_C_PAR | LCD_C_SPI3_10 | LCD_C_I2C | LCD_C_PDN),                           /**<  WS0012 4/8 bit, SPI, I2C                     */
+
     };
 
 
@@ -266,6 +277,14 @@
     };
 
 
+   /** Convert ASCII character code to the LCD fonttable code
+     *
+     * @param c The character to write to the display
+     * @return The character code for the specific fonttable of the controller
+     */
+   int ASCII_2_LCD (int c);
+
+
 #if(LCD_PRINTF != 1)
    /** Write a character to the LCD
      *
@@ -436,7 +455,7 @@
         _LCDCtrl_1,  /*<  Secondary */            
     };
 
-    /** LCD Datalength control to select between 4 or 8 bit data/commands, used for native Serial interface */
+    /** LCD Datalength control to select between 4 or 8 bit data/commands, mainly used for native Serial interface */
     enum _LCDDatalength {
         _LCD_DL_4 = 0x00,  /**<  Datalength 4 bit */    
         _LCD_DL_8 = 0x10   /**<  Datalength 8 bit */            
@@ -529,17 +548,18 @@
     virtual void _writeByte(int value);
 
 //Display type
-    LCDType _type;
-    int _nr_cols;    
+    LCDType _type;      // Display type 
+    int _nr_cols;       
     int _nr_rows;    
-    int _addr_mode;    
-        
+    int _addr_mode;     // Addressing mode of LCDType, defines relation between display row,col and controller memory address
+       
 //Display mode
     LCDMode _currentMode;
 
 //Controller type 
-    LCDCtrl _ctrl;    
-
+    LCDCtrl _ctrl;      // Controller type
+    int _font;          // ASCII character fonttable
+    
 //Controller select, mainly used for LCD40x4 
     _LCDCtrl_Idx _ctrl_idx;    
 
@@ -607,7 +627,6 @@
   */   
     virtual void _setData(int value);
 
-
 /** Regular mbed pins bus
   */
     DigitalOut _rs, _e;
@@ -616,7 +635,7 @@
 /** Optional Hardware pins for the Backlight and LCD40x4 device
   * Default PinName value is NC, must be used as pointer to avoid issues with mbed lib and DigitalOut pins
   */
-    DigitalOut *_bl, *_e2;       
+    DigitalOut *_bl, *_e2;                                                                                                                                                                                                                                                     
 };
 
 //----------- End TextLCD ---------------
@@ -633,7 +652,7 @@
    /** Create a TextLCD interface using an I2C PCF8574 (or PCF8574A) or MCP23008 portexpander
      *
      * @param i2c             I2C Bus
-     * @param deviceAddress   I2C slave address (PCF8574 or PCF8574A, default = PCF8574_SA0 = 0x40)
+     * @param deviceAddress   I2C slave address (PCF8574 (or PCF8574A) or MCP23008 portexpander, default = PCF8574_SA0 = 0x40)
      * @param type            Sets the panel size/addressing mode (default = LCD16x2)
      * @param ctrl            LCD controller (default = HD44780)                
      */
@@ -641,6 +660,13 @@
 
 private:
     
+/** Place the Enable bit in the databus shadowvalue
+  *  Used for mbed I2C portexpander
+  *  @param value data to write
+  *  @return none
+  */
+    void _setEnableBit(bool value);    
+
 /** Implementation of pure Virtual Low level writes to LCD Bus (serial expander)
   * Set the Enable pin.
   */
@@ -656,24 +682,38 @@
   */   
     virtual void _setBL(bool value);
     
+/** Place the 4bit data in the databus shadowvalue
+  *  Used for mbed I2C portexpander
+  *  @param value data to write
+  *  @return none
+  */
+    void _setDataBits(int value);
+
 /** Implementation of pure Virtual Low level writes to LCD Bus (serial expander)
   * Set the databus value (4 bit).
   */   
     virtual void _setData(int value);
-      
+    
+//New optimized
+//Test faster _writeByte 0.11s vs 0.27s for a 20x4 fillscreen (PCF8574)
+//Test faster _writeByte 0.14s vs 0.34s for a 20x4 fillscreen (MCP23008)
+
+/** Low level writes to LCD serial bus expander
+  */
+    virtual void _writeByte(int value);   
+
 /** Write data to MCP23008 I2C portexpander
   *  @param reg register to write
   *  @param value data to write
   *  @return none     
-  *
   */
-    void _write_register (int reg, int value);     
+    void _writeRegister (int reg, int value);     
   
 //I2C bus
     I2C *_i2c;
     char _slaveAddress;
     
-// Internal bus mirror value for serial bus only
+// Internal bus shadow value for serial bus only
     char _lcd_bus;      
 };
 #endif /* I2C Expander PCF8574/MCP23008 */
@@ -718,28 +758,82 @@
 /** Implementation of pure Virtual Low level writes to LCD Bus (serial expander)
   * Set the databus value (4 bit).
   */   
-    virtual void _setData(int value);
-    
-/** Implementation of Low level writes to LCD Bus (serial expander)
-  * Set the CS pin (0 = select, 1 = deselect).
-  */   
-    virtual void _setCS(bool value);
-    
-///** Low level writes to LCD serial bus only (serial expander)
-//  */
-//    void _writeBus();      
+    virtual void _setData(int value);     
    
 // SPI bus        
     SPI *_spi;
     DigitalOut _cs;    
     
-// Internal bus mirror value for serial bus only
+// Internal bus shadow value for serial bus only
     char _lcd_bus;   
 };
 #endif /* SPI Expander SN74595          */
 //---------- End TextLCD_SPI ------------
 
 
+//--------- Start TextLCD_I2C_N -----------
+#if(LCD_I2C_N == 1)  /* Native I2C */
+
+/** Create a TextLCD interface using a controller with native I2C interface
+  *
+  */
+class TextLCD_I2C_N : public TextLCD_Base {    
+public:
+    /** Create a TextLCD interface using a controller with native I2C interface
+     *
+     * @param i2c             I2C Bus
+     * @param deviceAddress   I2C slave address (default = ST7032_SA = 0x7C)  
+     * @param type            Sets the panel size/addressing mode (default = LCD16x2)
+     * @param bl              Backlight control line (optional, default = NC)       
+     * @param ctrl            LCD controller (default = ST7032_3V3)                     
+     */
+    TextLCD_I2C_N(I2C *i2c, char deviceAddress = ST7032_SA, LCDType type = LCD16x2, PinName bl = NC, LCDCtrl ctrl = ST7032_3V3);
+
+  /** Destruct a TextLCD interface using a controller with native I2C interface
+    */
+    virtual ~TextLCD_I2C_N(void);
+
+private:
+
+/** Implementation of pure Virtual Low level writes to LCD Bus (serial native)
+  * Set the Enable pin.
+  */
+    virtual void _setEnable(bool value);
+
+/** Implementation of pure Virtual Low level writes to LCD Bus (serial native)
+  * Set the RS pin ( 0 = Command, 1 = Data).
+  */   
+    virtual void _setRS(bool value);  
+
+/** Implementation of pure Virtual Low level writes to LCD Bus (serial native)
+  * Set the BL pin (0 = Backlight Off, 1 = Backlight On).
+  */   
+    virtual void _setBL(bool value);
+    
+/** Implementation of pure Virtual Low level writes to LCD Bus (serial native)
+  * Set the databus value (4 bit).
+  */   
+    virtual void _setData(int value);
+
+/** Low level writes to LCD serial bus only (serial native)
+  */
+    virtual void _writeByte(int value);
+
+//I2C bus
+    I2C *_i2c;
+    char _slaveAddress;
+    
+// controlbyte to select between data and command. Internal shadow value for serial bus only
+    char _controlbyte;   
+    
+//Backlight
+    DigitalOut *_bl;       
+   
+};
+#endif /* Native I2C */
+//---------- End TextLCD_I2C_N ------------
+
+
 //--------- Start TextLCD_SPI_N -----------
 #if(LCD_SPI_N == 1) /* Native SPI bus     */
 
@@ -758,6 +852,9 @@
      * @param ctrl            LCD controller (default = ST7032_3V3)                     
      */
     TextLCD_SPI_N(SPI *spi, PinName cs, PinName rs, LCDType type = LCD16x2, PinName bl = NC, LCDCtrl ctrl = ST7032_3V3);
+
+    /** Destruct a TextLCD interface using a controller with native SPI4 interface
+      */
     virtual ~TextLCD_SPI_N(void);
 
 private:
@@ -800,7 +897,10 @@
 
 //-------- Start TextLCD_SPI_N_3_8 --------
 #if(LCD_SPI_N_3_8 == 1) /* Native SPI bus     */
-
+/** Create a TextLCD interface using a controller with native SPI3 8 bits interface
+  * This mode is supported by ST7070. 
+  *
+  */
 class TextLCD_SPI_N_3_8 : public TextLCD_Base {    
 public:
  /** Create a TextLCD interface using a controller with a native SPI3 8 bits interface
@@ -815,6 +915,8 @@
    */       
   TextLCD_SPI_N_3_8(SPI *spi, PinName cs, LCDType type = LCD16x2, PinName bl = NC, LCDCtrl ctrl = ST7070);
 
+  /** Destruct a TextLCD interface using a controller with native SPI3_8 interface
+    */
   virtual ~TextLCD_SPI_N_3_8(void);
 
 private:
@@ -847,7 +949,7 @@
     SPI *_spi;
     DigitalOut _cs;    
 
-// controlbyte to select between data and command. Internal value for serial bus only
+// controlbyte to select between data and command. Internal shadow value for serial bus only
     char _controlbyte;   
     
 //Backlight    
@@ -858,7 +960,6 @@
 //------- End TextLCD_SPI_N_3_8 -----------
 
 
-
 //------- Start TextLCD_SPI_N_3_9 ---------
 #if(LCD_SPI_N_3_9 == 1) /* Native SPI bus     */
 //Code checked out on logic analyser. Not yet tested on hardware..
@@ -879,6 +980,9 @@
      * @param ctrl            LCD controller (default = AIP31068)                     
      */
     TextLCD_SPI_N_3_9(SPI *spi, PinName cs, LCDType type = LCD16x2, PinName bl = NC, LCDCtrl ctrl = AIP31068);
+
+  /** Destruct a TextLCD interface using a controller with native SPI3_9 interface
+    */
     virtual ~TextLCD_SPI_N_3_9(void);
 
 private:
@@ -911,7 +1015,7 @@
     SPI *_spi;
     DigitalOut _cs;    
    
-// controlbyte to select between data and command. Internal value for serial bus only
+// controlbyte to select between data and command. Internal shadow value for serial bus only
     char _controlbyte;   
 
 //Backlight
@@ -940,6 +1044,9 @@
      * @param ctrl            LCD controller (default = AIP31068)                     
      */
     TextLCD_SPI_N_3_10(SPI *spi, PinName cs, LCDType type = LCD16x2, PinName bl = NC, LCDCtrl ctrl = AIP31068);
+
+  /** Destruct a TextLCD interface using a controller with native SPI3_10 interface
+    */
     virtual ~TextLCD_SPI_N_3_10(void);
 
 private:
@@ -972,7 +1079,7 @@
     SPI *_spi;
     DigitalOut _cs;    
        
-// controlbyte to select between data and command. Internal value for serial bus only
+// controlbyte to select between data and command. Internal shadow value for serial bus only
     char _controlbyte;   
 
 //Backlight
@@ -985,7 +1092,6 @@
 
 //------- Start TextLCD_SPI_N_3_16 ---------
 #if(LCD_SPI_N_3_16 == 1) /* Native SPI bus     */
-//Code checked out on logic analyser. Not yet tested on hardware..
 
 /** Create a TextLCD interface using a controller with native SPI3 16 bits interface
   *
@@ -1001,6 +1107,9 @@
      * @param ctrl            LCD controller (default = PT6314)                     
      */
     TextLCD_SPI_N_3_16(SPI *spi, PinName cs, LCDType type = LCD16x2, PinName bl = NC, LCDCtrl ctrl = PT6314);
+
+  /** Destruct a TextLCD interface using a controller with native SPI3_16 interface
+    */
     virtual ~TextLCD_SPI_N_3_16(void);
 
 private:
@@ -1033,7 +1142,7 @@
     SPI *_spi;
     DigitalOut _cs;    
    
-// controlbyte to select between data and command. Internal value for serial bus only
+// controlbyte to select between data and command. Internal shadow value for serial bus only
     char _controlbyte;   
 
 //Backlight
@@ -1062,6 +1171,9 @@
      * @param ctrl            LCD controller (default = SSD1803)                     
      */
     TextLCD_SPI_N_3_24(SPI *spi, PinName cs, LCDType type = LCD16x2, PinName bl = NC, LCDCtrl ctrl = SSD1803_3V3);
+
+  /** Destruct a TextLCD interface using a controller with native SPI3_24 interface
+    */
     virtual ~TextLCD_SPI_N_3_24(void);
 
 private:
@@ -1103,64 +1215,4 @@
 #endif /* Native SPI bus     */
 //-------- End TextLCD_SPI_N_3_24 ----------
 
-
-//--------- Start TextLCD_I2C_N -----------
-#if(LCD_I2C_N == 1)  /* Native I2C */
-
-/** Create a TextLCD interface using a controller with native I2C interface
-  *
-  */
-class TextLCD_I2C_N : public TextLCD_Base {    
-public:
-    /** Create a TextLCD interface using a controller with native I2C interface
-     *
-     * @param i2c             I2C Bus
-     * @param deviceAddress   I2C slave address (default = ST7032_SA = 0x7C)  
-     * @param type            Sets the panel size/addressing mode (default = LCD16x2)
-     * @param bl              Backlight control line (optional, default = NC)       
-     * @param ctrl            LCD controller (default = ST7032_3V3)                     
-     */
-    TextLCD_I2C_N(I2C *i2c, char deviceAddress = ST7032_SA, LCDType type = LCD16x2, PinName bl = NC, LCDCtrl ctrl = ST7032_3V3);
-    virtual ~TextLCD_I2C_N(void);
-
-private:
-
-/** Implementation of pure Virtual Low level writes to LCD Bus (serial native)
-  * Set the Enable pin.
-  */
-    virtual void _setEnable(bool value);
-
-/** Implementation of pure Virtual Low level writes to LCD Bus (serial native)
-  * Set the RS pin ( 0 = Command, 1 = Data).
-  */   
-    virtual void _setRS(bool value);  
-
-/** Implementation of pure Virtual Low level writes to LCD Bus (serial native)
-  * Set the BL pin (0 = Backlight Off, 1 = Backlight On).
-  */   
-    virtual void _setBL(bool value);
-    
-/** Implementation of pure Virtual Low level writes to LCD Bus (serial native)
-  * Set the databus value (4 bit).
-  */   
-    virtual void _setData(int value);
-
-/** Low level writes to LCD serial bus only (serial native)
-  */
-    virtual void _writeByte(int value);
-
-//I2C bus
-    I2C *_i2c;
-    char _slaveAddress;
-    
-// controlbyte to select between data and command. Internal value for serial bus only
-    char _controlbyte;   
-    
-//Backlight
-    DigitalOut *_bl;       
-   
-};
-#endif /* Native I2C */
-//---------- End TextLCD_I2C_N ------------
-
 #endif
--- a/TextLCD_Config.h	Tue Nov 25 19:21:18 2014 +0000
+++ b/TextLCD_Config.h	Sun Mar 29 13:08:03 2015 +0000
@@ -1,8 +1,10 @@
-/* mbed TextLCD Library, for a 4-bit LCD based on HD44780
+/* mbed TextLCD Library, for LCDs based on HD44780 controllers
  * Copyright (c) 2014, WH
  *               2014, v01: WH, Extracted from TextLCD.h as of v14
  *               2014, v02: WH, Added AC780 support, added I2C expander modules, fixed setBacklight() for inverted logic modules. Fixed bug in LCD_SPI_N define
  *               2014, v03: WH, Added LCD_SPI_N_3_8 define for ST7070
+ *               2015, v04: WH, Added support for alternative fonttables (eg PCF21XX)
+ *               2015, v05: WH, Clean up low-level _writeCommand() and _writeData(), Added support for alt fonttables (eg PCF21XX), Added ST7066_ACM for ACM1602 module, fixed contrast for ST7032 
  *
  * Permission is hereby granted, free of charge, to any person obtaining a copy
  * of this software and associated documentation files (the "Software"), to deal
@@ -40,10 +42,14 @@
 #define LCD_UDC        1           /* Enable predefined UDC example*/                
 #define LCD_PRINTF     1           /* Enable Stream implementation */                
 
+//Select option to activate default fonttable or alternatively use conversion for specific controller versions (eg PCF2119C)
+#define LCD_DEFAULT_FONT 1      
+
 //Pin Defines for I2C PCF8574/PCF8574A or MCP23008 and SPI 74595 bus expander interfaces
-//LCD and serial portexpanders should be wired accordingly 
+//Different commercially available LCD portexpanders use different wiring conventions.
+//LCD and serial portexpanders should be wired according to the tables below.
 //
-//Select Hardware module (one option only)
+//Select Serial Port Expander Hardware module (one option only)
 #define DEFAULT        1
 #define ADAFRUIT       0
 #define DFROBOT        0
@@ -51,7 +57,6 @@
 #define GYLCD          0
 #define SYDZ           0
 
-//Select Hardware module (one option only)
 #if (DEFAULT==1)
 //Definitions for default (WH) mapping between serial port expander pins and LCD controller
 //This hardware supports the I2C bus expander (PCF8574/PCF8574A or MCP23008) and SPI bus expander (74595) interfaces
@@ -226,6 +231,7 @@
 #endif
 
 //Bitpattern Defines for I2C PCF8574/PCF8574A, MCP23008 and SPI 74595 Bus expanders
+//Don't change!
 //
 #define D_LCD_D4       (1<<D_LCD_PIN_D4)
 #define D_LCD_D5       (1<<D_LCD_PIN_D5)
@@ -291,6 +297,9 @@
 #define ST7036_SA2     0x7C
 #define ST7036_SA3     0x7E
 
+/* ST7066_ACM I2C slave address, Added for ACM1602 module  */
+#define ST7066_SA0     0xA0
+
 /* PCF21XX I2C slave address */
 #define PCF21XX_SA0    0x74
 #define PCF21XX_SA1    0x76
@@ -324,7 +333,7 @@
 //ST7032 EastRising ERC1602FS-4 display
 //Contrast setting 6 significant bits
 //Voltage Multiplier setting 3 significant bits
-#define LCD_ST7032_CONTRAST 0x18
+#define LCD_ST7032_CONTRAST 0x28 
 #define LCD_ST7032_RAB      0x04
 
 //ST7036 EA DOGM1603 display
--- a/TextLCD_UDC.h	Tue Nov 25 19:21:18 2014 +0000
+++ b/TextLCD_UDC.h	Sun Mar 29 13:08:03 2015 +0000
@@ -1,4 +1,4 @@
-/* mbed TextLCD Library, for a 4-bit LCD based on HD44780
+/* mbed TextLCD Library, for LCDs based on HD44780 controllers
  * Copyright (c) 2014, WH
  *               2014, v01: WH, Extracted from TextLCD.h as of v14
  *
--- a/TextLCD_UDC.inc	Tue Nov 25 19:21:18 2014 +0000
+++ b/TextLCD_UDC.inc	Sun Mar 29 13:08:03 2015 +0000
@@ -1,4 +1,4 @@
-/* mbed TextLCD Library, for a 4-bit LCD based on HD44780
+/* mbed TextLCD Library, for LCDs based on HD44780 controllers
  * Copyright (c) 2014, WH
  *               2014, v01: WH, Extracted from TextLCD.cpp as of v14
  *