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@3:a8f72d4864e6, 2014-05-27 (annotated)
- Committer:
- neilt6
- Date:
- Tue May 27 21:41:28 2014 +0000
- Revision:
- 3:a8f72d4864e6
- Parent:
- 2:bbfc18022ee5
Syntax improvements
Who changed what in which revision?
User | Revision | Line number | New contents of line |
---|---|---|---|
neilt6 | 2:bbfc18022ee5 | 1 | /* NeatGUI Library |
neilt6 | 2:bbfc18022ee5 | 2 | * Copyright (c) 2013 Neil Thiessen |
neilt6 | 2:bbfc18022ee5 | 3 | * |
neilt6 | 2:bbfc18022ee5 | 4 | * Licensed under the Apache License, Version 2.0 (the "License"); |
neilt6 | 2:bbfc18022ee5 | 5 | * you may not use this file except in compliance with the License. |
neilt6 | 2:bbfc18022ee5 | 6 | * You may obtain a copy of the License at |
neilt6 | 2:bbfc18022ee5 | 7 | * |
neilt6 | 2:bbfc18022ee5 | 8 | * http://www.apache.org/licenses/LICENSE-2.0 |
neilt6 | 2:bbfc18022ee5 | 9 | * |
neilt6 | 2:bbfc18022ee5 | 10 | * Unless required by applicable law or agreed to in writing, software |
neilt6 | 2:bbfc18022ee5 | 11 | * distributed under the License is distributed on an "AS IS" BASIS, |
neilt6 | 2:bbfc18022ee5 | 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. |
neilt6 | 2:bbfc18022ee5 | 13 | * See the License for the specific language governing permissions and |
neilt6 | 2:bbfc18022ee5 | 14 | * limitations under the License. |
neilt6 | 2:bbfc18022ee5 | 15 | */ |
neilt6 | 2:bbfc18022ee5 | 16 | |
neilt6 | 2:bbfc18022ee5 | 17 | #include "SSD1351_SPI.h" |
neilt6 | 2:bbfc18022ee5 | 18 | |
neilt6 | 2:bbfc18022ee5 | 19 | 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) |
neilt6 | 2:bbfc18022ee5 | 20 | { |
neilt6 | 2:bbfc18022ee5 | 21 | //Deselect the display |
neilt6 | 2:bbfc18022ee5 | 22 | m_CS = 1; |
neilt6 | 2:bbfc18022ee5 | 23 | |
neilt6 | 2:bbfc18022ee5 | 24 | //Set the SPI format to 8 bit data, high steady state clock, second edge capture |
neilt6 | 2:bbfc18022ee5 | 25 | m_SPI.format(8, 3); |
neilt6 | 2:bbfc18022ee5 | 26 | |
neilt6 | 2:bbfc18022ee5 | 27 | //Set the SPI frequency to 20MHz |
neilt6 | 2:bbfc18022ee5 | 28 | m_SPI.frequency(10000000); |
neilt6 | 2:bbfc18022ee5 | 29 | } |
neilt6 | 2:bbfc18022ee5 | 30 | |
neilt6 | 2:bbfc18022ee5 | 31 | bool SSD1351_SPI::open() |
neilt6 | 2:bbfc18022ee5 | 32 | { |
neilt6 | 2:bbfc18022ee5 | 33 | //Init sequence for 128x128 OLED module |
neilt6 | 2:bbfc18022ee5 | 34 | writeCommand(CMD_COMMANDLOCK); |
neilt6 | 2:bbfc18022ee5 | 35 | writeData(0x12); |
neilt6 | 2:bbfc18022ee5 | 36 | writeCommand(CMD_COMMANDLOCK); |
neilt6 | 2:bbfc18022ee5 | 37 | writeData(0xB1); |
neilt6 | 2:bbfc18022ee5 | 38 | writeCommand(CMD_DISPLAYOFF); |
neilt6 | 2:bbfc18022ee5 | 39 | writeCommand(CMD_CLOCKDIV); |
neilt6 | 2:bbfc18022ee5 | 40 | writeCommand(0xF1); |
neilt6 | 2:bbfc18022ee5 | 41 | writeCommand(CMD_MUXRATIO); |
neilt6 | 2:bbfc18022ee5 | 42 | writeData(127); |
neilt6 | 2:bbfc18022ee5 | 43 | writeCommand(CMD_SETREMAP); |
neilt6 | 2:bbfc18022ee5 | 44 | //writeData(0x74); |
neilt6 | 2:bbfc18022ee5 | 45 | writeData(0xB4); |
neilt6 | 2:bbfc18022ee5 | 46 | //writeData(0b01110100); |
neilt6 | 2:bbfc18022ee5 | 47 | writeCommand(CMD_SETCOLUMN); |
neilt6 | 2:bbfc18022ee5 | 48 | writeData(0x00); |
neilt6 | 2:bbfc18022ee5 | 49 | writeData(0x7F); |
neilt6 | 2:bbfc18022ee5 | 50 | writeCommand(CMD_SETROW); |
neilt6 | 2:bbfc18022ee5 | 51 | writeData(0x00); |
neilt6 | 2:bbfc18022ee5 | 52 | writeData(0x7F); |
neilt6 | 2:bbfc18022ee5 | 53 | writeCommand(CMD_STARTLINE); |
neilt6 | 2:bbfc18022ee5 | 54 | writeData(0x0); |
neilt6 | 2:bbfc18022ee5 | 55 | writeCommand(CMD_DISPLAYOFFSET); |
neilt6 | 2:bbfc18022ee5 | 56 | writeData(0x0); |
neilt6 | 2:bbfc18022ee5 | 57 | writeCommand(CMD_SETGPIO); |
neilt6 | 2:bbfc18022ee5 | 58 | writeData(0x00); |
neilt6 | 2:bbfc18022ee5 | 59 | writeCommand(CMD_FUNCTIONSELECT); |
neilt6 | 2:bbfc18022ee5 | 60 | writeData(0x01); |
neilt6 | 2:bbfc18022ee5 | 61 | writeCommand(CMD_PRECHARGE); |
neilt6 | 2:bbfc18022ee5 | 62 | writeCommand(0x32); |
neilt6 | 2:bbfc18022ee5 | 63 | writeCommand(CMD_VCOMH); |
neilt6 | 2:bbfc18022ee5 | 64 | writeCommand(0x05); |
neilt6 | 2:bbfc18022ee5 | 65 | writeCommand(CMD_NORMALDISPLAY); |
neilt6 | 2:bbfc18022ee5 | 66 | writeCommand(CMD_CONTRASTABC); |
neilt6 | 2:bbfc18022ee5 | 67 | writeData(0xC8); |
neilt6 | 2:bbfc18022ee5 | 68 | writeData(0x80); |
neilt6 | 2:bbfc18022ee5 | 69 | writeData(0xC8); |
neilt6 | 2:bbfc18022ee5 | 70 | writeCommand(CMD_CONTRASTMASTER); |
neilt6 | 2:bbfc18022ee5 | 71 | writeData(0x0F); |
neilt6 | 2:bbfc18022ee5 | 72 | writeCommand(CMD_SETVSL ); |
neilt6 | 2:bbfc18022ee5 | 73 | writeData(0xA0); |
neilt6 | 2:bbfc18022ee5 | 74 | writeData(0xB5); |
neilt6 | 2:bbfc18022ee5 | 75 | writeData(0x55); |
neilt6 | 2:bbfc18022ee5 | 76 | writeCommand(CMD_PRECHARGE2); |
neilt6 | 2:bbfc18022ee5 | 77 | writeData(0x01); |
neilt6 | 2:bbfc18022ee5 | 78 | |
neilt6 | 2:bbfc18022ee5 | 79 | //Return success |
neilt6 | 2:bbfc18022ee5 | 80 | return true; |
neilt6 | 2:bbfc18022ee5 | 81 | } |
neilt6 | 2:bbfc18022ee5 | 82 | |
neilt6 | 2:bbfc18022ee5 | 83 | void SSD1351_SPI::flush() |
neilt6 | 2:bbfc18022ee5 | 84 | { |
neilt6 | 2:bbfc18022ee5 | 85 | if (m_CacheIndex > 0) { |
neilt6 | 2:bbfc18022ee5 | 86 | //Set DC to data and select the display |
neilt6 | 2:bbfc18022ee5 | 87 | m_DC = 1; |
neilt6 | 2:bbfc18022ee5 | 88 | m_CS = 0; |
neilt6 | 2:bbfc18022ee5 | 89 | |
neilt6 | 2:bbfc18022ee5 | 90 | //Write the entire cache at once |
neilt6 | 2:bbfc18022ee5 | 91 | for (int i = 0; i < m_CacheIndex; i++) |
neilt6 | 2:bbfc18022ee5 | 92 | m_SPI.write(m_Cache[i]); |
neilt6 | 2:bbfc18022ee5 | 93 | |
neilt6 | 2:bbfc18022ee5 | 94 | //Deselect the display |
neilt6 | 2:bbfc18022ee5 | 95 | m_CS = 1; |
neilt6 | 2:bbfc18022ee5 | 96 | |
neilt6 | 2:bbfc18022ee5 | 97 | //Reset the cache index |
neilt6 | 2:bbfc18022ee5 | 98 | m_CacheIndex = 0; |
neilt6 | 2:bbfc18022ee5 | 99 | } |
neilt6 | 2:bbfc18022ee5 | 100 | } |
neilt6 | 2:bbfc18022ee5 | 101 | |
neilt6 | 2:bbfc18022ee5 | 102 | Display::State SSD1351_SPI::state() |
neilt6 | 2:bbfc18022ee5 | 103 | { |
neilt6 | 2:bbfc18022ee5 | 104 | //Return the base class's state |
neilt6 | 2:bbfc18022ee5 | 105 | return Display::state(); |
neilt6 | 2:bbfc18022ee5 | 106 | } |
neilt6 | 2:bbfc18022ee5 | 107 | |
neilt6 | 2:bbfc18022ee5 | 108 | void SSD1351_SPI::state(State s) |
neilt6 | 2:bbfc18022ee5 | 109 | { |
neilt6 | 2:bbfc18022ee5 | 110 | //Check what the requested state is |
neilt6 | 2:bbfc18022ee5 | 111 | if (s == Display::DISPLAY_ON) { |
neilt6 | 2:bbfc18022ee5 | 112 | //Turn the display on |
neilt6 | 2:bbfc18022ee5 | 113 | writeCommand(CMD_DISPLAYON); |
neilt6 | 2:bbfc18022ee5 | 114 | } else if (s == Display::DISPLAY_OFF) { |
neilt6 | 2:bbfc18022ee5 | 115 | //Turn the display off |
neilt6 | 2:bbfc18022ee5 | 116 | writeCommand(CMD_DISPLAYOFF); |
neilt6 | 2:bbfc18022ee5 | 117 | } |
neilt6 | 2:bbfc18022ee5 | 118 | |
neilt6 | 2:bbfc18022ee5 | 119 | //Update the base class |
neilt6 | 2:bbfc18022ee5 | 120 | Display::state(s); |
neilt6 | 2:bbfc18022ee5 | 121 | } |
neilt6 | 2:bbfc18022ee5 | 122 | |
neilt6 | 2:bbfc18022ee5 | 123 | void SSD1351_SPI::drawPixel(int x, int y, unsigned int c) |
neilt6 | 2:bbfc18022ee5 | 124 | { |
neilt6 | 2:bbfc18022ee5 | 125 | //Range check the pixel |
neilt6 | 2:bbfc18022ee5 | 126 | if ((x < 0) || (x >= width()) || (y < 0) || (y >= height())) |
neilt6 | 2:bbfc18022ee5 | 127 | return; |
neilt6 | 2:bbfc18022ee5 | 128 | |
neilt6 | 2:bbfc18022ee5 | 129 | //Only goto if the cursor is out of position |
neilt6 | 2:bbfc18022ee5 | 130 | if (x != m_CursX || y != m_CursY) { |
neilt6 | 2:bbfc18022ee5 | 131 | //First flush the cache |
neilt6 | 2:bbfc18022ee5 | 132 | flush(); |
neilt6 | 2:bbfc18022ee5 | 133 | |
neilt6 | 2:bbfc18022ee5 | 134 | //Set column start and end address (also moves pointer) |
neilt6 | 2:bbfc18022ee5 | 135 | writeCommand(CMD_SETCOLUMN); |
neilt6 | 2:bbfc18022ee5 | 136 | writeData(x); |
neilt6 | 2:bbfc18022ee5 | 137 | writeData(width() - 1); |
neilt6 | 2:bbfc18022ee5 | 138 | |
neilt6 | 2:bbfc18022ee5 | 139 | //Set row start and end address (also moves pointer) |
neilt6 | 2:bbfc18022ee5 | 140 | writeCommand(CMD_SETROW); |
neilt6 | 2:bbfc18022ee5 | 141 | writeData(y); |
neilt6 | 2:bbfc18022ee5 | 142 | writeData(height() - 1); |
neilt6 | 2:bbfc18022ee5 | 143 | |
neilt6 | 2:bbfc18022ee5 | 144 | writeCommand(CMD_WRITERAM); |
neilt6 | 2:bbfc18022ee5 | 145 | |
neilt6 | 2:bbfc18022ee5 | 146 | //Update the cursor variables |
neilt6 | 2:bbfc18022ee5 | 147 | m_StartX = x; |
neilt6 | 2:bbfc18022ee5 | 148 | m_StartY = y; |
neilt6 | 2:bbfc18022ee5 | 149 | m_CursX = x; |
neilt6 | 2:bbfc18022ee5 | 150 | m_CursY = y; |
neilt6 | 2:bbfc18022ee5 | 151 | } |
neilt6 | 2:bbfc18022ee5 | 152 | |
neilt6 | 2:bbfc18022ee5 | 153 | //Check if the cache is full |
neilt6 | 2:bbfc18022ee5 | 154 | if (m_CacheIndex > 1024 - 4) { |
neilt6 | 2:bbfc18022ee5 | 155 | //Flush the cache |
neilt6 | 2:bbfc18022ee5 | 156 | flush(); |
neilt6 | 2:bbfc18022ee5 | 157 | } |
neilt6 | 2:bbfc18022ee5 | 158 | |
neilt6 | 2:bbfc18022ee5 | 159 | //Add this pixel to the cache |
neilt6 | 2:bbfc18022ee5 | 160 | m_Cache[m_CacheIndex++] = c >> 18; |
neilt6 | 2:bbfc18022ee5 | 161 | m_Cache[m_CacheIndex++] = c >> 10; |
neilt6 | 2:bbfc18022ee5 | 162 | m_Cache[m_CacheIndex++] = c >> 2; |
neilt6 | 2:bbfc18022ee5 | 163 | |
neilt6 | 2:bbfc18022ee5 | 164 | //Increment the cursor with wrapping |
neilt6 | 2:bbfc18022ee5 | 165 | if (++m_CursX > width() - 1) { |
neilt6 | 2:bbfc18022ee5 | 166 | m_CursX = m_StartX; |
neilt6 | 2:bbfc18022ee5 | 167 | |
neilt6 | 2:bbfc18022ee5 | 168 | if (++m_CursY > height() - 1) { |
neilt6 | 2:bbfc18022ee5 | 169 | m_CursY = m_StartY; |
neilt6 | 2:bbfc18022ee5 | 170 | } |
neilt6 | 2:bbfc18022ee5 | 171 | } |
neilt6 | 2:bbfc18022ee5 | 172 | } |
neilt6 | 2:bbfc18022ee5 | 173 | |
neilt6 | 2:bbfc18022ee5 | 174 | void SSD1351_SPI::writeCommand(char command) |
neilt6 | 2:bbfc18022ee5 | 175 | { |
neilt6 | 2:bbfc18022ee5 | 176 | //Set DC to command and select the display |
neilt6 | 2:bbfc18022ee5 | 177 | m_DC = 0; |
neilt6 | 2:bbfc18022ee5 | 178 | m_CS = 0; |
neilt6 | 2:bbfc18022ee5 | 179 | |
neilt6 | 2:bbfc18022ee5 | 180 | //Write the command byte |
neilt6 | 2:bbfc18022ee5 | 181 | m_SPI.write(command); |
neilt6 | 2:bbfc18022ee5 | 182 | |
neilt6 | 2:bbfc18022ee5 | 183 | //Deselect the display |
neilt6 | 2:bbfc18022ee5 | 184 | m_CS = 1; |
neilt6 | 2:bbfc18022ee5 | 185 | } |
neilt6 | 2:bbfc18022ee5 | 186 | |
neilt6 | 2:bbfc18022ee5 | 187 | void SSD1351_SPI::writeData(char data) |
neilt6 | 2:bbfc18022ee5 | 188 | { |
neilt6 | 2:bbfc18022ee5 | 189 | //Set DC to data and select the display |
neilt6 | 2:bbfc18022ee5 | 190 | m_DC = 1; |
neilt6 | 2:bbfc18022ee5 | 191 | m_CS = 0; |
neilt6 | 2:bbfc18022ee5 | 192 | |
neilt6 | 2:bbfc18022ee5 | 193 | //Write the data byte |
neilt6 | 2:bbfc18022ee5 | 194 | m_SPI.write(data); |
neilt6 | 2:bbfc18022ee5 | 195 | |
neilt6 | 2:bbfc18022ee5 | 196 | //Deselect the display |
neilt6 | 2:bbfc18022ee5 | 197 | m_CS = 1; |
neilt6 | 2:bbfc18022ee5 | 198 | } |