best of I2CSPI-refactor

* cherry-picking my additions to pinmanger
* toDo: replace Wire.begin() with pinManager.joinWire()
This commit is contained in:
Frank
2023-01-08 19:09:30 +01:00
parent a10f1b20ac
commit b29ff1186b
5 changed files with 97 additions and 4 deletions

View File

@@ -309,7 +309,7 @@ bool deserializeConfig(JsonObject doc, bool fromFS) {
#ifdef ESP32
Wire.setPins(i2c_sda, i2c_scl); // this will fail if Wire is initilised (Wire.begin() called prior)
#endif
Wire.begin();
// Wire.begin(); // WLEDMM moved into pinManager
} else {
Serial.printf("pinmgr not success for global i2c %d %d\n", i2c_sda, i2c_scl);
}

View File

@@ -513,6 +513,89 @@ bool PinManagerClass::isPinAllocated(byte gpio, PinOwner tag)
return bitRead(pinAlloc[by], bi);
}
//
// WLEDMM: central handling of I2C startup (global Wire #0)
//
bool PinManagerClass::joinWire() { // shortcut in case no parameters provided
#ifdef ARDUINO_ARCH_ESP32
// ESP32 - i2c pins can be mapped to any GPIO
return joinWire(i2c_sda, i2c_scl);
#else
// ESP8266: I2C pins are fixed
return joinWire(HW_PIN_SDA, HW_PIN_SCL);
#endif
}
bool PinManagerClass::joinWire(int8_t pinSDA, int8_t pinSCL) {
// reject PIN = -1, reject SDA=SCL, reject "forbidden" pins
if ( (pinSDA < 0) || (pinSCL < 0)
|| (pinSDA == pinSCL)
|| !isPinOk(pinSDA, true)
|| !isPinOk(pinSCL, true)) {
DEBUG_PRINT(F("PIN Manager: invalid GPIO for I2C: SDA="));
DEBUG_PRINTF("%d, SCL=%d !\n",pinSDA, pinSCL);
return(false);
}
if ((wire0PinSDA < 0) || (wire0PinSCL < 0)) wire0isStarted = false; // this should not happen
// if wire already started, reject any other GPIO
if ((wire0isStarted == true) &&
(pinSDA != wire0PinSDA) && (pinSDA != wire0PinSCL) && // allow "swapped pins2, i.e. SDA <->SCL
(pinSCL != wire0PinSCL) && (pinSCL != wire0PinSDA)) {
DEBUG_PRINT(F("PIN Manager: invalid GPIO for I2C: SDA="));
DEBUG_PRINTF("%d, SCL=%d. Wire already started with sda=%d and scl=%d!\n",pinSDA, pinSCL, wirePinSDA, wirePinSCL);
return(false);
}
// make sure pins are allocated
PinManagerPinType pins[2] = {{pinSCL, true}, {pinSDA, true}};
if (!allocateMultiplePins(pins, 2, PinOwner::HW_I2C)) { // this will only FAIL when pins are invalid, or used already for other purposes
DEBUG_PRINT(F("PIN Manager: failed to allocate GPIO for I2C: SDA="));
DEBUG_PRINTF("%d, SCL=%d !\n",pinSDA, pinSCL);
return(false);
}
if(wire0isStarted == true) {
DEBUG_PRINTLN(F("PIN Manager: all good, I2C already started, nothing to do :-)"));
return(true);
}
// NOW do it - start Wire !!! fire ;-)
bool wireIsOK = true;
#ifdef ARDUINO_ARCH_ESP32 // ESP32 - i2c pins can be mapped to any GPIO
wireIsOK = Wire.setPins(pinSDA, pinSCL); // this will fail if Wire is initialised already (i.e. Wire.begin() called prior)
#else // 8266 - I2C pins are fixed
if((pinSDA != HW_PIN_SDA) || (pinSCL != HW_PIN_SCL)) {
DEBUG_PRINT(F("PIN Manager: warning ESP8266 I2C pins are fixed. please use SDA="));
DEBUG_PRINTF("%d, SCL=%d !\n",HW_PIN_SDA, HW_PIN_SCL);
}
#endif
if (wireIsOK == false) {
USER_PRINTLN(F("PIN Manager: warning - wire.setPins failed!"));
}
wireIsOK = Wire.begin(); // this will fail if wire is already running
if (wireIsOK == false) {
USER_PRINTLN(F("PIN Manager: warning - wire.begin failed!"));
} else {
USER_PRINTLN(F("PIN Manager: wire.begin successfull."));
}
#ifdef ARDUINO_ARCH_ESP32S3
Wire.setTimeOut(50); // workaround for wire timeout bug on -S3
Wire.setClock(400000); // 400kHz I2C clock. Comment this line if having wiring difficulties
#endif
wire0isStarted = true;
wire0PinSDA = pinSDA;
wire0PinSCL = pinSCL;
return(true);
}
/* see https://docs.espressif.com/projects/esp-idf/en/latest/esp32s3/api-reference/peripherals/gpio.html
* The ESP32-S3 chip features 45 physical GPIO pins (GPIO0 ~ GPIO21 and GPIO26 ~ GPIO48). Each pin can be used as a general-purpose I/O
* Strapping pins: GPIO0, GPIO3, GPIO45 and GPIO46 are strapping pins. For more infomation, please refer to ESP32-S3 datasheet.

View File

@@ -83,8 +83,13 @@ class PinManagerClass {
uint8_t spiAllocCount : 4; // allow multiple allocation of SPI bus pins but keep track of allocations
};
// WLEDMM: central handling of Wire (only for first bus)
bool wire0isStarted = false; // true is wire.begin() was done already
int8_t wire0PinSDA = -1; // GPIO currently in use for SDA
int8_t wire0PinSCL = -1; // GPIO currently in use for SCL
public:
PinManagerClass() : i2cAllocCount(0), spiAllocCount(0) {}
PinManagerClass() : i2cAllocCount(0), spiAllocCount(0), wire0isStarted(false) {} // WLEDMM: initialize wire0isStarted=false
// De-allocates a single pin
bool deallocatePin(byte gpio, PinOwner tag);
// De-allocates multiple pins but only if all can be deallocated (PinOwner has to be specified)
@@ -108,6 +113,11 @@ class PinManagerClass {
#endif
inline void deallocatePin(byte gpio) { deallocatePin(gpio, PinOwner::None); }
// WLEDMM: central initialization of Wire (Wire1 not supported yet)
bool joinWire(); // shortcut - use global pins when no parameters provided
bool joinWire(int8_t pinSDA, int8_t pinSCL); // use this instead of Wire.begin(SDA, SCL)
// toDo: may need to add calls for Wire.setClock, Wire.setPins Wire.end
// will return true for reserved pins
bool isPinAllocated(byte gpio, PinOwner tag = PinOwner::None);
// will return false for reserved pins

View File

@@ -543,7 +543,7 @@ void handleSettingsSet(AsyncWebServerRequest *request, byte subPage)
#ifdef ESP32
Wire.setPins(i2c_sda, i2c_scl); // this will fail if Wire is initilised (Wire.begin() called)
#endif
Wire.begin();
// Wire.begin(); // WLEDMM moved into pinManager
} else {
// there is no Wire.end()
DEBUG_PRINTLN(F("Could not allocate I2C pins."));

View File

@@ -8,7 +8,7 @@
*/
// version code in format yymmddb (b = daily build)
#define VERSION 2301082
#define VERSION 2301083
//uncomment this if you have a "my_config.h" file you'd like to use
//#define WLED_USE_MY_CONFIG