Skip to content

Commit bacad99

Browse files
committed
[I2C] Add support for multiple I2C interfaces
1 parent 6a95d04 commit bacad99

29 files changed

+984
-323
lines changed

src/_P017_PN532.ino

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -242,7 +242,7 @@ bool P017_handle_timer_in(struct EventStruct *event)
242242
# endif // ifdef P017_DEBUG_LOGIC_ANALYZER_PIN
243243

244244
// TODO: Clock stretching issue https://github.com/esp8266/Arduino/issues/1541
245-
if (Settings.isI2CEnabled()
245+
if (Settings.isI2CEnabled(get3BitFromUL(Settings.I2C_Flags[event->TaskIndex], I2C_FLAGS_BUS_NUMBER))
246246
&& ((DIRECT_pinRead(Settings.Pin_i2c_sda) == 0) || (DIRECT_pinRead(Settings.Pin_i2c_scl) == 0)))
247247
{
248248
addLog(LOG_LEVEL_ERROR, F("PN532: BUS error"));

src/_P139_AXP2101.ino

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -257,7 +257,7 @@ boolean Plugin_139(uint8_t function, struct EventStruct *event, String& string)
257257

258258
case PLUGIN_INIT:
259259
{
260-
if (Settings.isI2CEnabled()) {
260+
if (Settings.isI2CEnabled(get3BitFromUL(Settings.I2C_Flags[event->TaskIndex], I2C_FLAGS_BUS_NUMBER))) { // FIXME
261261
P139_data_struct *P139_init = static_cast<P139_data_struct *>(getPluginTaskData(event->TaskIndex));
262262

263263
if (nullptr != P139_init) {

src/_P166_GP8403.ino

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -214,7 +214,7 @@ boolean Plugin_166(uint8_t function, struct EventStruct *event, String& string)
214214

215215
case PLUGIN_INIT:
216216
{
217-
if (Settings.isI2CEnabled()) {
217+
if (Settings.isI2CEnabled(get3BitFromUL(Settings.I2C_Flags[event->TaskIndex], I2C_FLAGS_BUS_NUMBER))) {
218218
initPluginTaskData(event->TaskIndex,
219219
new (std::nothrow) P166_data_struct(P166_I2C_ADDRESS,
220220
static_cast<DFRobot_GP8403::eOutPutRange_t>(P166_MAX_VOLTAGE)));

src/src/Commands/GPIO.cpp

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,12 @@
1818
#include "../Helpers/PortStatus.h"
1919
#include "../Helpers/Numerical.h"
2020

21+
#if FEATURE_I2C_MULTIPLE
22+
#include "../Globals/Settings.h"
23+
#include "../Helpers/Hardware_device_info.h"
24+
#include "../Helpers/I2C_access.h"
25+
#endif // if FEATURE_I2C_MULTIPLE
26+
2127
#if FEATURE_GPIO_USE_ESP8266_WAVEFORM
2228
# include <core_esp8266_waveform.h>
2329
#endif
@@ -1216,6 +1222,11 @@ bool getGPIOPinStateValues(String& str) {
12161222
#if FEATURE_PINSTATE_EXTENDED
12171223
pluginID = PLUGIN_MCP;
12181224
#endif // if FEATURE_PINSTATE_EXTENDED
1225+
#if FEATURE_I2C_MULTIPLE
1226+
if (getI2CBusCount() >= 2) {
1227+
I2CSelectHighClockSpeed(get3BitFromUL(Settings.I2C_peripheral_bus, I2C_PERIPHERAL_BUS_PCFMCP));
1228+
}
1229+
#endif // if FEATURE_I2C_MULTIPLE
12191230
str = GPIO_MCP_Read(par1);
12201231
#ifndef BUILD_NO_DEBUG
12211232
logPrefix = F("MCP");
@@ -1229,6 +1240,11 @@ bool getGPIOPinStateValues(String& str) {
12291240
#if FEATURE_PINSTATE_EXTENDED
12301241
pluginID = PLUGIN_PCF;
12311242
#endif // if FEATURE_PINSTATE_EXTENDED
1243+
#if FEATURE_I2C_MULTIPLE
1244+
if (getI2CBusCount() >= 2) {
1245+
I2CSelectHighClockSpeed(get3BitFromUL(Settings.I2C_peripheral_bus, I2C_PERIPHERAL_BUS_PCFMCP));
1246+
}
1247+
#endif // if FEATURE_I2C_MULTIPLE
12321248
str = GPIO_PCF_Read(par1);
12331249
#ifndef BUILD_NO_DEBUG
12341250
logPrefix = F("PCF");

src/src/Commands/i2c.cpp

Lines changed: 22 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -37,27 +37,34 @@ void i2c_scanI2Cbus(bool dbg, int8_t channel) {
3737

3838
const __FlashStringHelper* Command_i2c_Scanner(struct EventStruct *event, const char *Line)
3939
{
40-
if (Settings.isI2CEnabled()) {
41-
const bool dbg = equals(parseString(Line, 2), F("1"));
42-
I2CSelect_Max100kHz_ClockSpeed(); // Scan bus using low speed
40+
const bool dbg = equals(parseString(Line, 2), F("1"));
41+
#if !FEATURE_I2C_MULTIPLE
42+
const uint8_t i2cBus = 0;
43+
#else // if !FEATURE_I2C_MULTIPLE
44+
for (uint8_t i2cBus = 0; i2cBus < getI2CBusCount(); ++i2cBus)
45+
#endif // if !FEATURE_I2C_MULTIPLE
46+
{
47+
if (Settings.isI2CEnabled(i2cBus)) {
48+
I2CSelect_Max100kHz_ClockSpeed(i2cBus); // Scan bus using low speed
4349

44-
i2c_scanI2Cbus(dbg, -1); // Base I2C bus
50+
i2c_scanI2Cbus(dbg, -1); // Base I2C bus
4551

46-
#if FEATURE_I2CMULTIPLEXER
52+
#if FEATURE_I2CMULTIPLEXER
4753

48-
if (isI2CMultiplexerEnabled()) {
49-
uint8_t mux_max = I2CMultiplexerMaxChannels();
54+
if (isI2CMultiplexerEnabled(i2cBus)) {
55+
uint8_t mux_max = I2CMultiplexerMaxChannels(i2cBus);
5056

51-
for (int8_t channel = 0; channel < mux_max; ++channel) {
52-
I2CMultiplexerSelect(channel);
53-
i2c_scanI2Cbus(dbg, channel); // Multiplexer I2C bus
57+
for (int8_t channel = 0; channel < mux_max; ++channel) {
58+
I2CMultiplexerSelect(i2cBus, channel);
59+
i2c_scanI2Cbus(dbg, channel); // Multiplexer I2C bus
60+
}
61+
I2CMultiplexerOff(0);
5462
}
55-
I2CMultiplexerOff();
63+
#endif // if FEATURE_I2CMULTIPLEXER
64+
} else {
65+
serialPrintln(F("I2C : Not enabled."));
5666
}
57-
#endif // if FEATURE_I2CMULTIPLEXER
58-
I2CSelectHighClockSpeed(); // By default the bus is in standard speed
59-
} else {
60-
serialPrintln(F("I2C : Not enabled."));
6167
}
68+
I2CSelectHighClockSpeed(0); // By default the bus is in standard speed
6269
return return_see_serial(event);
6370
}

src/src/CustomBuild/define_plugin_sets.h

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3646,6 +3646,23 @@ To create/register a plugin, you have to :
36463646
#define FEATURE_ALTERNATIVE_CDN_URL 1
36473647
*/
36483648

3649+
#ifndef FEATURE_I2C_MULTIPLE
3650+
#ifdef ESP8266
3651+
#define FEATURE_I2C_MULTIPLE 0 // NOT SUPPORTED
3652+
#endif
3653+
#ifdef ESP32
3654+
#define FEATURE_I2C_MULTIPLE 1
3655+
#endif
3656+
#endif
3657+
#if FEATURE_I2C_MULTIPLE
3658+
#ifndef FEATURE_I2C_INTERFACE_3
3659+
#define FEATURE_I2C_INTERFACE_3 0 // Not enabled by default
3660+
#endif
3661+
#endif
3662+
#if defined(ESP8266) && FEATURE_I2C_MULTIPLE
3663+
#undef FEATURE_I2C_MULTIPLE
3664+
#define FEATURE_I2C_MULTIPLE 0 // NOT SUPPORTED
3665+
#endif
36493666

36503667
#ifndef FEATURE_THINGSPEAK_EVENT
36513668
#ifdef LIMIT_BUILD_SIZE

src/src/DataStructs/DeviceStruct.h

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -38,6 +38,7 @@
3838

3939
#define I2C_FLAGS_SLOW_SPEED 0 // Force slow speed when this flag is set
4040
#define I2C_FLAGS_MUX_MULTICHANNEL 1 // Allow multiple multiplexer channels when set
41+
#define I2C_FLAGS_BUS_NUMBER 2 // 3 bits. The I2C bus number to use (ESP32 only), 3 bits allow for future expansion
4142

4243

4344

@@ -110,6 +111,7 @@ struct __attribute__((__packed__)) DeviceStruct
110111
bool I2CMax100kHz : 1; // When enabled, the device is only able to handle 100 kHz bus-clock speed, shows warning and enables "Force Slow I2C speed" by default
111112

112113
bool HasFormatUserVar : 1; // Optimization to only call this when PLUGIN_FORMAT_USERVAR is implemented
114+
bool I2CNoBusSelection : 1; // Dis-allow I2C Bus selection in device configuration
113115
};
114116

115117

src/src/DataStructs/SettingsStruct.h

Lines changed: 31 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -315,7 +315,19 @@ class SettingsStruct_tmpl
315315
bool isI2C_pin(int8_t pin) const;
316316

317317
// Return true if I2C settings are correct
318-
bool isI2CEnabled() const;
318+
bool isI2CEnabled(uint8_t i2cBus) const;
319+
320+
int8_t getI2CSdaPin(uint8_t i2cBus) const;
321+
int8_t getI2CSclPin(uint8_t i2cBus) const;
322+
uint32_t getI2CClockSpeed(uint8_t i2cBus) const;
323+
uint32_t getI2CClockSpeedSlow(uint8_t i2cBus) const;
324+
uint32_t getI2CClockStretch(uint8_t i2cBus) const;
325+
326+
#if FEATURE_I2CMULTIPLEXER
327+
int8_t getI2CMultiplexerType(uint8_t i2cBus) const;
328+
int8_t getI2CMultiplexerAddr(uint8_t i2cBus) const;
329+
int8_t getI2CMultiplexerResetPin(uint8_t i2cBus) const;
330+
#endif // if FEATURE_I2CMULTIPLEXER
319331

320332
// Return true when pin is one of the fixed Ethernet pins and Ethernet is enabled
321333
bool isEthernetPin(int8_t pin) const;
@@ -400,7 +412,24 @@ class SettingsStruct_tmpl
400412
uint8_t Notification[NOTIFICATION_MAX] = {0}; //notifications, point to a NPLUGIN id
401413
// FIXME TD-er: Must change to pluginID_t, but then also another check must be added since changing the pluginID_t will also render settings incompatible
402414
uint8_t TaskDeviceNumber[N_TASKS] = {0}; // The "plugin number" set at as task (e.g. 4 for P004_dallas)
403-
unsigned int OLD_TaskDeviceID[N_TASKS] = {0}; //UNUSED: this can be reused
415+
int8_t Pin_i2c2_sda = -1; // DEFAULT_PIN_I2C2_SDA; // From here, storage borrowed from OLD_TaskDeviceID array
416+
int8_t Pin_i2c2_scl = -1; // DEFAULT_PIN_I2C2_SCL;
417+
int8_t Pin_i2c3_sda = -1; // DEFAULT_PIN_I2C3_SDA;
418+
int8_t Pin_i2c3_scl = -1; // DEFAULT_PIN_I2C3_SCL;
419+
uint32_t I2C2_clockSpeed = 400000;
420+
uint32_t I2C2_clockSpeed_Slow = 100000;
421+
uint32_t I2C3_clockSpeed = 400000;
422+
uint32_t I2C3_clockSpeed_Slow = 100000;
423+
int8_t I2C2_Multiplexer_Type = I2C_MULTIPLEXER_NONE;
424+
int8_t I2C2_Multiplexer_Addr = -1;
425+
int8_t I2C2_Multiplexer_ResetPin = -1;
426+
int8_t I2C3_Multiplexer_Type = I2C_MULTIPLEXER_NONE;
427+
int8_t I2C3_Multiplexer_Addr = -1;
428+
int8_t I2C3_Multiplexer_ResetPin = -1;
429+
uint16_t I2C_peripheral_bus = 0;
430+
unsigned long Wire2ClockStretchLimit = 0;
431+
unsigned long Wire3ClockStretchLimit = 0;
432+
unsigned int OLD_TaskDeviceID[N_TASKS - 9] = {0}; //UNUSED: this can be reused
404433

405434
// FIXME TD-er: When used on ESP8266, this conversion union may not work
406435
// It might work as it is 32-bit in size.

src/src/DataStructs_templ/SettingsStruct.cpp

Lines changed: 163 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,9 @@
1717
#include "../Helpers/Misc.h"
1818
#include "../Helpers/StringParser.h"
1919

20+
#if FEATURE_I2C_MULTIPLE
21+
#include "../Helpers/Hardware_device_info.h"
22+
#endif
2023

2124
#if ESP_IDF_VERSION_MAJOR >= 5
2225
#include <driver/gpio.h>
@@ -963,16 +966,170 @@ bool SettingsStruct_tmpl<N_TASKS>::isSPI_valid() const {
963966
template<unsigned int N_TASKS>
964967
bool SettingsStruct_tmpl<N_TASKS>::isI2C_pin(int8_t pin) const {
965968
if (pin < 0) { return false; }
966-
return Pin_i2c_sda == pin || Pin_i2c_scl == pin;
969+
return Pin_i2c_sda == pin || Pin_i2c_scl == pin
970+
#if FEATURE_I2C_MULTIPLE
971+
|| ((getI2CBusCount() >= 2) && (Pin_i2c2_sda == pin || Pin_i2c2_scl == pin))
972+
#if FEATURE_I2C_INTERFACE_3
973+
|| ((getI2CBusCount() >= 3) && (Pin_i2c3_sda == pin || Pin_i2c3_scl == pin))
974+
#endif // if FEATURE_I2C_INTERFACE_3
975+
#endif // if FEATURE_I2C_MULTIPLE
976+
;
977+
}
978+
979+
template<unsigned int N_TASKS>
980+
bool SettingsStruct_tmpl<N_TASKS>::isI2CEnabled(uint8_t i2cBus) const {
981+
if (0 == i2cBus) {
982+
return (Pin_i2c_sda != -1) &&
983+
(Pin_i2c_scl != -1) &&
984+
(I2C_clockSpeed > 0) &&
985+
(I2C_clockSpeed_Slow > 0);
986+
#if FEATURE_I2C_MULTIPLE
987+
} else if (1 == i2cBus) {
988+
return (Pin_i2c2_sda != -1) &&
989+
(Pin_i2c2_scl != -1) &&
990+
(I2C2_clockSpeed > 0) &&
991+
(I2C2_clockSpeed_Slow > 0);
992+
#if FEATURE_I2C_INTERFACE_3
993+
} else {
994+
return (Pin_i2c3_sda != -1) &&
995+
(Pin_i2c3_scl != -1) &&
996+
(I2C3_clockSpeed > 0) &&
997+
(I2C3_clockSpeed_Slow > 0);
998+
#endif // if FEATURE_I2C_INTERFACE_3
999+
#endif // if FEATURE_I2C_MULTIPLE
1000+
}
1001+
return false;
1002+
}
1003+
1004+
template<unsigned int N_TASKS>
1005+
int8_t SettingsStruct_tmpl<N_TASKS>::getI2CSdaPin(uint8_t i2cBus) const {
1006+
if (0 == i2cBus) {
1007+
return Pin_i2c_sda;
1008+
#if FEATURE_I2C_MULTIPLE
1009+
} else if (1 == i2cBus) {
1010+
return Pin_i2c2_sda;
1011+
#if FEATURE_I2C_INTERFACE_3
1012+
} else {
1013+
return Pin_i2c3_sda;
1014+
#endif // if FEATURE_I2C_INTERFACE_3
1015+
#endif // if FEATURE_I2C_MULTIPLE
1016+
}
1017+
return -1;
1018+
}
1019+
1020+
template<unsigned int N_TASKS>
1021+
int8_t SettingsStruct_tmpl<N_TASKS>::getI2CSclPin(uint8_t i2cBus) const {
1022+
if (0 == i2cBus) {
1023+
return Pin_i2c_scl;
1024+
#if FEATURE_I2C_MULTIPLE
1025+
} else if (1 == i2cBus) {
1026+
return Pin_i2c2_scl;
1027+
#if FEATURE_I2C_INTERFACE_3
1028+
} else {
1029+
return Pin_i2c3_scl;
1030+
#endif // if FEATURE_I2C_INTERFACE_3
1031+
#endif // if FEATURE_I2C_MULTIPLE
1032+
}
1033+
return -1;
1034+
}
1035+
1036+
template<unsigned int N_TASKS>
1037+
uint32_t SettingsStruct_tmpl<N_TASKS>::getI2CClockSpeed(uint8_t i2cBus) const {
1038+
if (0 == i2cBus) {
1039+
return I2C_clockSpeed;
1040+
#if FEATURE_I2C_MULTIPLE
1041+
} else if (1 == i2cBus) {
1042+
return I2C2_clockSpeed;
1043+
#if FEATURE_I2C_INTERFACE_3
1044+
} else {
1045+
return I2C3_clockSpeed;
1046+
#endif // if FEATURE_I2C_INTERFACE_3
1047+
#endif // if FEATURE_I2C_MULTIPLE
1048+
}
1049+
return 0u;
9671050
}
9681051

9691052
template<unsigned int N_TASKS>
970-
bool SettingsStruct_tmpl<N_TASKS>::isI2CEnabled() const {
971-
return (Pin_i2c_sda != -1) &&
972-
(Pin_i2c_scl != -1) &&
973-
(I2C_clockSpeed > 0) &&
974-
(I2C_clockSpeed_Slow > 0);
1053+
uint32_t SettingsStruct_tmpl<N_TASKS>::getI2CClockSpeedSlow(uint8_t i2cBus) const {
1054+
if (0 == i2cBus) {
1055+
return I2C_clockSpeed_Slow;
1056+
#if FEATURE_I2C_MULTIPLE
1057+
} else if (1 == i2cBus) {
1058+
return I2C2_clockSpeed_Slow;
1059+
#if FEATURE_I2C_INTERFACE_3
1060+
} else {
1061+
return I2C3_clockSpeed_Slow;
1062+
#endif // if FEATURE_I2C_INTERFACE_3
1063+
#endif // if FEATURE_I2C_MULTIPLE
1064+
}
1065+
return 0u;
1066+
}
1067+
1068+
template<unsigned int N_TASKS>
1069+
uint32_t SettingsStruct_tmpl<N_TASKS>::getI2CClockStretch(uint8_t i2cBus) const {
1070+
if (0 == i2cBus) {
1071+
return WireClockStretchLimit;
1072+
#if FEATURE_I2C_MULTIPLE
1073+
} else if (1 == i2cBus) {
1074+
return Wire2ClockStretchLimit;
1075+
#if FEATURE_I2C_INTERFACE_3
1076+
} else {
1077+
return Wire3ClockStretchLimit;
1078+
#endif // if FEATURE_I2C_INTERFACE_3
1079+
#endif // if FEATURE_I2C_MULTIPLE
1080+
}
1081+
return 0u;
1082+
}
1083+
1084+
#if FEATURE_I2CMULTIPLEXER
1085+
template<unsigned int N_TASKS>
1086+
int8_t SettingsStruct_tmpl<N_TASKS>::getI2CMultiplexerType(uint8_t i2cBus) const {
1087+
if (0 == i2cBus) {
1088+
return I2C_Multiplexer_Type;
1089+
#if FEATURE_I2C_MULTIPLE
1090+
} else if (1 == i2cBus) {
1091+
return I2C2_Multiplexer_Type;
1092+
#if FEATURE_I2C_INTERFACE_3
1093+
} else {
1094+
return I2C3_Multiplexer_Type;
1095+
#endif // if FEATURE_I2C_INTERFACE_3
1096+
#endif // if FEATURE_I2C_MULTIPLE
1097+
}
1098+
return -1;
1099+
}
1100+
1101+
template<unsigned int N_TASKS>
1102+
int8_t SettingsStruct_tmpl<N_TASKS>::getI2CMultiplexerAddr(uint8_t i2cBus) const {
1103+
if (0 == i2cBus) {
1104+
return I2C_Multiplexer_Addr;
1105+
#if FEATURE_I2C_MULTIPLE
1106+
} else if (1 == i2cBus) {
1107+
return I2C2_Multiplexer_Addr;
1108+
#if FEATURE_I2C_INTERFACE_3
1109+
} else {
1110+
return I2C3_Multiplexer_Addr;
1111+
#endif // if FEATURE_I2C_INTERFACE_3
1112+
#endif // if FEATURE_I2C_MULTIPLE
1113+
}
1114+
return -1;
1115+
}
1116+
1117+
template<unsigned int N_TASKS>
1118+
int8_t SettingsStruct_tmpl<N_TASKS>::getI2CMultiplexerResetPin(uint8_t i2cBus) const {
1119+
if (0 == i2cBus) {
1120+
return I2C_Multiplexer_ResetPin;
1121+
#if FEATURE_I2C_MULTIPLE
1122+
} else if (1 == i2cBus) {
1123+
return I2C2_Multiplexer_ResetPin;
1124+
#if FEATURE_I2C_INTERFACE_3
1125+
} else {
1126+
return I2C3_Multiplexer_ResetPin;
1127+
#endif // if FEATURE_I2C_INTERFACE_3
1128+
#endif // if FEATURE_I2C_MULTIPLE
1129+
}
1130+
return -1;
9751131
}
1132+
#endif // if FEATURE_I2CMULTIPLEXER
9761133

9771134
template<unsigned int N_TASKS>
9781135
bool SettingsStruct_tmpl<N_TASKS>::isEthernetPin(int8_t pin) const {

0 commit comments

Comments
 (0)