A fork with a fix to work with newer versions of MBED
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) 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 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 00433 } 00434 00435 00436 /** @brief Write a string to the display using the 8x8 font 00437 * @brief Start at selected cursor location, text will wrap around until it is done 00438 * @param uint8_t row row number (0...ROWS/FONT_HEIGHT) 00439 * @param uint8_t col column number (0...COLUMNS/FONT_WIDTH) 00440 * @param const char * text pointer to text 00441 */ 00442 void SSD1308::writeString(uint8_t row, uint8_t col, const char * text) { 00443 uint16_t index = 0; 00444 uint16_t len = strlen(text); 00445 00446 setPageAddress (row, MAX_PAGE); 00447 const uint8_t col_addr = FONT8x8_WIDTH*col; 00448 setColumnAddress (col_addr, MAX_COL); 00449 00450 while ((col+index) < CHARS && (index < len)) { 00451 // write first line, starting at given position 00452 writeChar(text[index++]); 00453 } 00454 00455 // write remaining lines 00456 // write until the end of memory 00457 // then wrap around again from the top. 00458 if (index + 1 < len) { 00459 setPageAddress (row + 1, MAX_PAGE); 00460 setColumnAddress (0, MAX_COL); 00461 bool wrapEntireScreen = false; 00462 while (index + 1 < len) { 00463 writeChar(text[index++]); 00464 // if we've written the last character space on the screen, 00465 // reset the page and column address so that it wraps around from the top again 00466 if (!wrapEntireScreen && (row*CHARS + col + index) > 127) { 00467 setPageAddress (0, MAX_PAGE); 00468 setColumnAddress (0, MAX_COL); 00469 wrapEntireScreen = true; 00470 } 00471 } 00472 } 00473 } 00474 00475 00476 00477 /** @brief Write large character (16x24 font) 00478 * @param uint8_t row row number (0...MAX_ROW) 00479 * @param uint8_t col column number (0...MAX_COL) 00480 * @param char chr Used for displaying numbers 0 - 9 and '+', '-', '.' 00481 */ 00482 void SSD1308::writeBigChar(uint8_t row, uint8_t col, char chr) { 00483 00484 writeBitmap((uint8_t*) font_16x24[int(chr) - FONT16x24_START], 00485 row, (row + FONT16x24_BYTES - 1), 00486 col, (col + FONT16x24_WIDTH - 1)); 00487 } 00488 00489 00490 /** @brief Write command that has no parameters 00491 */ 00492 void SSD1308::_sendCommand(uint8_t command) { 00493 // I2Cdev::writeByte(m_devAddr, COMMAND_MODE, command); 00494 00495 #if (I2C_OPTIMIZE == 0) 00496 char databytes[2]; 00497 00498 databytes[0] = COMMAND_MODE; 00499 databytes[1] = command; 00500 _i2c.write(_writeOpcode, databytes, 2); // Write command 00501 #else 00502 00503 _i2c.start(); 00504 _i2c.write(_writeOpcode); 00505 00506 _i2c.write(COMMAND_MODE); 00507 _i2c.write(command); // Write Command 00508 00509 _i2c.stop(); 00510 #endif 00511 } 00512 00513 /** @brief Write command that has one parameter 00514 */ 00515 void SSD1308::_sendCommand(uint8_t command, uint8_t param1) { 00516 00517 // Note continuationbit is set, so COMMAND_MODE must be 00518 // repeated before each databyte that serves as parameter! 00519 #if (I2C_OPTIMIZE == 0) 00520 char databytes[4]; 00521 00522 databytes[0] = COMMAND_MODE; 00523 databytes[1] = command; 00524 databytes[2] = COMMAND_MODE; 00525 databytes[3] = param1; 00526 _i2c.write(_writeOpcode, databytes, 4); // Write command 00527 #else 00528 00529 _i2c.start(); 00530 _i2c.write(_writeOpcode); 00531 00532 _i2c.write(COMMAND_MODE); 00533 _i2c.write(command); // Write Command 00534 _i2c.write(COMMAND_MODE); 00535 _i2c.write(param1); // Write Param1 00536 00537 _i2c.stop(); 00538 #endif 00539 } 00540 00541 /** @brief Write command that has two parameters 00542 */ 00543 void SSD1308::_sendCommand(uint8_t command, uint8_t param1, uint8_t param2) { 00544 00545 // Note continuationbit is set, so COMMAND_MODE must be 00546 // repeated before each databyte that serves as parameter! 00547 #if (I2C_OPTIMIZE == 0) 00548 char databytes[6]; 00549 00550 databytes[0] = COMMAND_MODE; 00551 databytes[1] = command; 00552 databytes[2] = COMMAND_MODE; 00553 databytes[3] = param1; 00554 databytes[4] = COMMAND_MODE; 00555 databytes[5] = param2; 00556 _i2c.write(_writeOpcode, databytes, 6); // Write command 00557 #else 00558 _i2c.start(); 00559 _i2c.write(_writeOpcode); 00560 00561 _i2c.write(COMMAND_MODE); 00562 _i2c.write(command); // Write Command 00563 _i2c.write(COMMAND_MODE); 00564 _i2c.write(param1); // Write Param1 00565 _i2c.write(COMMAND_MODE); 00566 _i2c.write(param2); // Write Param2 00567 00568 _i2c.stop(); 00569 #endif 00570 } 00571 00572 /** @brief Write command that has five parameters 00573 */ 00574 void SSD1308::_sendCommand(uint8_t command, uint8_t param1, uint8_t param2, 00575 uint8_t param3, uint8_t param4, 00576 uint8_t param5) { 00577 00578 // Note continuationbit is set, so COMMAND_MODE must be 00579 // repeated before each databyte that serves as parameter! 00580 #if (I2C_OPTIMIZE == 0) 00581 char databytes[12]; 00582 00583 databytes[0] = COMMAND_MODE; 00584 databytes[1] = command; 00585 databytes[2] = COMMAND_MODE; 00586 databytes[3] = param1; 00587 databytes[4] = COMMAND_MODE; 00588 databytes[5] = param2; 00589 databytes[6] = COMMAND_MODE; 00590 databytes[7] = param3; 00591 databytes[8] = COMMAND_MODE; 00592 databytes[9] = param4; 00593 databytes[10] = COMMAND_MODE; 00594 databytes[11] = param5; 00595 _i2c.write(_writeOpcode, databytes, 12); // Write command 00596 #else 00597 _i2c.start(); 00598 _i2c.write(_writeOpcode); 00599 00600 _i2c.write(COMMAND_MODE); 00601 _i2c.write(command); // Write Command 00602 _i2c.write(COMMAND_MODE); 00603 _i2c.write(param1); // Write Param1 00604 _i2c.write(COMMAND_MODE); 00605 _i2c.write(param2); // Write Param2 00606 _i2c.write(COMMAND_MODE); 00607 _i2c.write(param3); // Write Param3 00608 _i2c.write(COMMAND_MODE); 00609 _i2c.write(param4); // Write Param4 00610 _i2c.write(COMMAND_MODE); 00611 _i2c.write(param5); // Write Param5 00612 00613 _i2c.stop(); 00614 #endif 00615 } 00616 00617 00618 /** @brief Write command that has six parameters 00619 */ 00620 void SSD1308::_sendCommand(uint8_t command, uint8_t param1, uint8_t param2, 00621 uint8_t param3, uint8_t param4, 00622 uint8_t param5, uint8_t param6) { 00623 00624 // Note continuationbit is set, so COMMAND_MODE must be 00625 // repeated before each databyte that serves as parameter! 00626 #if (I2C_OPTIMIZE == 0) 00627 char databytes[14]; 00628 00629 databytes[0] = COMMAND_MODE; 00630 databytes[1] = command; 00631 databytes[2] = COMMAND_MODE; 00632 databytes[3] = param1; 00633 databytes[4] = COMMAND_MODE; 00634 databytes[5] = param2; 00635 databytes[6] = COMMAND_MODE; 00636 databytes[7] = param3; 00637 databytes[8] = COMMAND_MODE; 00638 databytes[9] = param4; 00639 databytes[10] = COMMAND_MODE; 00640 databytes[11] = param5; 00641 databytes[12] = COMMAND_MODE; 00642 databytes[13] = param6; 00643 _i2c.write(_writeOpcode, databytes, 14); // Write command 00644 #else 00645 _i2c.start(); 00646 _i2c.write(_writeOpcode); 00647 00648 _i2c.write(COMMAND_MODE); 00649 _i2c.write(command); // Write Command 00650 _i2c.write(COMMAND_MODE); 00651 _i2c.write(param1); // Write Param1 00652 _i2c.write(COMMAND_MODE); 00653 _i2c.write(param2); // Write Param2 00654 _i2c.write(COMMAND_MODE); 00655 _i2c.write(param3); // Write Param3 00656 _i2c.write(COMMAND_MODE); 00657 _i2c.write(param4); // Write Param4 00658 _i2c.write(COMMAND_MODE); 00659 _i2c.write(param5); // Write Param5 00660 _i2c.write(COMMAND_MODE); 00661 _i2c.write(param6); // Write Param6 00662 00663 _i2c.stop(); 00664 #endif 00665 } 00666 00667 00668 #if(0) 00669 /** @brief Write command that has multiple parameters 00670 */ 00671 void SSD1308::_sendCommands(uint8_t len, uint8_t* commands) { 00672 00673 // I2Cdev::writeBytes(m_devAddr, COMMAND_MODE, len, commands); 00674 // Note this original code is not correct, continuationbit is set, 00675 // so COMMAND_MODE must be repeated before each databyte that serves as parameter! 00676 00677 _i2c.start(); 00678 _i2c.write(_writeOpcode); 00679 00680 for (int i=0; i<len ; i++) { 00681 _i2c.write(COMMAND_MODE); 00682 _i2c.write(commands[i]); // Write Commands 00683 } 00684 _i2c.stop(); 00685 00686 } 00687 #endif 00688 00689 /** @brief Write databyte to display 00690 * @brief Start at current cursor location 00691 * @param uint8_t data databyte to write 00692 */ 00693 void SSD1308::_sendData(uint8_t data){ 00694 00695 #if (I2C_OPTIMIZE == 0) 00696 //I2C Blockwrite versions dont seem to work ? 00697 //That may be related to fact that the SSD1308/SSD1306 does NOT return an acknowledge: blockwrite may abort the operation 00698 //Noted for mbed lib v63 on 20/7/13 00699 char databytes[2]; 00700 00701 databytes[0] = DATA_MODE; 00702 databytes[1] = data; 00703 _i2c.write(_writeOpcode, databytes, 2); // Write Data 00704 00705 #else 00706 _i2c.start(); 00707 _i2c.write(_writeOpcode); 00708 _i2c.write(DATA_MODE); 00709 _i2c.write(data); 00710 _i2c.stop(); 00711 #endif 00712 00713 } 00714 00715 /** @brief Write len bytes from buffer data to display, 00716 * @brief Start at current cursor location 00717 * @param uint8_t len number of bytes to write 00718 * @param uint8_t* data pointer to data 00719 */ 00720 void SSD1308::_sendData(uint8_t len, uint8_t* data) { 00721 // I2Cdev::writeBytes(m_devAddr, DATA_MODE, len, data); 00722 #if (I2C_OPTIMIZE == 0) 00723 for (int i=0; i<len ; i++) { 00724 _sendData(data[i]); // Write Data 00725 } 00726 #else 00727 _i2c.start(); 00728 _i2c.write(_writeOpcode); 00729 _i2c.write(DATA_MODE); 00730 for (int i=0; i<len ; i++) { 00731 _i2c.write(data[i]); // Write Data 00732 } 00733 _i2c.stop(); 00734 #endif 00735 } 00736 00737 00738 /** @brief Set Horizontal Addressing Mode (cursor incr left-to-right, top-to-bottom) 00739 * 00740 */ 00741 void SSD1308::setHorizontalAddressingMode(){ 00742 setMemoryAddressingMode(HORIZONTAL_ADDRESSING_MODE); 00743 } 00744 00745 /** @brief Set Vertical Addressing Mode (cursor incr top-to-bottom, left-to-right) 00746 * 00747 */ 00748 void SSD1308::setVerticalAddressingMode() { 00749 setMemoryAddressingMode(VERTICAL_ADDRESSING_MODE); 00750 } 00751 00752 /** @brief Set Page Addressing Mode (cursor incr left-to-right) 00753 * 00754 */ 00755 void SSD1308::setPageAddressingMode(){ 00756 setMemoryAddressingMode(PAGE_ADDRESSING_MODE); 00757 } 00758 00759 /** @brief Set Addressing Mode 00760 * @param uint8_t mode 00761 */ 00762 void SSD1308::setMemoryAddressingMode(uint8_t mode){ 00763 00764 _sendCommand(SET_MEMORY_ADDRESSING_MODE, mode); 00765 } 00766 00767 00768 /** @param uint8_t start startpage (valid range 0..MAX_PAGE) 00769 * @param uint8_t end endpage (valid range start..MAX_PAGE) 00770 */ 00771 void SSD1308::setPageAddress (uint8_t start, uint8_t end) { 00772 00773 _sendCommand(SET_PAGE_ADDRESS, start, end); 00774 } 00775 00776 00777 /** @param uint8_t start startcolumn (valid range 0..MAX_COL) 00778 * @param uint8_t end endcolumn (valid range start..MAX_COL) 00779 */ 00780 void SSD1308::setColumnAddress (uint8_t start, uint8_t end) { 00781 00782 _sendCommand(SET_COLUMN_ADDRESS, start, end); 00783 } 00784 00785 /** 00786 * @brief Set Display StartLine, takes one byte, 0x00-0x3F 00787 * @param uint8_t line startline (valid range 0..MAX_ROWS) 00788 */ 00789 void SSD1308::setDisplayStartLine(uint8_t line) { 00790 00791 line = line & MAX_ROW; 00792 00793 _sendCommand(SET_DISPLAY_START_LINE | line); 00794 } 00795 00796 00797 /** 00798 * @brief Set Column Start (for Page Addressing Mode only) 00799 * @param uint8_t column column start (valid range 0..MAX_COL) 00800 */ 00801 void SSD1308::setColumnStartForPageAddressingMode(uint8_t column) { 00802 00803 column = column & MAX_COL; 00804 00805 _sendCommand(SET_LOWER_COLUMN | ( column & 0x0F)); // lower nibble 00806 _sendCommand(SET_HIGHER_COLUMN | ((column>>4) & 0x0F)); // higher nibble 00807 } 00808 00809 00810 /** 00811 * @brief Set Page Start (for Page Addressing Mode only) 00812 * @param uint8_t page page start (valid range PAGE0 - PAGE7) 00813 */ 00814 void SSD1308::setPageStartForPageAddressingMode(uint8_t page) { 00815 00816 page = page & MAX_PAGE; 00817 00818 _sendCommand(SET_PAGE_START_ADDRESS | page); 00819 00820 } 00821 00822 00823 /** @brief Set Contrast 00824 * @param uint8_t contrast (valid range 0x00 (lowest) - 0xFF (highest)) 00825 */ 00826 void SSD1308::setContrastControl(uint8_t contrast) { 00827 00828 _sendCommand(SET_CONTRAST, contrast); 00829 } 00830 00831 /** @brief Enable Display 00832 */ 00833 void SSD1308::setDisplayOn() { 00834 _sendCommand(SET_DISPLAY_POWER_ON); 00835 } 00836 00837 /** @brief Disable Display 00838 */ 00839 void SSD1308::setDisplayOff() { 00840 _sendCommand(SET_DISPLAY_POWER_OFF); 00841 } 00842 00843 /** @brief Enable or Disable Display 00844 * @param bool on 00845 */ 00846 void SSD1308::setDisplayPower(bool on) { 00847 if (on) { 00848 setDisplayOn(); 00849 } else { 00850 setDisplayOff(); 00851 } 00852 } 00853 00854 /** @brief Show White pixels on Black background 00855 */ 00856 void SSD1308::setDisplayNormal() { 00857 _sendCommand(SET_NORMAL_DISPLAY); 00858 } 00859 00860 /** @brief Show Black pixels on White background 00861 */ 00862 void SSD1308::setDisplayInverse() { 00863 _sendCommand(SET_INVERSE_DISPLAY); 00864 } 00865 00866 /** @brief Blink display by fading in and out over a set number of frames 00867 * @param bool on 00868 */ 00869 void SSD1308::setDisplayBlink(bool on){ 00870 if (on) { 00871 _sendCommand(SET_FADE_BLINK, (BLINK_ENABLE | FADE_INTERVAL_128_FRAMES)); 00872 } 00873 else { 00874 _sendCommand(SET_FADE_BLINK, FADE_BLINK_DISABLE); 00875 } 00876 } 00877 00878 00879 /** @brief Fade out display in set number of frames 00880 * @param bool on 00881 */ 00882 void SSD1308::setDisplayFade(bool on) { 00883 if (on) { 00884 _sendCommand(SET_FADE_BLINK, (FADE_OUT_ENABLE | FADE_INTERVAL_128_FRAMES)); 00885 } 00886 else { 00887 _sendCommand(SET_FADE_BLINK, FADE_BLINK_DISABLE); 00888 } 00889 } 00890 00891 /** @brief Display Flip (Left/Right, Up/Down) 00892 * @param bool left flip Left/Right 00893 * @param bool down flip Up/Down 00894 */ 00895 void SSD1308::setDisplayFlip(bool left, bool down) { 00896 if (left) { 00897 // column address 0 is mapped to SEG0 (Reset) 00898 _sendCommand(SET_SEGMENT_REMAP_0); 00899 } 00900 else { 00901 // column address 127 is mapped to SEG0 00902 _sendCommand(SET_SEGMENT_REMAP_127); 00903 } 00904 00905 if (down) { 00906 // Reset mode 00907 _sendCommand(SET_COMMON_REMAP_0); 00908 } 00909 else { 00910 // Flip Up/Down (Need to rewrite display before H effect shows) 00911 _sendCommand(SET_COMMON_REMAP_63); 00912 } 00913 00914 } 00915 00916 /** @brief Sets Internal Iref 00917 */ 00918 void SSD1308::setInternalIref() { 00919 // uint8_t cmds[2] = {SET_IREF_SELECTION, INTERNAL_IREF}; 00920 // _sendCommands(2, cmds); 00921 00922 _sendCommand(SET_IREF_SELECTION, INTERNAL_IREF); 00923 } 00924 00925 /** @brief Sets External Iref (default) 00926 */ 00927 void SSD1308::setExternalIref() { 00928 // uint8_t cmds[2] = {SET_IREF_SELECTION, EXTERNAL_IREF}; 00929 // _sendCommands(2, cmds); 00930 _sendCommand(SET_IREF_SELECTION, EXTERNAL_IREF); 00931 } 00932 00933 00934 /** @brief Shows All Pixels On 00935 */ 00936 void SSD1308::setEntireDisplayOn(){ 00937 _sendCommand(SET_ENTIRE_DISPLAY_ON); 00938 } 00939 00940 /** @brief Shows Pixels as RAM content 00941 */ 00942 void SSD1308::setEntireDisplayRAM(){ 00943 _sendCommand(SET_DISPLAY_GDDRAM); 00944 } 00945 00946 /** @brief Shows Pixels On or as RAM content 00947 * @param bool on (true is All on, false is RAM content) 00948 */ 00949 void SSD1308::setEntireDisplay(bool on){ 00950 if (on) { 00951 setEntireDisplayOn(); // All Pixels on 00952 } 00953 else { 00954 setEntireDisplayRAM(); // Pixels are RAM content 00955 } 00956 } 00957 00958 00959 /** @brief Horizontal scroll by one column per interval 00960 * @param bool left select Left/Right scroll 00961 * @param uint8_t start_page begin page (0..MAX_PAGE) 00962 * @param uint8_t end_page end page (start_page..MAX_PAGE) 00963 * @param uint8_t interval scroll interval in frames (see codes above) 00964 */ 00965 void SSD1308::setContinuousHorizontalScroll(bool left, uint8_t start_page, uint8_t end_page, uint8_t interval) { 00966 if (left) { 00967 _sendCommand(SET_LEFT_HOR_SCROLL, 0x00, start_page, interval, end_page, 0x00, 0xFF); // Scroll Left 00968 } 00969 else { 00970 _sendCommand(SET_RIGHT_HOR_SCROLL, 0x00, start_page, interval, end_page, 0x00, 0xFF); // Scroll Right 00971 } 00972 00973 } 00974 00975 00976 /** @brief Horizontal and Vertical scroll by one column per interval 00977 * @param bool left select Left/Right scroll 00978 * @param uint8_t start_page begin page (0..MAX_PAGE) 00979 * @param uint8_t end_page end page (start_page..MAX_PAGE) 00980 * @param uint8_t offset vert offset (0x01..0x63) 00981 * @param uint8_t interval scroll interval in frames (see codes above) 00982 */ 00983 void SSD1308::setContinuousVerticalAndHorizontalScroll(bool left, uint8_t start_page, uint8_t end_page, 00984 uint8_t offset, uint8_t interval) { 00985 if (left) { 00986 _sendCommand(SET_VERT_LEFT_HOR_SCROLL, 0x00, start_page, interval, end_page, offset); // Scroll Left 00987 } 00988 else { 00989 _sendCommand(SET_VERT_RIGHT_HOR_SCROLL, 0x00, start_page, interval, end_page, offset); // Scroll Right 00990 } 00991 00992 } 00993 00994 /** @brief Set Vertical scroll area 00995 * @param uint8_t topRowsFixed fixed rows (0..MAX_ROW) 00996 * @param uint8_t scrollRowsoffset scroll rows (topRowsFixed..ROWS) 00997 */ 00998 void SSD1308::setVerticalScrollArea(uint8_t topRowsFixed, uint8_t scrollRows) { 00999 01000 if ((topRowsFixed + scrollRows) > ROWS) { 01001 scrollRows = ROWS - topRowsFixed; 01002 }; 01003 01004 _sendCommand(SET_VERTICAL_SCROLL_AREA, topRowsFixed, scrollRows); 01005 } 01006 01007 /** @brief Activate or Deactivate Horizontal and Vertical scroll 01008 * @brief Note: after deactivating scrolling, the RAM data needs to be rewritten 01009 * @param bool on activate scroll 01010 */ 01011 void SSD1308::setDisplayScroll(bool on) { 01012 if (on) { 01013 _sendCommand(SET_ACTIVATE_SCROLL); // Scroll on 01014 } 01015 else { 01016 _sendCommand(SET_DEACTIVATE_SCROLL); // Scroll off 01017 } 01018 } 01019 01020 01021 01022 /** @brief Low level Init 01023 * @brief Init the configuration registers in accordance with the datasheet 01024 */ 01025 void SSD1308::_init() { 01026 01027 _sendCommand(SET_DISPLAY_POWER_OFF); // 0xAE 01028 01029 // column address 0 is mapped to SEG0 (Reset) 01030 // row address 0 is mapped to COM0 (Reset) 01031 _sendCommand(SET_SEGMENT_REMAP_0); // 0xA0 (Reset) 01032 _sendCommand(SET_COMMON_REMAP_0); // 0xC0 (Reset) 01033 01034 setDisplayStartLine(0); // 0x40 (Reset) 01035 01036 _sendCommand(SET_COMMON_CONF, COMMON_BASE | COMMON_ALTERNATIVE | COMMON_LEFTRIGHT_NORMAL); // 0xDA, 0x12 (Reset) 01037 01038 // Pagemode or Horizontal mode 01039 // setPageAddressingMode(); // 0x20, 0x02 (Reset) 01040 // setColumnStartForPageAddressingMode(0); // 0x00, 0x10 (Reset = Column 0) 01041 // setPageStartForPageAddressingMode(PAGE_0);// 0xBO (Reset = Page 0) 01042 setHorizontalAddressingMode(); // 0x20, 0x00 (Non-Reset) 01043 setColumnAddress (0, MAX_COL); // 0x21, 0x00, 0x37 (Reset) 01044 setPageAddress (0, MAX_PAGE); // 0x22, 0x00, 0x07 (Reset) 01045 01046 setExternalIref(); // 0xAD, 0x10 (Reset) 01047 01048 _sendCommand(SET_DISPLAY_CLOCK, 0x70); // 0xD5, 0x70 (Reset = 0x80) 01049 _sendCommand(SET_PRECHARGE_TIME, 0x21); // 0xD9, 0x21 (Reset = 0x22) 01050 _sendCommand(SET_VCOMH_DESELECT_LEVEL, 0x30); // 0xDB, 0x30 (Reset = 0x20) 01051 _sendCommand(SET_MULTIPLEX_RATIO, 0x3F); // 0xA8, 0x3F (Reset) 01052 _sendCommand(SET_DISPLAY_OFFSET, 0x00); // 0xD3, 0x00 (Reset) 01053 01054 _sendCommand(SET_CONTRAST, 0x7F); // 0x81, 0x7F (Reset) 01055 01056 _sendCommand(SET_NORMAL_DISPLAY); // 0xA6 (Reset) 01057 01058 setEntireDisplayRAM(); // 0xA4 (Reset) 01059 setDisplayScroll(false); 01060 01061 clearDisplay(); 01062 01063 _sendCommand(SET_DISPLAY_POWER_ON); // 0xAF 01064 } 01065
Generated on Wed Jul 27 2022 18:40:34 by
1.7.2
