Addition Support for Arduino I2C based on PCF8574A

Fork of TextLCD by Wim Huiskamp

Files at this revision

API Documentation at this revision

Comitter:
wim
Date:
Sat Mar 02 16:51:01 2013 +0000
Parent:
16:c276b75e6585
Child:
18:bd65dc10f27f
Commit message:
Added support for Display On/Off. Improved 4bit bootprocess.

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
--- a/TextLCD.cpp	Wed Feb 20 19:37:53 2013 +0000
+++ b/TextLCD.cpp	Sat Mar 02 16:51:01 2013 +0000
@@ -3,6 +3,7 @@
  *               2013, v01: WH, Added LCD types, fixed LCD address issues, added Cursor and UDCs 
  *               2013, v02: WH, Added I2C and SPI bus interfaces  
  *               2013, v03: WH, Added support for LCD40x4 which uses 2 controllers 
+ *               2013, v04: WH, Added support for Display On/Off, improved 4bit bootprocess 
  *
  * Permission is hereby granted, free of charge, to any person obtaining a copy
  * of this software and associated documentation files (the "Software"), to deal
@@ -151,6 +152,18 @@
     
     wait_ms(20);        // Wait 20ms to ensure powered up
 
+#if(1)
+    // send "Display Settings" 3 times (Only top nibble of 0x30 as we've got 4-bit bus)    
+    for (int i=0; i<3; i++) {
+        _writeNibble(0x3);
+        wait_ms(15);     // this command takes 1.64ms, so wait for it 
+    }
+    _writeNibble(0x2);   // 4-bit mode
+    wait_us(40);         // most instructions take 40us
+#else
+//Original code. Does not comply with specification and causes problems
+//unless used right after power-on.
+
     // send "Display Settings" 3 times (Only top nibble of 0x30 as we've got 4-bit bus)
     for (int i=0; i<3; i++) {
         _writeByte(0x3);
@@ -158,6 +171,7 @@
     }
     _writeByte(0x2);     // 4-bit mode
     wait_us(40);         // most instructions take 40us
+#endif
     
     // Display is now in 4-bit mode
     switch (_type) {
@@ -214,9 +228,9 @@
                          //   S=0  (No display shift)                        
 
 //    _writeCommand(0x0C); // Display Ctrl 0000 1 D C B
-//                         //   Display On, Cursor Off, Blink Off
+//                         //   Display On, Cursor Off, Blink Off   
     setCursor(TextLCD::CurOff_BlkOff);     
-
+    setMode(TextLCD::DispOn);     
 }
 
 
@@ -228,7 +242,7 @@
     _ctrl=TextLCD::_LCDCtrl_1; // Select 2nd controller
 
     // Second LCD controller Cursor always Off
-    _setCursor(TextLCD::CurOff_BlkOff);
+    _setCursorAndDisplayMode(_currentMode, TextLCD::CurOff_BlkOff);
 
     // Second LCD controller Clearscreen
     _writeCommand(0x01); // cls, and set cursor to 0    
@@ -248,7 +262,7 @@
 
   // Restore cursormode on primary LCD controller when needed
   if(_type==LCD40x4) {
-    _setCursor(_currentCursor);
+    _setCursorAndDisplayMode(_currentMode,_currentCursor);     
   }
                    
   _row=0;          // Reset Cursor location
@@ -499,6 +513,22 @@
 }
 
 
+// Write a nibble using the 4-bit interface
+// Used for mbed pins, I2C bus expander or SPI shifregister
+void TextLCD::_writeNibble(int value) {
+
+// Enable is Low
+    _setEnable(true);        
+    _setData(value & 0x0F);   // Low nibble
+    wait_us(1); // Data setup time        
+    _setEnable(false);    
+    wait_us(1); // Datahold time
+
+// Enable is Low
+
+}
+
+
 // Write a byte using the 4-bit interface
 // Used for mbed pins, I2C bus expander or SPI shifregister
 void TextLCD::_writeByte(int value) {
@@ -656,14 +686,15 @@
           if (row<2) { 
             // Test to see if we need to switch between controllers  
             if (_ctrl != _LCDCtrl_0) {
+
               // Second LCD controller Cursor Off
-              _setCursor(TextLCD::CurOff_BlkOff);
+              _setCursorAndDisplayMode(_currentMode, TextLCD::CurOff_BlkOff);    
 
               // Select primary controller
               _ctrl = _LCDCtrl_0;
 
               // Restore cursormode on primary LCD controller
-              _setCursor(_currentCursor);
+              _setCursorAndDisplayMode(_currentMode, _currentCursor);    
             }           
             
             return 0x00 + (row * 0x40) + column;          
@@ -673,13 +704,13 @@
             // Test to see if we need to switch between controllers  
             if (_ctrl != _LCDCtrl_1) {
               // Primary LCD controller Cursor Off
-              _setCursor(TextLCD::CurOff_BlkOff);
+              _setCursorAndDisplayMode(_currentMode, TextLCD::CurOff_BlkOff);    
 
               // Select secondary controller
               _ctrl = _LCDCtrl_1;
 
               // Restore cursormode on secondary LCD controller
-              _setCursor(_currentCursor);
+              _setCursorAndDisplayMode(_currentMode, _currentCursor);    
             }           
                                    
             return 0x00 + ((row-2) * 0x40) + column;          
@@ -784,37 +815,66 @@
 }
 
 
-void TextLCD::setCursor(TextLCD::LCDCursor show) { 
+// Set the Cursor Mode (Cursor Off & Blink Off, Cursor On & Blink Off, Cursor Off & Blink On, Cursor On & Blink On
+void TextLCD::setCursor(TextLCD::LCDCursor cursorMode) { 
 
-  // Save new cursor mode, needed when 2 controllers are in use
-  _currentCursor = show;
+  // Save new cursor mode, needed when 2 controllers are in use or when display is switched off/on
+  _currentCursor = cursorMode;
     
-  // Configure current LCD controller
-  _setCursor(_currentCursor);
+  // Configure only current LCD controller
+  _setCursorAndDisplayMode(_currentMode, _currentCursor);
     
 }
 
-void TextLCD::_setCursor(TextLCD::LCDCursor show) { 
+// Set the Displaymode (On/Off)
+void TextLCD::setMode(TextLCD::LCDMode displayMode) { 
+
+  // Save new displayMode, needed when 2 controllers are in use or when cursor is changed
+  _currentMode = displayMode;
     
-    // Configure current LCD controller    
-    switch (show) {
-      case CurOff_BlkOff : _writeCommand(0x0C); // Cursor off and Blink Off
-                           break;
+  // Select and configure second LCD controller when needed
+  if(_type==LCD40x4) {
+    if (_ctrl==TextLCD::_LCDCtrl_0) {
+      // Configure primary LCD controller
+      _setCursorAndDisplayMode(_currentMode, _currentCursor);
 
-      case CurOn_BlkOff :  _writeCommand(0x0E); // Cursor on and Blink Off
-                           break;
+      // Select 2nd controller
+      _ctrl=TextLCD::_LCDCtrl_1;
+  
+      // Configure secondary LCD controller    
+      _setCursorAndDisplayMode(_currentMode, TextLCD::CurOff_BlkOff);
 
-      case CurOff_BlkOn :  _writeCommand(0x0D); // Cursor off and Blink On
-                           break;
+      // Restore current controller
+      _ctrl=TextLCD::_LCDCtrl_0;       
+    }
+    else {
+      // Select primary controller
+      _ctrl=TextLCD::_LCDCtrl_0;
+    
+      // Configure primary LCD controller
+      _setCursorAndDisplayMode(_currentMode, TextLCD::CurOff_BlkOff);
+       
+      // Restore current controller
+      _ctrl=TextLCD::_LCDCtrl_1;
 
-      case CurOn_BlkOn  :  _writeCommand(0x0F); // Cursor on and Blink char
-                           break;
+      // Configure secondary LCD controller    
+      _setCursorAndDisplayMode(_currentMode, _currentCursor);
 
-// Should never get here.
-      default : 
-                           break;
-                     
     }
+  }
+  else {
+    // Configure primary LCD controller
+    _setCursorAndDisplayMode(_currentMode, _currentCursor);
+  }   
+    
+}
+
+
+// Set the Displaymode (On/Off) and Cursortype for current controller
+void TextLCD::_setCursorAndDisplayMode(TextLCD::LCDMode displayMode, TextLCD::LCDCursor cursorType) { 
+    
+    // Configure current LCD controller       
+    _writeCommand(0x08 | displayMode | cursorType);
 }
 
 
--- a/TextLCD.h	Wed Feb 20 19:37:53 2013 +0000
+++ b/TextLCD.h	Sat Mar 02 16:51:01 2013 +0000
@@ -3,6 +3,7 @@
  *               2013, v01: WH, Added LCD types, fixed LCD address issues, added Cursor and UDCs 
  *               2013, v02: WH, Added I2C and SPI bus interfaces
  *               2013, v03: WH, Added support for LCD40x4 which uses 2 controllers   
+ *               2013, v04: WH, Added support for Display On/Off, improved 4bit bootprocess  
  *
  * Permission is hereby granted, free of charge, to any person obtaining a copy
  * of this software and associated documentation files (the "Software"), to deal
@@ -85,7 +86,6 @@
 #define D_LCD_BL       (1<<D_LCD_PIN_BL)
 
 
-
 /** Some sample User Defined Chars 5x7 dots */
 const char udc_ae[] = {0x00, 0x00, 0x1B, 0x05, 0x1F, 0x14, 0x1F, 0x00};  //æ
 const char udc_0e[] = {0x00, 0x00, 0x0E, 0x13, 0x15, 0x19, 0x0E, 0x00};  //ø
@@ -150,10 +150,17 @@
 
     /** LCD Cursor control */
     enum LCDCursor {
-        CurOff_BlkOff,  /**<  Cursor Off, Blinking Char Off */    
-        CurOn_BlkOff,   /**<  Cursor On, Blinking Char Off */    
-        CurOff_BlkOn,   /**<  Cursor Off, Blinking Char On */    
-        CurOn_BlkOn,    /**<  Cursor On, Blinking Char On */    
+        CurOff_BlkOff = 0x00,  /**<  Cursor Off, Blinking Char Off */    
+        CurOn_BlkOff  = 0x02,  /**<  Cursor On, Blinking Char Off */    
+        CurOff_BlkOn  = 0x01,  /**<  Cursor Off, Blinking Char On */    
+        CurOn_BlkOn   = 0x03   /**<  Cursor On, Blinking Char On */    
+    };
+
+
+    /** LCD Display control */
+    enum LCDMode {
+        DispOff = 0x00,  /**<  Display Off */    
+        DispOn  = 0x04   /**<  Display On */            
     };
 
 
@@ -242,9 +249,16 @@
 
     /** Set the Cursormode
      *
-     * @param show    The Cursor mode (CurOff_BlkOff, CurOn_BlkOff, CurOff_BlkOn, CurOn_BlkOn)
+     * @param cursorMode  The Cursor mode (CurOff_BlkOff, CurOn_BlkOff, CurOff_BlkOn, CurOn_BlkOn)
      */
-    void setCursor(LCDCursor show);     
+    void setCursor(LCDCursor cursorMode);     
+    
+
+    /** Set the Displaymode
+     *
+     * @param displayMode The Display mode (DispOff, DispOn)
+     */
+    void setMode(TextLCD::LCDMode displayMode);     
 
 
     /** Set User Defined Characters
@@ -277,9 +291,11 @@
     void _initCtrl();    
     int  _address(int column, int row);
     void _setCursor(TextLCD::LCDCursor show);
-    void _setUDC(unsigned char c, char *udc_data);     
+    void _setUDC(unsigned char c, char *udc_data);   
+    void _setCursorAndDisplayMode(TextLCD::LCDMode displayMode, TextLCD::LCDCursor cursorType);       
     
 //Low level write operations to LCD controller
+    void _writeNibble(int value);
     void _writeByte(int value);
     void _writeCommand(int command);
     void _writeData(int data);
@@ -315,6 +331,9 @@
 //Display type
     LCDType _type;
 
+//Display type
+    LCDMode _currentMode;
+
 //Controller select, mainly used for LCD40x4 
     _LCDCtrl _ctrl;