Driver for the Seeedstudio RGB OLED module for the xadow M0

src/SSD1331.cpp

Committer:
messi1
Date:
2015-11-12
Revision:
4:1707ca53e7d5
Parent:
3:af00512c9694
Child:
5:9de43186f5ea

File content as of revision 4:1707ca53e7d5:

/*
* SSD1331.cpp
* A library for RGB OLED module
*
* Copyright (c) 2014 seeed technology inc.
* Copyright (c) 2012, Adafruit Industries.
*
* All rights reserved.
*
* This library is based on Adafruit's SSD1331-OLED-Driver-Library. Thanks to 
* their contribution to the code, we modify it and add more interface to 
* support our Seeed's Xadow RGB OLED 96*64 module.
*
* Below is the introduction of Adafruit's Color OLED module, we add it to here
* to express our thanks to them.
*
* ****************************************************************************
* This is a library for the 0.96" 16-bit Color OLED with SSD1331 driver chip
*
*  Pick one up today in the adafruit shop!
*  ------> http://www.adafruit.com/products/684
*
* These displays use SPI to communicate.
*
* 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.
* Modifed by lawliet for Seeed Studio's RGB OLED module.
* BSD license, all text above must be included in any redistribution
* ******************************************************************************
*
* Software License Agreement (BSD License)
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
* 3. Neither the name of the copyright holders nor the
* names of its contributors may be used to endorse or promote products
* derived from this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS ''AS IS'' AND ANY
* EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
* DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER BE LIABLE FOR ANY
* DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
* ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*
*/
#include "DigitalOut.h"
#include "SPI.h"
#include "SSD1331.h"

SSD1331::SSD1331(PinName cs, PinName rst, PinName dc, PinName mosi, PinName miso, PinName sclk)
:SGL(RGB_OLED_WIDTH, RGB_OLED_HEIGHT), _cs(cs), _dc(dc), _spiPort(mosi, miso, sclk)
{
    _spiPort.format(8,3); //8bit frame and POL=1 /PHA=1(UpEdge Sampled)
    _spiPort.frequency(25000000); // modify later
    
    init();
};

//------------------------------------------------------------------------------------
void SSD1331::sendCmd(uint8_t cmd)
{
    _dc = 0;
    _cs = 0;
    _spiPort.write(cmd);
    _cs = 1;
}

//------------------------------------------------------------------------------------
void SSD1331::sendCmd(uint8_t cmd, uint8_t arg1)
{
    _dc = 0;
    _cs = 0;
    _spiPort.write(cmd);
    _spiPort.write(arg1);
    _cs = 1;
}

//------------------------------------------------------------------------------------    
void SSD1331::sendCmd(uint8_t cmd, uint8_t arg1, uint8_t arg2)
{
    _dc = 0;
    _cs = 0;
    _spiPort.write(cmd);
    _spiPort.write(arg1);
    _spiPort.write(arg2);
    _cs = 1;
}    

//------------------------------------------------------------------------------------
void  SSD1331::sendCmd(uint8_t *cmd, uint8_t count)
{
    if(!cmd) return;
    
    _dc = 0;
    _cs = 0;
    for(uint8_t i=0; i<count; ++i)
       _spiPort.write(*cmd++);
    _cs = 1;
}

//------------------------------------------------------------------------------------
void  SSD1331::sendData(uint16_t data)
{
    _dc = HIGH;
    _cs = LOW;
    _spiPort.write(data >> 8);
    _spiPort.write((data & 0x00ff));
    _cs = HIGH;
}

//------------------------------------------------------------------------------------
void SSD1331::init(void)
{
    // initialize sequence
    sendCmd(CMD_DISPLAY_OFF);    //OLED display OFF
    
    //Row Address
    sendCmd(CMD_SET_ROW_ADDRESS,    0x00, 0x3f); //Set Row Address with start=0,end=63
    sendCmd(CMD_SET_COLUMN_ADDRESS, 0x00, 0x5f); //Set Column Address with start=0,end=95
    
     //Contrast
    sendCmd(CMD_SET_REMAP,              0x76); //Set remap & data format 0111 0000 // 65k Color/8bit buswidth/format1
    sendCmd(CMD_SET_DISPLAY_START_LINE, 0x00); //Set display start row RAM
    sendCmd(CMD_SET_DISPLAY_OFFSET,     0x00); //Set dispaly offset
    sendCmd(CMD_NORMAL_DISPLAY);               //Set Display Mode
    sendCmd(CMD_SET_MULTIPLEX_RATIO,    0x3f); //Set Multiplex Ratio
    sendCmd(CMD_SET_MASTER_CONFIGURE,   0x8f); //Set Master Configuration (External VCC Supply Selected)
    sendCmd(CMD_POWER_SAVE_MODE,        0x1a); //Set Power Saving Mode
    sendCmd(CMD_PHASE_PERIOD_ADJUSTMENT, 0x74);//Set Phase 1 & 2 Period Adjustment
    sendCmd(CMD_DISPLAY_CLOCK_DIV,      0xd0); //Set Display Clock Divide Ratio / Oscillator Frequency
    sendCmd(CMD_SET_PRECHARGE_SPEED_A,  0x81); //Set Second Pre-charge Speed of Color A
    sendCmd(CMD_SET_PRECHARGE_SPEED_B,  0x82); //Set Second Pre-charge Speed of Color B
    sendCmd(CMD_SET_PRECHARGE_SPEED_C,  0x83); //Set Second Pre-charge Speed of Color C
    sendCmd(CMD_SET_PRECHARGE_VOLTAGE,  0x3e); //Set Pre-charge Level
    sendCmd(CMD_SET_V_VOLTAGE,          0x3e); //Set VCOMH
    sendCmd(CMD_MASTER_CURRENT_CONTROL, 0x0f); //Set Master Current Control
    sendCmd(CMD_SET_CONTRAST_A,         0x80); //Set Contrast Control for Color &#129;gA&#129;h
    sendCmd(CMD_SET_CONTRAST_B,         0x80); //Set Contrast Control for Color &#129;gB&#129;h
    sendCmd(CMD_SET_CONTRAST_C,         0x80); //Set Contrast Control for Color &#129;gC&#129;h 
    
    fillRectangle(0,0, RGB_OLED_WIDTH, RGB_OLED_HEIGHT, 0x0);
    sendCmd(CMD_NORMAL_BRIGHTNESS_DISPLAY_ON);    //display ON

//    sendCmd(CMD_DISPLAY_OFF);          //Display Off
//    sendCmd(CMD_SET_CONTRAST_A);       //Set contrast for color A
//    sendCmd(0x91);                     //145
//    sendCmd(CMD_SET_CONTRAST_B);       //Set contrast for color B
//    sendCmd(0x50);                     //80
//    sendCmd(CMD_SET_CONTRAST_C);       //Set contrast for color C
//    sendCmd(0x7D);                     //125
//    sendCmd(CMD_MASTER_CURRENT_CONTROL);//master current control
//    sendCmd(0x06);                     //6
//    sendCmd(CMD_SET_PRECHARGE_SPEED_A);//Set Second Pre-change Speed For ColorA
//    sendCmd(0x64);                     //100
//    sendCmd(CMD_SET_PRECHARGE_SPEED_B);//Set Second Pre-change Speed For ColorB
//    sendCmd(0x78);                     //120
//    sendCmd(CMD_SET_PRECHARGE_SPEED_C);//Set Second Pre-change Speed For ColorC
//    sendCmd(0x64);                     //100
//    sendCmd(CMD_SET_REMAP);            //set remap & data format
//    sendCmd(0x72);                     //0x72              
//    sendCmd(CMD_SET_DISPLAY_START_LINE);//Set display Start Line
//    sendCmd(0x0);
//    sendCmd(CMD_SET_DISPLAY_OFFSET);   //Set display offset
//    sendCmd(0x0);
//    sendCmd(CMD_NORMAL_DISPLAY);       //Set display mode
//    sendCmd(CMD_SET_MULTIPLEX_RATIO);  //Set multiplex ratio
//    sendCmd(0x3F);
//    sendCmd(CMD_SET_MASTER_CONFIGURE); //Set master configuration
//    sendCmd(0x8E);
//    sendCmd(CMD_POWER_SAVE_MODE);      //Set Power Save Mode
//    sendCmd(0x00);                     //0x00
//    sendCmd(CMD_PHASE_PERIOD_ADJUSTMENT);//phase 1 and 2 period adjustment
//    sendCmd(0x31);                     //0x31
//    sendCmd(CMD_DISPLAY_CLOCK_DIV);    //display clock divider/oscillator frequency
//    sendCmd(0xF0);
//    sendCmd(CMD_SET_PRECHARGE_VOLTAGE);//Set Pre-Change Level
//    sendCmd(0x3A);
//    sendCmd(CMD_SET_V_VOLTAGE);        //Set vcomH
//    sendCmd(0x3E);
//    sendCmd(CMD_DEACTIVE_SCROLLING);   //disable scrolling
//    sendCmd(CMD_NORMAL_BRIGHTNESS_DISPLAY_ON);//set display on
}

//------------------------------------------------------------------------------------
void SSD1331::drawPixel(uint8_t x, uint8_t y, uint16_t color)
{
    if ((x >= RGB_OLED_WIDTH) || (y >= RGB_OLED_HEIGHT))
        return;
        
    //                      set column point               set row point
    uint8_t cmd[6] = { CMD_SET_COLUMN_ADDRESS, x, x,  CMD_SET_ROW_ADDRESS, y, y };
    sendCmd(cmd, 6);

    //fill 16bit colour
    sendData(color);
}

//------------------------------------------------------------------------------------
void SSD1331::drawLine(uint8_t x0, uint8_t y0, uint8_t x1, uint8_t y1, uint16_t color)
{
    if (x0 >= RGB_OLED_WIDTH)  x0 = RGB_OLED_WIDTH  - 1;
    if (y0 >= RGB_OLED_HEIGHT) y0 = RGB_OLED_HEIGHT - 1;
    if (x1 >= RGB_OLED_WIDTH)  x1 = RGB_OLED_WIDTH  - 1;
    if (y1 >= RGB_OLED_HEIGHT) y1 = RGB_OLED_HEIGHT - 1;
    
    uint8_t cmd[8] = { CMD_DRAW_LINE, x0, y0, x1, y1, (uint8_t)((color>>11)&0x1F), (uint8_t)((color>>5)&0x3F), (uint8_t)(color&0x1F) };
    sendCmd(cmd, 8);
}

//------------------------------------------------------------------------------------
void SSD1331::drawFrame(uint16_t x0, uint16_t y0, uint16_t x1, uint16_t y1, uint16_t outColor, uint16_t fillColor)
{
    if (x0 >= RGB_OLED_WIDTH)  x0 = RGB_OLED_WIDTH  - 1;
    if (y0 >= RGB_OLED_HEIGHT) y0 = RGB_OLED_HEIGHT - 1;
    if (x1 >= RGB_OLED_WIDTH)  x1 = RGB_OLED_WIDTH  - 1;
    if (y1 >= RGB_OLED_HEIGHT) y1 = RGB_OLED_HEIGHT - 1;

    sendCmd(CMD_FILL_WINDOW);//fill window
    sendCmd(ENABLE_FILL);
    sendCmd(CMD_DRAW_RECTANGLE);//draw rectangle
    sendCmd(x0);//start column
    sendCmd(y0);//start row
    sendCmd(x1);//end column
    sendCmd(y1);//end row
    sendCmd((uint8_t)((outColor>>11)&0x1F));//R
    sendCmd((uint8_t)((outColor>>5)&0x3F));//G
    sendCmd((uint8_t)(outColor&0x1F));//B
    sendCmd((uint8_t)((fillColor>>11)&0x1F));//R
    sendCmd((uint8_t)((fillColor>>5)&0x3F));//G
    sendCmd((uint8_t)(fillColor&0x1F));//B
}

//------------------------------------------------------------------------------------
void SSD1331::copyWindow(uint16_t x0, uint16_t y0, uint16_t x1, uint16_t y1,uint16_t x2, uint16_t y2)
{
    sendCmd(CMD_COPY_WINDOW);//copy window
    sendCmd(x0);//start column
    sendCmd(y0);//start row
    sendCmd(x1);//end column
    sendCmd(y1);//end row
    sendCmd(x2);//new column
    sendCmd(y2);//new row
}

//------------------------------------------------------------------------------------
void SSD1331::dimWindow(uint16_t x0, uint16_t y0, uint16_t x1, uint16_t y1)
{
    sendCmd(CMD_DIM_WINDOW);//copy area
    sendCmd(x0);//start column
    sendCmd(y0);//start row
    sendCmd(x1);//end column
    sendCmd(y1);//end row
}

//------------------------------------------------------------------------------------
void SSD1331::clearWindow(uint16_t x0, uint16_t y0, uint16_t x1, uint16_t y1)
{
    sendCmd(CMD_CLEAR_WINDOW);//clear window
    sendCmd(x0);//start column
    sendCmd(y0);//start row
    sendCmd(x1);//end column
    sendCmd(y1);//end row
}

//------------------------------------------------------------------------------------
void SSD1331::setScolling(ScollingDirection direction, uint8_t rowAddr, uint8_t rowNum, uint8_t timeInterval)
{
    uint8_t scolling_horizontal = 0x0;
    uint8_t scolling_vertical = 0x0;
    switch(direction){
        case Horizontal:
            scolling_horizontal = 0x01;
            scolling_vertical = 0x00;
            break;
        case Vertical:
            scolling_horizontal = 0x00;
            scolling_vertical = 0x01;
            break;
        case Diagonal:
            scolling_horizontal = 0x01;
            scolling_vertical = 0x01;
            break;
        default:
            break;
    }
    sendCmd(CMD_CONTINUOUS_SCROLLING_SETUP);
    sendCmd(scolling_horizontal);
    sendCmd(rowAddr);
    sendCmd(rowNum);
    sendCmd(scolling_vertical);
    sendCmd(timeInterval);
    sendCmd(CMD_ACTIVE_SCROLLING);
}

//------------------------------------------------------------------------------------
void SSD1331::enableScolling(bool enable)
{
    if(enable)
        sendCmd(CMD_ACTIVE_SCROLLING);
    else
        sendCmd(CMD_DEACTIVE_SCROLLING);
}

//------------------------------------------------------------------------------------
void SSD1331::setDisplayMode(DisplayMode mode)
{
    sendCmd(mode);
}

//------------------------------------------------------------------------------------
void SSD1331::setDisplayPower(DisplayPower power)
{
    sendCmd(power);
}

//------------------------------------------------------------------------------------
int SSD1331::_getc() 
{
    return -1;
}

//------------------------------------------------------------------------------------
int SSD1331::_putc( int c )
{  
    return -1;
}