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/SSD1306_I2C.cpp
- Revision:
- 1:f7003ec66a51
- Child:
- 2:bbfc18022ee5
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/Drivers/SSD1306_I2C.cpp Fri Mar 14 19:17:44 2014 +0000 @@ -0,0 +1,145 @@ +/* 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 "SSD1306_I2C.h" + +SSD1306_I2C::SSD1306_I2C(PinName sda, PinName scl, Address addr) : Display(128, 64), m_I2C(sda, scl), m_ADDR((int)addr) +{ + //Set the I2C frequency to 400kHz + m_I2C.frequency(400000); +} + +bool SSD1306_I2C::open() +{ + //Probe for the SSD1306 using a Zero Length Transfer + if (!m_I2C.write(m_ADDR, NULL, 0)) { + //Init sequence for 128x64 OLED module + writeCommand(CMD_DISPLAYOFF); + writeCommand(CMD_SETDISPLAYCLOCKDIV); + writeCommand(0x80); + writeCommand(CMD_SETMULTIPLEX); + writeCommand(0x3F); + writeCommand(CMD_SETDISPLAYOFFSET); + writeCommand(0x0); + writeCommand(CMD_SETSTARTLINE | 0x0); + writeCommand(CMD_CHARGEPUMP); + writeCommand(CMD_CHARGEPUMPON); + writeCommand(CMD_MEMORYMODE); + writeCommand(0x00); + writeCommand(CMD_SEGREMAP | 0x1); + writeCommand(CMD_COMSCANDEC); + writeCommand(CMD_SETCOMPINS); + writeCommand(0x12); + writeCommand(CMD_SETCONTRAST); + writeCommand(0xCF); + writeCommand(CMD_SETPRECHARGE); + writeCommand(0xF1); + writeCommand(CMD_SETVCOMDETECT); + writeCommand(0x40); + writeCommand(CMD_DISPLAYALLON_RESUME); + writeCommand(CMD_NORMALDISPLAY); + + //Return success + return true; + } else { + //Return failure + return false; + } +} + +void SSD1306_I2C::finalize() +{ + //Select low col 0, hi col 0, line 0 + writeCommand(CMD_SETLOWCOLUMN | 0x0); + writeCommand(CMD_SETHIGHCOLUMN | 0x0); + writeCommand(CMD_SETSTARTLINE | 0x0); + + //Make sure the first byte in the buffer is the control byte + m_Buffer[0] = CONTROL_DATA; + + //Write the buffer + m_I2C.write(m_ADDR, m_Buffer, 1025); +} + +Display::State SSD1306_I2C::state() +{ + //Return the base class's state + return Display::state(); +} + +void SSD1306_I2C::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 SSD1306_I2C::drawPixel(int x, int y, unsigned int c) +{ + //Range check the pixel + if ((x < 0) || (x >= width()) || (y < 0) || (y >= height())) + return; + + //Make sure the color is fully opaque + if ((c >> 24) != 255) + return; + + //Determine the pixel byte index + unsigned short byteIndex = x + (y / 8) * width(); + + //HACK: Fix the whole 1025 byte i2c buffer thing + byteIndex++; + + //Set or clear the pixel + if ((c & 0x00FFFFFF) > 0) + m_Buffer[byteIndex] |= (1 << (y % 8)); + else + m_Buffer[byteIndex] &= ~(1 << (y % 8)); +} + +void SSD1306_I2C::writeCommand(char command) +{ + //Create a temporary buffer + char buff[2]; + + //Load the control byte and 8-bit command + buff[0] = CONTROL_COMMAND; + buff[1] = command; + + //Write the command + m_I2C.write(m_ADDR, buff, 2); +} + +void SSD1306_I2C::writeData(char data) +{ + //Create a temporary buffer + char buff[2]; + + //Load the control byte and 8-bit data + buff[0] = CONTROL_DATA; + buff[1] = data; + + //Write the data + m_I2C.write(m_ADDR, buff, 2); +}