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