ThingPulse OLED SSD1306
Dependents: Turtle_RadioShuttle mbed-os5-F303-18650-Manager-tp4056 Kretanje_kroz_izbornike_OLED128x64_4tipke
SSD1306I2C.h
00001 /** 00002 * The MIT License (MIT) 00003 * 00004 * Copyright (c) 2019 by Helmut Tschemernjak - www.radioshuttle.de 00005 * 00006 * Permission is hereby granted, free of charge, to any person obtaining a copy 00007 * of this software and associated documentation files (the "Software"), to deal 00008 * in the Software without restriction, including without limitation the rights 00009 * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 00010 * copies of the Software, and to permit persons to whom the Software is 00011 * furnished to do so, subject to the following conditions: 00012 * 00013 * The above copyright notice and this permission notice shall be included in all 00014 * copies or substantial portions of the Software. 00015 * 00016 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 00017 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 00018 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 00019 * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 00020 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 00021 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 00022 * SOFTWARE. 00023 * 00024 * ThingPulse invests considerable time and money to develop these open source libraries. 00025 * Please support us by buying our products (and not the clones) from 00026 * https://thingpulse.com 00027 * 00028 */ 00029 00030 #ifndef SSD1306I2C_h 00031 #define SSD1306I2C_h 00032 00033 00034 #ifdef __MBED__ 00035 00036 #include "OLEDDisplay.h" 00037 #include <mbed.h> 00038 00039 #ifndef UINT8_MAX 00040 #define UINT8_MAX 0xff 00041 #endif 00042 00043 class SSD1306I2C : public OLEDDisplay { 00044 public: 00045 SSD1306I2C(uint8_t _address, PinName _sda, PinName _scl, OLEDDISPLAY_GEOMETRY g = GEOMETRY_128_64) { 00046 setGeometry(g); 00047 00048 this->_address = _address << 1; // convert from 7 to 8 bit for mbed. 00049 this->_sda = _sda; 00050 this->_scl = _scl; 00051 _i2c = new I2C(_sda, _scl); 00052 } 00053 00054 bool connect() { 00055 // mbed supports 100k and 400k some device maybe 1000k 00056 #ifdef TARGET_STM32L4 00057 _i2c->frequency(1000000); 00058 #else 00059 _i2c->frequency(400000); 00060 #endif 00061 return true; 00062 } 00063 00064 void display(void) { 00065 const int x_offset = (128 - this->width()) / 2; 00066 #ifdef OLEDDISPLAY_DOUBLE_BUFFER 00067 uint8_t minBoundY = UINT8_MAX; 00068 uint8_t maxBoundY = 0; 00069 00070 uint8_t minBoundX = UINT8_MAX; 00071 uint8_t maxBoundX = 0; 00072 uint8_t x, y; 00073 00074 // Calculate the Y bounding box of changes 00075 // and copy buffer[pos] to buffer_back[pos]; 00076 for (y = 0; y < (this->height() / 8); y++) { 00077 for (x = 0; x < this->width(); x++) { 00078 uint16_t pos = x + y * this->width(); 00079 if (buffer[pos] != buffer_back[pos]) { 00080 minBoundY = std::min(minBoundY, y); 00081 maxBoundY = std::max(maxBoundY, y); 00082 minBoundX = std::min(minBoundX, x); 00083 maxBoundX = std::max(maxBoundX, x); 00084 } 00085 buffer_back[pos] = buffer[pos]; 00086 } 00087 yield(); 00088 } 00089 00090 // If the minBoundY wasn't updated 00091 // we can savely assume that buffer_back[pos] == buffer[pos] 00092 // holdes true for all values of pos 00093 00094 if (minBoundY == UINT8_MAX) return; 00095 00096 sendCommand(COLUMNADDR); 00097 sendCommand(x_offset + minBoundX); // column start address (0 = reset) 00098 sendCommand(x_offset + maxBoundX); // column end address (127 = reset) 00099 00100 sendCommand(PAGEADDR); 00101 sendCommand(minBoundY); // page start address 00102 sendCommand(maxBoundY); // page end address 00103 00104 for (y = minBoundY; y <= maxBoundY; y++) { 00105 uint8_t *start = &buffer[(minBoundX + y * this->width())-1]; 00106 uint8_t save = *start; 00107 00108 *start = 0x40; // control 00109 _i2c->write(_address, (char *)start, (maxBoundX-minBoundX) + 1 + 1); 00110 *start = save; 00111 } 00112 #else 00113 00114 sendCommand(COLUMNADDR); 00115 sendCommand(x_offset); // column start address (0 = reset) 00116 sendCommand(x_offset + (this->width() - 1));// column end address (127 = reset) 00117 00118 sendCommand(PAGEADDR); 00119 sendCommand(0x0); // page start address (0 = reset) 00120 00121 if (geometry == GEOMETRY_128_64) { 00122 sendCommand(0x7); 00123 } else if (geometry == GEOMETRY_128_32) { 00124 sendCommand(0x3); 00125 } 00126 00127 buffer[-1] = 0x40; // control 00128 _i2c->write(_address, (char *)&buffer[-1], displayBufferSize + 1); 00129 #endif 00130 } 00131 00132 private: 00133 int getBufferOffset(void) { 00134 return 0; 00135 } 00136 00137 inline void sendCommand(uint8_t command) __attribute__((always_inline)) { 00138 char _data[2]; 00139 _data[0] = 0x80; // control 00140 _data[1] = command; 00141 _i2c->write(_address, _data, sizeof(_data)); 00142 } 00143 00144 uint8_t _address; 00145 PinName _sda; 00146 PinName _scl; 00147 I2C *_i2c; 00148 }; 00149 00150 #endif 00151 00152 #endif
Generated on Wed Jul 13 2022 11:33:40 by
1.7.2
Helmut Tschemernjak