Skip to content

Commit 65615be

Browse files
authored
Add support for 2nd HW I2C (ThingPulse#292)
1 parent 6aa3629 commit 65615be

File tree

4 files changed

+99
-38
lines changed

4 files changed

+99
-38
lines changed

README.md

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -76,6 +76,11 @@ The library supports different protocols to access the OLED display. Currently t
7676
SSD1306Wire display(0x3c, SDA, SCL); // ADDRESS, SDA, SCL
7777
// for 128x32 displays:
7878
// SSD1306Wire display(0x3c, SDA, SCL, GEOMETRY_128_32); // ADDRESS, SDA, SCL, GEOMETRY_128_32 (or 128_64)
79+
// for using 2nd Hardware I2C (if available)
80+
// SSD1306Wire(0x3c, SDA, SCL, GEOMETRY_128_64, I2C_TWO); //default value is I2C_ONE if not mentioned
81+
// By default SD1306Wire set I2C frequency to 700000, you can use set either another frequency or skip setting the frequency by providing -1 value
82+
// SSD1306Wire(0x3c, SDA, SCL, GEOMETRY_128_64, I2C_ONE, 400000); //set I2C frequency to 400kHz
83+
// SSD1306Wire(0x3c, SDA, SCL, GEOMETRY_128_64, I2C_ONE, -1); //skip setting the I2C bus frequency
7984
```
8085
8186
for a SH1106:
@@ -84,6 +89,9 @@ for a SH1106:
8489
#include "SH1106Wire.h"
8590
8691
SH1106Wire display(0x3c, SDA, SCL); // ADDRESS, SDA, SCL
92+
// By default SH1106Wire set I2C frequency to 700000, you can use set either another frequency or skip setting the frequency by providing -1 value
93+
// SH1106Wire(0x3c, SDA, SCL, GEOMETRY_128_64, I2C_ONE, 400000); //set I2C frequency to 400kHz
94+
// SH1106Wire(0x3c, SDA, SCL, GEOMETRY_128_64, I2C_ONE, -1); //skip setting the I2C bus frequency
8795
```
8896

8997
### I2C with brzo_i2c

src/OLEDDisplay.h

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -141,6 +141,11 @@ enum OLEDDISPLAY_GEOMETRY {
141141
GEOMETRY_RAWMODE,
142142
};
143143

144+
enum HW_I2C {
145+
I2C_ONE,
146+
I2C_TWO
147+
};
148+
144149
typedef char (*FontTableLookupFunction)(const uint8_t ch);
145150
char DefaultFontTableLookup(const uint8_t ch);
146151

src/SH1106Wire.h

Lines changed: 45 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -46,21 +46,47 @@ class SH1106Wire : public OLEDDisplay {
4646
uint8_t _sda;
4747
uint8_t _scl;
4848
bool _doI2cAutoInit = false;
49+
TwoWire* _wire = NULL;
50+
int _frequency;
4951

5052
public:
51-
SH1106Wire(uint8_t _address, uint8_t _sda, uint8_t _scl, OLEDDISPLAY_GEOMETRY g = GEOMETRY_128_64) {
53+
/**
54+
* Create and initialize the Display using Wire library
55+
*
56+
* Beware for retro-compatibility default values are provided for all parameters see below.
57+
* Please note that if you don't wan't SD1306Wire to initialize and change frequency speed ot need to
58+
* ensure -1 value are specified for all 3 parameters. This can be usefull to control TwoWire with multiple
59+
* device on the same bus.
60+
*
61+
* @param _address I2C Display address
62+
* @param _sda I2C SDA pin number, default to -1 to skip Wire begin call
63+
* @param _scl I2C SCL pin number, default to -1 (only SDA = -1 is considered to skip Wire begin call)
64+
* @param g display geometry dafault to generic GEOMETRY_128_64, see OLEDDISPLAY_GEOMETRY definition for other options
65+
* @param _i2cBus on ESP32 with 2 I2C HW buses, I2C_ONE for 1st Bus, I2C_TWO fot 2nd bus, default I2C_ONE
66+
* @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
67+
*/
68+
SH1106Wire(uint8_t _address, uint8_t _sda, uint8_t _scl, OLEDDISPLAY_GEOMETRY g = GEOMETRY_128_64, HW_I2C _i2cBus = I2C_ONE, int _frequency = 700000) {
5269
setGeometry(g);
5370

5471
this->_address = _address;
5572
this->_sda = _sda;
5673
this->_scl = _scl;
74+
this->_wire = (_i2cBus==I2C_ONE)?&Wire:&Wire1;
75+
this->_frequency = _frequency;
5776
}
5877

5978
bool connect() {
60-
Wire.begin(this->_sda, this->_scl);
79+
#if !defined(ARDUINO_ARCH_ESP32) && !defined(ARDUINO_ARCH8266)
80+
_wire->begin();
81+
#else
82+
// On ESP32 arduino, -1 means 'don't change pins', someone else has called begin for us.
83+
if(this->_sda != -1)
84+
_wire->begin(this->_sda, this->_scl);
85+
#endif
6186
// Let's use ~700khz if ESP8266 is in 160Mhz mode
6287
// this will be limited to ~400khz if the ESP8266 in 80Mhz mode.
63-
Wire.setClock(700000);
88+
if(this->_frequency != -1)
89+
_wire->setClock(this->_frequency);
6490
return true;
6591
}
6692

@@ -107,25 +133,25 @@ class SH1106Wire : public OLEDDisplay {
107133
sendCommand(minBoundXp2L);
108134
for (x = minBoundX; x <= maxBoundX; x++) {
109135
if (k == 0) {
110-
Wire.beginTransmission(_address);
111-
Wire.write(0x40);
136+
_wire->beginTransmission(_address);
137+
_wire->write(0x40);
112138
}
113-
Wire.write(buffer[x + y * displayWidth]);
139+
_wire->write(buffer[x + y * displayWidth]);
114140
k++;
115141
if (k == 16) {
116-
Wire.endTransmission();
142+
_wire->endTransmission();
117143
k = 0;
118144
}
119145
}
120146
if (k != 0) {
121-
Wire.endTransmission();
147+
_wire->endTransmission();
122148
k = 0;
123149
}
124150
yield();
125151
}
126152

127153
if (k != 0) {
128-
Wire.endTransmission();
154+
_wire->endTransmission();
129155
}
130156
#else
131157
uint8_t * p = &buffer[0];
@@ -134,12 +160,12 @@ class SH1106Wire : public OLEDDisplay {
134160
sendCommand(0x02);
135161
sendCommand(0x10);
136162
for( uint8_t x=0; x<8; x++) {
137-
Wire.beginTransmission(_address);
138-
Wire.write(0x40);
163+
_wire->beginTransmission(_address);
164+
_wire->write(0x40);
139165
for (uint8_t k = 0; k < 16; k++) {
140-
Wire.write(*p++);
166+
_wire->write(*p++);
141167
}
142-
Wire.endTransmission();
168+
_wire->endTransmission();
143169
}
144170
}
145171
#endif
@@ -154,18 +180,18 @@ class SH1106Wire : public OLEDDisplay {
154180
return 0;
155181
}
156182
inline void sendCommand(uint8_t command) __attribute__((always_inline)){
157-
Wire.beginTransmission(_address);
158-
Wire.write(0x80);
159-
Wire.write(command);
160-
Wire.endTransmission();
183+
_wire->beginTransmission(_address);
184+
_wire->write(0x80);
185+
_wire->write(command);
186+
_wire->endTransmission();
161187
}
162188

163189
void initI2cIfNeccesary() {
164190
if (_doI2cAutoInit) {
165191
#ifdef ARDUINO_ARCH_AVR
166-
Wire.begin();
192+
_wire->begin();
167193
#else
168-
Wire.begin(this->_sda, this->_scl);
194+
_wire->begin(this->_sda, this->_scl);
169195
#endif
170196
}
171197
}

src/SSD1306Wire.h

Lines changed: 41 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -39,34 +39,56 @@
3939
#define _min min
4040
#define _max max
4141
#endif
42+
//--------------------------------------
4243

4344
class SSD1306Wire : public OLEDDisplay {
4445
private:
4546
uint8_t _address;
4647
int _sda;
4748
int _scl;
4849
bool _doI2cAutoInit = false;
50+
TwoWire* _wire = NULL;
51+
int _frequency;
4952

5053
public:
51-
SSD1306Wire(uint8_t _address, int _sda = -1, int _scl = -1, OLEDDISPLAY_GEOMETRY g = GEOMETRY_128_64) {
54+
55+
/**
56+
* Create and initialize the Display using Wire library
57+
*
58+
* Beware for retro-compatibility default values are provided for all parameters see below.
59+
* Please note that if you don't wan't SD1306Wire to initialize and change frequency speed ot need to
60+
* ensure -1 value are specified for all 3 parameters. This can be usefull to control TwoWire with multiple
61+
* device on the same bus.
62+
*
63+
* @param _address I2C Display address
64+
* @param _sda I2C SDA pin number, default to -1 to skip Wire begin call
65+
* @param _scl I2C SCL pin number, default to -1 (only SDA = -1 is considered to skip Wire begin call)
66+
* @param g display geometry dafault to generic GEOMETRY_128_64, see OLEDDISPLAY_GEOMETRY definition for other options
67+
* @param _i2cBus on ESP32 with 2 I2C HW buses, I2C_ONE for 1st Bus, I2C_TWO fot 2nd bus, default I2C_ONE
68+
* @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
69+
*/
70+
SSD1306Wire(uint8_t _address, int _sda = -1, int _scl = -1, OLEDDISPLAY_GEOMETRY g = GEOMETRY_128_64, HW_I2C _i2cBus = I2C_ONE, int _frequency = 700000) {
5271
setGeometry(g);
5372

5473
this->_address = _address;
5574
this->_sda = _sda;
5675
this->_scl = _scl;
76+
this->_wire = (_i2cBus==I2C_ONE)?&Wire:&Wire1;
77+
this->_frequency = _frequency;
5778
}
5879

5980
bool connect() {
6081
#if !defined(ARDUINO_ARCH_ESP32) && !defined(ARDUINO_ARCH8266)
61-
Wire.begin();
82+
_wire->begin();
6283
#else
6384
// On ESP32 arduino, -1 means 'don't change pins', someone else has called begin for us.
6485
if(this->_sda != -1)
65-
Wire.begin(this->_sda, this->_scl);
86+
_wire->begin(this->_sda, this->_scl);
6687
#endif
6788
// Let's use ~700khz if ESP8266 is in 160Mhz mode
6889
// this will be limited to ~400khz if the ESP8266 in 80Mhz mode.
69-
Wire.setClock(700000);
90+
if(this->_frequency != -1)
91+
_wire->setClock(this->_frequency);
7092
return true;
7193
}
7294

@@ -115,22 +137,22 @@ class SSD1306Wire : public OLEDDisplay {
115137
for (y = minBoundY; y <= maxBoundY; y++) {
116138
for (x = minBoundX; x <= maxBoundX; x++) {
117139
if (k == 0) {
118-
Wire.beginTransmission(_address);
119-
Wire.write(0x40);
140+
_wire->beginTransmission(_address);
141+
_wire->write(0x40);
120142
}
121143

122-
Wire.write(buffer[x + y * this->width()]);
144+
_wire->write(buffer[x + y * this->width()]);
123145
k++;
124146
if (k == 16) {
125-
Wire.endTransmission();
147+
_wire->endTransmission();
126148
k = 0;
127149
}
128150
}
129151
yield();
130152
}
131153

132154
if (k != 0) {
133-
Wire.endTransmission();
155+
_wire->endTransmission();
134156
}
135157
#else
136158

@@ -148,14 +170,14 @@ class SSD1306Wire : public OLEDDisplay {
148170
}
149171

150172
for (uint16_t i=0; i < displayBufferSize; i++) {
151-
Wire.beginTransmission(this->_address);
152-
Wire.write(0x40);
173+
_wire->beginTransmission(this->_address);
174+
_wire->write(0x40);
153175
for (uint8_t x = 0; x < 16; x++) {
154-
Wire.write(buffer[i]);
176+
_wire->write(buffer[i]);
155177
i++;
156178
}
157179
i--;
158-
Wire.endTransmission();
180+
_wire->endTransmission();
159181
}
160182
#endif
161183
}
@@ -170,18 +192,18 @@ class SSD1306Wire : public OLEDDisplay {
170192
}
171193
inline void sendCommand(uint8_t command) __attribute__((always_inline)){
172194
initI2cIfNeccesary();
173-
Wire.beginTransmission(_address);
174-
Wire.write(0x80);
175-
Wire.write(command);
176-
Wire.endTransmission();
195+
_wire->beginTransmission(_address);
196+
_wire->write(0x80);
197+
_wire->write(command);
198+
_wire->endTransmission();
177199
}
178200

179201
void initI2cIfNeccesary() {
180202
if (_doI2cAutoInit) {
181203
#if !defined(ARDUINO_ARCH_ESP32) && !defined(ARDUINO_ARCH8266)
182-
Wire.begin();
204+
_wire->begin();
183205
#else
184-
Wire.begin(this->_sda, this->_scl);
206+
_wire->begin(this->_sda, this->_scl);
185207
#endif
186208
}
187209
}

0 commit comments

Comments
 (0)