SSD1308 128x64 OLED Driver with I2C interface

Dependents:   sense xadow_m0_ada_gps xadow_m0_SD_Hello sense-DHT11 ... more

See http://mbed.org/users/wim/notebook/oled-display-with-ssd1308-driver/#c6729

Files at this revision

API Documentation at this revision

Comitter:
wim
Date:
Thu Jan 01 17:53:40 2015 +0000
Parent:
3:fa18169dd7e6
Child:
5:e564cde8e03e
Commit message:
Added option to select optimisation using low level I2C methods. Used for testing on F401 and LPC1768.

Changed in this revision

SSD1308.cpp Show annotated file Show diff for this revision Revisions of this file
SSD1308.h Show annotated file Show diff for this revision Revisions of this file
--- a/SSD1308.cpp	Mon Jul 23 20:24:11 2012 +0000
+++ b/SSD1308.cpp	Thu Jan 01 17:53:40 2015 +0000
@@ -12,12 +12,14 @@
 // Changelog:
 //   2011-08-25 - Initial release by Andrew Schamp <schamp@gmail.com>
 //   2012-06-19 - Ported to mbed and optimised (WH)
+//   2013-07-12 - Minor comment fix and placeholder for SSD1306 (WH)
+//   2015-01-01 - Switch for optimised I2C calls to test on F401 (WH)
 //       
-/*
+/* 
 ================================================================================
 I2Cdev device library code is placed under the MIT license
 Copyright (c) 2011 Andrew Schamp
-Copyright (c) 2012 WH (mbed port)
+Copyright (c) 2012,2013 WH (mbed port)
 
 Permission is hereby granted, free of charge, to any person obtaining a copy
 of this software and associated documentation files (the "Software"), to deal
@@ -49,6 +51,12 @@
 //#include "font_16x20.h"
 #include "font_16x24.h"
 
+#if defined(TARGET_LPC1768)
+#define I2C_OPTIMIZE   1
+#else
+#define I2C_OPTIMIZE   0
+#endif
+
 /**
  *@brief Constructor
  *@param I2C &i2c reference to i2c
@@ -77,7 +85,7 @@
 
 /** @brief clear the display
 */
-#if(0)
+#if (I2C_OPTIMIZE == 0)
 // Standard version
 void SSD1308::clearDisplay() {
  
@@ -120,24 +128,31 @@
 
 /** @brief fill the display
  *  @param uint8_t pattern fillpattern vertical patch or 8 bits 
+ *  @param uint8_t start_page begin page   (0..MAX_PAGE)
+ *  @param uint8_t end_page   end page     (start_page..MAX_PAGE)                     
+ *  @param uint8_t start_col  begin column (0..MAX_COL)
+ *  @param uint8_t end_col    end column   (start_col..MAX_COL)
 */
-#if(0)
+#if (I2C_OPTIMIZE == 0)
 //Standard version
-void SSD1308::fillDisplay(uint8_t pattern) {
-  
-  //setDisplayOff();  
+
+void SSD1308::fillDisplay(uint8_t pattern,
+                          uint8_t start_page, uint8_t end_page,
+                          uint8_t start_col, uint8_t end_col) {
   
-  setPageAddress(0, MAX_PAGE);  // all pages
-  setColumnAddress(0, MAX_COL); // all columns
+  int count = (end_page - start_page + 1) * (end_col - start_col + 1);
+  
+  //setDisplayOff();
+  setPageAddress(start_page, end_page);  // set page window
+  setColumnAddress(start_col, end_col);  // set column window
+ 
+  for (int i=0; i<count; i++) {
+    _sendData(pattern); // Write Data    
+  }
 
-  for (uint8_t page = 0; page < PAGES; page++) {
-    for (uint8_t col = 0; col < COLUMNS; col++) {
-      _sendData(pattern); 
-    }
-  }
- 
-  //setDisplayOn();  
+  //setDisplayOn();
 }
+
 #else
 
 //Optimised version
@@ -175,26 +190,26 @@
  *  @param uint8_t start_col  begin column (0..MAX_COL)
  *  @param uint8_t end_col    end column   (start_col..MAX_COL)
 */
-#if(0)
+#if (I2C_OPTIMIZE == 0)
 //Standard version
-void SSD1308::writeBitmap(int len, uint8_t* data) {
+void SSD1308::writeBitmap(uint8_t* data,
+                          uint8_t start_page, uint8_t end_page,
+                          uint8_t start_col, uint8_t end_col){
+  
+  int count = (end_page - start_page + 1) * (end_col - start_col + 1);
 
   //setDisplayOff();
-  setPageAddress(0, MAX_PAGE);  // all pages
-  setColumnAddress(0, MAX_COL); // all columns
+  setPageAddress(start_page, end_page);  // set page window
+  setColumnAddress(start_col, end_col);  // set column window
 
-  _i2c.start();
-  _i2c.write(_writeOpcode);
-  _i2c.write(DATA_MODE);  
-  for (int i=0; i<len; i++) {
-    _i2c.write(data[i]);  // Write Data   
+  for (int i=0; i<count; i++) {
+    _sendData(data[i]); // Write Data   
   }
-  _i2c.stop();
 
   //setDisplayOn();
 }
+
 #else
-
 //Optimised version
 // Save lots of I2C S,P, address and datacommands:
 // Send S, address, DATA_MODE, data, data, data,...., P
@@ -219,6 +234,7 @@
 
   //setDisplayOn();
 }
+
 #endif
 
 
@@ -234,7 +250,7 @@
 //#define PRG_ACTIVE      0xBD
 #define PRG_NOT_ACTIVE  0x81
 
-#if(0)
+#if (I2C_OPTIMIZE == 0)
 //Standard version
 void SSD1308::writeProgressBar(uint8_t page, uint8_t col, int percentage) {
   uint8_t scale_value;
@@ -319,6 +335,40 @@
  *  @param uint8_t col  begin column (0..MAX_COL)
  *  @param int percentage value      (0..100)
 */
+#if (I2C_OPTIMIZE == 0)
+void SSD1308::writeLevelBar(uint8_t page, uint8_t col, int percentage) {
+  uint8_t scale_value;
+  
+  if (percentage <= 0) {
+    scale_value = 0;
+  } else if (percentage >= 100) {
+      scale_value = PRG_MAX_SCALE - 1;
+  }
+  else {
+    scale_value = (percentage * PRG_MAX_SCALE) / 100; 
+  }      
+      
+  //setDisplayOff();
+  setPageAddress(page, page);  
+  setColumnAddress(col, MAX_COL); 
+ 
+  _sendData(PRG_LEFT_EDGE);   
+
+  for (uint8_t col = 0; col < scale_value; col++) {
+     _sendData(PRG_NOT_ACTIVE);  // Write Data                       
+  }
+
+  _sendData(PRG_ACTIVE);  // Write Data at active meterlevel
+
+  for (uint8_t col = scale_value+1; col < PRG_MAX_SCALE; col++) {
+      _sendData(PRG_NOT_ACTIVE);                
+  }
+         
+  _sendData(PRG_RIGHT_EDGE);
+    
+  //setDisplayOn();
+}
+#else
 //Optimised version
 // Save lots of I2C S,P, address and datacommands:
 // Send S, address, DATA_MODE, data, data, data,...., P
@@ -361,6 +411,7 @@
     
   //setDisplayOn();
 }
+#endif
 
 /** @brief Write single character to the display using the 8x8 fontable
  *  @brief Start at current cursor location
@@ -386,7 +437,6 @@
  *  @brief Start at selected cursor location, text will wrap around until it is done
  *  @param uint8_t row  row number    (0...ROWS/FONT_HEIGHT)
  *  @param uint8_t col  column number (0...COLUMNS/FONT_WIDTH)
- *  @param uint16_t len number of chars in text
  *  @param const char * text pointer to text
  */
 void SSD1308::writeString(uint8_t row, uint8_t col, const char * text) {
@@ -442,14 +492,14 @@
 void SSD1308::_sendCommand(uint8_t command) {
 //  I2Cdev::writeByte(m_devAddr, COMMAND_MODE, command);
 
-#if(0)
+#if (I2C_OPTIMIZE == 0)
   char databytes[2];
     
   databytes[0] = COMMAND_MODE;
   databytes[1] = command;    
   _i2c.write(_writeOpcode, databytes, 2);    // Write command   
-#endif
-  
+#else  
+
   _i2c.start();
   _i2c.write(_writeOpcode);
   
@@ -457,7 +507,7 @@
   _i2c.write(command);       // Write Command   
 
   _i2c.stop();  
-
+#endif
 }
 
 /** @brief Write command that has one parameter
@@ -466,6 +516,15 @@
 
 //  Note continuationbit is set, so COMMAND_MODE must be
 //  repeated before each databyte that serves as parameter!
+#if (I2C_OPTIMIZE == 0)
+  char databytes[4];
+    
+  databytes[0] = COMMAND_MODE;
+  databytes[1] = command;    
+  databytes[2] = COMMAND_MODE;
+  databytes[3] = param1; 
+  _i2c.write(_writeOpcode, databytes, 4);    // Write command   
+#else  
 
   _i2c.start();
   _i2c.write(_writeOpcode);
@@ -476,7 +535,7 @@
   _i2c.write(param1);        // Write Param1   
 
   _i2c.stop();
-  
+#endif  
 }
 
 /** @brief Write command that has two parameters
@@ -485,7 +544,17 @@
 
 //  Note continuationbit is set, so COMMAND_MODE must be
 //  repeated before each databyte that serves as parameter!
-
+#if (I2C_OPTIMIZE == 0)
+  char databytes[6];
+    
+  databytes[0] = COMMAND_MODE;
+  databytes[1] = command;    
+  databytes[2] = COMMAND_MODE;
+  databytes[3] = param1; 
+  databytes[4] = COMMAND_MODE;
+  databytes[5] = param2; 
+  _i2c.write(_writeOpcode, databytes, 6);    // Write command   
+#else  
   _i2c.start();
   _i2c.write(_writeOpcode);
   
@@ -497,7 +566,7 @@
   _i2c.write(param2);        // Write Param2   
 
   _i2c.stop();
-  
+ #endif 
 }
 
 /** @brief Write command that has five parameters
@@ -508,7 +577,23 @@
 
 //  Note continuationbit is set, so COMMAND_MODE must be
 //  repeated before each databyte that serves as parameter!
-
+#if (I2C_OPTIMIZE == 0)
+  char databytes[12];
+    
+  databytes[0] = COMMAND_MODE;
+  databytes[1] = command;    
+  databytes[2] = COMMAND_MODE;
+  databytes[3] = param1; 
+  databytes[4] = COMMAND_MODE;
+  databytes[5] = param2; 
+  databytes[6] = COMMAND_MODE;
+  databytes[7] = param3; 
+  databytes[8] = COMMAND_MODE;
+  databytes[9] = param4; 
+  databytes[10] = COMMAND_MODE;
+  databytes[11] = param5;       
+  _i2c.write(_writeOpcode, databytes, 12);    // Write command   
+#else  
   _i2c.start();
   _i2c.write(_writeOpcode);
   
@@ -526,7 +611,7 @@
   _i2c.write(param5);        // Write Param5   
 
   _i2c.stop();
-  
+#endif  
 }
 
 
@@ -538,7 +623,25 @@
 
 //  Note continuationbit is set, so COMMAND_MODE must be
 //  repeated before each databyte that serves as parameter!
-
+#if (I2C_OPTIMIZE == 0)
+  char databytes[14];
+    
+  databytes[0] = COMMAND_MODE;
+  databytes[1] = command;    
+  databytes[2] = COMMAND_MODE;
+  databytes[3] = param1; 
+  databytes[4] = COMMAND_MODE;
+  databytes[5] = param2; 
+  databytes[6] = COMMAND_MODE;
+  databytes[7] = param3; 
+  databytes[8] = COMMAND_MODE;
+  databytes[9] = param4; 
+  databytes[10] = COMMAND_MODE;
+  databytes[11] = param5;   
+  databytes[12] = COMMAND_MODE;
+  databytes[13] = param6;       
+  _i2c.write(_writeOpcode, databytes, 14);    // Write command   
+#else  
   _i2c.start();
   _i2c.write(_writeOpcode);
   
@@ -558,7 +661,7 @@
   _i2c.write(param6);        // Write Param6   
 
   _i2c.stop();
-  
+#endif  
 }
 
 
@@ -588,14 +691,25 @@
  *  @param uint8_t data databyte to write
 */
 void SSD1308::_sendData(uint8_t data){
-//  I2Cdev::writeByte(m_devAddr, DATA_MODE, data);
 
+#if (I2C_OPTIMIZE == 0)
+//I2C Blockwrite versions dont seem to work ?
+//That may be related to fact that the SSD1308/SSD1306 does NOT return an acknowledge: blockwrite may abort the operation
+//Noted for mbed lib v63 on 20/7/13 
   char databytes[2];
     
   databytes[0] = DATA_MODE;
   databytes[1] = data;    
   _i2c.write(_writeOpcode, databytes, 2);    // Write Data   
-  
+
+#else
+  _i2c.start();
+  _i2c.write(_writeOpcode);
+  _i2c.write(DATA_MODE);  
+  _i2c.write(data); 
+  _i2c.stop();  
+#endif
+
 }
 
 /** @brief Write len bytes from buffer data to display, 
@@ -605,7 +719,11 @@
 */
 void SSD1308::_sendData(uint8_t len, uint8_t* data) {
 //  I2Cdev::writeBytes(m_devAddr, DATA_MODE, len, data);
-  
+#if (I2C_OPTIMIZE == 0)
+  for (int i=0; i<len ; i++) {
+    _sendData(data[i]);  // Write Data   
+  }
+#else  
   _i2c.start();
   _i2c.write(_writeOpcode);
   _i2c.write(DATA_MODE);  
@@ -613,7 +731,7 @@
     _i2c.write(data[i]);  // Write Data   
   }
   _i2c.stop();
-    
+#endif 
 }
 
 
--- a/SSD1308.h	Mon Jul 23 20:24:11 2012 +0000
+++ b/SSD1308.h	Thu Jan 01 17:53:40 2015 +0000
@@ -12,11 +12,14 @@
 // Changelog:
 //   2011-08-25 - Initial release by Andrew Schamp <schamp@gmail.com>
 //   2012-06-19 - Ported to mbed and optimised (WH)
+//   2013-07-12 - Minor comment fix and placeholder for SSD1306 (WH)
+//   2015-01-01 - Switch for optimised I2C calls to test on F401 (WH)
 //             
-/* ============================================
+/* 
+================================================================================
 I2Cdev device library code is placed under the MIT license
 Copyright (c) 2011 Andrew Schamp
-Copyright (c) 2012 WH (mbed port)
+Copyright (c) 2012,2013 WH (mbed port)
 
 Permission is hereby granted, free of charge, to any person obtaining a copy
 of this software and associated documentation files (the "Software"), to deal
@@ -35,7 +38,7 @@
 LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
 OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
 THE SOFTWARE.
-===============================================
+================================================================================
 */
 
 #ifndef SSD1308_H
@@ -236,6 +239,10 @@
 
 /** @brief fill the display
  *  @param uint8_t pattern fillpattern vertical patch or 8 bits 
+ *  @param uint8_t start_page begin page   (0..MAX_PAGE)
+ *  @param uint8_t end_page   end page     (start_page..MAX_PAGE)                     
+ *  @param uint8_t start_col  begin column (0..MAX_COL)
+ *  @param uint8_t end_col    end column   (start_col..MAX_COL)
 */ 
     void fillDisplay(uint8_t pattern = 0x00,
                      uint8_t start_page=0, uint8_t end_page=MAX_PAGE,
@@ -290,10 +297,8 @@
  *  @brief Start at selected cursor location, text will wrap around until it is done
  *  @param uint8_t row  row number    (0...ROWS/FONT_HEIGHT)
  *  @param uint8_t col  column number (0...COLUMNS/FONT_WIDTH)
- *  @param uint16_t len number of chars in text
  *  @param const char * text pointer to text
  */   
-//    void writeString(uint8_t row, uint8_t col, uint16_t len, const char* txt);
     void writeString(uint8_t row, uint8_t col, const char* txt);
     
     // Stream implementation - provides printf() interface