Demonstration of SSD1308 OLED driver library

Dependencies:   mbed SSD1308_128x64_I2C

Revision:
2:d86478c0f5da
Parent:
1:00053cb70ac5
Child:
3:1337e3d65ed0
--- a/SSD1308.cpp	Sat Jun 30 14:44:39 2012 +0000
+++ b/SSD1308.cpp	Mon Jul 09 20:46:27 2012 +0000
@@ -3,11 +3,11 @@
 //   The SSD1308 is used for example in the Seeed 128x64 OLED Display
 //   http://www.seeedstudio.com/depot/grove-oled-display-12864-p-781.html?cPath=163_167
 //
-// The original code is using (and submitted as a part of) Jeff Rowberg's I2Cdevlib library,
+// The original code is using (and has been submitted as a part of) Jeff Rowberg's I2Cdevlib library,
 // which should (hopefully) always be available at https://github.com/jrowberg/i2cdevlib
 //
 // Changelog:
-//   2011-08-25 - initial release by Andrew Schamp <schamp@gmail.com>
+//   2011-08-25 - Initial release by Andrew Schamp <schamp@gmail.com>
 //   2012-06-19 - Ported to mbed and optimised (WH)
 //       
 /* ============================================
@@ -64,6 +64,7 @@
 #if(0)
 // Standard version
 void SSD1308::clearDisplay() {
+ 
   //setDisplayOff();
   setPageAddress(0, MAX_PAGE);  // all pages
   setColumnAddress(0, MAX_COL); // all columns
@@ -74,7 +75,7 @@
     }
   }
 
-//  setDisplayOn();
+  //setDisplayOn();
 }
 #else
 //Optimised version
@@ -96,7 +97,7 @@
   }
   _i2c.stop();
 
-//  setDisplayOn();
+  //setDisplayOn();
 }
 #endif
 
@@ -116,7 +117,7 @@
     }
   }
  
-  //  setDisplayOn();  
+  //setDisplayOn();  
 }
 #else
 //Optimised version
@@ -137,12 +138,13 @@
   }
   _i2c.stop();
 
-//  setDisplayOn();
+  //setDisplayOn();
 }
 #endif
 
 
 void SSD1308::writeBitmap(int len, uint8_t* data) {
+
   //setDisplayOff();
   setPageAddress(0, MAX_PAGE);  // all pages
   setColumnAddress(0, MAX_COL); // all columns
@@ -155,24 +157,35 @@
   }
   _i2c.stop();
 
-//  setDisplayOn();
+  //setDisplayOn();
 }
 
-void SSD1308::writeChar(char chr) {
-//#ifdef SSD1308_USE_FONT
+
+// Write single character to the display using the 8x8 fontable
+// Start at current cursor location
+//     char chr character
+//     bool inverted invert pixels
+void SSD1308::writeChar(char chr, bool inverted) {
 
   const uint8_t char_index = chr - 0x20;
   for (uint8_t i = 0; i < 8; i++) {
 //     const uint8_t b = pgm_read_byte( &fontData[char_index][i] );
 //     const uint8_t b = fontData[char_index][i];     
 //     sendData( b ); 
-     sendData( fontData[char_index][i] );      
+     if (inverted) {
+       sendData( ~fontData[char_index][i] );           
+     }
+     else {
+       sendData( fontData[char_index][i] );
+     }  
   }
 
-//#endif
 }
 
-void SSD1308::writeString(uint8_t row, uint8_t col, uint16_t len, const char * text) {
+
+// Write a string to the display using the 8x8 fontable
+// Start at current cursor location
+void SSD1308::writeString(uint8_t row, uint8_t col, uint16_t len, const char * text, bool inverted) {
   uint16_t index = 0;
   setPageAddress(row, MAX_PAGE);
   const uint8_t col_addr = FONT_WIDTH*col;
@@ -180,7 +193,7 @@
 
   while ((col+index) < CHARS && (index < len)) {
      // write first line, starting at given position
-     writeChar(text[index++]);
+     writeChar(text[index++], inverted);
   }
 
   // write remaining lines
@@ -191,7 +204,7 @@
     setColumnAddress(0, MAX_COL);
     bool wrapEntireScreen = false;
     while (index + 1 < len) {
-       writeChar(text[index++]);
+       writeChar(text[index++], inverted);
        // if we've written the last character space on the screen, 
        // reset the page and column address so that it wraps around from the top again
        if (!wrapEntireScreen && (row*CHARS + col + index) > 127) {
@@ -203,6 +216,8 @@
   }
 }
 
+// Write command that has no parameters
+// 
 void SSD1308::sendCommand(uint8_t command) {
 //  I2Cdev::writeByte(m_devAddr, COMMAND_MODE, command);
 
@@ -214,10 +229,55 @@
 
 }
 
+// Write command that has one parameter
+// 
+void SSD1308::sendCommand(uint8_t command, uint8_t param1) {
+
+//  Note continuationbit is set, so COMMAND_MODE must be
+//  repeated before each databyte that serves as parameter!
+
+  _i2c.start();
+  _i2c.write(_writeOpcode);
+  
+  _i2c.write(COMMAND_MODE);      
+  _i2c.write(command);       // Write Command   
+  _i2c.write(COMMAND_MODE);      
+  _i2c.write(param1);        // Write Param1   
+
+  _i2c.stop();
+  
+}
+
+// Write command that has two parameters
+// 
+void SSD1308::sendCommand(uint8_t command, uint8_t param1, uint8_t param2) {
+
+//  Note continuationbit is set, so COMMAND_MODE must be
+//  repeated before each databyte that serves as parameter!
+
+  _i2c.start();
+  _i2c.write(_writeOpcode);
+  
+  _i2c.write(COMMAND_MODE);      
+  _i2c.write(command);       // Write Command   
+  _i2c.write(COMMAND_MODE);      
+  _i2c.write(param1);        // Write Param1   
+  _i2c.write(COMMAND_MODE);      
+  _i2c.write(param2);        // Write Param2   
+
+  _i2c.stop();
+  
+}
+
+
+
+// Write command that has multiple parameters
+// 
 void SSD1308::sendCommands(uint8_t len, uint8_t* commands) {
 
 //  I2Cdev::writeBytes(m_devAddr, COMMAND_MODE, len, commands);
-//  Note this original code is not correct, continuationbit is set!
+//  Note this original code is not correct, continuationbit is set, 
+//  so COMMAND_MODE must be repeated before each databyte that serves as parameter!
 
   _i2c.start();
   _i2c.write(_writeOpcode);
@@ -230,6 +290,8 @@
   
 }
 
+// Write databyte to display
+// Start at current cursor location
 void SSD1308::sendData(uint8_t data){
 //  I2Cdev::writeByte(m_devAddr, DATA_MODE, data);
 
@@ -241,6 +303,8 @@
   
 }
 
+// Write len bytes from buffer data to display
+// Start at current cursor location
 void SSD1308::sendData(uint8_t len, uint8_t* data) {
 //  I2Cdev::writeBytes(m_devAddr, DATA_MODE, len, data);
   
@@ -284,10 +348,22 @@
 }
 
 
+// takes one byte, 0x00 (lowest) - 0xFF (highest)
+void SSD1308::setContrastControl(uint8_t contrast) {
+//  uint8_t cmds[2] = { SET_CONTRAST, contrast };
+//  sendCommands(2, cmds); 
+  
+    sendCommand(SET_CONTRAST, contrast);  
+} 
+
+// Enable Display
+// 
 void SSD1308::setDisplayOn() {
   sendCommand(SET_DISPLAY_POWER_ON);
 }
 
+// Disable Display
+// 
 void SSD1308::setDisplayOff() {
   sendCommand(SET_DISPLAY_POWER_OFF);
 }
@@ -300,27 +376,81 @@
   }
 }
 
+// White on Black background
+// 
 void SSD1308::setDisplayNormal() {
   sendCommand(SET_NORMAL_DISPLAY);
 }
 
-
+// Black on White background
+// 
 void SSD1308::setDisplayInverse() {
   sendCommand(SET_INVERSE_DISPLAY);
 }
 
 
+// Display Flip (Left/Right, Up/Down)
+// 
+void SSD1308::setDisplayFlip(bool left, bool down) {
+  if (left) {
+    // column address   0 is mapped to SEG0 (Reset)    
+    sendCommand(SET_SEGMENT_REMAP_0);
+  }
+  else {
+    // column address 127 is mapped to SEG0    
+    sendCommand(SET_SEGMENT_REMAP_127);
+  }  
+
+  if (down) {
+    // Reset mode
+    sendCommand(SET_COMMON_REMAP_0);    
+  }
+  else {
+    // Flip Up/Down (Need to rewrite display before H effect shows)
+    sendCommand(SET_COMMON_REMAP_63);        
+  }  
+
+}
+
+// Sets Internal Iref
+//
+void SSD1308::setInternalIref() {
+  uint8_t cmds[2] = {SET_IREF_SELECTION, INTERNAL_IREF};
+  sendCommands(2, cmds); 
+}
+
+// Sets External Iref
+//
+void SSD1308::setExternalIref() {
+  uint8_t cmds[2] = {SET_IREF_SELECTION, EXTERNAL_IREF};
+  sendCommands(2, cmds); 
+}
+
+
 // Low level Init
 // Init the configuration registers in accordance with the datasheet
 //
 void SSD1308::_init() {
+
+//not complete yet  
+  sendCommand(SET_DISPLAY_POWER_OFF);
+  
+  // column address   0 is mapped to SEG0 (Reset)    
+  // row address   0 is mapped to COMM0 (Reset)      
+  sendCommand(SET_SEGMENT_REMAP_0);
+  sendCommand(SET_COMMON_REMAP_0);    
+  
+  uint8_t cmds[2] = { SET_COMMON_CONF, COMMON_BASE | COMMON_ALTERNATIVE | COMMON_LEFTRIGHT_NORMAL};
+  sendCommands(2, cmds); 
+
   setHorizontalAddressingMode();
-  clearDisplay();
   
-  sendCommand(SET_DISPLAY_POWER_OFF);
+  setExternalIref();
     
   sendCommand(SET_NORMAL_DISPLAY);  
   
-  sendCommand(SET_DISPLAY_POWER_ON);  
+  clearDisplay();   
+  
+  sendCommand(SET_DISPLAY_POWER_ON);
 }