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:
Mon Dec 18 18:46:05 2017 +0000
Revision:
5:e564cde8e03e
Parent:
4:df92b0c0cb92
Fixed non-copyable issue (Thx kenjiArai)

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