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.
Diff: Drivers/SSD1351_SPI.cpp
- Revision:
- 2:bbfc18022ee5
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/Drivers/SSD1351_SPI.cpp Tue May 27 20:05:29 2014 +0000 @@ -0,0 +1,198 @@ +/* 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; +}