Rod Coleman / I2CTextLCD
Revision:
9:16c12a5da0ac
Parent:
8:4816fdd57607
--- a/I2CTextLCD.cpp	Thu Dec 01 13:34:17 2011 +0000
+++ b/I2CTextLCD.cpp	Tue Oct 15 10:44:20 2013 +0000
@@ -10,32 +10,6 @@
 
 using namespace mbed;
 
-/*
-     * useful info found at http://www.a-netz.de/lcd.en.php
-     *
-     *
-     * Initialisation
-     * ==============
-     *
-     * After attaching the supply voltage/after a reset, the display needs to be brought in to a defined state
-     *
-     * - wait approximately 15 ms so the display is ready to execute commands
-     * - Execute the command 0x30 ("Display Settings") three times (wait 1,64ms after each command, the busy flag cannot be queried now).
-     * - The display is in 8 bit mode, so if you have only connected 4 data pins you should only transmit the higher nibble of each command.
-     * - If you want to use the 4 bit mode, now you can execute the command to switch over to this mode now.
-         * - Execute the "clear display" command
-     *
-     * Timing
-     * ======
-     *
-     * Nearly all commands transmitted to the display need 40us for execution.
-     * Exceptions are the commands "Clear Display and Reset" and "Set Cursor to Start Position"
-     * These commands need 1.64ms for execution. These timings are valid for all displays working with an
-     * internal clock of 250kHz. But I do not know any displays that use other frequencies. Any time you
-     * can use the busy flag to test if the display is ready to accept the next command.
-     *
-     */
-
 I2CTextLCD::I2CTextLCD(PinName sda, PinName scl, int i2cAddress , int columns, int rows,
                        bool backlight) : _i2c(sda, scl) {
 
@@ -44,52 +18,33 @@
     _rows = rows;
     _backlight=backlight;
     _i2c.frequency(70000); //  RC:2011-12-1 put this back in
- // Winstar 20x4 WH2004-NYG- needs 40ms after VDD> 4,5V
-    /*
-    wait(0.5);
-    writeCommand(0x2); // 4-bit mode
-    wait(0.05);
-    writeCommand(0x28);    // Function set 001 BW N F - -
-    wait(0.05);
-    */
+
+    // Winstar 20x4 WH2004-NYG- needs 40ms after VDD> 4,5V
     //RC:2011-11-23: Newhaven 20x4 OLED data sheet method
-    writeCommand(0x2); // 4-bit mode
+    wait(0.055);
+    init8574A();         // I2C chip PCF85774A init - E high - E falls with 0x2 on the D-nibble (set 4-bit mode command)
+    writeCommand(0x2);   // 4-bit mode
     wait(0.05);
-    writeCommand(0x2); // 4-bit mode
+    writeCommand(0x2);   // 4-bit mode
     wait(0.05);
-    writeCommand(0x28); // display OFF, "Function Set". Newhaven say 0x08, but this loses 2 rows!
+    writeCommand(0x2A);  // 2012-6-22 RC: Russian font Table. was 0x28. display OFF, "Function Set". Newhaven say 0x08, but this loses 2 rows!
     wait(0.05); 
-    writeCommand(0x1); // display clear
+    writeCommand(0x1);  // display clear
     wait(0.05);
-    writeCommand(0x6); // entry mode set
+    writeCommand(0x6);  // entry mode set
     wait(0.05); 
-    writeCommand(0x2); // 4-bit mode
+    writeCommand(0x2);  // 4-bit mode
     wait(0.05);                  
     writeCommand(0x0C); // ON-OFF ctrl: turns display ON, no cursor. Use 0x0E for cursor ON.
-    /* 0x28 also works for Winstar WEH002004ALPP5N00000 OLED display. 0x29= westEuro fon table, 0x2A = UK/Russian
-*/
-    // Added RC 2011-8-11
-    /*
-    writeCommand(0x05); // clear display RAM all to 00
-    wait(0.05);        // 6.2ms specified for OLED display to recover from RAM clear
-    
-    writeCommand(0x06);  //  Entry mode Set. Cursor Direction and Display Shift : 0000 01 CD S (CD 0-left, 1-right S(hift) 0-no, 1-yes
-    wait(0.05); 
-   writeCommand(0x14);  // OLED display shift disable etc
-    wait(0.05);
-    writeCommand(0x17);  // disable graphic mode, power ON
-    //cls();
-    wait(0.05);
-    writeCommand (0x01);  //clear entire display.
-    wait(0.07);
-*/
-
+    /* 0x28 also works for Winstar WEH002004ALPP5N00000 OLED display. 0x29= westEuro fon table, 0x2A = UK/Russian*/
+    wait(0.015);        // Wait 15ms to ensure powered up
 }
 
 int I2CTextLCD::_putc(int value) {
     if (value == '\n') {
         newline();
-    } else {
+    } 
+    else {
         writeData(value);
     }
     return value;
@@ -155,51 +110,41 @@
 void I2CTextLCD::reset() {
     cls();
 }
-
-void I2CTextLCD::writeByte(int c, bool rs) {  // This is the actual I2C transfer of the display data:
-        char cmd[2]; //led = 1;
-        cmd[0]=c>>2;                  // upper nibble
-        cmd[0]=cmd[0] & 0x3c;         // mask out bits other than 5:2 for data (RS and E are enabled separately, below:)
-        cmd[1]=c<<2;                 // lower nibble
-        cmd[1]=cmd[1] & 0x3c;
-        if (rs) {
-        cmd[0]=cmd[0] | 0x01;        // RS selects display DATA or a COMMAND. It's on bit 0:
-        cmd[1]=cmd[1] | 0x01;
-        }
-        _i2c.write( _i2cAddress,cmd,1); // E=0, write upper nibble. E's on bit 1!
-        wait_us(1);
+void I2CTextLCD::init8574A(void) {  // This puts the first command on the bus with E high
+                                    // to prevent E going LOW at init with undef data lines, WS0010 does not like.
+        char cmd[2]; 
+        cmd[0]=(0x2)<<2;                 // lower nibble
+        cmd[0]=cmd[0] & 0x3c; // 3C = 0011 1100
+        //RS = 0 for commands - and for init (only), we start with E high
         cmd[0]=cmd[0]|0x02; //E=1
         _i2c.write( _i2cAddress, cmd,1); 
-        wait_us(1);
         cmd[0]=cmd[0]&0x3d; //E=0, RS preserved in bit 0
         _i2c.write( _i2cAddress, cmd,1); 
         wait_us(1);
-        cmd[0]=cmd[1]; //E=0, write lower nibble
-        wait_us(1);
+    }
+void I2CTextLCD::writeByte(int c, bool rs) {  // This is the actual I2C transfer of the display data:
+        char cmd[2]; 
+        cmd[0]=c>>2;                  // upper nibble
+        cmd[0]=cmd[0] & 0x3c;         // mask out bits other than 5:2 for data (RS and E are enabled separately, below:)
+        cmd[1]=c<<2;                 // lower nibble
+        cmd[1]=cmd[1] & 0x3c;        // 3C = 0011 1100
+        if (rs) {
+            cmd[0]=cmd[0] | 0x01;        // RS selects display DATA or a COMMAND. It's on bit 0:
+            cmd[1]=cmd[1] | 0x01;
+        }
         cmd[0]=cmd[0]|0x02; //E=1
         _i2c.write( _i2cAddress, cmd,1); 
-        wait_us(1);
-        cmd[0]=cmd[0]&0x3d; //E=0, RS preserved in bit 0
+        //wait_us(1); **  delays between nibbles not needed. At 70kHz, the time for the I2C command writes is 114us per byte
+        cmd[0]=cmd[0]&0x3d; //E=0, RS preserved in bit 0. Data latched on fall of E (tS(d) = 40ns; tH(d) = 20ns)
+        _i2c.write( _i2cAddress, cmd,1); 
+        cmd[0]=cmd[1];         // prepare lower nibble
+        cmd[0]=cmd[0]|0x02;    //E=1
+        _i2c.write( _i2cAddress, cmd,1); 
+        cmd[0]=cmd[0]&0x3d;    //E=0, RS preserved in bit 0. this preserves E low beween cycles.
         _i2c.write( _i2cAddress, cmd,1);
-        _i2c.write ( _i2cAddress,cmd,1);              
-        // led = 0;
-        wait_us(1);
+        // ****** RECOVERY TIME:
+        wait_us(300);         // specified max. recovery time for all operations, except cls(), is 600us
     }
- // This is the original authors method:
-    //void I2CTextLCD::writeByte(int data, bool rs) {
-
-
-/*
-    writeNibble(data >> 4 , rs);
-    writeNibble(data >> 0 , rs);
-    RC 2011-8-11. change to d4..d7 - PCF8574 ports P2 .. P5
-*/
-//data = data>>2;
-//data = data & 0x3c;
-//writeNibble(data , rs);
-//data = data<<2;
-//data = data & 0x3c;
-//writeNibble(data , rs);
 
 void I2CTextLCD::writeCommand(int command) {
     // RS = 0;
@@ -214,17 +159,4 @@
     if (_column >= _columns) {
         newline();
     }
-}
-
-/* void I2CTextLCD::writeI2CByte(int data) {
-    char cmd[2];
-    cmd[0] = (data & 0xFF);
-    cmd[1] = (data >> 8);
-     _i2c.write(_i2cAddress, cmd, 2);
-*/
-
-
-
-
-
-
+}
\ No newline at end of file