A simple yet powerful library for controlling graphical displays. Multiple display controllers are supported using inheritance.

Dependents:   mbed_rifletool Hexi_Bubble_Game Hexi_Catch-the-dot_Game Hexi_Acceleromagnetic_Synth

NOTE: This library is in beta right now. As far as I know, everything here works, but there are many features that are lacking so far. Most notably containers, button handling, and display drivers other than the SSD1306.

Drivers/SSD1351_SPI.cpp

Committer:
neilt6
Date:
2014-05-27
Revision:
3:a8f72d4864e6
Parent:
2:bbfc18022ee5

File content as of revision 3:a8f72d4864e6:

/* NeatGUI Library
 * Copyright (c) 2013 Neil Thiessen
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *     http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

#include "SSD1351_SPI.h"

SSD1351_SPI::SSD1351_SPI(PinName mosi, PinName miso, PinName sclk, PinName cs, PinName dc) : Display(128, 128), m_SPI(mosi, miso, sclk), m_CS(cs), m_DC(dc)
{
    //Deselect the display
    m_CS = 1;

    //Set the SPI format to 8 bit data, high steady state clock, second edge capture
    m_SPI.format(8, 3);

    //Set the SPI frequency to 20MHz
    m_SPI.frequency(10000000);
}

bool SSD1351_SPI::open()
{
    //Init sequence for 128x128 OLED module
    writeCommand(CMD_COMMANDLOCK);
    writeData(0x12);
    writeCommand(CMD_COMMANDLOCK);
    writeData(0xB1);
    writeCommand(CMD_DISPLAYOFF);
    writeCommand(CMD_CLOCKDIV);
    writeCommand(0xF1);
    writeCommand(CMD_MUXRATIO);
    writeData(127);
    writeCommand(CMD_SETREMAP);
    //writeData(0x74);
    writeData(0xB4);
    //writeData(0b01110100);
    writeCommand(CMD_SETCOLUMN);
    writeData(0x00);
    writeData(0x7F);
    writeCommand(CMD_SETROW);
    writeData(0x00);
    writeData(0x7F);
    writeCommand(CMD_STARTLINE);
    writeData(0x0);
    writeCommand(CMD_DISPLAYOFFSET);
    writeData(0x0);
    writeCommand(CMD_SETGPIO);
    writeData(0x00);
    writeCommand(CMD_FUNCTIONSELECT);
    writeData(0x01);
    writeCommand(CMD_PRECHARGE);
    writeCommand(0x32);
    writeCommand(CMD_VCOMH);
    writeCommand(0x05);
    writeCommand(CMD_NORMALDISPLAY);
    writeCommand(CMD_CONTRASTABC);
    writeData(0xC8);
    writeData(0x80);
    writeData(0xC8);
    writeCommand(CMD_CONTRASTMASTER);
    writeData(0x0F);
    writeCommand(CMD_SETVSL );
    writeData(0xA0);
    writeData(0xB5);
    writeData(0x55);
    writeCommand(CMD_PRECHARGE2);
    writeData(0x01);

    //Return success
    return true;
}

void SSD1351_SPI::flush()
{
    if (m_CacheIndex > 0) {
        //Set DC to data and select the display
        m_DC = 1;
        m_CS = 0;

        //Write the entire cache at once
        for (int i = 0; i < m_CacheIndex; i++)
            m_SPI.write(m_Cache[i]);

        //Deselect the display
        m_CS = 1;

        //Reset the cache index
        m_CacheIndex = 0;
    }
}

Display::State SSD1351_SPI::state()
{
    //Return the base class's state
    return Display::state();
}

void SSD1351_SPI::state(State s)
{
    //Check what the requested state is
    if (s == Display::DISPLAY_ON) {
        //Turn the display on
        writeCommand(CMD_DISPLAYON);
    } else if (s == Display::DISPLAY_OFF) {
        //Turn the display off
        writeCommand(CMD_DISPLAYOFF);
    }

    //Update the base class
    Display::state(s);
}

void SSD1351_SPI::drawPixel(int x, int y, unsigned int c)
{
    //Range check the pixel
    if ((x < 0) || (x >= width()) || (y < 0) || (y >= height()))
        return;

    //Only goto if the cursor is out of position
    if (x != m_CursX || y != m_CursY) {
        //First flush the cache
        flush();

        //Set column start and end address (also moves pointer)
        writeCommand(CMD_SETCOLUMN);
        writeData(x);
        writeData(width() - 1);

        //Set row start and end address (also moves pointer)
        writeCommand(CMD_SETROW);
        writeData(y);
        writeData(height() - 1);

        writeCommand(CMD_WRITERAM);

        //Update the cursor variables
        m_StartX = x;
        m_StartY = y;
        m_CursX = x;
        m_CursY = y;
    }

    //Check if the cache is full
    if (m_CacheIndex > 1024 - 4) {
        //Flush the cache
        flush();
    }

    //Add this pixel to the cache
    m_Cache[m_CacheIndex++] = c >> 18;
    m_Cache[m_CacheIndex++] = c >> 10;
    m_Cache[m_CacheIndex++] = c >> 2;

    //Increment the cursor with wrapping
    if (++m_CursX > width() - 1) {
        m_CursX = m_StartX;

        if (++m_CursY > height() - 1) {
            m_CursY = m_StartY;
        }
    }
}

void SSD1351_SPI::writeCommand(char command)
{
    //Set DC to command and select the display
    m_DC = 0;
    m_CS = 0;

    //Write the command byte
    m_SPI.write(command);

    //Deselect the display
    m_CS = 1;
}

void SSD1351_SPI::writeData(char data)
{
    //Set DC to data and select the display
    m_DC = 1;
    m_CS = 0;

    //Write the data byte
    m_SPI.write(data);

    //Deselect the display
    m_CS = 1;
}