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

Revision:
4:df92b0c0cb92
Parent:
2:16c84a134393
Child:
5:e564cde8e03e
--- 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 
 }