Important changes to repositories hosted on mbed.com
Mbed hosted mercurial repositories are deprecated and are due to be permanently deleted in July 2026.
To keep a copy of this software download the repository Zip archive or clone locally using Mercurial.
It is also possible to export all your personal repositories from the account settings page.
Dependents: Zavrsni_Daljinski Zavrsni_Daljinsk_vfinal
SSD1308.cpp
00001 /** @file SSD1308 I2C device class file 00002 * Based on Solomon Systech SSD1308 datasheet, rev. 1, 10/2008 00003 * The SSD1308 is used for example in the Seeed 128x64 OLED Display 00004 * http://www.seeedstudio.com/depot/grove-oled-display-12864-p-781.html?cPath=163_167 00005 */ 00006 // The original code by Andrew Schamp is using (and has been submitted as a part of) Jeff Rowberg's I2Cdevlib library, 00007 // which should (hopefully) always be available at https://github.com/jrowberg/i2cdevlib 00008 // Some parts also mashed up from Graphic Library for driving monochrome displays based on the PCD8544, 00009 // Copyright (c) 2011, Wim De Roeve, who in turn did partial port of code found on 00010 // http://serdisplib.sourceforge.net/ser/pcd8544.html#links and by Petras Saduikis <petras@petras.co.uk> 00011 // 00012 // Changelog: 00013 // 2011-08-25 - Initial release by Andrew Schamp <schamp@gmail.com> 00014 // 2012-06-19 - Ported to mbed and optimised (WH) 00015 // 2013-07-12 - Minor comment fix and placeholder for SSD1306 (WH) 00016 // 2015-01-01 - Switch for optimised I2C calls to test on F401 (WH) 00017 // 2017-12-18 - Fixed non-copyable issue (Thx kenjiArai) 00018 // 00019 /* 00020 ================================================================================ 00021 I2Cdev device library code is placed under the MIT license 00022 Copyright (c) 2011 Andrew Schamp 00023 Copyright (c) 2012,2013,2017 WH (mbed port) 00024 00025 Permission is hereby granted, free of charge, to any person obtaining a copy 00026 of this software and associated documentation files (the "Software"), to deal 00027 in the Software without restriction, including without limitation the rights 00028 to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 00029 copies of the Software, and to permit persons to whom the Software is 00030 furnished to do so, subject to the following conditions: 00031 00032 The above copyright notice and this permission notice shall be included in 00033 all copies or substantial portions of the Software. 00034 00035 THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 00036 IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 00037 FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 00038 AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 00039 LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 00040 OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 00041 THE SOFTWARE. 00042 ================================================================================ 00043 */ 00044 #include "mbed.h" 00045 #include "SSD1308.h" 00046 00047 //#include "font_3x5.h" 00048 //#include "font_5x7.h" 00049 //#include "font_6x8.h" 00050 #include "font_8x8.h" 00051 //#include "font_8x12.h" 00052 //#include "font_16x20.h" 00053 #include "font_16x24.h" 00054 00055 #if defined(TARGET_LPC1768) 00056 #define I2C_OPTIMIZE 1 00057 #else 00058 #define I2C_OPTIMIZE 0 00059 #endif 00060 00061 /** 00062 *@brief Constructor 00063 *@param I2C *i2c reference to i2c 00064 *@param uint8_t deviceAddress slaveaddress 00065 */ 00066 SSD1308::SSD1308(I2C *i2c, uint8_t deviceAddress) : _i2c(i2c) { 00067 00068 _writeOpcode = deviceAddress & 0xFE; // low order bit = 0 for write 00069 _readOpcode = deviceAddress | 0x01; // low order bit = 1 for read 00070 00071 initialize(); 00072 } 00073 00074 /** @brief High level Init, most settings remain at Power-On reset value 00075 */ 00076 void SSD1308::initialize() { 00077 setHorizontalAddressingMode(); 00078 00079 clearDisplay(); 00080 00081 setInverted(false); 00082 00083 setDisplayOn(); 00084 } 00085 00086 00087 /** @brief clear the display 00088 */ 00089 #if (I2C_OPTIMIZE == 0) 00090 // Standard version 00091 void SSD1308::clearDisplay() { 00092 00093 //setDisplayOff(); 00094 setPageAddress (0, MAX_PAGE); // all pages 00095 setColumnAddress (0, MAX_COL); // all columns 00096 00097 for (uint8_t page = 0; page < PAGES; page++) { 00098 for (uint8_t col = 0; col < COLUMNS; col++) { 00099 _sendData(0x00); 00100 } 00101 } 00102 00103 //setDisplayOn(); 00104 } 00105 #else 00106 //Optimised version 00107 // Save lots of I2C S,P, address and datacommands: 00108 // Send S, address, DATA_MODE, data, data, data,...., P 00109 // 00110 void SSD1308::clearDisplay() { 00111 00112 //setDisplayOff(); 00113 00114 setPageAddress (0, MAX_PAGE); // all pages 00115 setColumnAddress (0, MAX_COL); // all columns 00116 00117 _i2c->start(); 00118 _i2c->write(_writeOpcode); 00119 _i2c->write(DATA_MODE); 00120 for (int i=0; i<(PAGES * COLUMNS); i++) { 00121 _i2c->write(0x00); // Write Data 00122 } 00123 _i2c->stop(); 00124 00125 //setDisplayOn(); 00126 } 00127 #endif 00128 00129 00130 /** @brief fill the display 00131 * @param uint8_t pattern fillpattern vertical patch or 8 bits 00132 * @param uint8_t start_page begin page (0..MAX_PAGE) 00133 * @param uint8_t end_page end page (start_page..MAX_PAGE) 00134 * @param uint8_t start_col begin column (0..MAX_COL) 00135 * @param uint8_t end_col end column (start_col..MAX_COL) 00136 */ 00137 #if (I2C_OPTIMIZE == 0) 00138 //Standard version 00139 00140 void SSD1308::fillDisplay(uint8_t pattern, 00141 uint8_t start_page, uint8_t end_page, 00142 uint8_t start_col, uint8_t end_col) { 00143 00144 int count = (end_page - start_page + 1) * (end_col - start_col + 1); 00145 00146 //setDisplayOff(); 00147 setPageAddress (start_page, end_page); // set page window 00148 setColumnAddress (start_col, end_col); // set column window 00149 00150 for (int i=0; i<count; i++) { 00151 _sendData(pattern); // Write Data 00152 } 00153 00154 //setDisplayOn(); 00155 } 00156 00157 #else 00158 00159 //Optimised version 00160 // Save lots of I2C S,P, address and datacommands: 00161 // Send S, address, DATA_MODE, data, data, data,...., P 00162 // 00163 void SSD1308::fillDisplay(uint8_t pattern, 00164 uint8_t start_page, uint8_t end_page, 00165 uint8_t start_col, uint8_t end_col) { 00166 00167 int count = (end_page - start_page + 1) * (end_col - start_col + 1); 00168 00169 //setDisplayOff(); 00170 setPageAddress (start_page, end_page); // set page window 00171 setColumnAddress (start_col, end_col); // set column window 00172 00173 _i2c->start(); 00174 _i2c->write(_writeOpcode); 00175 _i2c->write(DATA_MODE); 00176 for (int i=0; i<count; i++) { 00177 _i2c->write(pattern); // Write Data 00178 } 00179 _i2c->stop(); 00180 00181 //setDisplayOn(); 00182 } 00183 00184 #endif 00185 00186 00187 /** @brief write a bitmap to the display 00188 * @param uint8_t* data pointer to bitmap 00189 * @param uint8_t start_page begin page (0..MAX_PAGE) 00190 * @param uint8_t end_page end page (start_page..MAX_PAGE) 00191 * @param uint8_t start_col begin column (0..MAX_COL) 00192 * @param uint8_t end_col end column (start_col..MAX_COL) 00193 */ 00194 #if (I2C_OPTIMIZE == 0) 00195 //Standard version 00196 void SSD1308::writeBitmap(uint8_t* data, 00197 uint8_t start_page, uint8_t end_page, 00198 uint8_t start_col, uint8_t end_col){ 00199 00200 int count = (end_page - start_page + 1) * (end_col - start_col + 1); 00201 00202 //setDisplayOff(); 00203 setPageAddress (start_page, end_page); // set page window 00204 setColumnAddress (start_col, end_col); // set column window 00205 00206 for (int i=0; i<count; i++) { 00207 _sendData(data[i]); // Write Data 00208 } 00209 00210 //setDisplayOn(); 00211 } 00212 00213 #else 00214 //Optimised version 00215 // Save lots of I2C S,P, address and datacommands: 00216 // Send S, address, DATA_MODE, data, data, data,...., P 00217 // 00218 void SSD1308::writeBitmap(uint8_t* data, 00219 uint8_t start_page, uint8_t end_page, 00220 uint8_t start_col, uint8_t end_col){ 00221 00222 int count = (end_page - start_page + 1) * (end_col - start_col + 1); 00223 00224 //setDisplayOff(); 00225 setPageAddress (start_page, end_page); // set page window 00226 setColumnAddress (start_col, end_col); // set column window 00227 00228 _i2c->start(); 00229 _i2c->write(_writeOpcode); 00230 _i2c->write(DATA_MODE); 00231 for (int i=0; i<count; i++) { 00232 _i2c->write(data[i]); // Write Data 00233 } 00234 _i2c->stop(); 00235 00236 //setDisplayOn(); 00237 } 00238 00239 #endif 00240 00241 00242 /** @brief write a progressbar to the display, Width is (PRG_MAX_SCALE + 2) pixels 00243 * @param uint8_t page begin page (0..MAX_PAGE) 00244 * @param uint8_t col begin column (0..MAX_COL) 00245 * @param int percentage value (0..100) 00246 */ 00247 #define PRG_MAX_SCALE 50 00248 #define PRG_LEFT_EDGE 0xFF 00249 #define PRG_RIGHT_EDGE 0xFF 00250 #define PRG_ACTIVE 0xFF 00251 //#define PRG_ACTIVE 0xBD 00252 #define PRG_NOT_ACTIVE 0x81 00253 00254 #if (I2C_OPTIMIZE == 0) 00255 //Standard version 00256 void SSD1308::writeProgressBar(uint8_t page, uint8_t col, int percentage) { 00257 uint8_t scale_value; 00258 00259 if (percentage <= 0) { 00260 scale_value = 0; 00261 } else if (percentage >= 100) { 00262 scale_value = PRG_MAX_SCALE - 1; 00263 } 00264 else { 00265 scale_value = (percentage * PRG_MAX_SCALE) / 100; 00266 } 00267 00268 //setDisplayOff(); 00269 setPageAddress (page, page); 00270 setColumnAddress (col, MAX_COL); 00271 00272 _sendData(PRG_LEFT_EDGE); 00273 00274 for (uint8_t col = 0; col < scale_value; col++) { 00275 _sendData(PRG_ACTIVE); 00276 } 00277 00278 _sendData(PRG_ACTIVE); 00279 00280 for (uint8_t col = (scale_value+1); col < PRG_MAX_SCALE; col++) { 00281 _sendData(PRG_NOT_ACTIVE); 00282 } 00283 00284 _sendData(PRG_RIGHT_EDGE); 00285 00286 //setDisplayOn(); 00287 } 00288 #else 00289 00290 //Optimised version 00291 // Save lots of I2C S,P, address and datacommands: 00292 // Send S, address, DATA_MODE, data, data, data,...., P 00293 // 00294 void SSD1308::writeProgressBar(uint8_t page, uint8_t col, int percentage) { 00295 uint8_t scale_value; 00296 00297 if (percentage <= 0) { 00298 scale_value = 0; 00299 } else if (percentage >= 100) { 00300 scale_value = PRG_MAX_SCALE - 1 ; 00301 } 00302 else { 00303 scale_value = (percentage * PRG_MAX_SCALE) / 100; 00304 } 00305 00306 //setDisplayOff(); 00307 setPageAddress (page, page); 00308 setColumnAddress (col, MAX_COL); 00309 00310 _i2c->start(); 00311 _i2c->write(_writeOpcode); 00312 _i2c->write(DATA_MODE); 00313 00314 _i2c->write(PRG_LEFT_EDGE); // Write Data 00315 00316 for (uint8_t col = 0; col < scale_value; col++) { 00317 _i2c->write(PRG_ACTIVE); // Write Data 00318 } 00319 00320 _i2c->write(PRG_ACTIVE); // Write Data 00321 00322 for (uint8_t col = (scale_value+1); col < PRG_MAX_SCALE; col++) { 00323 _i2c->write(PRG_NOT_ACTIVE); // Write Data 00324 } 00325 00326 _i2c->write(PRG_RIGHT_EDGE); // Write Data 00327 00328 _i2c->stop(); 00329 00330 //setDisplayOn(); 00331 } 00332 #endif 00333 00334 /** @brief write a level meter to the display, Width is (PRG_MAX_SCALE + 2) pixels 00335 * @param uint8_t page begin page (0..MAX_PAGE) 00336 * @param uint8_t col begin column (0..MAX_COL) 00337 * @param int percentage value (0..100) 00338 */ 00339 #if (I2C_OPTIMIZE == 0) 00340 void SSD1308::writeLevelBar(uint8_t page, uint8_t col, int percentage) { 00341 uint8_t scale_value; 00342 00343 if (percentage <= 0) { 00344 scale_value = 0; 00345 } else if (percentage >= 100) { 00346 scale_value = PRG_MAX_SCALE - 1; 00347 } 00348 else { 00349 scale_value = (percentage * PRG_MAX_SCALE) / 100; 00350 } 00351 00352 //setDisplayOff(); 00353 setPageAddress (page, page); 00354 setColumnAddress (col, MAX_COL); 00355 00356 _sendData(PRG_LEFT_EDGE); 00357 00358 for (uint8_t col = 0; col < scale_value; col++) { 00359 _sendData(PRG_NOT_ACTIVE); // Write Data 00360 } 00361 00362 _sendData(PRG_ACTIVE); // Write Data at active meterlevel 00363 00364 for (uint8_t col = scale_value+1; col < PRG_MAX_SCALE; col++) { 00365 _sendData(PRG_NOT_ACTIVE); 00366 } 00367 00368 _sendData(PRG_RIGHT_EDGE); 00369 00370 //setDisplayOn(); 00371 } 00372 #else 00373 //Optimised version 00374 // Save lots of I2C S,P, address and datacommands: 00375 // Send S, address, DATA_MODE, data, data, data,...., P 00376 // 00377 void SSD1308::writeLevelBar(uint8_t page, uint8_t col, int percentage) { 00378 uint8_t scale_value; 00379 00380 if (percentage <= 0) { 00381 scale_value = 0; 00382 } else if (percentage >= 100) { 00383 scale_value = PRG_MAX_SCALE - 1; 00384 } 00385 else { 00386 scale_value = (percentage * PRG_MAX_SCALE) / 100; 00387 } 00388 00389 //setDisplayOff(); 00390 setPageAddress (page, page); 00391 setColumnAddress (col, MAX_COL); 00392 00393 _i2c->start(); 00394 _i2c->write(_writeOpcode); 00395 _i2c->write(DATA_MODE); 00396 00397 _i2c->write(PRG_LEFT_EDGE); // Write Data 00398 00399 for (uint8_t col = 0; col < scale_value; col++) { 00400 _i2c->write(PRG_NOT_ACTIVE); // Write Data 00401 } 00402 00403 _i2c->write(PRG_ACTIVE); // Write Data at active meterlevel 00404 00405 for (uint8_t col = scale_value+1; col < PRG_MAX_SCALE; col++) { 00406 _i2c->write(PRG_NOT_ACTIVE); // Write Data 00407 } 00408 00409 _i2c->write(PRG_RIGHT_EDGE); // Write Data 00410 00411 _i2c->stop(); 00412 00413 //setDisplayOn(); 00414 } 00415 #endif 00416 00417 /** @brief Write single character to the display using the 8x8 fontable 00418 * @brief Start at current cursor location 00419 * @param char chr character to write 00420 */ 00421 void SSD1308::writeChar(char chr) { 00422 00423 const uint8_t char_index = chr - 0x20; 00424 00425 for (uint8_t i = 0; i < 8; i++) { 00426 if (_inverted) { 00427 _sendData( ~font_8x8[char_index][i] ); 00428 } 00429 else { 00430 _sendData( font_8x8[char_index][i] ); 00431 } 00432 } 00433 00434 } 00435 00436 00437 /** @brief Write a string to the display using the 8x8 font 00438 * @brief Start at selected cursor location, text will wrap around until it is done 00439 * @param uint8_t row row number (0...ROWS/FONT_HEIGHT) 00440 * @param uint8_t col column number (0...COLUMNS/FONT_WIDTH) 00441 * @param const char * text pointer to text 00442 */ 00443 void SSD1308::writeString(uint8_t row, uint8_t col, const char * text) { 00444 uint16_t index = 0; 00445 uint16_t len = strlen(text); 00446 00447 setPageAddress (row, MAX_PAGE); 00448 const uint8_t col_addr = FONT8x8_WIDTH*col; 00449 setColumnAddress (col_addr, MAX_COL); 00450 00451 while ((col+index) < CHARS && (index < len)) { 00452 // write first line, starting at given position 00453 writeChar(text[index++]); 00454 } 00455 00456 // write remaining lines 00457 // write until the end of memory 00458 // then wrap around again from the top. 00459 if (index + 1 < len) { 00460 setPageAddress (row + 1, MAX_PAGE); 00461 setColumnAddress (0, MAX_COL); 00462 bool wrapEntireScreen = false; 00463 while (index + 1 < len) { 00464 writeChar(text[index++]); 00465 // if we've written the last character space on the screen, 00466 // reset the page and column address so that it wraps around from the top again 00467 if (!wrapEntireScreen && (row*CHARS + col + index) > 127) { 00468 setPageAddress (0, MAX_PAGE); 00469 setColumnAddress (0, MAX_COL); 00470 wrapEntireScreen = true; 00471 } 00472 } 00473 } 00474 } 00475 00476 00477 00478 /** @brief Write large character (16x24 font) 00479 * @param uint8_t row row number (0...MAX_ROW) 00480 * @param uint8_t col column number (0...MAX_COL) 00481 * @param char chr Used for displaying numbers 0 - 9 and '+', '-', '.' 00482 */ 00483 void SSD1308::writeBigChar(uint8_t row, uint8_t col, char chr) { 00484 00485 writeBitmap((uint8_t*) font_16x24[int(chr) - FONT16x24_START], 00486 row, (row + FONT16x24_BYTES - 1), 00487 col, (col + FONT16x24_WIDTH - 1)); 00488 } 00489 00490 00491 /** @brief Write command that has no parameters 00492 */ 00493 void SSD1308::_sendCommand(uint8_t command) { 00494 // I2Cdev::writeByte(m_devAddr, COMMAND_MODE, command); 00495 00496 #if (I2C_OPTIMIZE == 0) 00497 char databytes[2]; 00498 00499 databytes[0] = COMMAND_MODE; 00500 databytes[1] = command; 00501 _i2c->write(_writeOpcode, databytes, 2); // Write command 00502 #else 00503 00504 _i2c->start(); 00505 _i2c->write(_writeOpcode); 00506 00507 _i2c->write(COMMAND_MODE); 00508 _i2c->write(command); // Write Command 00509 00510 _i2c->stop(); 00511 #endif 00512 } 00513 00514 /** @brief Write command that has one parameter 00515 */ 00516 void SSD1308::_sendCommand(uint8_t command, uint8_t param1) { 00517 00518 // Note continuationbit is set, so COMMAND_MODE must be 00519 // repeated before each databyte that serves as parameter! 00520 #if (I2C_OPTIMIZE == 0) 00521 char databytes[4]; 00522 00523 databytes[0] = COMMAND_MODE; 00524 databytes[1] = command; 00525 databytes[2] = COMMAND_MODE; 00526 databytes[3] = param1; 00527 _i2c->write(_writeOpcode, databytes, 4); // Write command 00528 #else 00529 00530 _i2c->start(); 00531 _i2c->write(_writeOpcode); 00532 00533 _i2c->write(COMMAND_MODE); 00534 _i2c->write(command); // Write Command 00535 _i2c->write(COMMAND_MODE); 00536 _i2c->write(param1); // Write Param1 00537 00538 _i2c->stop(); 00539 #endif 00540 } 00541 00542 /** @brief Write command that has two parameters 00543 */ 00544 void SSD1308::_sendCommand(uint8_t command, uint8_t param1, uint8_t param2) { 00545 00546 // Note continuationbit is set, so COMMAND_MODE must be 00547 // repeated before each databyte that serves as parameter! 00548 #if (I2C_OPTIMIZE == 0) 00549 char databytes[6]; 00550 00551 databytes[0] = COMMAND_MODE; 00552 databytes[1] = command; 00553 databytes[2] = COMMAND_MODE; 00554 databytes[3] = param1; 00555 databytes[4] = COMMAND_MODE; 00556 databytes[5] = param2; 00557 _i2c->write(_writeOpcode, databytes, 6); // Write command 00558 #else 00559 _i2c->start(); 00560 _i2c->write(_writeOpcode); 00561 00562 _i2c->write(COMMAND_MODE); 00563 _i2c->write(command); // Write Command 00564 _i2c->write(COMMAND_MODE); 00565 _i2c->write(param1); // Write Param1 00566 _i2c->write(COMMAND_MODE); 00567 _i2c->write(param2); // Write Param2 00568 00569 _i2c->stop(); 00570 #endif 00571 } 00572 00573 /** @brief Write command that has five parameters 00574 */ 00575 void SSD1308::_sendCommand(uint8_t command, uint8_t param1, uint8_t param2, 00576 uint8_t param3, uint8_t param4, 00577 uint8_t param5) { 00578 00579 // Note continuationbit is set, so COMMAND_MODE must be 00580 // repeated before each databyte that serves as parameter! 00581 #if (I2C_OPTIMIZE == 0) 00582 char databytes[12]; 00583 00584 databytes[0] = COMMAND_MODE; 00585 databytes[1] = command; 00586 databytes[2] = COMMAND_MODE; 00587 databytes[3] = param1; 00588 databytes[4] = COMMAND_MODE; 00589 databytes[5] = param2; 00590 databytes[6] = COMMAND_MODE; 00591 databytes[7] = param3; 00592 databytes[8] = COMMAND_MODE; 00593 databytes[9] = param4; 00594 databytes[10] = COMMAND_MODE; 00595 databytes[11] = param5; 00596 _i2c->write(_writeOpcode, databytes, 12); // Write command 00597 #else 00598 _i2c->start(); 00599 _i2c->write(_writeOpcode); 00600 00601 _i2c->write(COMMAND_MODE); 00602 _i2c->write(command); // Write Command 00603 _i2c->write(COMMAND_MODE); 00604 _i2c->write(param1); // Write Param1 00605 _i2c->write(COMMAND_MODE); 00606 _i2c->write(param2); // Write Param2 00607 _i2c->write(COMMAND_MODE); 00608 _i2c->write(param3); // Write Param3 00609 _i2c->write(COMMAND_MODE); 00610 _i2c->write(param4); // Write Param4 00611 _i2c->write(COMMAND_MODE); 00612 _i2c->write(param5); // Write Param5 00613 00614 _i2c->stop(); 00615 #endif 00616 } 00617 00618 00619 /** @brief Write command that has six parameters 00620 */ 00621 void SSD1308::_sendCommand(uint8_t command, uint8_t param1, uint8_t param2, 00622 uint8_t param3, uint8_t param4, 00623 uint8_t param5, uint8_t param6) { 00624 00625 // Note continuationbit is set, so COMMAND_MODE must be 00626 // repeated before each databyte that serves as parameter! 00627 #if (I2C_OPTIMIZE == 0) 00628 char databytes[14]; 00629 00630 databytes[0] = COMMAND_MODE; 00631 databytes[1] = command; 00632 databytes[2] = COMMAND_MODE; 00633 databytes[3] = param1; 00634 databytes[4] = COMMAND_MODE; 00635 databytes[5] = param2; 00636 databytes[6] = COMMAND_MODE; 00637 databytes[7] = param3; 00638 databytes[8] = COMMAND_MODE; 00639 databytes[9] = param4; 00640 databytes[10] = COMMAND_MODE; 00641 databytes[11] = param5; 00642 databytes[12] = COMMAND_MODE; 00643 databytes[13] = param6; 00644 _i2c->write(_writeOpcode, databytes, 14); // Write command 00645 #else 00646 _i2c->start(); 00647 _i2c->write(_writeOpcode); 00648 00649 _i2c->write(COMMAND_MODE); 00650 _i2c->write(command); // Write Command 00651 _i2c->write(COMMAND_MODE); 00652 _i2c->write(param1); // Write Param1 00653 _i2c->write(COMMAND_MODE); 00654 _i2c->write(param2); // Write Param2 00655 _i2c->write(COMMAND_MODE); 00656 _i2c->write(param3); // Write Param3 00657 _i2c->write(COMMAND_MODE); 00658 _i2c->write(param4); // Write Param4 00659 _i2c->write(COMMAND_MODE); 00660 _i2c->write(param5); // Write Param5 00661 _i2c->write(COMMAND_MODE); 00662 _i2c->write(param6); // Write Param6 00663 00664 _i2c->stop(); 00665 #endif 00666 } 00667 00668 00669 #if(0) 00670 /** @brief Write command that has multiple parameters 00671 */ 00672 void SSD1308::_sendCommands(uint8_t len, uint8_t* commands) { 00673 00674 // I2Cdev::writeBytes(m_devAddr, COMMAND_MODE, len, commands); 00675 // Note this original code is not correct, continuationbit is set, 00676 // so COMMAND_MODE must be repeated before each databyte that serves as parameter! 00677 00678 _i2c->start(); 00679 _i2c->write(_writeOpcode); 00680 00681 for (int i=0; i<len ; i++) { 00682 _i2c->write(COMMAND_MODE); 00683 _i2c->write(commands[i]); // Write Commands 00684 } 00685 _i2c->stop(); 00686 00687 } 00688 #endif 00689 00690 /** @brief Write databyte to display 00691 * @brief Start at current cursor location 00692 * @param uint8_t data databyte to write 00693 */ 00694 void SSD1308::_sendData(uint8_t data){ 00695 00696 #if (I2C_OPTIMIZE == 0) 00697 //I2C Blockwrite versions dont seem to work ? 00698 //That may be related to fact that the SSD1308/SSD1306 does NOT return an acknowledge: blockwrite may abort the operation 00699 //Noted for mbed lib v63 on 20/7/13 00700 char databytes[2]; 00701 00702 databytes[0] = DATA_MODE; 00703 databytes[1] = data; 00704 _i2c->write(_writeOpcode, databytes, 2); // Write Data 00705 00706 #else 00707 _i2c->start(); 00708 _i2c->write(_writeOpcode); 00709 _i2c->write(DATA_MODE); 00710 _i2c->write(data); 00711 _i2c->stop(); 00712 #endif 00713 00714 } 00715 00716 /** @brief Write len bytes from buffer data to display, 00717 * @brief Start at current cursor location 00718 * @param uint8_t len number of bytes to write 00719 * @param uint8_t* data pointer to data 00720 */ 00721 void SSD1308::_sendData(uint8_t len, uint8_t* data) { 00722 // I2Cdev::writeBytes(m_devAddr, DATA_MODE, len, data); 00723 #if (I2C_OPTIMIZE == 0) 00724 for (int i=0; i<len ; i++) { 00725 _sendData(data[i]); // Write Data 00726 } 00727 #else 00728 _i2c->start(); 00729 _i2c->write(_writeOpcode); 00730 _i2c->write(DATA_MODE); 00731 for (int i=0; i<len ; i++) { 00732 _i2c->write(data[i]); // Write Data 00733 } 00734 _i2c->stop(); 00735 #endif 00736 } 00737 00738 00739 /** @brief Set Horizontal Addressing Mode (cursor incr left-to-right, top-to-bottom) 00740 * 00741 */ 00742 void SSD1308::setHorizontalAddressingMode(){ 00743 setMemoryAddressingMode(HORIZONTAL_ADDRESSING_MODE); 00744 } 00745 00746 /** @brief Set Vertical Addressing Mode (cursor incr top-to-bottom, left-to-right) 00747 * 00748 */ 00749 void SSD1308::setVerticalAddressingMode() { 00750 setMemoryAddressingMode(VERTICAL_ADDRESSING_MODE); 00751 } 00752 00753 /** @brief Set Page Addressing Mode (cursor incr left-to-right) 00754 * 00755 */ 00756 void SSD1308::setPageAddressingMode(){ 00757 setMemoryAddressingMode(PAGE_ADDRESSING_MODE); 00758 } 00759 00760 /** @brief Set Addressing Mode 00761 * @param uint8_t mode 00762 */ 00763 void SSD1308::setMemoryAddressingMode(uint8_t mode){ 00764 00765 _sendCommand(SET_MEMORY_ADDRESSING_MODE, mode); 00766 } 00767 00768 00769 /** @param uint8_t start startpage (valid range 0..MAX_PAGE) 00770 * @param uint8_t end endpage (valid range start..MAX_PAGE) 00771 */ 00772 void SSD1308::setPageAddress (uint8_t start, uint8_t end) { 00773 00774 _sendCommand(SET_PAGE_ADDRESS, start, end); 00775 } 00776 00777 00778 /** @param uint8_t start startcolumn (valid range 0..MAX_COL) 00779 * @param uint8_t end endcolumn (valid range start..MAX_COL) 00780 */ 00781 void SSD1308::setColumnAddress (uint8_t start, uint8_t end) { 00782 00783 _sendCommand(SET_COLUMN_ADDRESS, start, end); 00784 } 00785 00786 /** 00787 * @brief Set Display StartLine, takes one byte, 0x00-0x3F 00788 * @param uint8_t line startline (valid range 0..MAX_ROWS) 00789 */ 00790 void SSD1308::setDisplayStartLine(uint8_t line) { 00791 00792 line = line & MAX_ROW; 00793 00794 _sendCommand(SET_DISPLAY_START_LINE | line); 00795 } 00796 00797 00798 /** 00799 * @brief Set Column Start (for Page Addressing Mode only) 00800 * @param uint8_t column column start (valid range 0..MAX_COL) 00801 */ 00802 void SSD1308::setColumnStartForPageAddressingMode(uint8_t column) { 00803 00804 column = column & MAX_COL; 00805 00806 _sendCommand(SET_LOWER_COLUMN | ( column & 0x0F)); // lower nibble 00807 _sendCommand(SET_HIGHER_COLUMN | ((column>>4) & 0x0F)); // higher nibble 00808 } 00809 00810 00811 /** 00812 * @brief Set Page Start (for Page Addressing Mode only) 00813 * @param uint8_t page page start (valid range PAGE0 - PAGE7) 00814 */ 00815 void SSD1308::setPageStartForPageAddressingMode(uint8_t page) { 00816 00817 page = page & MAX_PAGE; 00818 00819 _sendCommand(SET_PAGE_START_ADDRESS | page); 00820 00821 } 00822 00823 00824 /** @brief Set Contrast 00825 * @param uint8_t contrast (valid range 0x00 (lowest) - 0xFF (highest)) 00826 */ 00827 void SSD1308::setContrastControl(uint8_t contrast) { 00828 00829 _sendCommand(SET_CONTRAST, contrast); 00830 } 00831 00832 /** @brief Enable Display 00833 */ 00834 void SSD1308::setDisplayOn() { 00835 _sendCommand(SET_DISPLAY_POWER_ON); 00836 } 00837 00838 /** @brief Disable Display 00839 */ 00840 void SSD1308::setDisplayOff() { 00841 _sendCommand(SET_DISPLAY_POWER_OFF); 00842 } 00843 00844 /** @brief Enable or Disable Display 00845 * @param bool on 00846 */ 00847 void SSD1308::setDisplayPower(bool on) { 00848 if (on) { 00849 setDisplayOn(); 00850 } else { 00851 setDisplayOff(); 00852 } 00853 } 00854 00855 /** @brief Show White pixels on Black background 00856 */ 00857 void SSD1308::setDisplayNormal() { 00858 _sendCommand(SET_NORMAL_DISPLAY); 00859 } 00860 00861 /** @brief Show Black pixels on White background 00862 */ 00863 void SSD1308::setDisplayInverse() { 00864 _sendCommand(SET_INVERSE_DISPLAY); 00865 } 00866 00867 /** @brief Blink display by fading in and out over a set number of frames 00868 * @param bool on 00869 */ 00870 void SSD1308::setDisplayBlink(bool on){ 00871 if (on) { 00872 _sendCommand(SET_FADE_BLINK, (BLINK_ENABLE | FADE_INTERVAL_128_FRAMES)); 00873 } 00874 else { 00875 _sendCommand(SET_FADE_BLINK, FADE_BLINK_DISABLE); 00876 } 00877 } 00878 00879 00880 /** @brief Fade out display in set number of frames 00881 * @param bool on 00882 */ 00883 void SSD1308::setDisplayFade(bool on) { 00884 if (on) { 00885 _sendCommand(SET_FADE_BLINK, (FADE_OUT_ENABLE | FADE_INTERVAL_128_FRAMES)); 00886 } 00887 else { 00888 _sendCommand(SET_FADE_BLINK, FADE_BLINK_DISABLE); 00889 } 00890 } 00891 00892 /** @brief Display Flip (Left/Right, Up/Down) 00893 * @param bool left flip Left/Right 00894 * @param bool down flip Up/Down 00895 */ 00896 void SSD1308::setDisplayFlip(bool left, bool down) { 00897 if (left) { 00898 // column address 0 is mapped to SEG0 (Reset) 00899 _sendCommand(SET_SEGMENT_REMAP_0); 00900 } 00901 else { 00902 // column address 127 is mapped to SEG0 00903 _sendCommand(SET_SEGMENT_REMAP_127); 00904 } 00905 00906 if (down) { 00907 // Reset mode 00908 _sendCommand(SET_COMMON_REMAP_0); 00909 } 00910 else { 00911 // Flip Up/Down (Need to rewrite display before H effect shows) 00912 _sendCommand(SET_COMMON_REMAP_63); 00913 } 00914 00915 } 00916 00917 /** @brief Sets Internal Iref 00918 */ 00919 void SSD1308::setInternalIref() { 00920 // uint8_t cmds[2] = {SET_IREF_SELECTION, INTERNAL_IREF}; 00921 // _sendCommands(2, cmds); 00922 00923 _sendCommand(SET_IREF_SELECTION, INTERNAL_IREF); 00924 } 00925 00926 /** @brief Sets External Iref (default) 00927 */ 00928 void SSD1308::setExternalIref() { 00929 // uint8_t cmds[2] = {SET_IREF_SELECTION, EXTERNAL_IREF}; 00930 // _sendCommands(2, cmds); 00931 _sendCommand(SET_IREF_SELECTION, EXTERNAL_IREF); 00932 } 00933 00934 00935 /** @brief Shows All Pixels On 00936 */ 00937 void SSD1308::setEntireDisplayOn(){ 00938 _sendCommand(SET_ENTIRE_DISPLAY_ON); 00939 } 00940 00941 /** @brief Shows Pixels as RAM content 00942 */ 00943 void SSD1308::setEntireDisplayRAM(){ 00944 _sendCommand(SET_DISPLAY_GDDRAM); 00945 } 00946 00947 /** @brief Shows Pixels On or as RAM content 00948 * @param bool on (true is All on, false is RAM content) 00949 */ 00950 void SSD1308::setEntireDisplay(bool on){ 00951 if (on) { 00952 setEntireDisplayOn(); // All Pixels on 00953 } 00954 else { 00955 setEntireDisplayRAM(); // Pixels are RAM content 00956 } 00957 } 00958 00959 00960 /** @brief Horizontal scroll by one column per interval 00961 * @param bool left select Left/Right scroll 00962 * @param uint8_t start_page begin page (0..MAX_PAGE) 00963 * @param uint8_t end_page end page (start_page..MAX_PAGE) 00964 * @param uint8_t interval scroll interval in frames (see codes above) 00965 */ 00966 void SSD1308::setContinuousHorizontalScroll(bool left, uint8_t start_page, uint8_t end_page, uint8_t interval) { 00967 if (left) { 00968 _sendCommand(SET_LEFT_HOR_SCROLL, 0x00, start_page, interval, end_page, 0x00, 0xFF); // Scroll Left 00969 } 00970 else { 00971 _sendCommand(SET_RIGHT_HOR_SCROLL, 0x00, start_page, interval, end_page, 0x00, 0xFF); // Scroll Right 00972 } 00973 00974 } 00975 00976 00977 /** @brief Horizontal and Vertical scroll by one column per interval 00978 * @param bool left select Left/Right scroll 00979 * @param uint8_t start_page begin page (0..MAX_PAGE) 00980 * @param uint8_t end_page end page (start_page..MAX_PAGE) 00981 * @param uint8_t offset vert offset (0x01..0x63) 00982 * @param uint8_t interval scroll interval in frames (see codes above) 00983 */ 00984 void SSD1308::setContinuousVerticalAndHorizontalScroll(bool left, uint8_t start_page, uint8_t end_page, 00985 uint8_t offset, uint8_t interval) { 00986 if (left) { 00987 _sendCommand(SET_VERT_LEFT_HOR_SCROLL, 0x00, start_page, interval, end_page, offset); // Scroll Left 00988 } 00989 else { 00990 _sendCommand(SET_VERT_RIGHT_HOR_SCROLL, 0x00, start_page, interval, end_page, offset); // Scroll Right 00991 } 00992 00993 } 00994 00995 /** @brief Set Vertical scroll area 00996 * @param uint8_t topRowsFixed fixed rows (0..MAX_ROW) 00997 * @param uint8_t scrollRowsoffset scroll rows (topRowsFixed..ROWS) 00998 */ 00999 void SSD1308::setVerticalScrollArea(uint8_t topRowsFixed, uint8_t scrollRows) { 01000 01001 if ((topRowsFixed + scrollRows) > ROWS) { 01002 scrollRows = ROWS - topRowsFixed; 01003 }; 01004 01005 _sendCommand(SET_VERTICAL_SCROLL_AREA, topRowsFixed, scrollRows); 01006 } 01007 01008 /** @brief Activate or Deactivate Horizontal and Vertical scroll 01009 * @brief Note: after deactivating scrolling, the RAM data needs to be rewritten 01010 * @param bool on activate scroll 01011 */ 01012 void SSD1308::setDisplayScroll(bool on) { 01013 if (on) { 01014 _sendCommand(SET_ACTIVATE_SCROLL); // Scroll on 01015 } 01016 else { 01017 _sendCommand(SET_DEACTIVATE_SCROLL); // Scroll off 01018 } 01019 } 01020 01021 01022 01023 /** @brief Low level Init 01024 * @brief Init the configuration registers in accordance with the datasheet 01025 */ 01026 void SSD1308::_init() { 01027 01028 _sendCommand(SET_DISPLAY_POWER_OFF); // 0xAE 01029 01030 // column address 0 is mapped to SEG0 (Reset) 01031 // row address 0 is mapped to COM0 (Reset) 01032 _sendCommand(SET_SEGMENT_REMAP_0); // 0xA0 (Reset) 01033 _sendCommand(SET_COMMON_REMAP_0); // 0xC0 (Reset) 01034 01035 setDisplayStartLine(0); // 0x40 (Reset) 01036 01037 _sendCommand(SET_COMMON_CONF, COMMON_BASE | COMMON_ALTERNATIVE | COMMON_LEFTRIGHT_NORMAL); // 0xDA, 0x12 (Reset) 01038 01039 // Pagemode or Horizontal mode 01040 // setPageAddressingMode(); // 0x20, 0x02 (Reset) 01041 // setColumnStartForPageAddressingMode(0); // 0x00, 0x10 (Reset = Column 0) 01042 // setPageStartForPageAddressingMode(PAGE_0);// 0xBO (Reset = Page 0) 01043 setHorizontalAddressingMode(); // 0x20, 0x00 (Non-Reset) 01044 setColumnAddress (0, MAX_COL); // 0x21, 0x00, 0x37 (Reset) 01045 setPageAddress (0, MAX_PAGE); // 0x22, 0x00, 0x07 (Reset) 01046 01047 setExternalIref(); // 0xAD, 0x10 (Reset) 01048 01049 _sendCommand(SET_DISPLAY_CLOCK, 0x70); // 0xD5, 0x70 (Reset = 0x80) 01050 _sendCommand(SET_PRECHARGE_TIME, 0x21); // 0xD9, 0x21 (Reset = 0x22) 01051 _sendCommand(SET_VCOMH_DESELECT_LEVEL, 0x30); // 0xDB, 0x30 (Reset = 0x20) 01052 _sendCommand(SET_MULTIPLEX_RATIO, 0x3F); // 0xA8, 0x3F (Reset) 01053 _sendCommand(SET_DISPLAY_OFFSET, 0x00); // 0xD3, 0x00 (Reset) 01054 01055 _sendCommand(SET_CONTRAST, 0x7F); // 0x81, 0x7F (Reset) 01056 01057 _sendCommand(SET_NORMAL_DISPLAY); // 0xA6 (Reset) 01058 01059 setEntireDisplayRAM(); // 0xA4 (Reset) 01060 setDisplayScroll(false); 01061 01062 clearDisplay(); 01063 01064 _sendCommand(SET_DISPLAY_POWER_ON); // 0xAF 01065 } 01066
Generated on Mon Jul 18 2022 08:24:50 by
1.7.2