SPKDisplay - A mbed display class and processing imaging tools for 128x64 OLEDs using the SSD1305 driver, connected via SPI.

Dependents:   SPK-DVIMXR SPK-DMXer

Committer:
tobyspark
Date:
Sun Apr 15 16:51:01 2012 +0000
Revision:
0:76bb084fa033
Child:
1:dd3faa2ab1dd
Initial commit after internal dev as part of SPK-DVIMXR

Who changed what in which revision?

UserRevisionLine numberNew contents of line
tobyspark 0:76bb084fa033 1 // *spark audio-visual
tobyspark 0:76bb084fa033 2 // OLED display using SSD1305 driver
tobyspark 0:76bb084fa033 3 // Copyright *spark audio-visual 2012
tobyspark 0:76bb084fa033 4
tobyspark 0:76bb084fa033 5 #include "spk_oled_ssd1305.h"
tobyspark 0:76bb084fa033 6 #include "mbed.h"
tobyspark 0:76bb084fa033 7
tobyspark 0:76bb084fa033 8 SPKDisplay::SPKDisplay(PinName mosiPin, PinName clkPin, PinName csPin, PinName dcPin, PinName resPin, Serial *debugSerial)
tobyspark 0:76bb084fa033 9 {
tobyspark 0:76bb084fa033 10 bufferHasChanged = false;
tobyspark 0:76bb084fa033 11
tobyspark 0:76bb084fa033 12 spi = new SPI(mosiPin, NC, clkPin);
tobyspark 0:76bb084fa033 13 spi->format(8,3);
tobyspark 0:76bb084fa033 14 spi->frequency(2000000);
tobyspark 0:76bb084fa033 15
tobyspark 0:76bb084fa033 16 cs = new DigitalOut(csPin);
tobyspark 0:76bb084fa033 17 dc = new DigitalOut(dcPin);
tobyspark 0:76bb084fa033 18 res = new DigitalOut(resPin);
tobyspark 0:76bb084fa033 19
tobyspark 0:76bb084fa033 20 // Link up debug Serial object
tobyspark 0:76bb084fa033 21 // Passing in shared object as debugging is shared between all DVI mixer functions
tobyspark 0:76bb084fa033 22 debug = debugSerial;
tobyspark 0:76bb084fa033 23
tobyspark 0:76bb084fa033 24 setup();
tobyspark 0:76bb084fa033 25
tobyspark 0:76bb084fa033 26 clearBuffer();
tobyspark 0:76bb084fa033 27
tobyspark 0:76bb084fa033 28 if (debug) debug->printf("SPKDisplay loaded\n\r");
tobyspark 0:76bb084fa033 29 }
tobyspark 0:76bb084fa033 30
tobyspark 0:76bb084fa033 31 void SPKDisplay::clearBuffer()
tobyspark 0:76bb084fa033 32 {
tobyspark 0:76bb084fa033 33 memset(buffer, 0, bufferCount);
tobyspark 0:76bb084fa033 34 bufferHasChanged = true;
tobyspark 0:76bb084fa033 35 }
tobyspark 0:76bb084fa033 36
tobyspark 0:76bb084fa033 37 void SPKDisplay::imageToBuffer()
tobyspark 0:76bb084fa033 38 {
tobyspark 0:76bb084fa033 39 memcpy(buffer, image, bufferCount);
tobyspark 0:76bb084fa033 40 bufferHasChanged = true;
tobyspark 0:76bb084fa033 41 }
tobyspark 0:76bb084fa033 42
tobyspark 0:76bb084fa033 43 void SPKDisplay::clearBufferRow(int row)
tobyspark 0:76bb084fa033 44 {
tobyspark 0:76bb084fa033 45 // Range check
tobyspark 0:76bb084fa033 46 if (row >= 8)
tobyspark 0:76bb084fa033 47 {
tobyspark 0:76bb084fa033 48 if (debug) debug->printf("SPKDisplay::clearBufferRow sent out of bounds row");
tobyspark 0:76bb084fa033 49 return;
tobyspark 0:76bb084fa033 50 }
tobyspark 0:76bb084fa033 51 int bStart = row*bufferWidth;
tobyspark 0:76bb084fa033 52 int bEnd = bStart + pixelWidth;
tobyspark 0:76bb084fa033 53
tobyspark 0:76bb084fa033 54 for (int bPos = bStart; bPos <= bEnd; bPos++)
tobyspark 0:76bb084fa033 55 {
tobyspark 0:76bb084fa033 56 buffer[bPos] = 0x00;
tobyspark 0:76bb084fa033 57 }
tobyspark 0:76bb084fa033 58
tobyspark 0:76bb084fa033 59 bufferHasChanged = true;
tobyspark 0:76bb084fa033 60 }
tobyspark 0:76bb084fa033 61
tobyspark 0:76bb084fa033 62 void SPKDisplay::horizLineToBuffer(int y)
tobyspark 0:76bb084fa033 63 {
tobyspark 0:76bb084fa033 64 if (y >= pixelHeight)
tobyspark 0:76bb084fa033 65 {
tobyspark 0:76bb084fa033 66 if (debug) debug->printf("SPKDisplay::clearBufferRow sent out of bounds y");
tobyspark 0:76bb084fa033 67 return;
tobyspark 0:76bb084fa033 68 }
tobyspark 0:76bb084fa033 69
tobyspark 0:76bb084fa033 70 int row = (y*pixInPage) / pixelHeight;
tobyspark 0:76bb084fa033 71 int posInRow = y % pixInPage;
tobyspark 0:76bb084fa033 72
tobyspark 0:76bb084fa033 73 int bStart = row*bufferWidth;
tobyspark 0:76bb084fa033 74 int bEnd = bStart + pixelWidth;
tobyspark 0:76bb084fa033 75
tobyspark 0:76bb084fa033 76 for (int bPos = bStart; bPos <= bEnd; bPos++)
tobyspark 0:76bb084fa033 77 {
tobyspark 0:76bb084fa033 78 // Need to bitwise OR as setting single bit (the line) in byte (the row)
tobyspark 0:76bb084fa033 79 buffer[bPos] = buffer[bPos] | 0x01 << posInRow;
tobyspark 0:76bb084fa033 80 }
tobyspark 0:76bb084fa033 81
tobyspark 0:76bb084fa033 82 bufferHasChanged = true;
tobyspark 0:76bb084fa033 83 }
tobyspark 0:76bb084fa033 84
tobyspark 0:76bb084fa033 85 void SPKDisplay::textToBuffer(std::string message, int row)
tobyspark 0:76bb084fa033 86 {
tobyspark 0:76bb084fa033 87 // Range check
tobyspark 0:76bb084fa033 88 if (row >= 8) row = 7;
tobyspark 0:76bb084fa033 89 int bStart = row*bufferWidth;
tobyspark 0:76bb084fa033 90 int bEnd = bStart + pixelWidth;
tobyspark 0:76bb084fa033 91
tobyspark 0:76bb084fa033 92 int bPos = bStart;
tobyspark 0:76bb084fa033 93 for (int i = 0; i < message.size(); i++)
tobyspark 0:76bb084fa033 94 {
tobyspark 0:76bb084fa033 95 char character = message.at(i);
tobyspark 0:76bb084fa033 96
tobyspark 0:76bb084fa033 97 // Is it outside the range we have glyphs for?
tobyspark 0:76bb084fa033 98 if ((character < characterBytesStartChar) || (character > characterBytesEndChar))
tobyspark 0:76bb084fa033 99 {
tobyspark 0:76bb084fa033 100 // Treat as a space
tobyspark 0:76bb084fa033 101 for (int j = 0; j < 5; j++)
tobyspark 0:76bb084fa033 102 {
tobyspark 0:76bb084fa033 103 if (bPos >= bEnd) break;
tobyspark 0:76bb084fa033 104 buffer[bPos++] = 0x00;
tobyspark 0:76bb084fa033 105 }
tobyspark 0:76bb084fa033 106
tobyspark 0:76bb084fa033 107 // Warn if not
tobyspark 0:76bb084fa033 108 if (debug)
tobyspark 0:76bb084fa033 109 {
tobyspark 0:76bb084fa033 110 if (character != ' ') debug->printf("No glyph for character %c at position %i", character, i);
tobyspark 0:76bb084fa033 111 }
tobyspark 0:76bb084fa033 112 }
tobyspark 0:76bb084fa033 113 // If not, typeset it!
tobyspark 0:76bb084fa033 114 else
tobyspark 0:76bb084fa033 115 {
tobyspark 0:76bb084fa033 116 // Shift into our array's indexing
tobyspark 0:76bb084fa033 117 character -= characterBytesStartChar;
tobyspark 0:76bb084fa033 118
tobyspark 0:76bb084fa033 119 // Write each byte's vertical column of 8bits into the buffer.
tobyspark 0:76bb084fa033 120 for (int j = 0; j < characterBytes[character][0]; j++)
tobyspark 0:76bb084fa033 121 {
tobyspark 0:76bb084fa033 122 if (bPos >= bEnd) break;
tobyspark 0:76bb084fa033 123 buffer[bPos++] = characterBytes[character][j+1];
tobyspark 0:76bb084fa033 124 }
tobyspark 0:76bb084fa033 125
tobyspark 0:76bb084fa033 126 // Put 1px letter spacing at end
tobyspark 0:76bb084fa033 127 if (bPos >= bEnd) break;
tobyspark 0:76bb084fa033 128 buffer[bPos++] = 0x00; // 1 px letter spacing
tobyspark 0:76bb084fa033 129 }
tobyspark 0:76bb084fa033 130 }
tobyspark 0:76bb084fa033 131
tobyspark 0:76bb084fa033 132 bufferHasChanged = true;
tobyspark 0:76bb084fa033 133 }
tobyspark 0:76bb084fa033 134
tobyspark 0:76bb084fa033 135 void SPKDisplay::sendBuffer()
tobyspark 0:76bb084fa033 136 {
tobyspark 0:76bb084fa033 137 if (bufferHasChanged)
tobyspark 0:76bb084fa033 138 {
tobyspark 0:76bb084fa033 139 // Select the device by seting chip select low
tobyspark 0:76bb084fa033 140 *cs = 0;
tobyspark 0:76bb084fa033 141
tobyspark 0:76bb084fa033 142 // Set to receive DATA not commands
tobyspark 0:76bb084fa033 143 *dc = 1;
tobyspark 0:76bb084fa033 144
tobyspark 0:76bb084fa033 145 for (int i = 0; i < bufferCount; i++)
tobyspark 0:76bb084fa033 146 {
tobyspark 0:76bb084fa033 147 spi->write(buffer[i]);
tobyspark 0:76bb084fa033 148 }
tobyspark 0:76bb084fa033 149
tobyspark 0:76bb084fa033 150 // Deselect the device
tobyspark 0:76bb084fa033 151 *cs = 1;
tobyspark 0:76bb084fa033 152
tobyspark 0:76bb084fa033 153 bufferHasChanged = false;
tobyspark 0:76bb084fa033 154 }
tobyspark 0:76bb084fa033 155 }
tobyspark 0:76bb084fa033 156
tobyspark 0:76bb084fa033 157 void SPKDisplay::setup()
tobyspark 0:76bb084fa033 158 {
tobyspark 0:76bb084fa033 159 // TASK: SCREEN OFF, Run pre-flight
tobyspark 0:76bb084fa033 160
tobyspark 0:76bb084fa033 161 // Hard reset the OLED
tobyspark 0:76bb084fa033 162 *res = 0;
tobyspark 0:76bb084fa033 163 wait_ms(1);
tobyspark 0:76bb084fa033 164 *res = 1;
tobyspark 0:76bb084fa033 165
tobyspark 0:76bb084fa033 166 // Select the device by seting chip select low
tobyspark 0:76bb084fa033 167 *cs = 0;
tobyspark 0:76bb084fa033 168
tobyspark 0:76bb084fa033 169 // Set to receive COMMANDS not data
tobyspark 0:76bb084fa033 170 *dc = 0;
tobyspark 0:76bb084fa033 171
tobyspark 0:76bb084fa033 172 spi->write(0xAE); // set display off
tobyspark 0:76bb084fa033 173 spi->write(0xD5); // set display clock divide ratio
tobyspark 0:76bb084fa033 174 spi->write(0xA0);
tobyspark 0:76bb084fa033 175 spi->write(0xA8); // set multiplex ratio
tobyspark 0:76bb084fa033 176 spi->write(0x3F);
tobyspark 0:76bb084fa033 177 spi->write(0xD3); // set display offset
tobyspark 0:76bb084fa033 178 spi->write(0x00);
tobyspark 0:76bb084fa033 179 spi->write(0x40); // set display start line
tobyspark 0:76bb084fa033 180 spi->write(0xAD); // set master configuration
tobyspark 0:76bb084fa033 181 spi->write(0x8E);
tobyspark 0:76bb084fa033 182 spi->write(0xD8); // set area color mode
tobyspark 0:76bb084fa033 183 spi->write(0x05);
tobyspark 0:76bb084fa033 184 spi->write(0xA1); // set segment re-map
tobyspark 0:76bb084fa033 185 spi->write(0xC8); // set com output scan direction
tobyspark 0:76bb084fa033 186 spi->write(0xDA); // set com pins hardware configuration
tobyspark 0:76bb084fa033 187 spi->write(0x12);
tobyspark 0:76bb084fa033 188 spi->write(0x91); // set look-up table
tobyspark 0:76bb084fa033 189 spi->write(0x3F);
tobyspark 0:76bb084fa033 190 spi->write(0x3F);
tobyspark 0:76bb084fa033 191 spi->write(0x3F);
tobyspark 0:76bb084fa033 192 spi->write(0x3F);
tobyspark 0:76bb084fa033 193 spi->write(0x81); // set current control for bank 0
tobyspark 0:76bb084fa033 194 spi->write(0x8F);
tobyspark 0:76bb084fa033 195 spi->write(0xD9); // set pre-charge period
tobyspark 0:76bb084fa033 196 spi->write(0xD2);
tobyspark 0:76bb084fa033 197 spi->write(0xDB); //set vcomh deselect level
tobyspark 0:76bb084fa033 198 spi->write(0x34);
tobyspark 0:76bb084fa033 199 spi->write(0xA4); // set entire display on/off
tobyspark 0:76bb084fa033 200 spi->write(0xA6); // set normal/inverse display
tobyspark 0:76bb084fa033 201
tobyspark 0:76bb084fa033 202 spi->write(0x20); // page mode
tobyspark 0:76bb084fa033 203 spi->write(0x00);
tobyspark 0:76bb084fa033 204
tobyspark 0:76bb084fa033 205 // TASK: Clear screen's content buffer
tobyspark 0:76bb084fa033 206
tobyspark 0:76bb084fa033 207 // Is this neccessary when switching command/data?
tobyspark 0:76bb084fa033 208 *cs = 1;
tobyspark 0:76bb084fa033 209 wait_ms(1);
tobyspark 0:76bb084fa033 210 *cs = 0;
tobyspark 0:76bb084fa033 211
tobyspark 0:76bb084fa033 212 // Set to receive DATA not commands
tobyspark 0:76bb084fa033 213 *dc = 1;
tobyspark 0:76bb084fa033 214
tobyspark 0:76bb084fa033 215 for (int i = 0; i < bufferCount; i++)
tobyspark 0:76bb084fa033 216 {
tobyspark 0:76bb084fa033 217 spi->write(0x00);
tobyspark 0:76bb084fa033 218 }
tobyspark 0:76bb084fa033 219
tobyspark 0:76bb084fa033 220 // TASK: SCREEN ON
tobyspark 0:76bb084fa033 221
tobyspark 0:76bb084fa033 222 // Is this neccessary when switching command/data?
tobyspark 0:76bb084fa033 223 *cs = 1;
tobyspark 0:76bb084fa033 224 wait_ms(1);
tobyspark 0:76bb084fa033 225 *cs = 0;
tobyspark 0:76bb084fa033 226
tobyspark 0:76bb084fa033 227 // Set to receive COMMANDS not data
tobyspark 0:76bb084fa033 228 *dc = 0;
tobyspark 0:76bb084fa033 229
tobyspark 0:76bb084fa033 230 spi->write(0xAF); // set display on
tobyspark 0:76bb084fa033 231
tobyspark 0:76bb084fa033 232 // Deselect the device
tobyspark 0:76bb084fa033 233 *cs = 1;
tobyspark 0:76bb084fa033 234 }