Library for Modtronix im4OLED board with 128x64 OLED and 4 buttons. For details, see product page http://modtronix.com/im4oled.html. Is a clone of Adafruit_GFX library, with some additional code added.

Fork of Adafruit_GFX by Neal Horman

Revision:
22:f63aeb3769b5
Child:
23:44309099c532
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/mx_ssd1306.cpp	Tue Oct 20 17:18:02 2015 +1100
@@ -0,0 +1,452 @@
+/*********************************************************************
+This is a library for our Monochrome OLEDs based on SSD1306 drivers
+
+  Pick one up today in the adafruit shop!
+  ------> http://www.adafruit.com/category/63_98
+
+These displays use SPI to communicate, 4 or 5 pins are required to  
+interface
+
+Adafruit invests time and resources providing this open source code, 
+please support Adafruit and open-source hardware by purchasing 
+products from Adafruit!
+
+Written by Limor Fried/Ladyada  for Adafruit Industries.  
+BSD license, check license.txt for more information
+All text above, and the splash screen below must be included in any redistribution
+*********************************************************************/
+
+/*
+ *  Modified by Neal Horman 7/14/2012 for use in mbed
+ */
+#include "mbed.h"
+#include "mx_ssd1306.h"
+
+//MODTRONIX BEGIN /////////////////////////////////////////////////////////////
+#define DEBUG_ENABLE            0
+#if (DEBUG_ENABLE == 1)
+    extern Stream* pMxDebug;            //Define Stream for debug output in user code called pMxDebug
+    #define MX_DEBUG pMxDebug->printf
+#else
+    #define MX_DEBUG(format, args...) ((void)0)
+#endif
+//MODTRONIX END ///////////////////////////////////////////////////////////////
+
+
+#define SSD1306_SETLOWCOLUMN            0x00    //Only used for "Page Addresss Mode"! Column start, will wrap around to this column
+#define SSD1306_SETHIGHCOLUMN           0x10    //Only used for "Page Addresss Mode"! Column end, will wrap around after this column
+#define SSD1306_MEMORYMODE              0x20    //0x22=Page Address mode, 0x20=Horizontal Address Mode
+//Only used for "Horizontal Address Mode"! Set Col start and end. Two command must follow, Col start(Reset=0) & Col End(Reset=127)
+#define SSD1306_SET_COLUMN_ADR          0x21
+//Only used for "Horizontal Address Mode"! Set Page start and end. Two command must follow, Page start(Reset=0) & Page End(Reset=7)
+#define SSD1306_SET_PAGE_ADR            0x22
+#define SSD1306_DISABLE_SCROLLING       0x2E
+#define SSD1306_SETSTARTLINE            0x40
+#define SSD1306_SETCONTRAST             0x81
+#define SSD1306_CHARGEPUMP              0x8D
+#define SSD1306_SEGREMAP                0xA0
+#define SSD1306_DISPLAYALLON_RESUME     0xA4
+#define SSD1306_DISPLAYALLON            0xA5
+#define SSD1306_NORMALDISPLAY           0xA6
+#define SSD1306_INVERTDISPLAY           0xA7
+#define SSD1306_SETMULTIPLEX            0xA8
+#define SSD1306_DISPLAYOFF              0xAE
+#define SSD1306_DISPLAYON               0xAF
+#define SSD1306_SET_PAGE_START_ADR      0xB0    //Only used for "Page Address Mode"! Set Page start address(Reset=0)
+#define SSD1306_COMSCANINC              0xC0
+#define SSD1306_COMSCANDEC              0xC8
+#define SSD1306_SETDISPLAYOFFSET        0xD3
+#define SSD1306_SETDISPLAYCLOCKDIV      0xD5
+#define SSD1306_SETPRECHARGE            0xD9
+#define SSD1306_SETCOMPINS              0xDA
+#define SSD1306_SETVCOMDETECT           0xDB
+
+uint8_t MxSSD1306::begin(uint8_t vccstate)
+{
+    uint8_t retVal;
+#if (OLED_HAS_RESET==1)
+    rst = 1;
+#endif
+    // VDD (3.3V) goes high at start, lets just chill for a ms
+    wait_ms(1);
+#if (OLED_HAS_RESET==1)
+    // bring reset low
+    rst = 0;
+#endif
+    // wait 10ms
+    wait_ms(10);
+#if (OLED_HAS_RESET==1)
+    // bring out of reset
+    rst = 1;
+#endif
+    // turn on VCC (9V?)
+
+    if((retVal=command(SSD1306_DISPLAYOFF)) != 0) {
+        return retVal;  //Return error code
+    }
+    command(SSD1306_SETDISPLAYCLOCKDIV);
+    command(0x80);                                  // the suggested ratio 0x80
+
+    command(SSD1306_SETMULTIPLEX);
+    command(_rawHeight-1);
+
+    command(SSD1306_SETDISPLAYOFFSET);
+    command(0x0);                                   // no offset
+
+    command(SSD1306_SETSTARTLINE | 0x0);            // line #0
+
+    command(SSD1306_CHARGEPUMP);
+    command((vccstate == SSD1306_EXTERNALVCC) ? 0x10 : 0x14);
+
+    command(SSD1306_MEMORYMODE);                    // Set for "Page addressing mode"
+    command(0x02);                                  // 2 = Page addressing mode
+
+    command(SSD1306_SEGREMAP | 0x1);
+
+    command(SSD1306_COMSCANDEC);
+
+    command(SSD1306_SETCOMPINS);
+    command(_rawHeight == 32 ? 0x02 : 0x12);        // TODO - calculate based on _rawHieght ?
+
+    command(SSD1306_SETCONTRAST);
+    command(_rawHeight == 32 ? 0x8F : ((vccstate == SSD1306_EXTERNALVCC) ? 0x9F : 0xCF) );
+
+    command(SSD1306_SETPRECHARGE);
+    command((vccstate == SSD1306_EXTERNALVCC) ? 0x22 : 0xF1);
+
+    command(SSD1306_SETVCOMDETECT);
+    command(0x40);
+
+    command(SSD1306_DISABLE_SCROLLING);
+
+    command(SSD1306_DISPLAYALLON_RESUME);
+
+    command(SSD1306_NORMALDISPLAY);
+    
+    if((retVal=command(SSD1306_DISPLAYON)) != 0) {
+        return retVal;  //Return error code
+    }
+    return 0;   //Success
+}
+
+// Set a single pixel
+void MxSSD1306::drawPixel(int16_t x, int16_t y, uint16_t color)
+{
+    bool changed = false;
+    uint8_t colMask;
+    uint8_t mask;
+    uint16_t bufAdr;
+
+    if ((x < 0) || (x >= width()) || (y < 0) || (y >= height()))
+        return;
+    
+    // check rotation, move pixel around if necessary
+    switch (getRotation())
+    {
+        case 1:
+            swap(x, y);
+            x = _rawWidth - x - 1;
+            break;
+        case 2:
+            x = _rawWidth - x - 1;
+            y = _rawHeight - y - 1;
+            break;
+        case 3:
+            swap(x, y);
+            y = _rawHeight - y - 1;
+            break;
+    }  
+    
+    //Get address of byte in buffer
+    bufAdr = x+ ((y/8)*_rawWidth);
+
+    mask = 0x01 << (y%8);
+
+    // x is which column
+    if (color == WHITE) {
+        //If bit changed
+        if((buffer[bufAdr]&mask) == 0) {
+            buffer[bufAdr] |= mask; //Set bit
+            changed = true;
+        }
+    }
+    // else black
+    else {
+        //If bit changed
+        if((buffer[bufAdr]&mask) != 0) {
+            buffer[bufAdr] &= ~mask;    //Clear bit
+            changed = true;
+        }
+    }
+
+    //Set dirty bit IF CHANGED. Each dirty[] element contains dirty bits for 8 rows(y/8).
+    //Each bit is for 16 columns(x/16). For example:
+    // - bit 0 of dirty[0] will be "Rows 0-7, and Columns 0-15"
+    // - bit 1 of dirty[0] will be "Rows 0-7, and Columns 16-31"
+    // - bit 7 of dirty[0] will be "Rows 0-7, and Columns 112-127"
+    // - bit 0 of dirty[1] will be "Rows 8-15, and Columns 0-15"
+    if(changed) {
+        colMask = 0x01 << (x/16);
+        dirty[y/8] = dirty[y/8] | colMask;  //Set the dirty bit
+    }
+}
+
+/** Set display contrast
+ * @return 0 if success, else I2C or SPI error code
+ */
+uint8_t MxSSD1306::setContrast(uint8_t contrast) {
+    uint8_t retVal;
+    if((retVal=command(SSD1306_SETCONTRAST)) != 0) {
+        return retVal;
+    }
+    return command(contrast);
+}
+
+/** Turn display on or off
+ * @return 0 if success, else I2C or SPI error code
+ */
+uint8_t MxSSD1306::displayOn(bool on) {
+    return command(on ? SSD1306_DISPLAYON : SSD1306_DISPLAYOFF);
+}
+
+uint8_t MxSSD1306::invertDisplay(bool i)
+{
+	return command(i ? SSD1306_INVERTDISPLAY : SSD1306_NORMALDISPLAY);
+}
+
+/** Send the display buffer out to the display
+ * @return 0 if success, else I2C or SPI error code
+ */
+uint8_t MxSSD1306::display(void)
+{
+    uint8_t retVal;
+    static uint8_t oldColBlock = 0xfe;  //Do NOT use 0xff, seeing that is incremented by 1 below for test!
+    static uint8_t oldRowBlock = 0xfe;
+
+    // Page Address Mode //////////////////////////////////////////////////////
+    // Set "Page Address Mode". This mode requires SSD1306_SETLOWCOLUMN, SSD1306_SETHIGHCOLUMN and
+    // Only do this after setAllDirty() is called, which sets rowBlock to 0xf0
+    if(rowBlock==0xf0) {
+        rowBlock = 0;
+        if ((retVal=command(SSD1306_MEMORYMODE)) != 0) {return retVal;}     //Set "Page Address Mode"
+        if ((retVal=command(2)) != 0) {return retVal;}
+        oldColBlock = oldRowBlock = 0xfe;   //Cause column and row command to be sent to OLED again
+    }
+
+//dirty is array of 8 x uint8_t elements
+#if ((OLED_WIDTH == 128 ) && (OLED_HEIGHT==64))
+    uint8_t colMask;    //Width is 128 or less. Required 8 bits or less for colMask. Each bit = 16 columns. 8 bits = 128 columns.
+    uint32_t * pDirty = (uint32_t*)&dirty[0];
+    //Nothing to do
+    if ((pDirty[0]==0) && (pDirty[1]==0)) {
+        colBlock = rowBlock = 0;    //Reset
+        return 0;   //Return OK
+    }
+
+#elif (OLED_WIDTH <= 256 )
+    uint16_t colMask;    //Width is 256 or less. Required 16 bits or less for colMask. Each bit = 16 columns. 16 bits = 256 columns.
+    bool isDirty = false;
+    for(int iDirty=0; iDirty<(OLED_HEIGHT/8); iDirty++) {
+        if(dirty[iDirty] != 0) {
+            isDirty=true;
+            break;
+        }
+    }
+    //Nothing to do
+    if (isDirty == false) {
+        colBlock = rowBlock = 0;    //Reset
+        return 0;   //Return OK
+    }
+#else
+    #error "OLED width and height not supported yet!"
+#endif
+
+    //Find dirty block!
+    //Check if current block of display data is dirty. Each dirty[] element contains bits for whole
+    //row(all columns). Each bit of dirty = 16 columns. For example:
+    // - bit 0 of dirty[0] will be "Rows 0-7, and Columns 0-15"
+    // - bit 1 of dirty[0] will be "Rows 0-7, and Columns 16-31"
+    // - bit 7 of dirty[0] will be "Rows 0-7, and Columns 112-127"
+    // - bit 0 of dirty[1] will be "Rows 8-15, and Columns 0-15"
+    while(1) {
+        colMask = 0x01 << colBlock; //Get current column
+        //Found the dirty bit, break!
+        if((dirty[rowBlock] & colMask) != 0) {
+            //Clear the dirty bit
+            dirty[rowBlock] = dirty[rowBlock] & (~colMask);
+            break;
+        }
+        //Increment colBlock and rowBlock
+        if (++colBlock >= (OLED_WIDTH/16)) {
+            colBlock = 0;
+            rowBlock = (rowBlock+1) % (OLED_HEIGHT/8);
+        }
+    }
+
+    MX_DEBUG("\r\nOLED.display %d,%d", rowBlock, colBlock);
+
+    //Set "Current Page" -  Required by "Page Addressing Mode" (Page is NOT auto incremented in "Page Mode")
+    if (rowBlock != oldRowBlock) {
+        oldRowBlock = rowBlock;
+        // Set current Page. Each page = 8 rows
+        if ((retVal=command(SSD1306_SET_PAGE_START_ADR | rowBlock)) != 0) {return retVal;}
+    }
+
+    //Set "Current Column" - Required by "Page Addressing Mode"
+    //Not required if last written colBlock was previous one. In that case, will automatically increments (columns are auto incremented in "Page Mode")
+    if (colBlock != (oldColBlock+1)) {
+        uint8_t column  = colBlock * 16;
+        // Column Low nibble (bits 0-3) = 0
+        if ((retVal=command(SSD1306_SETLOWCOLUMN | (column & 0x0f))) != 0) {return retVal;}
+        // Column High nibble (bits 4-7) = 0
+        if ((retVal=command(SSD1306_SETHIGHCOLUMN | ((column>>4) & 0x0f))) != 0) {return retVal;}
+    }
+    oldColBlock = colBlock;
+
+    if ((retVal=sendDisplayBuffer(rowBlock, colBlock)) != 0) {
+        return retVal;  //Return error
+    }
+
+    return 0;   //Success
+
+    //----- Alternative Method -----
+    //If used, MUST ALSO update begin() function to initialize with "Horizontal Address Mode"
+//    // Horizontal Address Mode ////////////////////////////////////////////////
+//    //Set "Horizontal Address Mode". This mode requires SSD1306_SET_COLUMN_ADR and SSD1306_SET_PAGE_ADR
+//    //commands to set start/stop column & page
+//    if ((retVal=command(SSD1306_MEMORYMODE)) != 0) {return retVal;}     //Set "Horizontal Address Mode"
+//    if ((retVal=command(0)) != 0) {return retVal;}
+//
+//    //Set column Start and End, used for "Horizontal Address Mode".
+//    if ((retVal=command(SSD1306_SET_COLUMN_ADR)) != 0) {return retVal;}
+//    if ((retVal=command(0)) != 0) {return retVal;}    //Column 0 - first column
+//    if ((retVal=command(127)) != 0) {return retVal;}  //Column 7 - last column
+//
+//    //Set page Start and End, used for "Horizontal Address Mode".
+//    if ((retVal=command(SSD1306_SET_PAGE_ADR)) != 0) {return retVal;}
+//    if ((retVal=command(0)) != 0) {return retVal;}    //Page 0 - first page
+//    if ((retVal=command(7)) != 0) {return retVal;}    //Page 7 - last page
+//
+//    for(rowBlock=0; rowBlock<8; rowBlock++) {
+//        for(colBlock=0; colBlock<8; colBlock++) {
+//            if ((retVal=sendDisplayBuffer(rowBlock, colBlock)) != 0) {
+//                return retVal;  //Return error
+//            }
+//        }
+//    }
+}
+
+
+void MxSSD1306::clearDisplay(void)
+{
+    setAllDirty();  //Set whole display as dirty
+
+#if defined(OLED_NO_VECTOR)
+    for(uint i=0; i<sizeof(buffer); i++) {
+        buffer[i] = 0;
+    }
+#else
+	std::fill(buffer.begin(),buffer.end(),0);
+#endif
+}
+
+// Set whole display as being dirty
+void MxSSD1306::setAllDirty(void) {
+    colBlock = 0;
+    rowBlock = 0xf0;    //Mark with 0xf0 so SSD1306_MEMORYMODE command is sent again in display() function
+    //Set whole display as Dirty
+#if (OLED_WIDTH == 128) //Each entry of dirty[] is a UINT8, and each bit is 16 columns
+    memset(&dirty[0], 0xff, sizeof(dirty)); //Test - make ALL dirty
+#elif (OLED_WIDTH == 256) //Each entry of dirty[] is a UINT16, and each bit is 16 columns
+    memset(&dirty[0], 0xff, sizeof(dirty)); //Test - make ALL dirty
+#else
+    #error "setAllDirty() does not support current screen width"
+#endif
+}
+
+
+void MxSSD1306::splash(void)
+{
+#ifndef OLED_NO_SPLASH
+	uint8_t adaFruitLogo[64 * 128 / 8] =
+	{ 
+		0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+		0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+		0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+		0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80,
+		0x80, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+		0x00, 0x80, 0x80, 0xC0, 0xC0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+		0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+		0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+		0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+		0x00, 0x00, 0x00, 0x00, 0x80, 0xC0, 0xE0, 0xF0, 0xF8, 0xFC, 0xF8, 0xE0, 0x00, 0x00, 0x00, 0x00,
+		0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0x80, 0x80,
+		0x80, 0x80, 0x00, 0x80, 0x80, 0x00, 0x00, 0x00, 0x00, 0x80, 0x80, 0x80, 0x80, 0x80, 0x00, 0xFF,
+		0xFF, 0xFF, 0x00, 0x00, 0x00, 0x00, 0x80, 0x80, 0x80, 0x80, 0x00, 0x00, 0x80, 0x80, 0x00, 0x00,
+		0x80, 0xFF, 0xFF, 0x80, 0x80, 0x00, 0x80, 0x80, 0x00, 0x80, 0x80, 0x80, 0x80, 0x00, 0x80, 0x80,
+		0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0x80, 0x00, 0x00, 0x8C, 0x8E, 0x84, 0x00, 0x00, 0x80, 0xF8,
+		0xF8, 0xF8, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+		0xF0, 0xF0, 0xF0, 0xF0, 0xF0, 0xF0, 0xF0, 0xF0, 0xF0, 0xF0, 0xF0, 0xF0, 0xE0, 0xE0, 0xC0, 0x80,
+		0x00, 0xE0, 0xFC, 0xFE, 0xFF, 0xFF, 0xFF, 0x7F, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x00, 0x00, 0x00,
+		0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xFE, 0xFF, 0xC7, 0x01, 0x01,
+		0x01, 0x01, 0x83, 0xFF, 0xFF, 0x00, 0x00, 0x7C, 0xFE, 0xC7, 0x01, 0x01, 0x01, 0x01, 0x83, 0xFF,
+		0xFF, 0xFF, 0x00, 0x38, 0xFE, 0xC7, 0x83, 0x01, 0x01, 0x01, 0x83, 0xC7, 0xFF, 0xFF, 0x00, 0x00,
+		0x01, 0xFF, 0xFF, 0x01, 0x01, 0x00, 0xFF, 0xFF, 0x07, 0x01, 0x01, 0x01, 0x00, 0x00, 0x7F, 0xFF,
+		0x80, 0x00, 0x00, 0x00, 0xFF, 0xFF, 0x7F, 0x00, 0x00, 0xFF, 0xFF, 0xFF, 0x00, 0x00, 0x01, 0xFF,
+		0xFF, 0xFF, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+		0x03, 0x0F, 0x3F, 0x7F, 0x7F, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xE7, 0xC7, 0xC7, 0x8F,
+		0x8F, 0x9F, 0xBF, 0xFF, 0xFF, 0xC3, 0xC0, 0xF0, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFC, 0xFC, 0xFC,
+		0xFC, 0xFC, 0xFC, 0xFC, 0xFC, 0xF8, 0xF8, 0xF0, 0xF0, 0xE0, 0xC0, 0x00, 0x01, 0x03, 0x03, 0x03,
+		0x03, 0x03, 0x01, 0x03, 0x03, 0x00, 0x00, 0x00, 0x00, 0x01, 0x03, 0x03, 0x03, 0x03, 0x01, 0x01,
+		0x03, 0x01, 0x00, 0x00, 0x00, 0x01, 0x03, 0x03, 0x03, 0x03, 0x01, 0x01, 0x03, 0x03, 0x00, 0x00,
+		0x00, 0x03, 0x03, 0x00, 0x00, 0x00, 0x03, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01,
+		0x03, 0x03, 0x03, 0x03, 0x03, 0x01, 0x00, 0x00, 0x00, 0x01, 0x03, 0x01, 0x00, 0x00, 0x00, 0x03,
+		0x03, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+		// 128x32^^^  128x64vvv
+		0x00, 0x00, 0x00, 0x80, 0xC0, 0xE0, 0xF0, 0xF9, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x3F, 0x1F, 0x0F,
+		0x87, 0xC7, 0xF7, 0xFF, 0xFF, 0x1F, 0x1F, 0x3D, 0xFC, 0xF8, 0xF8, 0xF8, 0xF8, 0x7C, 0x7D, 0xFF,
+		0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x7F, 0x3F, 0x0F, 0x07, 0x00, 0x30, 0x30, 0x00, 0x00,
+		0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+		0x00, 0x00, 0x00, 0x00, 0xFE, 0xFE, 0xFC, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+		0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xE0, 0xC0, 0x00,
+		0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x30, 0x30, 0x00, 0x00, 0x00, 0x00,
+		0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+		0x00, 0xC0, 0xFE, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x7F, 0x7F, 0x3F, 0x1F,
+		0x0F, 0x07, 0x1F, 0x7F, 0xFF, 0xFF, 0xF8, 0xF8, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFE, 0xF8, 0xE0,
+		0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xFE, 0xFE, 0x00, 0x00,
+		0x00, 0xFC, 0xFE, 0xFC, 0x0C, 0x06, 0x06, 0x0E, 0xFC, 0xF8, 0x00, 0x00, 0xF0, 0xF8, 0x1C, 0x0E,
+		0x06, 0x06, 0x06, 0x0C, 0xFF, 0xFF, 0xFF, 0x00, 0x00, 0xFE, 0xFE, 0x00, 0x00, 0x00, 0x00, 0xFC,
+		0xFE, 0xFC, 0x00, 0x18, 0x3C, 0x7E, 0x66, 0xE6, 0xCE, 0x84, 0x00, 0x00, 0x06, 0xFF, 0xFF, 0x06,
+		0x06, 0xFC, 0xFE, 0xFC, 0x0C, 0x06, 0x06, 0x06, 0x00, 0x00, 0xFE, 0xFE, 0x00, 0x00, 0xC0, 0xF8,
+		0xFC, 0x4E, 0x46, 0x46, 0x46, 0x4E, 0x7C, 0x78, 0x40, 0x18, 0x3C, 0x76, 0xE6, 0xCE, 0xCC, 0x80,
+		0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+		0x00, 0x00, 0x00, 0x00, 0x01, 0x07, 0x0F, 0x1F, 0x1F, 0x3F, 0x3F, 0x3F, 0x3F, 0x1F, 0x0F, 0x03,
+		0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0F, 0x0F, 0x00, 0x00,
+		0x00, 0x0F, 0x0F, 0x0F, 0x00, 0x00, 0x00, 0x00, 0x0F, 0x0F, 0x00, 0x00, 0x03, 0x07, 0x0E, 0x0C,
+		0x18, 0x18, 0x0C, 0x06, 0x0F, 0x0F, 0x0F, 0x00, 0x00, 0x01, 0x0F, 0x0E, 0x0C, 0x18, 0x0C, 0x0F,
+		0x07, 0x01, 0x00, 0x04, 0x0E, 0x0C, 0x18, 0x0C, 0x0F, 0x07, 0x00, 0x00, 0x00, 0x0F, 0x0F, 0x00,
+		0x00, 0x0F, 0x0F, 0x0F, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0F, 0x0F, 0x00, 0x00, 0x00, 0x07,
+		0x07, 0x0C, 0x0C, 0x18, 0x1C, 0x0C, 0x06, 0x06, 0x00, 0x04, 0x0E, 0x0C, 0x18, 0x0C, 0x0F, 0x07,
+		0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+		0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+		0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+		0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+		0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+		0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+		0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+		0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+	};
+
+	setAllDirty();  //Set whole display as dirty
+
+#if defined(OLED_NO_VECTOR)
+    memcpy(&buffer[0], &adaFruitLogo[0], sizeof(adaFruitLogo));
+#else
+	std::copy(
+		&adaFruitLogo[0]
+		, &adaFruitLogo[0] + (_rawHeight == 32 ? sizeof(adaFruitLogo)/2 : sizeof(adaFruitLogo))
+		, buffer.begin()
+		);
+#endif
+#endif
+}