Updated

Dependents:   Assignment_5

Adafruit_SSD1306.cpp

Committer:
DrCoyle
Date:
2014-08-26
Revision:
4:f79c4a74f266
Parent:
0:c3dcd4c4983a
Child:
5:c3e0f8165538

File content as of revision 4:f79c4a74f266:

/*********************************************************************
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 LPC1768
 */

#include "mbed.h"
#include "Adafruit_SSD1306.h"

uint8_t splashScreen[SSD1306_LCDHEIGHT * SSD1306_LCDWIDTH / 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, 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, 0x60, 0xC0, 0x98, 0x70, 0xE6, 0x9C, 0x78, 0xE7, 0x8E, 0x38, 0xF0, 0xC0,
0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x80, 0xC0, 0x20, 0xC0, 0x60, 0xB0, 0xD8, 0x68, 0x34, 0xB0, 0xC8, 0x64, 0xB2,
0xD8, 0x68, 0x24, 0x14, 0x18, 0x08, 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, 0x12, 0x24, 0x4C, 0x9B, 0xB6, 0x6C, 0x5B, 0xB2, 0xAC, 0x59, 0xD3, 0xA4, 0x49,
0xD3, 0xA6, 0x6C, 0x58, 0xB0, 0x60, 0xC0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xE0, 0x10,
0xE0, 0x38, 0xC6, 0x39, 0xCE, 0x7B, 0x1C, 0x46, 0x63, 0x39, 0x0E, 0x17, 0x0B, 0x06, 0x03, 0x01,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xC0, 0xF0, 0x10, 0x10, 0x18, 0x10,
0x10, 0x00, 0x00, 0x00, 0x00, 0x80, 0x80, 0xC0, 0x80, 0x80, 0x00, 0x00, 0x00, 0x40, 0xC0, 0x00,
0x00, 0x00, 0xC0, 0x40, 0x00, 0x00, 0xF8, 0x00, 0x00, 0x00, 0x00, 0x80, 0xC0, 0xC0, 0x80, 0x80,
0x00, 0x00, 0x00, 0xF8, 0xF8, 0x98, 0x98, 0x98, 0xF0, 0x70, 0x00, 0x00, 0x00, 0x00, 0x80, 0x80,
0xC0, 0x80, 0x80, 0x00, 0x00, 0x00, 0xC0, 0xF0, 0xC0, 0xC0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x01, 0x01, 0x02, 0x04, 0x05, 0x0B, 0xAA, 0x36, 0x57, 0x46, 0x4F, 0xCD,
0x2A, 0x1A, 0x55, 0xD5, 0xCA, 0xAA, 0xA1, 0x8C, 0xB0, 0xC0, 0x80, 0xF8, 0x00, 0xFF, 0xF0, 0xFE,
0x81, 0x0E, 0xF3, 0xCC, 0x32, 0x04, 0x58, 0x22, 0x18, 0x06, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x03, 0x0F, 0x08, 0x08, 0x18, 0x08,
0x0C, 0x04, 0x00, 0x00, 0x02, 0x0F, 0x08, 0x18, 0x08, 0x0F, 0x07, 0x00, 0x00, 0x40, 0xC3, 0x4E,
0x78, 0x0E, 0x03, 0x00, 0x00, 0x00, 0x1F, 0x00, 0x00, 0x00, 0x07, 0x0A, 0x1A, 0x1A, 0x0A, 0x0B,
0x02, 0x00, 0x00, 0x1F, 0x1F, 0x19, 0x19, 0x19, 0x09, 0x0F, 0x06, 0x00, 0x00, 0x07, 0x0F, 0x08,
0x18, 0x08, 0x0F, 0x07, 0x00, 0x00, 0x00, 0x0F, 0x18, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x01, 0x07, 0x03, 0x0A,
0x2A, 0x2A, 0x2A, 0xE1, 0xE0, 0x4A, 0x4A, 0x2B, 0x29, 0x68, 0x69, 0x6A, 0xD4, 0x8B, 0x93, 0x27,
0xFF, 0xE0, 0xEB, 0xF5, 0xF2, 0xF1, 0xF0, 0xF8, 0xFC, 0xFC, 0xFC, 0x78, 0x7E, 0x2E, 0x28, 0x18,
0x18, 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, 0xE0, 0xE0, 0x00, 0x00, 0x00,
0x00, 0xC0, 0xE0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0xE0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x80, 0xC0, 0x60, 0x60, 0xC0, 0x80, 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, 0x80, 0xC0, 0xC0, 0xC0, 0xC0, 0xC0, 0xE0,
0xE0, 0xE1, 0xF1, 0xF1, 0xF5, 0xFD, 0xFB, 0xFA, 0xFA, 0x7C, 0xFC, 0xF8, 0xFA, 0xFD, 0xFD, 0xFE,
0xFF, 0xFF, 0x3F, 0xFF, 0xFF, 0xFF, 0xFF, 0xE3, 0xC1, 0x80, 0x80, 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, 0x03, 0x1F, 0x70, 0x70,
0x3E, 0x07, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x7F, 0x00, 0x00, 0x00, 0x00, 0x00, 0x70,
0x00, 0x00, 0x00, 0x1F, 0x30, 0x60, 0x60, 0x20, 0x1F, 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, 0x02, 0x02, 0x02, 0x02, 0x02, 0x0B, 0x0B, 0x0F, 0x17,
0x1F, 0x0F, 0x1F, 0x1F, 0x0F, 0x1F, 0x1F, 0x07, 0x0F, 0x08, 0x00, 0x00, 0x03, 0x07, 0x07, 0x0F,
0x0F, 0x0F, 0x0E, 0x7D, 0xAB, 0x8D, 0x1D, 0x15, 0x01, 0x03, 0x03, 0x03, 0x0F, 0x48, 0x3C, 0x8C,
0x0C, 0x1C, 0x00, 0x02, 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, 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
};

Adafruit_SSD1306::Adafruit_SSD1306(SPI &spi, PinName DC, PinName RST, PinName CS)
    : Adafruit_GFX(SSD1306_LCDWIDTH, SSD1306_LCDHEIGHT)
    , rst(RST,false), cs(CS,true), dc(DC,false), mspi(spi)
{
    memcpy(buffer,splashScreen,sizeof(buffer));
    begin();
    display();
};

void Adafruit_SSD1306::begin(uint8_t vccstate)
{
    rst = 1;
    // VDD (3.3V) goes high at start, lets just chill for a ms
    wait_ms(1);
    // bring reset low
    rst = 0;
    // wait 10ms
    wait_ms(10);
    // bring out of reset
    rst = 1;
    // turn on VCC (9V?)
    
/*#if defined SSD1306_128_32
    // Init sequence for 128x32 OLED module
    ssd1306_command(SSD1306_DISPLAYOFF);                    // 0xAE
    ssd1306_command(SSD1306_SETDISPLAYCLOCKDIV);            // 0xD5
    ssd1306_command(0x80);                                  // the suggested ratio 0x80
    ssd1306_command(SSD1306_SETMULTIPLEX);                  // 0xA8
    ssd1306_command(0x1F);
    ssd1306_command(SSD1306_SETDISPLAYOFFSET);              // 0xD3
    ssd1306_command(0x0);                                   // no offset
    ssd1306_command(SSD1306_SETSTARTLINE | 0x0);            // line #0
    ssd1306_command(SSD1306_CHARGEPUMP);                    // 0x8D
    if (vccstate == SSD1306_EXTERNALVCC) 
    { ssd1306_command(0x10); }
    else 
    { ssd1306_command(0x14); }
    ssd1306_command(SSD1306_MEMORYMODE);                    // 0x20
    ssd1306_command(0x00);                                  // 0x0 act like ks0108
    ssd1306_command(SSD1306_SEGREMAP | 0x1);
    ssd1306_command(SSD1306_COMSCANDEC);
    ssd1306_command(SSD1306_SETCOMPINS);                    // 0xDA
    ssd1306_command(0x02);
    ssd1306_command(SSD1306_SETCONTRAST);                   // 0x81
    ssd1306_command(0x8F);
    ssd1306_command(SSD1306_SETPRECHARGE);                  // 0xd9
    if (vccstate == SSD1306_EXTERNALVCC) 
    { ssd1306_command(0x22); }
    else 
    { ssd1306_command(0xF1); }
    ssd1306_command(SSD1306_SETVCOMDETECT);                 // 0xDB
    ssd1306_command(0x40);
    ssd1306_command(SSD1306_DISPLAYALLON_RESUME);           // 0xA4
    ssd1306_command(SSD1306_NORMALDISPLAY);                 // 0xA6
#endif*/
    
#if defined SSD1306_128_64
    // Init sequence for 128x64 OLED module
    ssd1306_command(SSD1306_DISPLAYOFF);                    // 0xAE
    ssd1306_command(SSD1306_SETDISPLAYCLOCKDIV);            // 0xD5
    ssd1306_command(0x80);                                  // the suggested ratio 0x80
    ssd1306_command(SSD1306_SETMULTIPLEX);                  // 0xA8
    ssd1306_command(0x3F);
    ssd1306_command(SSD1306_SETDISPLAYOFFSET);              // 0xD3
    ssd1306_command(0x0);                                   // no offset
    ssd1306_command(SSD1306_SETSTARTLINE | 0x0);            // line #0
    ssd1306_command(SSD1306_CHARGEPUMP);                    // 0x8D
    if (vccstate == SSD1306_EXTERNALVCC) 
    { ssd1306_command(0x10); }
    else 
    { ssd1306_command(0x14); }
    ssd1306_command(SSD1306_MEMORYMODE);                    // 0x20
    ssd1306_command(0x00);                                  // 0x0 act like ks0108
    ssd1306_command(SSD1306_SEGREMAP | 0x1);
    ssd1306_command(SSD1306_COMSCANDEC);
    ssd1306_command(SSD1306_SETCOMPINS);                    // 0xDA
    ssd1306_command(0x12);
    ssd1306_command(SSD1306_SETCONTRAST);                   // 0x81
    if (vccstate == SSD1306_EXTERNALVCC) 
    { ssd1306_command(0x9F); }
    else 
    { ssd1306_command(0xCF); }
    ssd1306_command(SSD1306_SETPRECHARGE);                  // 0xd9
    if (vccstate == SSD1306_EXTERNALVCC) 
    { ssd1306_command(0x22); }
    else 
    { ssd1306_command(0xF1); }
    ssd1306_command(SSD1306_SETVCOMDETECT);                 // 0xDB
    ssd1306_command(0x40);
    ssd1306_command(SSD1306_DISPLAYALLON_RESUME);           // 0xA4
    ssd1306_command(SSD1306_NORMALDISPLAY);                 // 0xA6
#endif
    
    ssd1306_command(SSD1306_DISPLAYON);//--turn on oled panel
}

// the most basic function, set a single pixel
void Adafruit_SSD1306::drawPixel(int16_t x, int16_t y, uint16_t color)
{
    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;
    }  
    
    // x is which column
    if (color == WHITE) 
        buffer[x+ (y/8)*SSD1306_LCDWIDTH] |= _BV((y%8));  
    else
        buffer[x+ (y/8)*SSD1306_LCDWIDTH] &= ~_BV((y%8)); 
}

void Adafruit_SSD1306::invertDisplay(bool i)
{
    if (i)
        ssd1306_command(SSD1306_INVERTDISPLAY);
    else
        ssd1306_command(SSD1306_NORMALDISPLAY);
}

//function inverts display of num characters starting at row x, column y
void Adafruit_SSD1306::invertSection(int16_t x, int16_t y, int16_t num)
{
    if (x+num > 21 || y>8)
        return;
    else {
    int k;
    for (k=0;k<(num*6);k++)
    buffer[x*6+y*SSD1306_LCDWIDTH+k]=~buffer[x*6+y*SSD1306_LCDWIDTH+k];
    }
}

void Adafruit_SSD1306::ssd1306_command(uint8_t c)
{
    cs = 1;
    dc = 0;
    cs = 0;
    mspi.write(c);
    cs = 1;
}

void Adafruit_SSD1306::ssd1306_data(uint8_t c)
{
    cs = 1;
    dc = 1;
    cs = 0;
    mspi.write(c);
    cs = 1;
}

void Adafruit_SSD1306::display(void)
{
    ssd1306_command(SSD1306_SETLOWCOLUMN | 0x0);  // low col = 0
    ssd1306_command(SSD1306_SETHIGHCOLUMN | 0x0);  // hi col = 0
    ssd1306_command(SSD1306_SETSTARTLINE | 0x0); // line #0

    cs = 1;
    dc = 1;
    cs = 0;
    
    for (uint16_t i=0; i<(SSD1306_LCDWIDTH*SSD1306_LCDHEIGHT/8); i++)
        mspi.write(buffer[i]);

    // i wonder why we have to do this (check datasheet)
    if (SSD1306_LCDHEIGHT == 32)
    {
        for (uint16_t i=0; i<(SSD1306_LCDWIDTH*SSD1306_LCDHEIGHT/8); i++)
            mspi.write(0);
    }
    
    cs = 1;
}

// clear everything
void Adafruit_SSD1306::clearDisplay(void)
{
    memset(buffer,0,sizeof(buffer));
}