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:
Thu Jan 01 17:53:40 2015 +0000
Revision:
4:df92b0c0cb92
Parent:
2:16c84a134393
Child:
5:e564cde8e03e
Added option to select optimisation using low level I2C methods. Used for testing on F401 and LPC1768.

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 4:df92b0c0cb92 15 // 2013-07-12 - Minor comment fix and placeholder for SSD1306 (WH)
wim 4:df92b0c0cb92 16 // 2015-01-01 - Switch for optimised I2C calls to test on F401 (WH)
wim 0:300d08d9b058 17 //
wim 4:df92b0c0cb92 18 /*
wim 1:b7e8f5139026 19 ================================================================================
wim 0:300d08d9b058 20 I2Cdev device library code is placed under the MIT license
wim 0:300d08d9b058 21 Copyright (c) 2011 Andrew Schamp
wim 4:df92b0c0cb92 22 Copyright (c) 2012,2013 WH (mbed port)
wim 0:300d08d9b058 23
wim 0:300d08d9b058 24 Permission is hereby granted, free of charge, to any person obtaining a copy
wim 0:300d08d9b058 25 of this software and associated documentation files (the "Software"), to deal
wim 0:300d08d9b058 26 in the Software without restriction, including without limitation the rights
wim 0:300d08d9b058 27 to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
wim 0:300d08d9b058 28 copies of the Software, and to permit persons to whom the Software is
wim 0:300d08d9b058 29 furnished to do so, subject to the following conditions:
wim 0:300d08d9b058 30
wim 0:300d08d9b058 31 The above copyright notice and this permission notice shall be included in
wim 0:300d08d9b058 32 all copies or substantial portions of the Software.
wim 0:300d08d9b058 33
wim 0:300d08d9b058 34 THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
wim 0:300d08d9b058 35 IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
wim 0:300d08d9b058 36 FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
wim 0:300d08d9b058 37 AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
wim 0:300d08d9b058 38 LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
wim 0:300d08d9b058 39 OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
wim 0:300d08d9b058 40 THE SOFTWARE.
wim 1:b7e8f5139026 41 ================================================================================
wim 0:300d08d9b058 42 */
wim 0:300d08d9b058 43 #include "mbed.h"
wim 0:300d08d9b058 44 #include "SSD1308.h"
wim 0:300d08d9b058 45
wim 0:300d08d9b058 46 //#include "font_3x5.h"
wim 0:300d08d9b058 47 //#include "font_5x7.h"
wim 0:300d08d9b058 48 //#include "font_6x8.h"
wim 0:300d08d9b058 49 #include "font_8x8.h"
wim 0:300d08d9b058 50 //#include "font_8x12.h"
wim 0:300d08d9b058 51 //#include "font_16x20.h"
wim 0:300d08d9b058 52 #include "font_16x24.h"
wim 0:300d08d9b058 53
wim 4:df92b0c0cb92 54 #if defined(TARGET_LPC1768)
wim 4:df92b0c0cb92 55 #define I2C_OPTIMIZE 1
wim 4:df92b0c0cb92 56 #else
wim 4:df92b0c0cb92 57 #define I2C_OPTIMIZE 0
wim 4:df92b0c0cb92 58 #endif
wim 4:df92b0c0cb92 59
wim 1:b7e8f5139026 60 /**
wim 1:b7e8f5139026 61 *@brief Constructor
wim 1:b7e8f5139026 62 *@param I2C &i2c reference to i2c
wim 1:b7e8f5139026 63 *@param uint8_t deviceAddress slaveaddress
wim 1:b7e8f5139026 64 */
wim 0:300d08d9b058 65 SSD1308::SSD1308(I2C &i2c, uint8_t deviceAddress) : _i2c(i2c) {
wim 0:300d08d9b058 66
wim 0:300d08d9b058 67 _writeOpcode = deviceAddress & 0xFE; // low order bit = 0 for write
wim 0:300d08d9b058 68 _readOpcode = deviceAddress | 0x01; // low order bit = 1 for read
wim 0:300d08d9b058 69
wim 0:300d08d9b058 70 initialize();
wim 0:300d08d9b058 71 }
wim 0:300d08d9b058 72
wim 1:b7e8f5139026 73 /** @brief High level Init, most settings remain at Power-On reset value
wim 1:b7e8f5139026 74 */
wim 0:300d08d9b058 75 void SSD1308::initialize() {
wim 0:300d08d9b058 76 setHorizontalAddressingMode();
wim 0:300d08d9b058 77
wim 0:300d08d9b058 78 clearDisplay();
wim 0:300d08d9b058 79
wim 0:300d08d9b058 80 setInverted(false);
wim 0:300d08d9b058 81
wim 0:300d08d9b058 82 setDisplayOn();
wim 0:300d08d9b058 83 }
wim 0:300d08d9b058 84
wim 0:300d08d9b058 85
wim 1:b7e8f5139026 86 /** @brief clear the display
wim 1:b7e8f5139026 87 */
wim 4:df92b0c0cb92 88 #if (I2C_OPTIMIZE == 0)
wim 0:300d08d9b058 89 // Standard version
wim 0:300d08d9b058 90 void SSD1308::clearDisplay() {
wim 0:300d08d9b058 91
wim 0:300d08d9b058 92 //setDisplayOff();
wim 0:300d08d9b058 93 setPageAddress(0, MAX_PAGE); // all pages
wim 0:300d08d9b058 94 setColumnAddress(0, MAX_COL); // all columns
wim 0:300d08d9b058 95
wim 0:300d08d9b058 96 for (uint8_t page = 0; page < PAGES; page++) {
wim 0:300d08d9b058 97 for (uint8_t col = 0; col < COLUMNS; col++) {
wim 0:300d08d9b058 98 _sendData(0x00);
wim 0:300d08d9b058 99 }
wim 0:300d08d9b058 100 }
wim 0:300d08d9b058 101
wim 0:300d08d9b058 102 //setDisplayOn();
wim 0:300d08d9b058 103 }
wim 0:300d08d9b058 104 #else
wim 0:300d08d9b058 105 //Optimised version
wim 0:300d08d9b058 106 // Save lots of I2C S,P, address and datacommands:
wim 0:300d08d9b058 107 // Send S, address, DATA_MODE, data, data, data,...., P
wim 0:300d08d9b058 108 //
wim 0:300d08d9b058 109 void SSD1308::clearDisplay() {
wim 0:300d08d9b058 110
wim 0:300d08d9b058 111 //setDisplayOff();
wim 0:300d08d9b058 112
wim 0:300d08d9b058 113 setPageAddress(0, MAX_PAGE); // all pages
wim 0:300d08d9b058 114 setColumnAddress(0, MAX_COL); // all columns
wim 0:300d08d9b058 115
wim 0:300d08d9b058 116 _i2c.start();
wim 0:300d08d9b058 117 _i2c.write(_writeOpcode);
wim 0:300d08d9b058 118 _i2c.write(DATA_MODE);
wim 0:300d08d9b058 119 for (int i=0; i<(PAGES * COLUMNS); i++) {
wim 0:300d08d9b058 120 _i2c.write(0x00); // Write Data
wim 0:300d08d9b058 121 }
wim 0:300d08d9b058 122 _i2c.stop();
wim 0:300d08d9b058 123
wim 0:300d08d9b058 124 //setDisplayOn();
wim 0:300d08d9b058 125 }
wim 0:300d08d9b058 126 #endif
wim 0:300d08d9b058 127
wim 0:300d08d9b058 128
wim 1:b7e8f5139026 129 /** @brief fill the display
wim 1:b7e8f5139026 130 * @param uint8_t pattern fillpattern vertical patch or 8 bits
wim 4:df92b0c0cb92 131 * @param uint8_t start_page begin page (0..MAX_PAGE)
wim 4:df92b0c0cb92 132 * @param uint8_t end_page end page (start_page..MAX_PAGE)
wim 4:df92b0c0cb92 133 * @param uint8_t start_col begin column (0..MAX_COL)
wim 4:df92b0c0cb92 134 * @param uint8_t end_col end column (start_col..MAX_COL)
wim 1:b7e8f5139026 135 */
wim 4:df92b0c0cb92 136 #if (I2C_OPTIMIZE == 0)
wim 0:300d08d9b058 137 //Standard version
wim 4:df92b0c0cb92 138
wim 4:df92b0c0cb92 139 void SSD1308::fillDisplay(uint8_t pattern,
wim 4:df92b0c0cb92 140 uint8_t start_page, uint8_t end_page,
wim 4:df92b0c0cb92 141 uint8_t start_col, uint8_t end_col) {
wim 0:300d08d9b058 142
wim 4:df92b0c0cb92 143 int count = (end_page - start_page + 1) * (end_col - start_col + 1);
wim 4:df92b0c0cb92 144
wim 4:df92b0c0cb92 145 //setDisplayOff();
wim 4:df92b0c0cb92 146 setPageAddress(start_page, end_page); // set page window
wim 4:df92b0c0cb92 147 setColumnAddress(start_col, end_col); // set column window
wim 4:df92b0c0cb92 148
wim 4:df92b0c0cb92 149 for (int i=0; i<count; i++) {
wim 4:df92b0c0cb92 150 _sendData(pattern); // Write Data
wim 4:df92b0c0cb92 151 }
wim 0:300d08d9b058 152
wim 4:df92b0c0cb92 153 //setDisplayOn();
wim 0:300d08d9b058 154 }
wim 4:df92b0c0cb92 155
wim 0:300d08d9b058 156 #else
wim 0:300d08d9b058 157
wim 0:300d08d9b058 158 //Optimised version
wim 0:300d08d9b058 159 // Save lots of I2C S,P, address and datacommands:
wim 0:300d08d9b058 160 // Send S, address, DATA_MODE, data, data, data,...., P
wim 0:300d08d9b058 161 //
wim 0:300d08d9b058 162 void SSD1308::fillDisplay(uint8_t pattern,
wim 0:300d08d9b058 163 uint8_t start_page, uint8_t end_page,
wim 0:300d08d9b058 164 uint8_t start_col, uint8_t end_col) {
wim 0:300d08d9b058 165
wim 0:300d08d9b058 166 int count = (end_page - start_page + 1) * (end_col - start_col + 1);
wim 0:300d08d9b058 167
wim 0:300d08d9b058 168 //setDisplayOff();
wim 0:300d08d9b058 169 setPageAddress(start_page, end_page); // set page window
wim 0:300d08d9b058 170 setColumnAddress(start_col, end_col); // set column window
wim 0:300d08d9b058 171
wim 0:300d08d9b058 172 _i2c.start();
wim 0:300d08d9b058 173 _i2c.write(_writeOpcode);
wim 0:300d08d9b058 174 _i2c.write(DATA_MODE);
wim 0:300d08d9b058 175 for (int i=0; i<count; i++) {
wim 0:300d08d9b058 176 _i2c.write(pattern); // Write Data
wim 0:300d08d9b058 177 }
wim 0:300d08d9b058 178 _i2c.stop();
wim 0:300d08d9b058 179
wim 0:300d08d9b058 180 //setDisplayOn();
wim 0:300d08d9b058 181 }
wim 0:300d08d9b058 182
wim 0:300d08d9b058 183 #endif
wim 0:300d08d9b058 184
wim 0:300d08d9b058 185
wim 1:b7e8f5139026 186 /** @brief write a bitmap to the display
wim 1:b7e8f5139026 187 * @param uint8_t* data pointer to bitmap
wim 1:b7e8f5139026 188 * @param uint8_t start_page begin page (0..MAX_PAGE)
wim 1:b7e8f5139026 189 * @param uint8_t end_page end page (start_page..MAX_PAGE)
wim 1:b7e8f5139026 190 * @param uint8_t start_col begin column (0..MAX_COL)
wim 1:b7e8f5139026 191 * @param uint8_t end_col end column (start_col..MAX_COL)
wim 1:b7e8f5139026 192 */
wim 4:df92b0c0cb92 193 #if (I2C_OPTIMIZE == 0)
wim 0:300d08d9b058 194 //Standard version
wim 4:df92b0c0cb92 195 void SSD1308::writeBitmap(uint8_t* data,
wim 4:df92b0c0cb92 196 uint8_t start_page, uint8_t end_page,
wim 4:df92b0c0cb92 197 uint8_t start_col, uint8_t end_col){
wim 4:df92b0c0cb92 198
wim 4:df92b0c0cb92 199 int count = (end_page - start_page + 1) * (end_col - start_col + 1);
wim 0:300d08d9b058 200
wim 0:300d08d9b058 201 //setDisplayOff();
wim 4:df92b0c0cb92 202 setPageAddress(start_page, end_page); // set page window
wim 4:df92b0c0cb92 203 setColumnAddress(start_col, end_col); // set column window
wim 0:300d08d9b058 204
wim 4:df92b0c0cb92 205 for (int i=0; i<count; i++) {
wim 4:df92b0c0cb92 206 _sendData(data[i]); // Write Data
wim 0:300d08d9b058 207 }
wim 0:300d08d9b058 208
wim 0:300d08d9b058 209 //setDisplayOn();
wim 0:300d08d9b058 210 }
wim 4:df92b0c0cb92 211
wim 0:300d08d9b058 212 #else
wim 0:300d08d9b058 213 //Optimised version
wim 0:300d08d9b058 214 // Save lots of I2C S,P, address and datacommands:
wim 0:300d08d9b058 215 // Send S, address, DATA_MODE, data, data, data,...., P
wim 0:300d08d9b058 216 //
wim 0:300d08d9b058 217 void SSD1308::writeBitmap(uint8_t* data,
wim 0:300d08d9b058 218 uint8_t start_page, uint8_t end_page,
wim 0:300d08d9b058 219 uint8_t start_col, uint8_t end_col){
wim 0:300d08d9b058 220
wim 0:300d08d9b058 221 int count = (end_page - start_page + 1) * (end_col - start_col + 1);
wim 0:300d08d9b058 222
wim 0:300d08d9b058 223 //setDisplayOff();
wim 0:300d08d9b058 224 setPageAddress(start_page, end_page); // set page window
wim 0:300d08d9b058 225 setColumnAddress(start_col, end_col); // set column window
wim 0:300d08d9b058 226
wim 0:300d08d9b058 227 _i2c.start();
wim 0:300d08d9b058 228 _i2c.write(_writeOpcode);
wim 0:300d08d9b058 229 _i2c.write(DATA_MODE);
wim 0:300d08d9b058 230 for (int i=0; i<count; i++) {
wim 0:300d08d9b058 231 _i2c.write(data[i]); // Write Data
wim 0:300d08d9b058 232 }
wim 0:300d08d9b058 233 _i2c.stop();
wim 0:300d08d9b058 234
wim 0:300d08d9b058 235 //setDisplayOn();
wim 0:300d08d9b058 236 }
wim 4:df92b0c0cb92 237
wim 0:300d08d9b058 238 #endif
wim 0:300d08d9b058 239
wim 0:300d08d9b058 240
wim 2:16c84a134393 241 /** @brief write a progressbar to the display, Width is (PRG_MAX_SCALE + 2) pixels
wim 1:b7e8f5139026 242 * @param uint8_t page begin page (0..MAX_PAGE)
wim 1:b7e8f5139026 243 * @param uint8_t col begin column (0..MAX_COL)
wim 1:b7e8f5139026 244 * @param int percentage value (0..100)
wim 1:b7e8f5139026 245 */
wim 1:b7e8f5139026 246 #define PRG_MAX_SCALE 50
wim 1:b7e8f5139026 247 #define PRG_LEFT_EDGE 0xFF
wim 1:b7e8f5139026 248 #define PRG_RIGHT_EDGE 0xFF
wim 1:b7e8f5139026 249 #define PRG_ACTIVE 0xFF
wim 2:16c84a134393 250 //#define PRG_ACTIVE 0xBD
wim 1:b7e8f5139026 251 #define PRG_NOT_ACTIVE 0x81
wim 1:b7e8f5139026 252
wim 4:df92b0c0cb92 253 #if (I2C_OPTIMIZE == 0)
wim 1:b7e8f5139026 254 //Standard version
wim 1:b7e8f5139026 255 void SSD1308::writeProgressBar(uint8_t page, uint8_t col, int percentage) {
wim 1:b7e8f5139026 256 uint8_t scale_value;
wim 1:b7e8f5139026 257
wim 2:16c84a134393 258 if (percentage <= 0) {
wim 1:b7e8f5139026 259 scale_value = 0;
wim 2:16c84a134393 260 } else if (percentage >= 100) {
wim 2:16c84a134393 261 scale_value = PRG_MAX_SCALE - 1;
wim 1:b7e8f5139026 262 }
wim 1:b7e8f5139026 263 else {
wim 1:b7e8f5139026 264 scale_value = (percentage * PRG_MAX_SCALE) / 100;
wim 1:b7e8f5139026 265 }
wim 1:b7e8f5139026 266
wim 1:b7e8f5139026 267 //setDisplayOff();
wim 1:b7e8f5139026 268 setPageAddress(page, page);
wim 1:b7e8f5139026 269 setColumnAddress(col, MAX_COL);
wim 1:b7e8f5139026 270
wim 1:b7e8f5139026 271 _sendData(PRG_LEFT_EDGE);
wim 1:b7e8f5139026 272
wim 1:b7e8f5139026 273 for (uint8_t col = 0; col < scale_value; col++) {
wim 1:b7e8f5139026 274 _sendData(PRG_ACTIVE);
wim 1:b7e8f5139026 275 }
wim 2:16c84a134393 276
wim 2:16c84a134393 277 _sendData(PRG_ACTIVE);
wim 2:16c84a134393 278
wim 2:16c84a134393 279 for (uint8_t col = (scale_value+1); col < PRG_MAX_SCALE; col++) {
wim 1:b7e8f5139026 280 _sendData(PRG_NOT_ACTIVE);
wim 1:b7e8f5139026 281 }
wim 1:b7e8f5139026 282
wim 1:b7e8f5139026 283 _sendData(PRG_RIGHT_EDGE);
wim 1:b7e8f5139026 284
wim 1:b7e8f5139026 285 //setDisplayOn();
wim 1:b7e8f5139026 286 }
wim 1:b7e8f5139026 287 #else
wim 1:b7e8f5139026 288
wim 1:b7e8f5139026 289 //Optimised version
wim 1:b7e8f5139026 290 // Save lots of I2C S,P, address and datacommands:
wim 1:b7e8f5139026 291 // Send S, address, DATA_MODE, data, data, data,...., P
wim 0:300d08d9b058 292 //
wim 1:b7e8f5139026 293 void SSD1308::writeProgressBar(uint8_t page, uint8_t col, int percentage) {
wim 1:b7e8f5139026 294 uint8_t scale_value;
wim 1:b7e8f5139026 295
wim 2:16c84a134393 296 if (percentage <= 0) {
wim 1:b7e8f5139026 297 scale_value = 0;
wim 2:16c84a134393 298 } else if (percentage >= 100) {
wim 2:16c84a134393 299 scale_value = PRG_MAX_SCALE - 1 ;
wim 1:b7e8f5139026 300 }
wim 1:b7e8f5139026 301 else {
wim 1:b7e8f5139026 302 scale_value = (percentage * PRG_MAX_SCALE) / 100;
wim 1:b7e8f5139026 303 }
wim 1:b7e8f5139026 304
wim 1:b7e8f5139026 305 //setDisplayOff();
wim 1:b7e8f5139026 306 setPageAddress(page, page);
wim 1:b7e8f5139026 307 setColumnAddress(col, MAX_COL);
wim 1:b7e8f5139026 308
wim 1:b7e8f5139026 309 _i2c.start();
wim 1:b7e8f5139026 310 _i2c.write(_writeOpcode);
wim 1:b7e8f5139026 311 _i2c.write(DATA_MODE);
wim 1:b7e8f5139026 312
wim 1:b7e8f5139026 313 _i2c.write(PRG_LEFT_EDGE); // Write Data
wim 1:b7e8f5139026 314
wim 1:b7e8f5139026 315 for (uint8_t col = 0; col < scale_value; col++) {
wim 1:b7e8f5139026 316 _i2c.write(PRG_ACTIVE); // Write Data
wim 1:b7e8f5139026 317 }
wim 1:b7e8f5139026 318
wim 2:16c84a134393 319 _i2c.write(PRG_ACTIVE); // Write Data
wim 2:16c84a134393 320
wim 2:16c84a134393 321 for (uint8_t col = (scale_value+1); col < PRG_MAX_SCALE; col++) {
wim 1:b7e8f5139026 322 _i2c.write(PRG_NOT_ACTIVE); // Write Data
wim 1:b7e8f5139026 323 }
wim 1:b7e8f5139026 324
wim 1:b7e8f5139026 325 _i2c.write(PRG_RIGHT_EDGE); // Write Data
wim 1:b7e8f5139026 326
wim 1:b7e8f5139026 327 _i2c.stop();
wim 1:b7e8f5139026 328
wim 1:b7e8f5139026 329 //setDisplayOn();
wim 1:b7e8f5139026 330 }
wim 1:b7e8f5139026 331 #endif
wim 1:b7e8f5139026 332
wim 2:16c84a134393 333 /** @brief write a level meter to the display, Width is (PRG_MAX_SCALE + 2) pixels
wim 2:16c84a134393 334 * @param uint8_t page begin page (0..MAX_PAGE)
wim 2:16c84a134393 335 * @param uint8_t col begin column (0..MAX_COL)
wim 2:16c84a134393 336 * @param int percentage value (0..100)
wim 2:16c84a134393 337 */
wim 4:df92b0c0cb92 338 #if (I2C_OPTIMIZE == 0)
wim 4:df92b0c0cb92 339 void SSD1308::writeLevelBar(uint8_t page, uint8_t col, int percentage) {
wim 4:df92b0c0cb92 340 uint8_t scale_value;
wim 4:df92b0c0cb92 341
wim 4:df92b0c0cb92 342 if (percentage <= 0) {
wim 4:df92b0c0cb92 343 scale_value = 0;
wim 4:df92b0c0cb92 344 } else if (percentage >= 100) {
wim 4:df92b0c0cb92 345 scale_value = PRG_MAX_SCALE - 1;
wim 4:df92b0c0cb92 346 }
wim 4:df92b0c0cb92 347 else {
wim 4:df92b0c0cb92 348 scale_value = (percentage * PRG_MAX_SCALE) / 100;
wim 4:df92b0c0cb92 349 }
wim 4:df92b0c0cb92 350
wim 4:df92b0c0cb92 351 //setDisplayOff();
wim 4:df92b0c0cb92 352 setPageAddress(page, page);
wim 4:df92b0c0cb92 353 setColumnAddress(col, MAX_COL);
wim 4:df92b0c0cb92 354
wim 4:df92b0c0cb92 355 _sendData(PRG_LEFT_EDGE);
wim 4:df92b0c0cb92 356
wim 4:df92b0c0cb92 357 for (uint8_t col = 0; col < scale_value; col++) {
wim 4:df92b0c0cb92 358 _sendData(PRG_NOT_ACTIVE); // Write Data
wim 4:df92b0c0cb92 359 }
wim 4:df92b0c0cb92 360
wim 4:df92b0c0cb92 361 _sendData(PRG_ACTIVE); // Write Data at active meterlevel
wim 4:df92b0c0cb92 362
wim 4:df92b0c0cb92 363 for (uint8_t col = scale_value+1; col < PRG_MAX_SCALE; col++) {
wim 4:df92b0c0cb92 364 _sendData(PRG_NOT_ACTIVE);
wim 4:df92b0c0cb92 365 }
wim 4:df92b0c0cb92 366
wim 4:df92b0c0cb92 367 _sendData(PRG_RIGHT_EDGE);
wim 4:df92b0c0cb92 368
wim 4:df92b0c0cb92 369 //setDisplayOn();
wim 4:df92b0c0cb92 370 }
wim 4:df92b0c0cb92 371 #else
wim 2:16c84a134393 372 //Optimised version
wim 2:16c84a134393 373 // Save lots of I2C S,P, address and datacommands:
wim 2:16c84a134393 374 // Send S, address, DATA_MODE, data, data, data,...., P
wim 2:16c84a134393 375 //
wim 2:16c84a134393 376 void SSD1308::writeLevelBar(uint8_t page, uint8_t col, int percentage) {
wim 2:16c84a134393 377 uint8_t scale_value;
wim 2:16c84a134393 378
wim 2:16c84a134393 379 if (percentage <= 0) {
wim 2:16c84a134393 380 scale_value = 0;
wim 2:16c84a134393 381 } else if (percentage >= 100) {
wim 2:16c84a134393 382 scale_value = PRG_MAX_SCALE - 1;
wim 2:16c84a134393 383 }
wim 2:16c84a134393 384 else {
wim 2:16c84a134393 385 scale_value = (percentage * PRG_MAX_SCALE) / 100;
wim 2:16c84a134393 386 }
wim 2:16c84a134393 387
wim 2:16c84a134393 388 //setDisplayOff();
wim 2:16c84a134393 389 setPageAddress(page, page);
wim 2:16c84a134393 390 setColumnAddress(col, MAX_COL);
wim 1:b7e8f5139026 391
wim 2:16c84a134393 392 _i2c.start();
wim 2:16c84a134393 393 _i2c.write(_writeOpcode);
wim 2:16c84a134393 394 _i2c.write(DATA_MODE);
wim 1:b7e8f5139026 395
wim 2:16c84a134393 396 _i2c.write(PRG_LEFT_EDGE); // Write Data
wim 2:16c84a134393 397
wim 2:16c84a134393 398 for (uint8_t col = 0; col < scale_value; col++) {
wim 2:16c84a134393 399 _i2c.write(PRG_NOT_ACTIVE); // Write Data
wim 2:16c84a134393 400 }
wim 2:16c84a134393 401
wim 2:16c84a134393 402 _i2c.write(PRG_ACTIVE); // Write Data at active meterlevel
wim 2:16c84a134393 403
wim 2:16c84a134393 404 for (uint8_t col = scale_value+1; col < PRG_MAX_SCALE; col++) {
wim 2:16c84a134393 405 _i2c.write(PRG_NOT_ACTIVE); // Write Data
wim 2:16c84a134393 406 }
wim 2:16c84a134393 407
wim 2:16c84a134393 408 _i2c.write(PRG_RIGHT_EDGE); // Write Data
wim 2:16c84a134393 409
wim 2:16c84a134393 410 _i2c.stop();
wim 2:16c84a134393 411
wim 2:16c84a134393 412 //setDisplayOn();
wim 2:16c84a134393 413 }
wim 4:df92b0c0cb92 414 #endif
wim 1:b7e8f5139026 415
wim 1:b7e8f5139026 416 /** @brief Write single character to the display using the 8x8 fontable
wim 1:b7e8f5139026 417 * @brief Start at current cursor location
wim 1:b7e8f5139026 418 * @param char chr character to write
wim 1:b7e8f5139026 419 */
wim 0:300d08d9b058 420 void SSD1308::writeChar(char chr) {
wim 0:300d08d9b058 421
wim 0:300d08d9b058 422 const uint8_t char_index = chr - 0x20;
wim 0:300d08d9b058 423
wim 0:300d08d9b058 424 for (uint8_t i = 0; i < 8; i++) {
wim 0:300d08d9b058 425 if (_inverted) {
wim 0:300d08d9b058 426 _sendData( ~font_8x8[char_index][i] );
wim 0:300d08d9b058 427 }
wim 0:300d08d9b058 428 else {
wim 0:300d08d9b058 429 _sendData( font_8x8[char_index][i] );
wim 0:300d08d9b058 430 }
wim 0:300d08d9b058 431 }
wim 0:300d08d9b058 432
wim 0:300d08d9b058 433 }
wim 0:300d08d9b058 434
wim 0:300d08d9b058 435
wim 1:b7e8f5139026 436 /** @brief Write a string to the display using the 8x8 font
wim 2:16c84a134393 437 * @brief Start at selected cursor location, text will wrap around until it is done
wim 1:b7e8f5139026 438 * @param uint8_t row row number (0...ROWS/FONT_HEIGHT)
wim 1:b7e8f5139026 439 * @param uint8_t col column number (0...COLUMNS/FONT_WIDTH)
wim 1:b7e8f5139026 440 * @param const char * text pointer to text
wim 1:b7e8f5139026 441 */
wim 2:16c84a134393 442 void SSD1308::writeString(uint8_t row, uint8_t col, const char * text) {
wim 0:300d08d9b058 443 uint16_t index = 0;
wim 2:16c84a134393 444 uint16_t len = strlen(text);
wim 2:16c84a134393 445
wim 0:300d08d9b058 446 setPageAddress(row, MAX_PAGE);
wim 0:300d08d9b058 447 const uint8_t col_addr = FONT8x8_WIDTH*col;
wim 0:300d08d9b058 448 setColumnAddress(col_addr, MAX_COL);
wim 0:300d08d9b058 449
wim 0:300d08d9b058 450 while ((col+index) < CHARS && (index < len)) {
wim 0:300d08d9b058 451 // write first line, starting at given position
wim 0:300d08d9b058 452 writeChar(text[index++]);
wim 0:300d08d9b058 453 }
wim 0:300d08d9b058 454
wim 0:300d08d9b058 455 // write remaining lines
wim 0:300d08d9b058 456 // write until the end of memory
wim 0:300d08d9b058 457 // then wrap around again from the top.
wim 0:300d08d9b058 458 if (index + 1 < len) {
wim 0:300d08d9b058 459 setPageAddress(row + 1, MAX_PAGE);
wim 0:300d08d9b058 460 setColumnAddress(0, MAX_COL);
wim 0:300d08d9b058 461 bool wrapEntireScreen = false;
wim 0:300d08d9b058 462 while (index + 1 < len) {
wim 0:300d08d9b058 463 writeChar(text[index++]);
wim 0:300d08d9b058 464 // if we've written the last character space on the screen,
wim 0:300d08d9b058 465 // reset the page and column address so that it wraps around from the top again
wim 0:300d08d9b058 466 if (!wrapEntireScreen && (row*CHARS + col + index) > 127) {
wim 0:300d08d9b058 467 setPageAddress(0, MAX_PAGE);
wim 0:300d08d9b058 468 setColumnAddress(0, MAX_COL);
wim 0:300d08d9b058 469 wrapEntireScreen = true;
wim 0:300d08d9b058 470 }
wim 0:300d08d9b058 471 }
wim 0:300d08d9b058 472 }
wim 0:300d08d9b058 473 }
wim 0:300d08d9b058 474
wim 0:300d08d9b058 475
wim 0:300d08d9b058 476
wim 1:b7e8f5139026 477 /** @brief Write large character (16x24 font)
wim 1:b7e8f5139026 478 * @param uint8_t row row number (0...MAX_ROW)
wim 1:b7e8f5139026 479 * @param uint8_t col column number (0...MAX_COL)
wim 1:b7e8f5139026 480 * @param char chr Used for displaying numbers 0 - 9 and '+', '-', '.'
wim 1:b7e8f5139026 481 */
wim 0:300d08d9b058 482 void SSD1308::writeBigChar(uint8_t row, uint8_t col, char chr) {
wim 0:300d08d9b058 483
wim 0:300d08d9b058 484 writeBitmap((uint8_t*) font_16x24[int(chr) - FONT16x24_START],
wim 0:300d08d9b058 485 row, (row + FONT16x24_BYTES - 1),
wim 0:300d08d9b058 486 col, (col + FONT16x24_WIDTH - 1));
wim 0:300d08d9b058 487 }
wim 0:300d08d9b058 488
wim 0:300d08d9b058 489
wim 1:b7e8f5139026 490 /** @brief Write command that has no parameters
wim 1:b7e8f5139026 491 */
wim 0:300d08d9b058 492 void SSD1308::_sendCommand(uint8_t command) {
wim 0:300d08d9b058 493 // I2Cdev::writeByte(m_devAddr, COMMAND_MODE, command);
wim 0:300d08d9b058 494
wim 4:df92b0c0cb92 495 #if (I2C_OPTIMIZE == 0)
wim 0:300d08d9b058 496 char databytes[2];
wim 0:300d08d9b058 497
wim 0:300d08d9b058 498 databytes[0] = COMMAND_MODE;
wim 0:300d08d9b058 499 databytes[1] = command;
wim 0:300d08d9b058 500 _i2c.write(_writeOpcode, databytes, 2); // Write command
wim 4:df92b0c0cb92 501 #else
wim 4:df92b0c0cb92 502
wim 0:300d08d9b058 503 _i2c.start();
wim 0:300d08d9b058 504 _i2c.write(_writeOpcode);
wim 0:300d08d9b058 505
wim 0:300d08d9b058 506 _i2c.write(COMMAND_MODE);
wim 0:300d08d9b058 507 _i2c.write(command); // Write Command
wim 0:300d08d9b058 508
wim 0:300d08d9b058 509 _i2c.stop();
wim 4:df92b0c0cb92 510 #endif
wim 0:300d08d9b058 511 }
wim 0:300d08d9b058 512
wim 1:b7e8f5139026 513 /** @brief Write command that has one parameter
wim 1:b7e8f5139026 514 */
wim 0:300d08d9b058 515 void SSD1308::_sendCommand(uint8_t command, uint8_t param1) {
wim 0:300d08d9b058 516
wim 0:300d08d9b058 517 // Note continuationbit is set, so COMMAND_MODE must be
wim 0:300d08d9b058 518 // repeated before each databyte that serves as parameter!
wim 4:df92b0c0cb92 519 #if (I2C_OPTIMIZE == 0)
wim 4:df92b0c0cb92 520 char databytes[4];
wim 4:df92b0c0cb92 521
wim 4:df92b0c0cb92 522 databytes[0] = COMMAND_MODE;
wim 4:df92b0c0cb92 523 databytes[1] = command;
wim 4:df92b0c0cb92 524 databytes[2] = COMMAND_MODE;
wim 4:df92b0c0cb92 525 databytes[3] = param1;
wim 4:df92b0c0cb92 526 _i2c.write(_writeOpcode, databytes, 4); // Write command
wim 4:df92b0c0cb92 527 #else
wim 0:300d08d9b058 528
wim 0:300d08d9b058 529 _i2c.start();
wim 0:300d08d9b058 530 _i2c.write(_writeOpcode);
wim 0:300d08d9b058 531
wim 0:300d08d9b058 532 _i2c.write(COMMAND_MODE);
wim 0:300d08d9b058 533 _i2c.write(command); // Write Command
wim 0:300d08d9b058 534 _i2c.write(COMMAND_MODE);
wim 0:300d08d9b058 535 _i2c.write(param1); // Write Param1
wim 0:300d08d9b058 536
wim 0:300d08d9b058 537 _i2c.stop();
wim 4:df92b0c0cb92 538 #endif
wim 0:300d08d9b058 539 }
wim 0:300d08d9b058 540
wim 1:b7e8f5139026 541 /** @brief Write command that has two parameters
wim 1:b7e8f5139026 542 */
wim 0:300d08d9b058 543 void SSD1308::_sendCommand(uint8_t command, uint8_t param1, uint8_t param2) {
wim 0:300d08d9b058 544
wim 0:300d08d9b058 545 // Note continuationbit is set, so COMMAND_MODE must be
wim 0:300d08d9b058 546 // repeated before each databyte that serves as parameter!
wim 4:df92b0c0cb92 547 #if (I2C_OPTIMIZE == 0)
wim 4:df92b0c0cb92 548 char databytes[6];
wim 4:df92b0c0cb92 549
wim 4:df92b0c0cb92 550 databytes[0] = COMMAND_MODE;
wim 4:df92b0c0cb92 551 databytes[1] = command;
wim 4:df92b0c0cb92 552 databytes[2] = COMMAND_MODE;
wim 4:df92b0c0cb92 553 databytes[3] = param1;
wim 4:df92b0c0cb92 554 databytes[4] = COMMAND_MODE;
wim 4:df92b0c0cb92 555 databytes[5] = param2;
wim 4:df92b0c0cb92 556 _i2c.write(_writeOpcode, databytes, 6); // Write command
wim 4:df92b0c0cb92 557 #else
wim 0:300d08d9b058 558 _i2c.start();
wim 0:300d08d9b058 559 _i2c.write(_writeOpcode);
wim 0:300d08d9b058 560
wim 0:300d08d9b058 561 _i2c.write(COMMAND_MODE);
wim 0:300d08d9b058 562 _i2c.write(command); // Write Command
wim 0:300d08d9b058 563 _i2c.write(COMMAND_MODE);
wim 0:300d08d9b058 564 _i2c.write(param1); // Write Param1
wim 0:300d08d9b058 565 _i2c.write(COMMAND_MODE);
wim 0:300d08d9b058 566 _i2c.write(param2); // Write Param2
wim 0:300d08d9b058 567
wim 0:300d08d9b058 568 _i2c.stop();
wim 4:df92b0c0cb92 569 #endif
wim 0:300d08d9b058 570 }
wim 0:300d08d9b058 571
wim 2:16c84a134393 572 /** @brief Write command that has five parameters
wim 2:16c84a134393 573 */
wim 2:16c84a134393 574 void SSD1308::_sendCommand(uint8_t command, uint8_t param1, uint8_t param2,
wim 2:16c84a134393 575 uint8_t param3, uint8_t param4,
wim 2:16c84a134393 576 uint8_t param5) {
wim 2:16c84a134393 577
wim 2:16c84a134393 578 // Note continuationbit is set, so COMMAND_MODE must be
wim 2:16c84a134393 579 // repeated before each databyte that serves as parameter!
wim 4:df92b0c0cb92 580 #if (I2C_OPTIMIZE == 0)
wim 4:df92b0c0cb92 581 char databytes[12];
wim 4:df92b0c0cb92 582
wim 4:df92b0c0cb92 583 databytes[0] = COMMAND_MODE;
wim 4:df92b0c0cb92 584 databytes[1] = command;
wim 4:df92b0c0cb92 585 databytes[2] = COMMAND_MODE;
wim 4:df92b0c0cb92 586 databytes[3] = param1;
wim 4:df92b0c0cb92 587 databytes[4] = COMMAND_MODE;
wim 4:df92b0c0cb92 588 databytes[5] = param2;
wim 4:df92b0c0cb92 589 databytes[6] = COMMAND_MODE;
wim 4:df92b0c0cb92 590 databytes[7] = param3;
wim 4:df92b0c0cb92 591 databytes[8] = COMMAND_MODE;
wim 4:df92b0c0cb92 592 databytes[9] = param4;
wim 4:df92b0c0cb92 593 databytes[10] = COMMAND_MODE;
wim 4:df92b0c0cb92 594 databytes[11] = param5;
wim 4:df92b0c0cb92 595 _i2c.write(_writeOpcode, databytes, 12); // Write command
wim 4:df92b0c0cb92 596 #else
wim 2:16c84a134393 597 _i2c.start();
wim 2:16c84a134393 598 _i2c.write(_writeOpcode);
wim 2:16c84a134393 599
wim 2:16c84a134393 600 _i2c.write(COMMAND_MODE);
wim 2:16c84a134393 601 _i2c.write(command); // Write Command
wim 2:16c84a134393 602 _i2c.write(COMMAND_MODE);
wim 2:16c84a134393 603 _i2c.write(param1); // Write Param1
wim 2:16c84a134393 604 _i2c.write(COMMAND_MODE);
wim 2:16c84a134393 605 _i2c.write(param2); // Write Param2
wim 2:16c84a134393 606 _i2c.write(COMMAND_MODE);
wim 2:16c84a134393 607 _i2c.write(param3); // Write Param3
wim 2:16c84a134393 608 _i2c.write(COMMAND_MODE);
wim 2:16c84a134393 609 _i2c.write(param4); // Write Param4
wim 2:16c84a134393 610 _i2c.write(COMMAND_MODE);
wim 2:16c84a134393 611 _i2c.write(param5); // Write Param5
wim 2:16c84a134393 612
wim 2:16c84a134393 613 _i2c.stop();
wim 4:df92b0c0cb92 614 #endif
wim 2:16c84a134393 615 }
wim 2:16c84a134393 616
wim 2:16c84a134393 617
wim 2:16c84a134393 618 /** @brief Write command that has six parameters
wim 2:16c84a134393 619 */
wim 2:16c84a134393 620 void SSD1308::_sendCommand(uint8_t command, uint8_t param1, uint8_t param2,
wim 2:16c84a134393 621 uint8_t param3, uint8_t param4,
wim 2:16c84a134393 622 uint8_t param5, uint8_t param6) {
wim 2:16c84a134393 623
wim 2:16c84a134393 624 // Note continuationbit is set, so COMMAND_MODE must be
wim 2:16c84a134393 625 // repeated before each databyte that serves as parameter!
wim 4:df92b0c0cb92 626 #if (I2C_OPTIMIZE == 0)
wim 4:df92b0c0cb92 627 char databytes[14];
wim 4:df92b0c0cb92 628
wim 4:df92b0c0cb92 629 databytes[0] = COMMAND_MODE;
wim 4:df92b0c0cb92 630 databytes[1] = command;
wim 4:df92b0c0cb92 631 databytes[2] = COMMAND_MODE;
wim 4:df92b0c0cb92 632 databytes[3] = param1;
wim 4:df92b0c0cb92 633 databytes[4] = COMMAND_MODE;
wim 4:df92b0c0cb92 634 databytes[5] = param2;
wim 4:df92b0c0cb92 635 databytes[6] = COMMAND_MODE;
wim 4:df92b0c0cb92 636 databytes[7] = param3;
wim 4:df92b0c0cb92 637 databytes[8] = COMMAND_MODE;
wim 4:df92b0c0cb92 638 databytes[9] = param4;
wim 4:df92b0c0cb92 639 databytes[10] = COMMAND_MODE;
wim 4:df92b0c0cb92 640 databytes[11] = param5;
wim 4:df92b0c0cb92 641 databytes[12] = COMMAND_MODE;
wim 4:df92b0c0cb92 642 databytes[13] = param6;
wim 4:df92b0c0cb92 643 _i2c.write(_writeOpcode, databytes, 14); // Write command
wim 4:df92b0c0cb92 644 #else
wim 2:16c84a134393 645 _i2c.start();
wim 2:16c84a134393 646 _i2c.write(_writeOpcode);
wim 2:16c84a134393 647
wim 2:16c84a134393 648 _i2c.write(COMMAND_MODE);
wim 2:16c84a134393 649 _i2c.write(command); // Write Command
wim 2:16c84a134393 650 _i2c.write(COMMAND_MODE);
wim 2:16c84a134393 651 _i2c.write(param1); // Write Param1
wim 2:16c84a134393 652 _i2c.write(COMMAND_MODE);
wim 2:16c84a134393 653 _i2c.write(param2); // Write Param2
wim 2:16c84a134393 654 _i2c.write(COMMAND_MODE);
wim 2:16c84a134393 655 _i2c.write(param3); // Write Param3
wim 2:16c84a134393 656 _i2c.write(COMMAND_MODE);
wim 2:16c84a134393 657 _i2c.write(param4); // Write Param4
wim 2:16c84a134393 658 _i2c.write(COMMAND_MODE);
wim 2:16c84a134393 659 _i2c.write(param5); // Write Param5
wim 2:16c84a134393 660 _i2c.write(COMMAND_MODE);
wim 2:16c84a134393 661 _i2c.write(param6); // Write Param6
wim 2:16c84a134393 662
wim 2:16c84a134393 663 _i2c.stop();
wim 4:df92b0c0cb92 664 #endif
wim 2:16c84a134393 665 }
wim 2:16c84a134393 666
wim 2:16c84a134393 667
wim 0:300d08d9b058 668 #if(0)
wim 1:b7e8f5139026 669 /** @brief Write command that has multiple parameters
wim 1:b7e8f5139026 670 */
wim 0:300d08d9b058 671 void SSD1308::_sendCommands(uint8_t len, uint8_t* commands) {
wim 0:300d08d9b058 672
wim 0:300d08d9b058 673 // I2Cdev::writeBytes(m_devAddr, COMMAND_MODE, len, commands);
wim 0:300d08d9b058 674 // Note this original code is not correct, continuationbit is set,
wim 0:300d08d9b058 675 // so COMMAND_MODE must be repeated before each databyte that serves as parameter!
wim 0:300d08d9b058 676
wim 0:300d08d9b058 677 _i2c.start();
wim 0:300d08d9b058 678 _i2c.write(_writeOpcode);
wim 0:300d08d9b058 679
wim 0:300d08d9b058 680 for (int i=0; i<len ; i++) {
wim 0:300d08d9b058 681 _i2c.write(COMMAND_MODE);
wim 0:300d08d9b058 682 _i2c.write(commands[i]); // Write Commands
wim 0:300d08d9b058 683 }
wim 0:300d08d9b058 684 _i2c.stop();
wim 0:300d08d9b058 685
wim 0:300d08d9b058 686 }
wim 0:300d08d9b058 687 #endif
wim 0:300d08d9b058 688
wim 1:b7e8f5139026 689 /** @brief Write databyte to display
wim 1:b7e8f5139026 690 * @brief Start at current cursor location
wim 1:b7e8f5139026 691 * @param uint8_t data databyte to write
wim 1:b7e8f5139026 692 */
wim 0:300d08d9b058 693 void SSD1308::_sendData(uint8_t data){
wim 0:300d08d9b058 694
wim 4:df92b0c0cb92 695 #if (I2C_OPTIMIZE == 0)
wim 4:df92b0c0cb92 696 //I2C Blockwrite versions dont seem to work ?
wim 4:df92b0c0cb92 697 //That may be related to fact that the SSD1308/SSD1306 does NOT return an acknowledge: blockwrite may abort the operation
wim 4:df92b0c0cb92 698 //Noted for mbed lib v63 on 20/7/13
wim 0:300d08d9b058 699 char databytes[2];
wim 0:300d08d9b058 700
wim 0:300d08d9b058 701 databytes[0] = DATA_MODE;
wim 0:300d08d9b058 702 databytes[1] = data;
wim 0:300d08d9b058 703 _i2c.write(_writeOpcode, databytes, 2); // Write Data
wim 4:df92b0c0cb92 704
wim 4:df92b0c0cb92 705 #else
wim 4:df92b0c0cb92 706 _i2c.start();
wim 4:df92b0c0cb92 707 _i2c.write(_writeOpcode);
wim 4:df92b0c0cb92 708 _i2c.write(DATA_MODE);
wim 4:df92b0c0cb92 709 _i2c.write(data);
wim 4:df92b0c0cb92 710 _i2c.stop();
wim 4:df92b0c0cb92 711 #endif
wim 4:df92b0c0cb92 712
wim 0:300d08d9b058 713 }
wim 0:300d08d9b058 714
wim 1:b7e8f5139026 715 /** @brief Write len bytes from buffer data to display,
wim 1:b7e8f5139026 716 * @brief Start at current cursor location
wim 1:b7e8f5139026 717 * @param uint8_t len number of bytes to write
wim 1:b7e8f5139026 718 * @param uint8_t* data pointer to data
wim 1:b7e8f5139026 719 */
wim 0:300d08d9b058 720 void SSD1308::_sendData(uint8_t len, uint8_t* data) {
wim 0:300d08d9b058 721 // I2Cdev::writeBytes(m_devAddr, DATA_MODE, len, data);
wim 4:df92b0c0cb92 722 #if (I2C_OPTIMIZE == 0)
wim 4:df92b0c0cb92 723 for (int i=0; i<len ; i++) {
wim 4:df92b0c0cb92 724 _sendData(data[i]); // Write Data
wim 4:df92b0c0cb92 725 }
wim 4:df92b0c0cb92 726 #else
wim 0:300d08d9b058 727 _i2c.start();
wim 0:300d08d9b058 728 _i2c.write(_writeOpcode);
wim 0:300d08d9b058 729 _i2c.write(DATA_MODE);
wim 0:300d08d9b058 730 for (int i=0; i<len ; i++) {
wim 0:300d08d9b058 731 _i2c.write(data[i]); // Write Data
wim 0:300d08d9b058 732 }
wim 0:300d08d9b058 733 _i2c.stop();
wim 4:df92b0c0cb92 734 #endif
wim 0:300d08d9b058 735 }
wim 0:300d08d9b058 736
wim 0:300d08d9b058 737
wim 2:16c84a134393 738 /** @brief Set Horizontal Addressing Mode (cursor incr left-to-right, top-to-bottom)
wim 2:16c84a134393 739 *
wim 2:16c84a134393 740 */
wim 0:300d08d9b058 741 void SSD1308::setHorizontalAddressingMode(){
wim 0:300d08d9b058 742 setMemoryAddressingMode(HORIZONTAL_ADDRESSING_MODE);
wim 0:300d08d9b058 743 }
wim 0:300d08d9b058 744
wim 2:16c84a134393 745 /** @brief Set Vertical Addressing Mode (cursor incr top-to-bottom, left-to-right)
wim 2:16c84a134393 746 *
wim 2:16c84a134393 747 */
wim 0:300d08d9b058 748 void SSD1308::setVerticalAddressingMode() {
wim 0:300d08d9b058 749 setMemoryAddressingMode(VERTICAL_ADDRESSING_MODE);
wim 0:300d08d9b058 750 }
wim 0:300d08d9b058 751
wim 2:16c84a134393 752 /** @brief Set Page Addressing Mode (cursor incr left-to-right)
wim 2:16c84a134393 753 *
wim 2:16c84a134393 754 */
wim 0:300d08d9b058 755 void SSD1308::setPageAddressingMode(){
wim 0:300d08d9b058 756 setMemoryAddressingMode(PAGE_ADDRESSING_MODE);
wim 0:300d08d9b058 757 }
wim 0:300d08d9b058 758
wim 2:16c84a134393 759 /** @brief Set Addressing Mode
wim 2:16c84a134393 760 * @param uint8_t mode
wim 2:16c84a134393 761 */
wim 0:300d08d9b058 762 void SSD1308::setMemoryAddressingMode(uint8_t mode){
wim 0:300d08d9b058 763
wim 0:300d08d9b058 764 _sendCommand(SET_MEMORY_ADDRESSING_MODE, mode);
wim 0:300d08d9b058 765 }
wim 0:300d08d9b058 766
wim 0:300d08d9b058 767
wim 1:b7e8f5139026 768 /** @param uint8_t start startpage (valid range 0..MAX_PAGE)
wim 1:b7e8f5139026 769 * @param uint8_t end endpage (valid range start..MAX_PAGE)
wim 1:b7e8f5139026 770 */
wim 0:300d08d9b058 771 void SSD1308::setPageAddress(uint8_t start, uint8_t end) {
wim 0:300d08d9b058 772
wim 0:300d08d9b058 773 _sendCommand(SET_PAGE_ADDRESS, start, end);
wim 0:300d08d9b058 774 }
wim 0:300d08d9b058 775
wim 0:300d08d9b058 776
wim 1:b7e8f5139026 777 /** @param uint8_t start startcolumn (valid range 0..MAX_COL)
wim 1:b7e8f5139026 778 * @param uint8_t end endcolumn (valid range start..MAX_COL)
wim 1:b7e8f5139026 779 */
wim 0:300d08d9b058 780 void SSD1308::setColumnAddress(uint8_t start, uint8_t end) {
wim 0:300d08d9b058 781
wim 0:300d08d9b058 782 _sendCommand(SET_COLUMN_ADDRESS, start, end);
wim 0:300d08d9b058 783 }
wim 0:300d08d9b058 784
wim 2:16c84a134393 785 /**
wim 2:16c84a134393 786 * @brief Set Display StartLine, takes one byte, 0x00-0x3F
wim 2:16c84a134393 787 * @param uint8_t line startline (valid range 0..MAX_ROWS)
wim 2:16c84a134393 788 */
wim 2:16c84a134393 789 void SSD1308::setDisplayStartLine(uint8_t line) {
wim 2:16c84a134393 790
wim 2:16c84a134393 791 line = line & MAX_ROW;
wim 2:16c84a134393 792
wim 2:16c84a134393 793 _sendCommand(SET_DISPLAY_START_LINE | line);
wim 2:16c84a134393 794 }
wim 2:16c84a134393 795
wim 2:16c84a134393 796
wim 2:16c84a134393 797 /**
wim 2:16c84a134393 798 * @brief Set Column Start (for Page Addressing Mode only)
wim 2:16c84a134393 799 * @param uint8_t column column start (valid range 0..MAX_COL)
wim 2:16c84a134393 800 */
wim 2:16c84a134393 801 void SSD1308::setColumnStartForPageAddressingMode(uint8_t column) {
wim 2:16c84a134393 802
wim 2:16c84a134393 803 column = column & MAX_COL;
wim 2:16c84a134393 804
wim 2:16c84a134393 805 _sendCommand(SET_LOWER_COLUMN | ( column & 0x0F)); // lower nibble
wim 2:16c84a134393 806 _sendCommand(SET_HIGHER_COLUMN | ((column>>4) & 0x0F)); // higher nibble
wim 2:16c84a134393 807 }
wim 2:16c84a134393 808
wim 2:16c84a134393 809
wim 2:16c84a134393 810 /**
wim 2:16c84a134393 811 * @brief Set Page Start (for Page Addressing Mode only)
wim 2:16c84a134393 812 * @param uint8_t page page start (valid range PAGE0 - PAGE7)
wim 2:16c84a134393 813 */
wim 2:16c84a134393 814 void SSD1308::setPageStartForPageAddressingMode(uint8_t page) {
wim 2:16c84a134393 815
wim 2:16c84a134393 816 page = page & MAX_PAGE;
wim 2:16c84a134393 817
wim 2:16c84a134393 818 _sendCommand(SET_PAGE_START_ADDRESS | page);
wim 2:16c84a134393 819
wim 2:16c84a134393 820 }
wim 2:16c84a134393 821
wim 2:16c84a134393 822
wim 1:b7e8f5139026 823 /** @brief Set Contrast
wim 1:b7e8f5139026 824 * @param uint8_t contrast (valid range 0x00 (lowest) - 0xFF (highest))
wim 1:b7e8f5139026 825 */
wim 0:300d08d9b058 826 void SSD1308::setContrastControl(uint8_t contrast) {
wim 0:300d08d9b058 827
wim 0:300d08d9b058 828 _sendCommand(SET_CONTRAST, contrast);
wim 0:300d08d9b058 829 }
wim 0:300d08d9b058 830
wim 1:b7e8f5139026 831 /** @brief Enable Display
wim 1:b7e8f5139026 832 */
wim 0:300d08d9b058 833 void SSD1308::setDisplayOn() {
wim 0:300d08d9b058 834 _sendCommand(SET_DISPLAY_POWER_ON);
wim 0:300d08d9b058 835 }
wim 0:300d08d9b058 836
wim 1:b7e8f5139026 837 /** @brief Disable Display
wim 1:b7e8f5139026 838 */
wim 0:300d08d9b058 839 void SSD1308::setDisplayOff() {
wim 0:300d08d9b058 840 _sendCommand(SET_DISPLAY_POWER_OFF);
wim 0:300d08d9b058 841 }
wim 0:300d08d9b058 842
wim 1:b7e8f5139026 843 /** @brief Enable or Disable Display
wim 1:b7e8f5139026 844 * @param bool on
wim 1:b7e8f5139026 845 */
wim 0:300d08d9b058 846 void SSD1308::setDisplayPower(bool on) {
wim 0:300d08d9b058 847 if (on) {
wim 0:300d08d9b058 848 setDisplayOn();
wim 0:300d08d9b058 849 } else {
wim 0:300d08d9b058 850 setDisplayOff();
wim 0:300d08d9b058 851 }
wim 0:300d08d9b058 852 }
wim 0:300d08d9b058 853
wim 1:b7e8f5139026 854 /** @brief Show White pixels on Black background
wim 1:b7e8f5139026 855 */
wim 0:300d08d9b058 856 void SSD1308::setDisplayNormal() {
wim 0:300d08d9b058 857 _sendCommand(SET_NORMAL_DISPLAY);
wim 0:300d08d9b058 858 }
wim 0:300d08d9b058 859
wim 1:b7e8f5139026 860 /** @brief Show Black pixels on White background
wim 1:b7e8f5139026 861 */
wim 0:300d08d9b058 862 void SSD1308::setDisplayInverse() {
wim 0:300d08d9b058 863 _sendCommand(SET_INVERSE_DISPLAY);
wim 0:300d08d9b058 864 }
wim 0:300d08d9b058 865
wim 1:b7e8f5139026 866 /** @brief Blink display by fading in and out over a set number of frames
wim 1:b7e8f5139026 867 * @param bool on
wim 1:b7e8f5139026 868 */
wim 0:300d08d9b058 869 void SSD1308::setDisplayBlink(bool on){
wim 0:300d08d9b058 870 if (on) {
wim 0:300d08d9b058 871 _sendCommand(SET_FADE_BLINK, (BLINK_ENABLE | FADE_INTERVAL_128_FRAMES));
wim 0:300d08d9b058 872 }
wim 0:300d08d9b058 873 else {
wim 0:300d08d9b058 874 _sendCommand(SET_FADE_BLINK, FADE_BLINK_DISABLE);
wim 0:300d08d9b058 875 }
wim 0:300d08d9b058 876 }
wim 0:300d08d9b058 877
wim 0:300d08d9b058 878
wim 1:b7e8f5139026 879 /** @brief Fade out display in set number of frames
wim 1:b7e8f5139026 880 * @param bool on
wim 1:b7e8f5139026 881 */
wim 0:300d08d9b058 882 void SSD1308::setDisplayFade(bool on) {
wim 0:300d08d9b058 883 if (on) {
wim 0:300d08d9b058 884 _sendCommand(SET_FADE_BLINK, (FADE_OUT_ENABLE | FADE_INTERVAL_128_FRAMES));
wim 0:300d08d9b058 885 }
wim 0:300d08d9b058 886 else {
wim 0:300d08d9b058 887 _sendCommand(SET_FADE_BLINK, FADE_BLINK_DISABLE);
wim 0:300d08d9b058 888 }
wim 0:300d08d9b058 889 }
wim 0:300d08d9b058 890
wim 1:b7e8f5139026 891 /** @brief Display Flip (Left/Right, Up/Down)
wim 1:b7e8f5139026 892 * @param bool left flip Left/Right
wim 1:b7e8f5139026 893 * @param bool down flip Up/Down
wim 1:b7e8f5139026 894 */
wim 0:300d08d9b058 895 void SSD1308::setDisplayFlip(bool left, bool down) {
wim 0:300d08d9b058 896 if (left) {
wim 0:300d08d9b058 897 // column address 0 is mapped to SEG0 (Reset)
wim 0:300d08d9b058 898 _sendCommand(SET_SEGMENT_REMAP_0);
wim 0:300d08d9b058 899 }
wim 0:300d08d9b058 900 else {
wim 0:300d08d9b058 901 // column address 127 is mapped to SEG0
wim 0:300d08d9b058 902 _sendCommand(SET_SEGMENT_REMAP_127);
wim 0:300d08d9b058 903 }
wim 0:300d08d9b058 904
wim 0:300d08d9b058 905 if (down) {
wim 0:300d08d9b058 906 // Reset mode
wim 0:300d08d9b058 907 _sendCommand(SET_COMMON_REMAP_0);
wim 0:300d08d9b058 908 }
wim 0:300d08d9b058 909 else {
wim 0:300d08d9b058 910 // Flip Up/Down (Need to rewrite display before H effect shows)
wim 0:300d08d9b058 911 _sendCommand(SET_COMMON_REMAP_63);
wim 0:300d08d9b058 912 }
wim 0:300d08d9b058 913
wim 0:300d08d9b058 914 }
wim 0:300d08d9b058 915
wim 1:b7e8f5139026 916 /** @brief Sets Internal Iref
wim 1:b7e8f5139026 917 */
wim 0:300d08d9b058 918 void SSD1308::setInternalIref() {
wim 0:300d08d9b058 919 // uint8_t cmds[2] = {SET_IREF_SELECTION, INTERNAL_IREF};
wim 0:300d08d9b058 920 // _sendCommands(2, cmds);
wim 0:300d08d9b058 921
wim 0:300d08d9b058 922 _sendCommand(SET_IREF_SELECTION, INTERNAL_IREF);
wim 0:300d08d9b058 923 }
wim 0:300d08d9b058 924
wim 1:b7e8f5139026 925 /** @brief Sets External Iref (default)
wim 1:b7e8f5139026 926 */
wim 0:300d08d9b058 927 void SSD1308::setExternalIref() {
wim 0:300d08d9b058 928 // uint8_t cmds[2] = {SET_IREF_SELECTION, EXTERNAL_IREF};
wim 0:300d08d9b058 929 // _sendCommands(2, cmds);
wim 0:300d08d9b058 930 _sendCommand(SET_IREF_SELECTION, EXTERNAL_IREF);
wim 0:300d08d9b058 931 }
wim 0:300d08d9b058 932
wim 0:300d08d9b058 933
wim 2:16c84a134393 934 /** @brief Shows All Pixels On
wim 2:16c84a134393 935 */
wim 2:16c84a134393 936 void SSD1308::setEntireDisplayOn(){
wim 2:16c84a134393 937 _sendCommand(SET_ENTIRE_DISPLAY_ON);
wim 2:16c84a134393 938 }
wim 2:16c84a134393 939
wim 2:16c84a134393 940 /** @brief Shows Pixels as RAM content
wim 2:16c84a134393 941 */
wim 2:16c84a134393 942 void SSD1308::setEntireDisplayRAM(){
wim 2:16c84a134393 943 _sendCommand(SET_DISPLAY_GDDRAM);
wim 2:16c84a134393 944 }
wim 2:16c84a134393 945
wim 2:16c84a134393 946 /** @brief Shows Pixels On or as RAM content
wim 2:16c84a134393 947 * @param bool on (true is All on, false is RAM content)
wim 2:16c84a134393 948 */
wim 2:16c84a134393 949 void SSD1308::setEntireDisplay(bool on){
wim 2:16c84a134393 950 if (on) {
wim 2:16c84a134393 951 setEntireDisplayOn(); // All Pixels on
wim 2:16c84a134393 952 }
wim 2:16c84a134393 953 else {
wim 2:16c84a134393 954 setEntireDisplayRAM(); // Pixels are RAM content
wim 2:16c84a134393 955 }
wim 2:16c84a134393 956 }
wim 2:16c84a134393 957
wim 2:16c84a134393 958
wim 2:16c84a134393 959 /** @brief Horizontal scroll by one column per interval
wim 2:16c84a134393 960 * @param bool left select Left/Right scroll
wim 2:16c84a134393 961 * @param uint8_t start_page begin page (0..MAX_PAGE)
wim 2:16c84a134393 962 * @param uint8_t end_page end page (start_page..MAX_PAGE)
wim 2:16c84a134393 963 * @param uint8_t interval scroll interval in frames (see codes above)
wim 2:16c84a134393 964 */
wim 2:16c84a134393 965 void SSD1308::setContinuousHorizontalScroll(bool left, uint8_t start_page, uint8_t end_page, uint8_t interval) {
wim 2:16c84a134393 966 if (left) {
wim 2:16c84a134393 967 _sendCommand(SET_LEFT_HOR_SCROLL, 0x00, start_page, interval, end_page, 0x00, 0xFF); // Scroll Left
wim 2:16c84a134393 968 }
wim 2:16c84a134393 969 else {
wim 2:16c84a134393 970 _sendCommand(SET_RIGHT_HOR_SCROLL, 0x00, start_page, interval, end_page, 0x00, 0xFF); // Scroll Right
wim 2:16c84a134393 971 }
wim 2:16c84a134393 972
wim 2:16c84a134393 973 }
wim 2:16c84a134393 974
wim 2:16c84a134393 975
wim 2:16c84a134393 976 /** @brief Horizontal and Vertical scroll by one column per interval
wim 2:16c84a134393 977 * @param bool left select Left/Right scroll
wim 2:16c84a134393 978 * @param uint8_t start_page begin page (0..MAX_PAGE)
wim 2:16c84a134393 979 * @param uint8_t end_page end page (start_page..MAX_PAGE)
wim 2:16c84a134393 980 * @param uint8_t offset vert offset (0x01..0x63)
wim 2:16c84a134393 981 * @param uint8_t interval scroll interval in frames (see codes above)
wim 2:16c84a134393 982 */
wim 2:16c84a134393 983 void SSD1308::setContinuousVerticalAndHorizontalScroll(bool left, uint8_t start_page, uint8_t end_page,
wim 2:16c84a134393 984 uint8_t offset, uint8_t interval) {
wim 2:16c84a134393 985 if (left) {
wim 2:16c84a134393 986 _sendCommand(SET_VERT_LEFT_HOR_SCROLL, 0x00, start_page, interval, end_page, offset); // Scroll Left
wim 2:16c84a134393 987 }
wim 2:16c84a134393 988 else {
wim 2:16c84a134393 989 _sendCommand(SET_VERT_RIGHT_HOR_SCROLL, 0x00, start_page, interval, end_page, offset); // Scroll Right
wim 2:16c84a134393 990 }
wim 2:16c84a134393 991
wim 2:16c84a134393 992 }
wim 2:16c84a134393 993
wim 2:16c84a134393 994 /** @brief Set Vertical scroll area
wim 2:16c84a134393 995 * @param uint8_t topRowsFixed fixed rows (0..MAX_ROW)
wim 2:16c84a134393 996 * @param uint8_t scrollRowsoffset scroll rows (topRowsFixed..ROWS)
wim 2:16c84a134393 997 */
wim 2:16c84a134393 998 void SSD1308::setVerticalScrollArea(uint8_t topRowsFixed, uint8_t scrollRows) {
wim 2:16c84a134393 999
wim 2:16c84a134393 1000 if ((topRowsFixed + scrollRows) > ROWS) {
wim 2:16c84a134393 1001 scrollRows = ROWS - topRowsFixed;
wim 2:16c84a134393 1002 };
wim 2:16c84a134393 1003
wim 2:16c84a134393 1004 _sendCommand(SET_VERTICAL_SCROLL_AREA, topRowsFixed, scrollRows);
wim 2:16c84a134393 1005 }
wim 2:16c84a134393 1006
wim 2:16c84a134393 1007 /** @brief Activate or Deactivate Horizontal and Vertical scroll
wim 2:16c84a134393 1008 * @brief Note: after deactivating scrolling, the RAM data needs to be rewritten
wim 2:16c84a134393 1009 * @param bool on activate scroll
wim 2:16c84a134393 1010 */
wim 2:16c84a134393 1011 void SSD1308::setDisplayScroll(bool on) {
wim 2:16c84a134393 1012 if (on) {
wim 2:16c84a134393 1013 _sendCommand(SET_ACTIVATE_SCROLL); // Scroll on
wim 2:16c84a134393 1014 }
wim 2:16c84a134393 1015 else {
wim 2:16c84a134393 1016 _sendCommand(SET_DEACTIVATE_SCROLL); // Scroll off
wim 2:16c84a134393 1017 }
wim 2:16c84a134393 1018 }
wim 2:16c84a134393 1019
wim 2:16c84a134393 1020
wim 2:16c84a134393 1021
wim 1:b7e8f5139026 1022 /** @brief Low level Init
wim 1:b7e8f5139026 1023 * @brief Init the configuration registers in accordance with the datasheet
wim 1:b7e8f5139026 1024 */
wim 0:300d08d9b058 1025 void SSD1308::_init() {
wim 0:300d08d9b058 1026
wim 2:16c84a134393 1027 _sendCommand(SET_DISPLAY_POWER_OFF); // 0xAE
wim 0:300d08d9b058 1028
wim 0:300d08d9b058 1029 // column address 0 is mapped to SEG0 (Reset)
wim 2:16c84a134393 1030 // row address 0 is mapped to COM0 (Reset)
wim 2:16c84a134393 1031 _sendCommand(SET_SEGMENT_REMAP_0); // 0xA0 (Reset)
wim 2:16c84a134393 1032 _sendCommand(SET_COMMON_REMAP_0); // 0xC0 (Reset)
wim 2:16c84a134393 1033
wim 2:16c84a134393 1034 setDisplayStartLine(0); // 0x40 (Reset)
wim 0:300d08d9b058 1035
wim 2:16c84a134393 1036 _sendCommand(SET_COMMON_CONF, COMMON_BASE | COMMON_ALTERNATIVE | COMMON_LEFTRIGHT_NORMAL); // 0xDA, 0x12 (Reset)
wim 0:300d08d9b058 1037
wim 2:16c84a134393 1038 // Pagemode or Horizontal mode
wim 2:16c84a134393 1039 // setPageAddressingMode(); // 0x20, 0x02 (Reset)
wim 2:16c84a134393 1040 // setColumnStartForPageAddressingMode(0); // 0x00, 0x10 (Reset = Column 0)
wim 2:16c84a134393 1041 // setPageStartForPageAddressingMode(PAGE_0);// 0xBO (Reset = Page 0)
wim 2:16c84a134393 1042 setHorizontalAddressingMode(); // 0x20, 0x00 (Non-Reset)
wim 2:16c84a134393 1043 setColumnAddress(0, MAX_COL); // 0x21, 0x00, 0x37 (Reset)
wim 2:16c84a134393 1044 setPageAddress(0, MAX_PAGE); // 0x22, 0x00, 0x07 (Reset)
wim 0:300d08d9b058 1045
wim 2:16c84a134393 1046 setExternalIref(); // 0xAD, 0x10 (Reset)
wim 2:16c84a134393 1047
wim 2:16c84a134393 1048 _sendCommand(SET_DISPLAY_CLOCK, 0x70); // 0xD5, 0x70 (Reset = 0x80)
wim 2:16c84a134393 1049 _sendCommand(SET_PRECHARGE_TIME, 0x21); // 0xD9, 0x21 (Reset = 0x22)
wim 2:16c84a134393 1050 _sendCommand(SET_VCOMH_DESELECT_LEVEL, 0x30); // 0xDB, 0x30 (Reset = 0x20)
wim 2:16c84a134393 1051 _sendCommand(SET_MULTIPLEX_RATIO, 0x3F); // 0xA8, 0x3F (Reset)
wim 2:16c84a134393 1052 _sendCommand(SET_DISPLAY_OFFSET, 0x00); // 0xD3, 0x00 (Reset)
wim 2:16c84a134393 1053
wim 2:16c84a134393 1054 _sendCommand(SET_CONTRAST, 0x7F); // 0x81, 0x7F (Reset)
wim 0:300d08d9b058 1055
wim 2:16c84a134393 1056 _sendCommand(SET_NORMAL_DISPLAY); // 0xA6 (Reset)
wim 2:16c84a134393 1057
wim 2:16c84a134393 1058 setEntireDisplayRAM(); // 0xA4 (Reset)
wim 2:16c84a134393 1059 setDisplayScroll(false);
wim 0:300d08d9b058 1060
wim 0:300d08d9b058 1061 clearDisplay();
wim 0:300d08d9b058 1062
wim 2:16c84a134393 1063 _sendCommand(SET_DISPLAY_POWER_ON); // 0xAF
wim 0:300d08d9b058 1064 }
wim 0:300d08d9b058 1065