diff --git a/README.md b/README.md index 04944b8..52a8be9 100644 --- a/README.md +++ b/README.md @@ -76,6 +76,11 @@ The library supports different protocols to access the OLED display. Currently t SSD1306Wire display(0x3c, SDA, SCL); // ADDRESS, SDA, SCL // for 128x32 displays: // SSD1306Wire display(0x3c, SDA, SCL, GEOMETRY_128_32); // ADDRESS, SDA, SCL, GEOMETRY_128_32 (or 128_64) +// for using 2nd Hardware I2C (if available) +// SSD1306Wire(0x3c, SDA, SCL, GEOMETRY_128_64, I2C_TWO); //default value is I2C_ONE if not mentioned +// By default SD1306Wire set I2C frequency to 700000, you can use set either another frequency or skip setting the frequency by providing -1 value +// SSD1306Wire(0x3c, SDA, SCL, GEOMETRY_128_64, I2C_ONE, 400000); //set I2C frequency to 400kHz +// SSD1306Wire(0x3c, SDA, SCL, GEOMETRY_128_64, I2C_ONE, -1); //skip setting the I2C bus frequency ``` for a SH1106: @@ -84,6 +89,9 @@ for a SH1106: #include "SH1106Wire.h" SH1106Wire display(0x3c, SDA, SCL); // ADDRESS, SDA, SCL +// By default SH1106Wire set I2C frequency to 700000, you can use set either another frequency or skip setting the frequency by providing -1 value +// SH1106Wire(0x3c, SDA, SCL, GEOMETRY_128_64, I2C_ONE, 400000); //set I2C frequency to 400kHz +// SH1106Wire(0x3c, SDA, SCL, GEOMETRY_128_64, I2C_ONE, -1); //skip setting the I2C bus frequency ``` ### I2C with brzo_i2c diff --git a/src/OLEDDisplay.h b/src/OLEDDisplay.h index 205dffc..ca351be 100644 --- a/src/OLEDDisplay.h +++ b/src/OLEDDisplay.h @@ -141,6 +141,11 @@ enum OLEDDISPLAY_GEOMETRY { GEOMETRY_RAWMODE, }; +enum HW_I2C { + I2C_ONE, + I2C_TWO +}; + typedef char (*FontTableLookupFunction)(const uint8_t ch); char DefaultFontTableLookup(const uint8_t ch); diff --git a/src/SH1106Wire.h b/src/SH1106Wire.h index 58f1c94..fd9085f 100644 --- a/src/SH1106Wire.h +++ b/src/SH1106Wire.h @@ -46,21 +46,47 @@ class SH1106Wire : public OLEDDisplay { uint8_t _sda; uint8_t _scl; bool _doI2cAutoInit = false; + TwoWire* _wire = NULL; + int _frequency; public: - SH1106Wire(uint8_t _address, uint8_t _sda, uint8_t _scl, OLEDDISPLAY_GEOMETRY g = GEOMETRY_128_64) { + /** + * Create and initialize the Display using Wire library + * + * Beware for retro-compatibility default values are provided for all parameters see below. + * Please note that if you don't wan't SD1306Wire to initialize and change frequency speed ot need to + * ensure -1 value are specified for all 3 parameters. This can be usefull to control TwoWire with multiple + * device on the same bus. + * + * @param _address I2C Display address + * @param _sda I2C SDA pin number, default to -1 to skip Wire begin call + * @param _scl I2C SCL pin number, default to -1 (only SDA = -1 is considered to skip Wire begin call) + * @param g display geometry dafault to generic GEOMETRY_128_64, see OLEDDISPLAY_GEOMETRY definition for other options + * @param _i2cBus on ESP32 with 2 I2C HW buses, I2C_ONE for 1st Bus, I2C_TWO fot 2nd bus, default I2C_ONE + * @param _frequency for Frequency by default Let's use ~700khz if ESP8266 is in 160Mhz mode, this will be limited to ~400khz if the ESP8266 in 80Mhz mode + */ + SH1106Wire(uint8_t _address, uint8_t _sda, uint8_t _scl, OLEDDISPLAY_GEOMETRY g = GEOMETRY_128_64, HW_I2C _i2cBus = I2C_ONE, int _frequency = 700000) { setGeometry(g); this->_address = _address; this->_sda = _sda; this->_scl = _scl; + this->_wire = (_i2cBus==I2C_ONE)?&Wire:&Wire1; + this->_frequency = _frequency; } bool connect() { - Wire.begin(this->_sda, this->_scl); +#if !defined(ARDUINO_ARCH_ESP32) && !defined(ARDUINO_ARCH8266) + _wire->begin(); +#else + // On ESP32 arduino, -1 means 'don't change pins', someone else has called begin for us. + if(this->_sda != -1) + _wire->begin(this->_sda, this->_scl); +#endif // Let's use ~700khz if ESP8266 is in 160Mhz mode // this will be limited to ~400khz if the ESP8266 in 80Mhz mode. - Wire.setClock(700000); + if(this->_frequency != -1) + _wire->setClock(this->_frequency); return true; } @@ -107,25 +133,25 @@ class SH1106Wire : public OLEDDisplay { sendCommand(minBoundXp2L); for (x = minBoundX; x <= maxBoundX; x++) { if (k == 0) { - Wire.beginTransmission(_address); - Wire.write(0x40); + _wire->beginTransmission(_address); + _wire->write(0x40); } - Wire.write(buffer[x + y * displayWidth]); + _wire->write(buffer[x + y * displayWidth]); k++; if (k == 16) { - Wire.endTransmission(); + _wire->endTransmission(); k = 0; } } if (k != 0) { - Wire.endTransmission(); + _wire->endTransmission(); k = 0; } yield(); } if (k != 0) { - Wire.endTransmission(); + _wire->endTransmission(); } #else uint8_t * p = &buffer[0]; @@ -134,12 +160,12 @@ class SH1106Wire : public OLEDDisplay { sendCommand(0x02); sendCommand(0x10); for( uint8_t x=0; x<8; x++) { - Wire.beginTransmission(_address); - Wire.write(0x40); + _wire->beginTransmission(_address); + _wire->write(0x40); for (uint8_t k = 0; k < 16; k++) { - Wire.write(*p++); + _wire->write(*p++); } - Wire.endTransmission(); + _wire->endTransmission(); } } #endif @@ -154,18 +180,18 @@ class SH1106Wire : public OLEDDisplay { return 0; } inline void sendCommand(uint8_t command) __attribute__((always_inline)){ - Wire.beginTransmission(_address); - Wire.write(0x80); - Wire.write(command); - Wire.endTransmission(); + _wire->beginTransmission(_address); + _wire->write(0x80); + _wire->write(command); + _wire->endTransmission(); } void initI2cIfNeccesary() { if (_doI2cAutoInit) { #ifdef ARDUINO_ARCH_AVR - Wire.begin(); + _wire->begin(); #else - Wire.begin(this->_sda, this->_scl); + _wire->begin(this->_sda, this->_scl); #endif } } diff --git a/src/SSD1306Wire.h b/src/SSD1306Wire.h index 9f30b4b..730d900 100644 --- a/src/SSD1306Wire.h +++ b/src/SSD1306Wire.h @@ -39,6 +39,7 @@ #define _min min #define _max max #endif +//-------------------------------------- class SSD1306Wire : public OLEDDisplay { private: @@ -46,27 +47,48 @@ class SSD1306Wire : public OLEDDisplay { int _sda; int _scl; bool _doI2cAutoInit = false; + TwoWire* _wire = NULL; + int _frequency; public: - SSD1306Wire(uint8_t _address, int _sda = -1, int _scl = -1, OLEDDISPLAY_GEOMETRY g = GEOMETRY_128_64) { + + /** + * Create and initialize the Display using Wire library + * + * Beware for retro-compatibility default values are provided for all parameters see below. + * Please note that if you don't wan't SD1306Wire to initialize and change frequency speed ot need to + * ensure -1 value are specified for all 3 parameters. This can be usefull to control TwoWire with multiple + * device on the same bus. + * + * @param _address I2C Display address + * @param _sda I2C SDA pin number, default to -1 to skip Wire begin call + * @param _scl I2C SCL pin number, default to -1 (only SDA = -1 is considered to skip Wire begin call) + * @param g display geometry dafault to generic GEOMETRY_128_64, see OLEDDISPLAY_GEOMETRY definition for other options + * @param _i2cBus on ESP32 with 2 I2C HW buses, I2C_ONE for 1st Bus, I2C_TWO fot 2nd bus, default I2C_ONE + * @param _frequency for Frequency by default Let's use ~700khz if ESP8266 is in 160Mhz mode, this will be limited to ~400khz if the ESP8266 in 80Mhz mode + */ + SSD1306Wire(uint8_t _address, int _sda = -1, int _scl = -1, OLEDDISPLAY_GEOMETRY g = GEOMETRY_128_64, HW_I2C _i2cBus = I2C_ONE, int _frequency = 700000) { setGeometry(g); this->_address = _address; this->_sda = _sda; this->_scl = _scl; + this->_wire = (_i2cBus==I2C_ONE)?&Wire:&Wire1; + this->_frequency = _frequency; } bool connect() { #if !defined(ARDUINO_ARCH_ESP32) && !defined(ARDUINO_ARCH8266) - Wire.begin(); + _wire->begin(); #else // On ESP32 arduino, -1 means 'don't change pins', someone else has called begin for us. if(this->_sda != -1) - Wire.begin(this->_sda, this->_scl); + _wire->begin(this->_sda, this->_scl); #endif // Let's use ~700khz if ESP8266 is in 160Mhz mode // this will be limited to ~400khz if the ESP8266 in 80Mhz mode. - Wire.setClock(700000); + if(this->_frequency != -1) + _wire->setClock(this->_frequency); return true; } @@ -115,14 +137,14 @@ class SSD1306Wire : public OLEDDisplay { for (y = minBoundY; y <= maxBoundY; y++) { for (x = minBoundX; x <= maxBoundX; x++) { if (k == 0) { - Wire.beginTransmission(_address); - Wire.write(0x40); + _wire->beginTransmission(_address); + _wire->write(0x40); } - Wire.write(buffer[x + y * this->width()]); + _wire->write(buffer[x + y * this->width()]); k++; if (k == 16) { - Wire.endTransmission(); + _wire->endTransmission(); k = 0; } } @@ -130,7 +152,7 @@ class SSD1306Wire : public OLEDDisplay { } if (k != 0) { - Wire.endTransmission(); + _wire->endTransmission(); } #else @@ -148,14 +170,14 @@ class SSD1306Wire : public OLEDDisplay { } for (uint16_t i=0; i < displayBufferSize; i++) { - Wire.beginTransmission(this->_address); - Wire.write(0x40); + _wire->beginTransmission(this->_address); + _wire->write(0x40); for (uint8_t x = 0; x < 16; x++) { - Wire.write(buffer[i]); + _wire->write(buffer[i]); i++; } i--; - Wire.endTransmission(); + _wire->endTransmission(); } #endif } @@ -170,18 +192,18 @@ class SSD1306Wire : public OLEDDisplay { } inline void sendCommand(uint8_t command) __attribute__((always_inline)){ initI2cIfNeccesary(); - Wire.beginTransmission(_address); - Wire.write(0x80); - Wire.write(command); - Wire.endTransmission(); + _wire->beginTransmission(_address); + _wire->write(0x80); + _wire->write(command); + _wire->endTransmission(); } void initI2cIfNeccesary() { if (_doI2cAutoInit) { #if !defined(ARDUINO_ARCH_ESP32) && !defined(ARDUINO_ARCH8266) - Wire.begin(); + _wire->begin(); #else - Wire.begin(this->_sda, this->_scl); + _wire->begin(this->_sda, this->_scl); #endif } }