SSD1308 128x64 OLED Driver with I2C interface

Dependents:   sense xadow_m0_ada_gps xadow_m0_SD_Hello sense-DHT11 ... more

See http://mbed.org/users/wim/notebook/oled-display-with-ssd1308-driver/#c6729

Committer:
wim
Date:
Sat Jul 21 12:49:33 2012 +0000
Revision:
1:b7e8f5139026
Parent:
0:300d08d9b058
Child:
2:16c84a134393
Added comments, Added progressbar

Who changed what in which revision?

UserRevisionLine numberNew contents of line
wim 1:b7e8f5139026 1 /** @file SSD1308 I2C device class file
wim 1:b7e8f5139026 2 * Based on Solomon Systech SSD1308 datasheet, rev. 1, 10/2008
wim 1:b7e8f5139026 3 * The SSD1308 is used for example in the Seeed 128x64 OLED Display
wim 1:b7e8f5139026 4 * http://www.seeedstudio.com/depot/grove-oled-display-12864-p-781.html?cPath=163_167
wim 1:b7e8f5139026 5 */
wim 0:300d08d9b058 6 // The original code by Andrew Schamp is using (and has been submitted as a part of) Jeff Rowberg's I2Cdevlib library,
wim 0:300d08d9b058 7 // which should (hopefully) always be available at https://github.com/jrowberg/i2cdevlib
wim 0:300d08d9b058 8 // Some parts also mashed up from Graphic Library for driving monochrome displays based on the PCD8544,
wim 0:300d08d9b058 9 // Copyright (c) 2011, Wim De Roeve, who in turn did partial port of code found on
wim 0:300d08d9b058 10 // http://serdisplib.sourceforge.net/ser/pcd8544.html#links and by Petras Saduikis <petras@petras.co.uk>
wim 0:300d08d9b058 11 //
wim 0:300d08d9b058 12 // Changelog:
wim 0:300d08d9b058 13 // 2011-08-25 - Initial release by Andrew Schamp <schamp@gmail.com>
wim 0:300d08d9b058 14 // 2012-06-19 - Ported to mbed and optimised (WH)
wim 0:300d08d9b058 15 //
wim 1:b7e8f5139026 16 /*
wim 1:b7e8f5139026 17 ================================================================================
wim 0:300d08d9b058 18 I2Cdev device library code is placed under the MIT license
wim 0:300d08d9b058 19 Copyright (c) 2011 Andrew Schamp
wim 0:300d08d9b058 20 Copyright (c) 2012 WH (mbed port)
wim 0:300d08d9b058 21
wim 0:300d08d9b058 22 Permission is hereby granted, free of charge, to any person obtaining a copy
wim 0:300d08d9b058 23 of this software and associated documentation files (the "Software"), to deal
wim 0:300d08d9b058 24 in the Software without restriction, including without limitation the rights
wim 0:300d08d9b058 25 to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
wim 0:300d08d9b058 26 copies of the Software, and to permit persons to whom the Software is
wim 0:300d08d9b058 27 furnished to do so, subject to the following conditions:
wim 0:300d08d9b058 28
wim 0:300d08d9b058 29 The above copyright notice and this permission notice shall be included in
wim 0:300d08d9b058 30 all copies or substantial portions of the Software.
wim 0:300d08d9b058 31
wim 0:300d08d9b058 32 THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
wim 0:300d08d9b058 33 IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
wim 0:300d08d9b058 34 FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
wim 0:300d08d9b058 35 AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
wim 0:300d08d9b058 36 LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
wim 0:300d08d9b058 37 OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
wim 0:300d08d9b058 38 THE SOFTWARE.
wim 1:b7e8f5139026 39 ================================================================================
wim 0:300d08d9b058 40 */
wim 0:300d08d9b058 41 #include "mbed.h"
wim 0:300d08d9b058 42 #include "SSD1308.h"
wim 0:300d08d9b058 43
wim 0:300d08d9b058 44 //#include "font_3x5.h"
wim 0:300d08d9b058 45 //#include "font_5x7.h"
wim 0:300d08d9b058 46 //#include "font_6x8.h"
wim 0:300d08d9b058 47 #include "font_8x8.h"
wim 0:300d08d9b058 48 //#include "font_8x12.h"
wim 0:300d08d9b058 49 //#include "font_16x20.h"
wim 0:300d08d9b058 50 #include "font_16x24.h"
wim 0:300d08d9b058 51
wim 1:b7e8f5139026 52 /**
wim 1:b7e8f5139026 53 *@brief Constructor
wim 1:b7e8f5139026 54 *@param I2C &i2c reference to i2c
wim 1:b7e8f5139026 55 *@param uint8_t deviceAddress slaveaddress
wim 1:b7e8f5139026 56 */
wim 0:300d08d9b058 57 SSD1308::SSD1308(I2C &i2c, uint8_t deviceAddress) : _i2c(i2c) {
wim 0:300d08d9b058 58 // m_devAddr = deviceAddress;
wim 0:300d08d9b058 59
wim 0:300d08d9b058 60 _writeOpcode = deviceAddress & 0xFE; // low order bit = 0 for write
wim 0:300d08d9b058 61 _readOpcode = deviceAddress | 0x01; // low order bit = 1 for read
wim 0:300d08d9b058 62
wim 0:300d08d9b058 63 initialize();
wim 0:300d08d9b058 64 }
wim 0:300d08d9b058 65
wim 1:b7e8f5139026 66 /** @brief High level Init, most settings remain at Power-On reset value
wim 1:b7e8f5139026 67 */
wim 0:300d08d9b058 68 void SSD1308::initialize() {
wim 0:300d08d9b058 69 setHorizontalAddressingMode();
wim 0:300d08d9b058 70
wim 0:300d08d9b058 71 clearDisplay();
wim 0:300d08d9b058 72
wim 0:300d08d9b058 73 setInverted(false);
wim 0:300d08d9b058 74
wim 0:300d08d9b058 75 setDisplayOn();
wim 0:300d08d9b058 76 }
wim 0:300d08d9b058 77
wim 0:300d08d9b058 78
wim 1:b7e8f5139026 79 /** @brief clear the display
wim 1:b7e8f5139026 80 */
wim 0:300d08d9b058 81 #if(0)
wim 0:300d08d9b058 82 // Standard version
wim 0:300d08d9b058 83 void SSD1308::clearDisplay() {
wim 0:300d08d9b058 84
wim 0:300d08d9b058 85 //setDisplayOff();
wim 0:300d08d9b058 86 setPageAddress(0, MAX_PAGE); // all pages
wim 0:300d08d9b058 87 setColumnAddress(0, MAX_COL); // all columns
wim 0:300d08d9b058 88
wim 0:300d08d9b058 89 for (uint8_t page = 0; page < PAGES; page++) {
wim 0:300d08d9b058 90 for (uint8_t col = 0; col < COLUMNS; col++) {
wim 0:300d08d9b058 91 _sendData(0x00);
wim 0:300d08d9b058 92 }
wim 0:300d08d9b058 93 }
wim 0:300d08d9b058 94
wim 0:300d08d9b058 95 //setDisplayOn();
wim 0:300d08d9b058 96 }
wim 0:300d08d9b058 97 #else
wim 0:300d08d9b058 98 //Optimised version
wim 0:300d08d9b058 99 // Save lots of I2C S,P, address and datacommands:
wim 0:300d08d9b058 100 // Send S, address, DATA_MODE, data, data, data,...., P
wim 0:300d08d9b058 101 //
wim 0:300d08d9b058 102 void SSD1308::clearDisplay() {
wim 0:300d08d9b058 103
wim 0:300d08d9b058 104 //setDisplayOff();
wim 0:300d08d9b058 105
wim 0:300d08d9b058 106 setPageAddress(0, MAX_PAGE); // all pages
wim 0:300d08d9b058 107 setColumnAddress(0, MAX_COL); // all columns
wim 0:300d08d9b058 108
wim 0:300d08d9b058 109 _i2c.start();
wim 0:300d08d9b058 110 _i2c.write(_writeOpcode);
wim 0:300d08d9b058 111 _i2c.write(DATA_MODE);
wim 0:300d08d9b058 112 for (int i=0; i<(PAGES * COLUMNS); i++) {
wim 0:300d08d9b058 113 _i2c.write(0x00); // Write Data
wim 0:300d08d9b058 114 }
wim 0:300d08d9b058 115 _i2c.stop();
wim 0:300d08d9b058 116
wim 0:300d08d9b058 117 //setDisplayOn();
wim 0:300d08d9b058 118 }
wim 0:300d08d9b058 119 #endif
wim 0:300d08d9b058 120
wim 0:300d08d9b058 121
wim 1:b7e8f5139026 122 /** @brief fill the display
wim 1:b7e8f5139026 123 * @param uint8_t pattern fillpattern vertical patch or 8 bits
wim 1:b7e8f5139026 124 */
wim 0:300d08d9b058 125 #if(0)
wim 0:300d08d9b058 126 //Standard version
wim 0:300d08d9b058 127 void SSD1308::fillDisplay(uint8_t pattern) {
wim 0:300d08d9b058 128
wim 0:300d08d9b058 129 //setDisplayOff();
wim 0:300d08d9b058 130
wim 0:300d08d9b058 131 setPageAddress(0, MAX_PAGE); // all pages
wim 0:300d08d9b058 132 setColumnAddress(0, MAX_COL); // all columns
wim 0:300d08d9b058 133
wim 0:300d08d9b058 134 for (uint8_t page = 0; page < PAGES; page++) {
wim 0:300d08d9b058 135 for (uint8_t col = 0; col < COLUMNS; col++) {
wim 0:300d08d9b058 136 _sendData(pattern);
wim 0:300d08d9b058 137 }
wim 0:300d08d9b058 138 }
wim 0:300d08d9b058 139
wim 0:300d08d9b058 140 //setDisplayOn();
wim 0:300d08d9b058 141 }
wim 0:300d08d9b058 142 #else
wim 0:300d08d9b058 143
wim 0:300d08d9b058 144 //Optimised version
wim 0:300d08d9b058 145 // Save lots of I2C S,P, address and datacommands:
wim 0:300d08d9b058 146 // Send S, address, DATA_MODE, data, data, data,...., P
wim 0:300d08d9b058 147 //
wim 0:300d08d9b058 148 void SSD1308::fillDisplay(uint8_t pattern,
wim 0:300d08d9b058 149 uint8_t start_page, uint8_t end_page,
wim 0:300d08d9b058 150 uint8_t start_col, uint8_t end_col) {
wim 0:300d08d9b058 151
wim 0:300d08d9b058 152 int count = (end_page - start_page + 1) * (end_col - start_col + 1);
wim 0:300d08d9b058 153
wim 0:300d08d9b058 154 //setDisplayOff();
wim 0:300d08d9b058 155 setPageAddress(start_page, end_page); // set page window
wim 0:300d08d9b058 156 setColumnAddress(start_col, end_col); // set column window
wim 0:300d08d9b058 157
wim 0:300d08d9b058 158 _i2c.start();
wim 0:300d08d9b058 159 _i2c.write(_writeOpcode);
wim 0:300d08d9b058 160 _i2c.write(DATA_MODE);
wim 0:300d08d9b058 161 for (int i=0; i<count; i++) {
wim 0:300d08d9b058 162 _i2c.write(pattern); // Write Data
wim 0:300d08d9b058 163 }
wim 0:300d08d9b058 164 _i2c.stop();
wim 0:300d08d9b058 165
wim 0:300d08d9b058 166 //setDisplayOn();
wim 0:300d08d9b058 167 }
wim 0:300d08d9b058 168
wim 0:300d08d9b058 169 #endif
wim 0:300d08d9b058 170
wim 0:300d08d9b058 171
wim 1:b7e8f5139026 172 /** @brief write a bitmap to the display
wim 1:b7e8f5139026 173 * @param uint8_t* data pointer to bitmap
wim 1:b7e8f5139026 174 * @param uint8_t start_page begin page (0..MAX_PAGE)
wim 1:b7e8f5139026 175 * @param uint8_t end_page end page (start_page..MAX_PAGE)
wim 1:b7e8f5139026 176 * @param uint8_t start_col begin column (0..MAX_COL)
wim 1:b7e8f5139026 177 * @param uint8_t end_col end column (start_col..MAX_COL)
wim 1:b7e8f5139026 178 */
wim 0:300d08d9b058 179 #if(0)
wim 0:300d08d9b058 180 //Standard version
wim 0:300d08d9b058 181 void SSD1308::writeBitmap(int len, uint8_t* data) {
wim 0:300d08d9b058 182
wim 0:300d08d9b058 183 //setDisplayOff();
wim 0:300d08d9b058 184 setPageAddress(0, MAX_PAGE); // all pages
wim 0:300d08d9b058 185 setColumnAddress(0, MAX_COL); // all columns
wim 0:300d08d9b058 186
wim 0:300d08d9b058 187 _i2c.start();
wim 0:300d08d9b058 188 _i2c.write(_writeOpcode);
wim 0:300d08d9b058 189 _i2c.write(DATA_MODE);
wim 0:300d08d9b058 190 for (int i=0; i<len; i++) {
wim 0:300d08d9b058 191 _i2c.write(data[i]); // Write Data
wim 0:300d08d9b058 192 }
wim 0:300d08d9b058 193 _i2c.stop();
wim 0:300d08d9b058 194
wim 0:300d08d9b058 195 //setDisplayOn();
wim 0:300d08d9b058 196 }
wim 0:300d08d9b058 197 #else
wim 0:300d08d9b058 198
wim 0:300d08d9b058 199 //Optimised version
wim 0:300d08d9b058 200 // Save lots of I2C S,P, address and datacommands:
wim 0:300d08d9b058 201 // Send S, address, DATA_MODE, data, data, data,...., P
wim 0:300d08d9b058 202 //
wim 0:300d08d9b058 203 void SSD1308::writeBitmap(uint8_t* data,
wim 0:300d08d9b058 204 uint8_t start_page, uint8_t end_page,
wim 0:300d08d9b058 205 uint8_t start_col, uint8_t end_col){
wim 0:300d08d9b058 206
wim 0:300d08d9b058 207 int count = (end_page - start_page + 1) * (end_col - start_col + 1);
wim 0:300d08d9b058 208
wim 0:300d08d9b058 209 //setDisplayOff();
wim 0:300d08d9b058 210 setPageAddress(start_page, end_page); // set page window
wim 0:300d08d9b058 211 setColumnAddress(start_col, end_col); // set column window
wim 0:300d08d9b058 212
wim 0:300d08d9b058 213 _i2c.start();
wim 0:300d08d9b058 214 _i2c.write(_writeOpcode);
wim 0:300d08d9b058 215 _i2c.write(DATA_MODE);
wim 0:300d08d9b058 216 for (int i=0; i<count; i++) {
wim 0:300d08d9b058 217 _i2c.write(data[i]); // Write Data
wim 0:300d08d9b058 218 }
wim 0:300d08d9b058 219 _i2c.stop();
wim 0:300d08d9b058 220
wim 0:300d08d9b058 221 //setDisplayOn();
wim 0:300d08d9b058 222 }
wim 0:300d08d9b058 223 #endif
wim 0:300d08d9b058 224
wim 0:300d08d9b058 225
wim 1:b7e8f5139026 226 /** @brief write a progressbar to the display, Max Width is 52 pixels
wim 1:b7e8f5139026 227 * @param uint8_t page begin page (0..MAX_PAGE)
wim 1:b7e8f5139026 228 * @param uint8_t col begin column (0..MAX_COL)
wim 1:b7e8f5139026 229 * @param int percentage value (0..100)
wim 1:b7e8f5139026 230 */
wim 1:b7e8f5139026 231 #define PRG_MAX_SCALE 50
wim 1:b7e8f5139026 232 #define PRG_LEFT_EDGE 0xFF
wim 1:b7e8f5139026 233 #define PRG_RIGHT_EDGE 0xFF
wim 1:b7e8f5139026 234 #define PRG_ACTIVE 0xFF
wim 1:b7e8f5139026 235 #define PRG_NOT_ACTIVE 0x81
wim 1:b7e8f5139026 236
wim 1:b7e8f5139026 237 #if(0)
wim 1:b7e8f5139026 238 //Standard version
wim 1:b7e8f5139026 239 void SSD1308::writeProgressBar(uint8_t page, uint8_t col, int percentage) {
wim 1:b7e8f5139026 240 uint8_t scale_value;
wim 1:b7e8f5139026 241
wim 1:b7e8f5139026 242 if (percentage < 0) {
wim 1:b7e8f5139026 243 scale_value = 0;
wim 1:b7e8f5139026 244 } else if (percentage > 100) {
wim 1:b7e8f5139026 245 scale_value = PRG_MAX_SCALE;
wim 1:b7e8f5139026 246 }
wim 1:b7e8f5139026 247 else {
wim 1:b7e8f5139026 248 scale_value = (percentage * PRG_MAX_SCALE) / 100;
wim 1:b7e8f5139026 249 }
wim 1:b7e8f5139026 250
wim 1:b7e8f5139026 251 //setDisplayOff();
wim 1:b7e8f5139026 252 setPageAddress(page, page);
wim 1:b7e8f5139026 253 setColumnAddress(col, MAX_COL);
wim 1:b7e8f5139026 254
wim 1:b7e8f5139026 255 _sendData(PRG_LEFT_EDGE);
wim 1:b7e8f5139026 256
wim 1:b7e8f5139026 257 for (uint8_t col = 0; col < scale_value; col++) {
wim 1:b7e8f5139026 258 _sendData(PRG_ACTIVE);
wim 1:b7e8f5139026 259 }
wim 1:b7e8f5139026 260
wim 1:b7e8f5139026 261 for (uint8_t col = scale_value; col < PRG_MAX_SCALE; col++) {
wim 1:b7e8f5139026 262 _sendData(PRG_NOT_ACTIVE);
wim 1:b7e8f5139026 263 }
wim 1:b7e8f5139026 264
wim 1:b7e8f5139026 265 _sendData(PRG_RIGHT_EDGE);
wim 1:b7e8f5139026 266
wim 1:b7e8f5139026 267 //setDisplayOn();
wim 1:b7e8f5139026 268 }
wim 1:b7e8f5139026 269 #else
wim 1:b7e8f5139026 270
wim 1:b7e8f5139026 271 //Optimised version
wim 1:b7e8f5139026 272 // Save lots of I2C S,P, address and datacommands:
wim 1:b7e8f5139026 273 // Send S, address, DATA_MODE, data, data, data,...., P
wim 0:300d08d9b058 274 //
wim 1:b7e8f5139026 275 void SSD1308::writeProgressBar(uint8_t page, uint8_t col, int percentage) {
wim 1:b7e8f5139026 276 uint8_t scale_value;
wim 1:b7e8f5139026 277
wim 1:b7e8f5139026 278 if (percentage < 0) {
wim 1:b7e8f5139026 279 scale_value = 0;
wim 1:b7e8f5139026 280 } else if (percentage > 100) {
wim 1:b7e8f5139026 281 scale_value = PRG_MAX_SCALE;
wim 1:b7e8f5139026 282 }
wim 1:b7e8f5139026 283 else {
wim 1:b7e8f5139026 284 scale_value = (percentage * PRG_MAX_SCALE) / 100;
wim 1:b7e8f5139026 285 }
wim 1:b7e8f5139026 286
wim 1:b7e8f5139026 287 //setDisplayOff();
wim 1:b7e8f5139026 288 setPageAddress(page, page);
wim 1:b7e8f5139026 289 setColumnAddress(col, MAX_COL);
wim 1:b7e8f5139026 290
wim 1:b7e8f5139026 291 _i2c.start();
wim 1:b7e8f5139026 292 _i2c.write(_writeOpcode);
wim 1:b7e8f5139026 293 _i2c.write(DATA_MODE);
wim 1:b7e8f5139026 294
wim 1:b7e8f5139026 295 _i2c.write(PRG_LEFT_EDGE); // Write Data
wim 1:b7e8f5139026 296
wim 1:b7e8f5139026 297 for (uint8_t col = 0; col < scale_value; col++) {
wim 1:b7e8f5139026 298 _i2c.write(PRG_ACTIVE); // Write Data
wim 1:b7e8f5139026 299 }
wim 1:b7e8f5139026 300
wim 1:b7e8f5139026 301 for (uint8_t col = scale_value; col < PRG_MAX_SCALE; col++) {
wim 1:b7e8f5139026 302 _i2c.write(PRG_NOT_ACTIVE); // Write Data
wim 1:b7e8f5139026 303 }
wim 1:b7e8f5139026 304
wim 1:b7e8f5139026 305 _i2c.write(PRG_RIGHT_EDGE); // Write Data
wim 1:b7e8f5139026 306
wim 1:b7e8f5139026 307 _i2c.stop();
wim 1:b7e8f5139026 308
wim 1:b7e8f5139026 309 //setDisplayOn();
wim 1:b7e8f5139026 310 }
wim 1:b7e8f5139026 311 #endif
wim 1:b7e8f5139026 312
wim 1:b7e8f5139026 313
wim 1:b7e8f5139026 314
wim 1:b7e8f5139026 315
wim 1:b7e8f5139026 316 /** @brief Write single character to the display using the 8x8 fontable
wim 1:b7e8f5139026 317 * @brief Start at current cursor location
wim 1:b7e8f5139026 318 * @param char chr character to write
wim 1:b7e8f5139026 319 */
wim 0:300d08d9b058 320 void SSD1308::writeChar(char chr) {
wim 0:300d08d9b058 321
wim 0:300d08d9b058 322 const uint8_t char_index = chr - 0x20;
wim 0:300d08d9b058 323
wim 0:300d08d9b058 324 for (uint8_t i = 0; i < 8; i++) {
wim 0:300d08d9b058 325 if (_inverted) {
wim 0:300d08d9b058 326 _sendData( ~font_8x8[char_index][i] );
wim 0:300d08d9b058 327 }
wim 0:300d08d9b058 328 else {
wim 0:300d08d9b058 329 _sendData( font_8x8[char_index][i] );
wim 0:300d08d9b058 330 }
wim 0:300d08d9b058 331 }
wim 0:300d08d9b058 332
wim 0:300d08d9b058 333 }
wim 0:300d08d9b058 334
wim 0:300d08d9b058 335
wim 1:b7e8f5139026 336 /** @brief Write a string to the display using the 8x8 font
wim 1:b7e8f5139026 337 * @brief Start at selected cursor location
wim 1:b7e8f5139026 338 * @param uint8_t row row number (0...ROWS/FONT_HEIGHT)
wim 1:b7e8f5139026 339 * @param uint8_t col column number (0...COLUMNS/FONT_WIDTH)
wim 1:b7e8f5139026 340 * @param uint16_t len number of chars in text
wim 1:b7e8f5139026 341 * @param const char * text pointer to text
wim 1:b7e8f5139026 342 */
wim 0:300d08d9b058 343 void SSD1308::writeString(uint8_t row, uint8_t col, uint16_t len, const char * text) {
wim 0:300d08d9b058 344 uint16_t index = 0;
wim 0:300d08d9b058 345 setPageAddress(row, MAX_PAGE);
wim 0:300d08d9b058 346 const uint8_t col_addr = FONT8x8_WIDTH*col;
wim 0:300d08d9b058 347 setColumnAddress(col_addr, MAX_COL);
wim 0:300d08d9b058 348
wim 0:300d08d9b058 349 while ((col+index) < CHARS && (index < len)) {
wim 0:300d08d9b058 350 // write first line, starting at given position
wim 0:300d08d9b058 351 writeChar(text[index++]);
wim 0:300d08d9b058 352 }
wim 0:300d08d9b058 353
wim 0:300d08d9b058 354 // write remaining lines
wim 0:300d08d9b058 355 // write until the end of memory
wim 0:300d08d9b058 356 // then wrap around again from the top.
wim 0:300d08d9b058 357 if (index + 1 < len) {
wim 0:300d08d9b058 358 setPageAddress(row + 1, MAX_PAGE);
wim 0:300d08d9b058 359 setColumnAddress(0, MAX_COL);
wim 0:300d08d9b058 360 bool wrapEntireScreen = false;
wim 0:300d08d9b058 361 while (index + 1 < len) {
wim 0:300d08d9b058 362 writeChar(text[index++]);
wim 0:300d08d9b058 363 // if we've written the last character space on the screen,
wim 0:300d08d9b058 364 // reset the page and column address so that it wraps around from the top again
wim 0:300d08d9b058 365 if (!wrapEntireScreen && (row*CHARS + col + index) > 127) {
wim 0:300d08d9b058 366 setPageAddress(0, MAX_PAGE);
wim 0:300d08d9b058 367 setColumnAddress(0, MAX_COL);
wim 0:300d08d9b058 368 wrapEntireScreen = true;
wim 0:300d08d9b058 369 }
wim 0:300d08d9b058 370 }
wim 0:300d08d9b058 371 }
wim 0:300d08d9b058 372 }
wim 0:300d08d9b058 373
wim 0:300d08d9b058 374
wim 0:300d08d9b058 375
wim 1:b7e8f5139026 376 /** @brief Write large character (16x24 font)
wim 1:b7e8f5139026 377 * @param uint8_t row row number (0...MAX_ROW)
wim 1:b7e8f5139026 378 * @param uint8_t col column number (0...MAX_COL)
wim 1:b7e8f5139026 379 * @param char chr Used for displaying numbers 0 - 9 and '+', '-', '.'
wim 1:b7e8f5139026 380 */
wim 0:300d08d9b058 381 void SSD1308::writeBigChar(uint8_t row, uint8_t col, char chr) {
wim 0:300d08d9b058 382
wim 0:300d08d9b058 383 writeBitmap((uint8_t*) font_16x24[int(chr) - FONT16x24_START],
wim 0:300d08d9b058 384 row, (row + FONT16x24_BYTES - 1),
wim 0:300d08d9b058 385 col, (col + FONT16x24_WIDTH - 1));
wim 0:300d08d9b058 386 }
wim 0:300d08d9b058 387
wim 0:300d08d9b058 388
wim 1:b7e8f5139026 389 /** @brief Write command that has no parameters
wim 1:b7e8f5139026 390 */
wim 0:300d08d9b058 391 void SSD1308::_sendCommand(uint8_t command) {
wim 0:300d08d9b058 392 // I2Cdev::writeByte(m_devAddr, COMMAND_MODE, command);
wim 0:300d08d9b058 393
wim 0:300d08d9b058 394 #if(0)
wim 0:300d08d9b058 395 char databytes[2];
wim 0:300d08d9b058 396
wim 0:300d08d9b058 397 databytes[0] = COMMAND_MODE;
wim 0:300d08d9b058 398 databytes[1] = command;
wim 0:300d08d9b058 399 _i2c.write(_writeOpcode, databytes, 2); // Write command
wim 0:300d08d9b058 400 #endif
wim 0:300d08d9b058 401
wim 0:300d08d9b058 402 _i2c.start();
wim 0:300d08d9b058 403 _i2c.write(_writeOpcode);
wim 0:300d08d9b058 404
wim 0:300d08d9b058 405 _i2c.write(COMMAND_MODE);
wim 0:300d08d9b058 406 _i2c.write(command); // Write Command
wim 0:300d08d9b058 407
wim 0:300d08d9b058 408 _i2c.stop();
wim 0:300d08d9b058 409
wim 0:300d08d9b058 410 }
wim 0:300d08d9b058 411
wim 1:b7e8f5139026 412 /** @brief Write command that has one parameter
wim 1:b7e8f5139026 413 */
wim 0:300d08d9b058 414 void SSD1308::_sendCommand(uint8_t command, uint8_t param1) {
wim 0:300d08d9b058 415
wim 0:300d08d9b058 416 // Note continuationbit is set, so COMMAND_MODE must be
wim 0:300d08d9b058 417 // repeated before each databyte that serves as parameter!
wim 0:300d08d9b058 418
wim 0:300d08d9b058 419 _i2c.start();
wim 0:300d08d9b058 420 _i2c.write(_writeOpcode);
wim 0:300d08d9b058 421
wim 0:300d08d9b058 422 _i2c.write(COMMAND_MODE);
wim 0:300d08d9b058 423 _i2c.write(command); // Write Command
wim 0:300d08d9b058 424 _i2c.write(COMMAND_MODE);
wim 0:300d08d9b058 425 _i2c.write(param1); // Write Param1
wim 0:300d08d9b058 426
wim 0:300d08d9b058 427 _i2c.stop();
wim 0:300d08d9b058 428
wim 0:300d08d9b058 429 }
wim 0:300d08d9b058 430
wim 1:b7e8f5139026 431 /** @brief Write command that has two parameters
wim 1:b7e8f5139026 432 */
wim 0:300d08d9b058 433 void SSD1308::_sendCommand(uint8_t command, uint8_t param1, uint8_t param2) {
wim 0:300d08d9b058 434
wim 0:300d08d9b058 435 // Note continuationbit is set, so COMMAND_MODE must be
wim 0:300d08d9b058 436 // repeated before each databyte that serves as parameter!
wim 0:300d08d9b058 437
wim 0:300d08d9b058 438 _i2c.start();
wim 0:300d08d9b058 439 _i2c.write(_writeOpcode);
wim 0:300d08d9b058 440
wim 0:300d08d9b058 441 _i2c.write(COMMAND_MODE);
wim 0:300d08d9b058 442 _i2c.write(command); // Write Command
wim 0:300d08d9b058 443 _i2c.write(COMMAND_MODE);
wim 0:300d08d9b058 444 _i2c.write(param1); // Write Param1
wim 0:300d08d9b058 445 _i2c.write(COMMAND_MODE);
wim 0:300d08d9b058 446 _i2c.write(param2); // Write Param2
wim 0:300d08d9b058 447
wim 0:300d08d9b058 448 _i2c.stop();
wim 0:300d08d9b058 449
wim 0:300d08d9b058 450 }
wim 0:300d08d9b058 451
wim 0:300d08d9b058 452 #if(0)
wim 1:b7e8f5139026 453 /** @brief Write command that has multiple parameters
wim 1:b7e8f5139026 454 */
wim 0:300d08d9b058 455 void SSD1308::_sendCommands(uint8_t len, uint8_t* commands) {
wim 0:300d08d9b058 456
wim 0:300d08d9b058 457 // I2Cdev::writeBytes(m_devAddr, COMMAND_MODE, len, commands);
wim 0:300d08d9b058 458 // Note this original code is not correct, continuationbit is set,
wim 0:300d08d9b058 459 // so COMMAND_MODE must be repeated before each databyte that serves as parameter!
wim 0:300d08d9b058 460
wim 0:300d08d9b058 461 _i2c.start();
wim 0:300d08d9b058 462 _i2c.write(_writeOpcode);
wim 0:300d08d9b058 463
wim 0:300d08d9b058 464 for (int i=0; i<len ; i++) {
wim 0:300d08d9b058 465 _i2c.write(COMMAND_MODE);
wim 0:300d08d9b058 466 _i2c.write(commands[i]); // Write Commands
wim 0:300d08d9b058 467 }
wim 0:300d08d9b058 468 _i2c.stop();
wim 0:300d08d9b058 469
wim 0:300d08d9b058 470 }
wim 0:300d08d9b058 471 #endif
wim 0:300d08d9b058 472
wim 1:b7e8f5139026 473 /** @brief Write databyte to display
wim 1:b7e8f5139026 474 * @brief Start at current cursor location
wim 1:b7e8f5139026 475 * @param uint8_t data databyte to write
wim 1:b7e8f5139026 476 */
wim 0:300d08d9b058 477 void SSD1308::_sendData(uint8_t data){
wim 0:300d08d9b058 478 // I2Cdev::writeByte(m_devAddr, DATA_MODE, data);
wim 0:300d08d9b058 479
wim 0:300d08d9b058 480 char databytes[2];
wim 0:300d08d9b058 481
wim 0:300d08d9b058 482 databytes[0] = DATA_MODE;
wim 0:300d08d9b058 483 databytes[1] = data;
wim 0:300d08d9b058 484 _i2c.write(_writeOpcode, databytes, 2); // Write Data
wim 0:300d08d9b058 485
wim 0:300d08d9b058 486 }
wim 0:300d08d9b058 487
wim 1:b7e8f5139026 488 /** @brief Write len bytes from buffer data to display,
wim 1:b7e8f5139026 489 * @brief Start at current cursor location
wim 1:b7e8f5139026 490 * @param uint8_t len number of bytes to write
wim 1:b7e8f5139026 491 * @param uint8_t* data pointer to data
wim 1:b7e8f5139026 492 */
wim 0:300d08d9b058 493 void SSD1308::_sendData(uint8_t len, uint8_t* data) {
wim 0:300d08d9b058 494 // I2Cdev::writeBytes(m_devAddr, DATA_MODE, len, data);
wim 0:300d08d9b058 495
wim 0:300d08d9b058 496 _i2c.start();
wim 0:300d08d9b058 497 _i2c.write(_writeOpcode);
wim 0:300d08d9b058 498 _i2c.write(DATA_MODE);
wim 0:300d08d9b058 499 for (int i=0; i<len ; i++) {
wim 0:300d08d9b058 500 _i2c.write(data[i]); // Write Data
wim 0:300d08d9b058 501 }
wim 0:300d08d9b058 502 _i2c.stop();
wim 0:300d08d9b058 503
wim 0:300d08d9b058 504 }
wim 0:300d08d9b058 505
wim 0:300d08d9b058 506
wim 0:300d08d9b058 507
wim 0:300d08d9b058 508 void SSD1308::setHorizontalAddressingMode(){
wim 0:300d08d9b058 509 setMemoryAddressingMode(HORIZONTAL_ADDRESSING_MODE);
wim 0:300d08d9b058 510 }
wim 0:300d08d9b058 511
wim 0:300d08d9b058 512 void SSD1308::setVerticalAddressingMode() {
wim 0:300d08d9b058 513 setMemoryAddressingMode(VERTICAL_ADDRESSING_MODE);
wim 0:300d08d9b058 514 }
wim 0:300d08d9b058 515
wim 0:300d08d9b058 516 void SSD1308::setPageAddressingMode(){
wim 0:300d08d9b058 517 setMemoryAddressingMode(PAGE_ADDRESSING_MODE);
wim 0:300d08d9b058 518 }
wim 0:300d08d9b058 519
wim 0:300d08d9b058 520 void SSD1308::setMemoryAddressingMode(uint8_t mode){
wim 0:300d08d9b058 521
wim 0:300d08d9b058 522 _sendCommand(SET_MEMORY_ADDRESSING_MODE, mode);
wim 0:300d08d9b058 523 }
wim 0:300d08d9b058 524
wim 0:300d08d9b058 525
wim 1:b7e8f5139026 526 /** @param uint8_t start startpage (valid range 0..MAX_PAGE)
wim 1:b7e8f5139026 527 * @param uint8_t end endpage (valid range start..MAX_PAGE)
wim 1:b7e8f5139026 528 */
wim 0:300d08d9b058 529 void SSD1308::setPageAddress(uint8_t start, uint8_t end) {
wim 0:300d08d9b058 530
wim 0:300d08d9b058 531 _sendCommand(SET_PAGE_ADDRESS, start, end);
wim 0:300d08d9b058 532 }
wim 0:300d08d9b058 533
wim 0:300d08d9b058 534
wim 1:b7e8f5139026 535 /** @param uint8_t start startcolumn (valid range 0..MAX_COL)
wim 1:b7e8f5139026 536 * @param uint8_t end endcolumn (valid range start..MAX_COL)
wim 1:b7e8f5139026 537 */
wim 0:300d08d9b058 538 void SSD1308::setColumnAddress(uint8_t start, uint8_t end) {
wim 0:300d08d9b058 539
wim 0:300d08d9b058 540 _sendCommand(SET_COLUMN_ADDRESS, start, end);
wim 0:300d08d9b058 541 }
wim 0:300d08d9b058 542
wim 1:b7e8f5139026 543 /** @brief Set Contrast
wim 1:b7e8f5139026 544 * @param uint8_t contrast (valid range 0x00 (lowest) - 0xFF (highest))
wim 1:b7e8f5139026 545 */
wim 0:300d08d9b058 546 void SSD1308::setContrastControl(uint8_t contrast) {
wim 0:300d08d9b058 547
wim 0:300d08d9b058 548 _sendCommand(SET_CONTRAST, contrast);
wim 0:300d08d9b058 549 }
wim 0:300d08d9b058 550
wim 1:b7e8f5139026 551 /** @brief Enable Display
wim 1:b7e8f5139026 552 */
wim 0:300d08d9b058 553 void SSD1308::setDisplayOn() {
wim 0:300d08d9b058 554 _sendCommand(SET_DISPLAY_POWER_ON);
wim 0:300d08d9b058 555 }
wim 0:300d08d9b058 556
wim 1:b7e8f5139026 557 /** @brief Disable Display
wim 1:b7e8f5139026 558 */
wim 0:300d08d9b058 559 void SSD1308::setDisplayOff() {
wim 0:300d08d9b058 560 _sendCommand(SET_DISPLAY_POWER_OFF);
wim 0:300d08d9b058 561 }
wim 0:300d08d9b058 562
wim 1:b7e8f5139026 563 /** @brief Enable or Disable Display
wim 1:b7e8f5139026 564 * @param bool on
wim 1:b7e8f5139026 565 */
wim 0:300d08d9b058 566 void SSD1308::setDisplayPower(bool on) {
wim 0:300d08d9b058 567 if (on) {
wim 0:300d08d9b058 568 setDisplayOn();
wim 0:300d08d9b058 569 } else {
wim 0:300d08d9b058 570 setDisplayOff();
wim 0:300d08d9b058 571 }
wim 0:300d08d9b058 572 }
wim 0:300d08d9b058 573
wim 1:b7e8f5139026 574 /** @brief Show White pixels on Black background
wim 1:b7e8f5139026 575 */
wim 0:300d08d9b058 576 void SSD1308::setDisplayNormal() {
wim 0:300d08d9b058 577 _sendCommand(SET_NORMAL_DISPLAY);
wim 0:300d08d9b058 578 }
wim 0:300d08d9b058 579
wim 1:b7e8f5139026 580 /** @brief Show Black pixels on White background
wim 1:b7e8f5139026 581 */
wim 0:300d08d9b058 582 void SSD1308::setDisplayInverse() {
wim 0:300d08d9b058 583 _sendCommand(SET_INVERSE_DISPLAY);
wim 0:300d08d9b058 584 }
wim 0:300d08d9b058 585
wim 1:b7e8f5139026 586 /** @brief Blink display by fading in and out over a set number of frames
wim 1:b7e8f5139026 587 * @param bool on
wim 1:b7e8f5139026 588 */
wim 0:300d08d9b058 589 void SSD1308::setDisplayBlink(bool on){
wim 0:300d08d9b058 590 if (on) {
wim 0:300d08d9b058 591 _sendCommand(SET_FADE_BLINK, (BLINK_ENABLE | FADE_INTERVAL_128_FRAMES));
wim 0:300d08d9b058 592 }
wim 0:300d08d9b058 593 else {
wim 0:300d08d9b058 594 _sendCommand(SET_FADE_BLINK, FADE_BLINK_DISABLE);
wim 0:300d08d9b058 595 }
wim 0:300d08d9b058 596 }
wim 0:300d08d9b058 597
wim 0:300d08d9b058 598
wim 1:b7e8f5139026 599 /** @brief Fade out display in set number of frames
wim 1:b7e8f5139026 600 * @param bool on
wim 1:b7e8f5139026 601 */
wim 0:300d08d9b058 602 void SSD1308::setDisplayFade(bool on) {
wim 0:300d08d9b058 603 if (on) {
wim 0:300d08d9b058 604 _sendCommand(SET_FADE_BLINK, (FADE_OUT_ENABLE | FADE_INTERVAL_128_FRAMES));
wim 0:300d08d9b058 605 }
wim 0:300d08d9b058 606 else {
wim 0:300d08d9b058 607 _sendCommand(SET_FADE_BLINK, FADE_BLINK_DISABLE);
wim 0:300d08d9b058 608 }
wim 0:300d08d9b058 609 }
wim 0:300d08d9b058 610
wim 1:b7e8f5139026 611 /** @brief Display Flip (Left/Right, Up/Down)
wim 1:b7e8f5139026 612 * @param bool left flip Left/Right
wim 1:b7e8f5139026 613 * @param bool down flip Up/Down
wim 1:b7e8f5139026 614 */
wim 0:300d08d9b058 615 void SSD1308::setDisplayFlip(bool left, bool down) {
wim 0:300d08d9b058 616 if (left) {
wim 0:300d08d9b058 617 // column address 0 is mapped to SEG0 (Reset)
wim 0:300d08d9b058 618 _sendCommand(SET_SEGMENT_REMAP_0);
wim 0:300d08d9b058 619 }
wim 0:300d08d9b058 620 else {
wim 0:300d08d9b058 621 // column address 127 is mapped to SEG0
wim 0:300d08d9b058 622 _sendCommand(SET_SEGMENT_REMAP_127);
wim 0:300d08d9b058 623 }
wim 0:300d08d9b058 624
wim 0:300d08d9b058 625 if (down) {
wim 0:300d08d9b058 626 // Reset mode
wim 0:300d08d9b058 627 _sendCommand(SET_COMMON_REMAP_0);
wim 0:300d08d9b058 628 }
wim 0:300d08d9b058 629 else {
wim 0:300d08d9b058 630 // Flip Up/Down (Need to rewrite display before H effect shows)
wim 0:300d08d9b058 631 _sendCommand(SET_COMMON_REMAP_63);
wim 0:300d08d9b058 632 }
wim 0:300d08d9b058 633
wim 0:300d08d9b058 634 }
wim 0:300d08d9b058 635
wim 1:b7e8f5139026 636 /** @brief Sets Internal Iref
wim 1:b7e8f5139026 637 */
wim 0:300d08d9b058 638 void SSD1308::setInternalIref() {
wim 0:300d08d9b058 639 // uint8_t cmds[2] = {SET_IREF_SELECTION, INTERNAL_IREF};
wim 0:300d08d9b058 640 // _sendCommands(2, cmds);
wim 0:300d08d9b058 641
wim 0:300d08d9b058 642 _sendCommand(SET_IREF_SELECTION, INTERNAL_IREF);
wim 0:300d08d9b058 643 }
wim 0:300d08d9b058 644
wim 1:b7e8f5139026 645 /** @brief Sets External Iref (default)
wim 1:b7e8f5139026 646 */
wim 0:300d08d9b058 647 void SSD1308::setExternalIref() {
wim 0:300d08d9b058 648 // uint8_t cmds[2] = {SET_IREF_SELECTION, EXTERNAL_IREF};
wim 0:300d08d9b058 649 // _sendCommands(2, cmds);
wim 0:300d08d9b058 650 _sendCommand(SET_IREF_SELECTION, EXTERNAL_IREF);
wim 0:300d08d9b058 651 }
wim 0:300d08d9b058 652
wim 0:300d08d9b058 653
wim 1:b7e8f5139026 654 /** @brief Low level Init
wim 1:b7e8f5139026 655 * @brief Init the configuration registers in accordance with the datasheet
wim 1:b7e8f5139026 656 */
wim 0:300d08d9b058 657 void SSD1308::_init() {
wim 0:300d08d9b058 658
wim 0:300d08d9b058 659 //not complete yet
wim 0:300d08d9b058 660 _sendCommand(SET_DISPLAY_POWER_OFF);
wim 0:300d08d9b058 661
wim 0:300d08d9b058 662 // column address 0 is mapped to SEG0 (Reset)
wim 0:300d08d9b058 663 // row address 0 is mapped to COMM0 (Reset)
wim 0:300d08d9b058 664 _sendCommand(SET_SEGMENT_REMAP_0);
wim 0:300d08d9b058 665 _sendCommand(SET_COMMON_REMAP_0);
wim 0:300d08d9b058 666
wim 0:300d08d9b058 667 _sendCommand(SET_COMMON_CONF, COMMON_BASE | COMMON_ALTERNATIVE | COMMON_LEFTRIGHT_NORMAL);
wim 0:300d08d9b058 668
wim 0:300d08d9b058 669 setHorizontalAddressingMode(); // (Non-Reset)
wim 0:300d08d9b058 670
wim 0:300d08d9b058 671 setExternalIref(); // (Reset)
wim 0:300d08d9b058 672
wim 0:300d08d9b058 673 _sendCommand(SET_CONTRAST, 0x7F); // (Reset)
wim 0:300d08d9b058 674
wim 0:300d08d9b058 675 _sendCommand(SET_NORMAL_DISPLAY);
wim 0:300d08d9b058 676
wim 0:300d08d9b058 677 clearDisplay();
wim 0:300d08d9b058 678
wim 0:300d08d9b058 679 _sendCommand(SET_DISPLAY_POWER_ON);
wim 0:300d08d9b058 680 }
wim 0:300d08d9b058 681