clean up I2C pin handling in audioreactive (ES7243+ES8388)

* remove double Wire.begin() - Wire cannot be re-initialized; its already started by pinManager.joinWire()
* Only use global I2C pins; make sure that audireactive I2C settings are aligned with global I2C pins
* minor cleanup
* remove I2C pins from AudioSource::initialize()

Note to self: sdaPin, sclPin are just dummy values now, good for UI consistency, but unused otherwise. Could be removed.
This commit is contained in:
Frank
2023-09-19 19:33:36 +02:00
parent b3d9621427
commit acc2d3aa10
2 changed files with 49 additions and 87 deletions

View File

@@ -1687,7 +1687,13 @@ class AudioReactive : public Usermod {
//useInputFilter = 0; // in case you need to disable low-cut software filtering //useInputFilter = 0; // in case you need to disable low-cut software filtering
audioSource = new ES7243(SAMPLE_RATE, BLOCK_SIZE); audioSource = new ES7243(SAMPLE_RATE, BLOCK_SIZE);
delay(100); delay(100);
if (audioSource) audioSource->initialize(sdaPin, sclPin, i2swsPin, i2ssdPin, i2sckPin, mclkPin); // WLEDMM align global pins
if ((sdaPin >= 0) && (i2c_sda < 0)) i2c_sda = sdaPin; // copy usermod prefs into globals (if globals not defined)
if ((sclPin >= 0) && (i2c_scl < 0)) i2c_scl = sclPin;
if (i2c_sda >= 0) sdaPin = -1; // -1 = use global
if (i2c_scl >= 0) sclPin = -1;
if (audioSource) audioSource->initialize(i2swsPin, i2ssdPin, i2sckPin, mclkPin);
break; break;
case 3: case 3:
DEBUGSR_PRINT(F("AR: SPH0645 Microphone - ")); DEBUGSR_PRINTLN(F(I2S_MIC_CHANNEL_TEXT)); DEBUGSR_PRINT(F("AR: SPH0645 Microphone - ")); DEBUGSR_PRINTLN(F(I2S_MIC_CHANNEL_TEXT));
@@ -1719,11 +1725,21 @@ class AudioReactive : public Usermod {
break; break;
#endif #endif
case 6: case 6:
DEBUGSR_PRINTLN(F("AR: ES8388 Source")); #ifdef use_es8388_mic
DEBUGSR_PRINTLN(F("AR: ES8388 Source (Mic)"));
#else
DEBUGSR_PRINTLN(F("AR: ES8388 Source (Line-In)"));
#endif
audioSource = new ES8388Source(SAMPLE_RATE, BLOCK_SIZE, 1.0f); audioSource = new ES8388Source(SAMPLE_RATE, BLOCK_SIZE, 1.0f);
//useInputFilter = 0; // to disable low-cut software filtering and restore previous behaviour //useInputFilter = 0; // to disable low-cut software filtering and restore previous behaviour
delay(100); delay(100);
if (audioSource) audioSource->initialize(sdaPin, sclPin, i2swsPin, i2ssdPin, i2sckPin, mclkPin); // WLEDMM align global pins
if ((sdaPin >= 0) && (i2c_sda < 0)) i2c_sda = sdaPin; // copy usermod prefs into globals (if globals not defined)
if ((sclPin >= 0) && (i2c_scl < 0)) i2c_scl = sclPin;
if (i2c_sda >= 0) sdaPin = -1; // -1 = use global
if (i2c_scl >= 0) sclPin = -1;
if (audioSource) audioSource->initialize(i2swsPin, i2ssdPin, i2sckPin, mclkPin);
break; break;
#if !defined(CONFIG_IDF_TARGET_ESP32S2) && !defined(CONFIG_IDF_TARGET_ESP32C3) && !defined(CONFIG_IDF_TARGET_ESP32S3) #if !defined(CONFIG_IDF_TARGET_ESP32S2) && !defined(CONFIG_IDF_TARGET_ESP32C3) && !defined(CONFIG_IDF_TARGET_ESP32S3)
@@ -2366,6 +2382,11 @@ class AudioReactive : public Usermod {
JsonObject dmic = top.createNestedObject(FPSTR(_digitalmic)); JsonObject dmic = top.createNestedObject(FPSTR(_digitalmic));
dmic[F("type")] = dmType; dmic[F("type")] = dmType;
// WLEDMM: align with globals I2C pins
if ((dmType == 2) || (dmType == 6)) { // only for ES7243 and ES8388
if (i2c_sda >= 0) sdaPin = -1; // -1 = use global
if (i2c_scl >= 0) sclPin = -1; // -1 = use global
}
JsonArray pinArray = dmic.createNestedArray("pin"); JsonArray pinArray = dmic.createNestedArray("pin");
pinArray.add(i2ssdPin); pinArray.add(i2ssdPin);
pinArray.add(i2swsPin); pinArray.add(i2swsPin);

View File

@@ -126,7 +126,7 @@ class AudioSource {
This function needs to take care of anything that needs to be done This function needs to take care of anything that needs to be done
before samples can be obtained from the microphone. before samples can be obtained from the microphone.
*/ */
virtual void initialize(int8_t = I2S_PIN_NO_CHANGE, int8_t = I2S_PIN_NO_CHANGE, int8_t = I2S_PIN_NO_CHANGE, int8_t = I2S_PIN_NO_CHANGE, int8_t = I2S_PIN_NO_CHANGE, int8_t = I2S_PIN_NO_CHANGE) = 0; virtual void initialize(int8_t = I2S_PIN_NO_CHANGE, int8_t = I2S_PIN_NO_CHANGE, int8_t = I2S_PIN_NO_CHANGE, int8_t = I2S_PIN_NO_CHANGE) = 0;
/* Deinitialize /* Deinitialize
Release all resources and deactivate any functionality that is used Release all resources and deactivate any functionality that is used
@@ -205,7 +205,7 @@ class I2SSource : public AudioSource {
}; };
} }
virtual void initialize(int8_t i2swsPin = I2S_PIN_NO_CHANGE, int8_t i2ssdPin = I2S_PIN_NO_CHANGE, int8_t i2sckPin = I2S_PIN_NO_CHANGE, int8_t mclkPin = I2S_PIN_NO_CHANGE, int8_t = I2S_PIN_NO_CHANGE, int8_t = I2S_PIN_NO_CHANGE) { virtual void initialize(int8_t i2swsPin = I2S_PIN_NO_CHANGE, int8_t i2ssdPin = I2S_PIN_NO_CHANGE, int8_t i2sckPin = I2S_PIN_NO_CHANGE, int8_t mclkPin = I2S_PIN_NO_CHANGE) {
DEBUGSR_PRINTLN("I2SSource:: initialize()."); DEBUGSR_PRINTLN("I2SSource:: initialize().");
if (i2swsPin != I2S_PIN_NO_CHANGE && i2ssdPin != I2S_PIN_NO_CHANGE) { if (i2swsPin != I2S_PIN_NO_CHANGE && i2ssdPin != I2S_PIN_NO_CHANGE) {
if (!pinManager.allocatePin(i2swsPin, true, PinOwner::UM_Audioreactive) || if (!pinManager.allocatePin(i2swsPin, true, PinOwner::UM_Audioreactive) ||
@@ -425,19 +425,14 @@ class ES7243 : public I2SSource {
private: private:
// I2C initialization functions for ES7243 // I2C initialization functions for ES7243
void _es7243I2cBegin() { void _es7243I2cBegin() {
bool i2c_initialized = Wire.begin(pin_ES7243_SDA, pin_ES7243_SCL, 100000U); Wire.setClock(100000);
if (i2c_initialized == false) {
ERRORSR_PRINTLN(F("AR: ES7243 failed to initialize I2C bus driver."));
}
} }
void _es7243I2cWrite(uint8_t reg, uint8_t val) { void _es7243I2cWrite(uint8_t reg, uint8_t val) {
#ifndef ES7243_ADDR #ifndef ES7243_ADDR
Wire.beginTransmission(0x13); #define ES7243_ADDR 0x13 // default address
#define ES7243_ADDR 0x13 // default address #endif
#else
Wire.beginTransmission(ES7243_ADDR); Wire.beginTransmission(ES7243_ADDR);
#endif
Wire.write((uint8_t)reg); Wire.write((uint8_t)reg);
Wire.write((uint8_t)val); Wire.write((uint8_t)val);
uint8_t i2cErr = Wire.endTransmission(); // i2cErr == 0 means OK uint8_t i2cErr = Wire.endTransmission(); // i2cErr == 0 means OK
@@ -462,54 +457,30 @@ public:
_config.channel_format = I2S_CHANNEL_FMT_ONLY_RIGHT; _config.channel_format = I2S_CHANNEL_FMT_ONLY_RIGHT;
}; };
void initialize(int8_t sdaPin, int8_t sclPin, int8_t i2swsPin, int8_t i2ssdPin, int8_t i2sckPin, int8_t mclkPin) { void initialize(int8_t i2swsPin, int8_t i2ssdPin, int8_t i2sckPin, int8_t mclkPin) {
DEBUGSR_PRINTLN("ES7243:: initialize();"); DEBUGSR_PRINTLN("ES7243:: initialize();");
// check that pins are valid
if ((sdaPin < 0) || (sclPin < 0)) {
ERRORSR_PRINTF("\nAR: invalid ES7243 I2C pins: SDA=%d, SCL=%d\n", sdaPin, sclPin);
return;
}
if ((i2c_sda < 0) || (i2c_scl < 0)) { // check that global I2C pins are not "undefined" // if ((i2sckPin < 0) || (mclkPin < 0)) { // WLEDMM not sure if this check is needed here, too
// ERRORSR_PRINTF("\nAR: invalid I2S pin: SCK=%d, MCLK=%d\n", i2sckPin, mclkPin);
// return;
// }
if ((i2c_sda < 0) || (i2c_scl < 0)) { // check that global I2C pins are not "undefined"
ERRORSR_PRINTF("\nAR: invalid ES7243 global I2C pins: SDA=%d, SCL=%d\n", i2c_sda, i2c_scl); ERRORSR_PRINTF("\nAR: invalid ES7243 global I2C pins: SDA=%d, SCL=%d\n", i2c_sda, i2c_scl);
return; return;
} }
if (!pinManager.joinWire()) { // WLEDMM specific: start I2C with globally defined pins if (!pinManager.joinWire(i2c_sda, i2c_scl)) { // WLEDMM specific: start I2C with globally defined pins
ERRORSR_PRINTF("\nAR: failed to join I2C bus with SDA=%d, SCL=%d\n", i2c_sda, i2c_scl); ERRORSR_PRINTF("\nAR: failed to join I2C bus with SDA=%d, SCL=%d\n", i2c_sda, i2c_scl);
return; return;
} }
if ((i2sckPin < 0) || (mclkPin < 0)) {
ERRORSR_PRINTF("\nAR: invalid I2S pin: SCK=%d, MCLK=%d\n", i2sckPin, mclkPin);
return;
}
// Reserve SDA and SCL pins of the I2C interface
PinManagerPinType es7243Pins[2] = { { sdaPin, true }, { sclPin, true } };
if (!pinManager.allocateMultiplePins(es7243Pins, 2, PinOwner::HW_I2C)) {
pinManager.deallocateMultiplePins(es7243Pins, 2, PinOwner::HW_I2C);
ERRORSR_PRINTF("\nAR: Failed to allocate ES7243 I2C pins: SDA=%d, SCL=%d\n", sdaPin, sclPin);
return;
}
pin_ES7243_SDA = sdaPin;
pin_ES7243_SCL = sclPin;
// First route mclk, then configure ADC over I2C, then configure I2S // First route mclk, then configure ADC over I2C, then configure I2S
_es7243InitAdc(); _es7243InitAdc();
I2SSource::initialize(i2swsPin, i2ssdPin, i2sckPin, mclkPin); I2SSource::initialize(i2swsPin, i2ssdPin, i2sckPin, mclkPin);
} }
void deinitialize() { void deinitialize() {
// Release SDA and SCL pins of the I2C interface
PinManagerPinType es7243Pins[2] = { { pin_ES7243_SDA, true }, { pin_ES7243_SCL, true } };
pinManager.deallocateMultiplePins(es7243Pins, 2, PinOwner::HW_I2C);
I2SSource::deinitialize(); I2SSource::deinitialize();
} }
private:
int8_t pin_ES7243_SDA;
int8_t pin_ES7243_SCL;
}; };
/* ES8388 Sound Modude /* ES8388 Sound Modude
@@ -520,19 +491,14 @@ class ES8388Source : public I2SSource {
private: private:
// I2C initialization functions for ES8388 // I2C initialization functions for ES8388
void _es8388I2cBegin() { void _es8388I2cBegin() {
bool i2c_initialized = Wire.begin(pin_ES8388_SDA, pin_ES8388_SCL, 100000U); Wire.setClock(100000);
if (i2c_initialized == false) {
ERRORSR_PRINTLN(F("AR: ES8388 failed to initialize I2C bus driver."));
}
} }
void _es8388I2cWrite(uint8_t reg, uint8_t val) { void _es8388I2cWrite(uint8_t reg, uint8_t val) {
#ifndef ES8388_ADDR #ifndef ES8388_ADDR
Wire.beginTransmission(0x10); #define ES8388_ADDR 0x10 // default address
#define ES8388_ADDR 0x10 // default address #endif
#else
Wire.beginTransmission(ES8388_ADDR); Wire.beginTransmission(ES8388_ADDR);
#endif
Wire.write((uint8_t)reg); Wire.write((uint8_t)reg);
Wire.write((uint8_t)val); Wire.write((uint8_t)val);
uint8_t i2cErr = Wire.endTransmission(); // i2cErr == 0 means OK uint8_t i2cErr = Wire.endTransmission(); // i2cErr == 0 means OK
@@ -619,59 +585,34 @@ class ES8388Source : public I2SSource {
_config.channel_format = I2S_CHANNEL_FMT_ONLY_LEFT; _config.channel_format = I2S_CHANNEL_FMT_ONLY_LEFT;
}; };
void initialize(int8_t sdaPin, int8_t sclPin, int8_t i2swsPin, int8_t i2ssdPin, int8_t i2sckPin, int8_t mclkPin) { void initialize(int8_t i2swsPin, int8_t i2ssdPin, int8_t i2sckPin, int8_t mclkPin) {
DEBUGSR_PRINTLN("ES8388Source:: initialize();"); DEBUGSR_PRINTLN("ES8388Source:: initialize();");
// if ((i2sckPin < 0) || (mclkPin < 0)) { // WLEDMM not sure if this check is needed here, too
// ERRORSR_PRINTF("\nAR: invalid I2S ES8388 pin: SCK=%d, MCLK=%d\n", i2sckPin, mclkPin);
// return;
// }
// BUG: "use global I2C pins" are valid as -1, and -1 is seen as invalid here. // BUG: "use global I2C pins" are valid as -1, and -1 is seen as invalid here.
// Workaround: Set I2C pins here, which will also set them globally. // Workaround: Set I2C pins here, which will also set them globally.
// Bug also exists in ES7243. // Bug also exists in ES7243.
// check that pins are valid
if ((sdaPin < 0) || (sclPin < 0)) {
ERRORSR_PRINTF("\nAR: invalid ES8388 I2C pins: SDA=%d, SCL=%d\n", sdaPin, sclPin);
return;
}
if ((i2c_sda < 0) || (i2c_scl < 0)) { // check that global I2C pins are not "undefined" if ((i2c_sda < 0) || (i2c_scl < 0)) { // check that global I2C pins are not "undefined"
ERRORSR_PRINTF("\nAR: invalid ES8388 global I2C pins: SDA=%d, SCL=%d\n", i2c_sda, i2c_scl); ERRORSR_PRINTF("\nAR: invalid ES8388 global I2C pins: SDA=%d, SCL=%d\n", i2c_sda, i2c_scl);
return; return;
} }
if (!pinManager.joinWire()) { // WLEDMM specific: start I2C with globally defined pins if (!pinManager.joinWire(i2c_sda, i2c_scl)) { // WLEDMM specific: start I2C with globally defined pins
ERRORSR_PRINTF("\nAR: failed to join I2C bus with SDA=%d, SCL=%d\n", i2c_sda, i2c_scl); ERRORSR_PRINTF("\nAR: failed to join I2C bus with SDA=%d, SCL=%d\n", i2c_sda, i2c_scl);
return; return;
} }
if ((i2sckPin < 0) || (mclkPin < 0)) {
ERRORSR_PRINTF("\nAR: invalid I2S pin: SCK=%d, MCLK=%d\n", i2sckPin, mclkPin);
return;
}
// Reserve SDA and SCL pins of the I2C interface
PinManagerPinType es8388Pins[2] = { { sdaPin, true }, { sclPin, true } };
if (!pinManager.allocateMultiplePins(es8388Pins, 2, PinOwner::HW_I2C)) {
pinManager.deallocateMultiplePins(es8388Pins, 2, PinOwner::HW_I2C);
ERRORSR_PRINTF("\nAR: Failed to allocate ES8388 I2C pins: SDA=%d, SCL=%d\n", sdaPin, sclPin);
return;
}
pin_ES8388_SDA = sdaPin;
pin_ES8388_SCL = sclPin;
// First route mclk, then configure ADC over I2C, then configure I2S // First route mclk, then configure ADC over I2C, then configure I2S
_es8388InitAdc(); _es8388InitAdc();
I2SSource::initialize(i2swsPin, i2ssdPin, i2sckPin, mclkPin); I2SSource::initialize(i2swsPin, i2ssdPin, i2sckPin, mclkPin);
} }
void deinitialize() { void deinitialize() {
// Release SDA and SCL pins of the I2C interface
PinManagerPinType es8388Pins[2] = { { pin_ES8388_SDA, true }, { pin_ES8388_SCL, true } };
pinManager.deallocateMultiplePins(es8388Pins, 2, PinOwner::HW_I2C);
I2SSource::deinitialize(); I2SSource::deinitialize();
} }
private:
int8_t pin_ES8388_SDA;
int8_t pin_ES8388_SCL;
}; };
#if ESP_IDF_VERSION >= ESP_IDF_VERSION_VAL(4, 2, 0) #if ESP_IDF_VERSION >= ESP_IDF_VERSION_VAL(4, 2, 0)
@@ -714,7 +655,7 @@ class I2SAdcSource : public I2SSource {
/* identify Audiosource type - I2S-ADC*/ /* identify Audiosource type - I2S-ADC*/
AudioSourceType getType(void) {return(Type_I2SAdc);} AudioSourceType getType(void) {return(Type_I2SAdc);}
void initialize(int8_t audioPin, int8_t = I2S_PIN_NO_CHANGE, int8_t = I2S_PIN_NO_CHANGE, int8_t = I2S_PIN_NO_CHANGE, int8_t = I2S_PIN_NO_CHANGE, int8_t = I2S_PIN_NO_CHANGE) { void initialize(int8_t audioPin, int8_t = I2S_PIN_NO_CHANGE, int8_t = I2S_PIN_NO_CHANGE, int8_t = I2S_PIN_NO_CHANGE) {
DEBUGSR_PRINTLN("I2SAdcSource:: initialize()."); DEBUGSR_PRINTLN("I2SAdcSource:: initialize().");
_myADCchannel = 0x0F; _myADCchannel = 0x0F;
if(!pinManager.allocatePin(audioPin, false, PinOwner::UM_Audioreactive)) { if(!pinManager.allocatePin(audioPin, false, PinOwner::UM_Audioreactive)) {
@@ -886,7 +827,7 @@ class SPH0654 : public I2SSource {
I2SSource(sampleRate, blockSize, sampleScale, i2sMaster) I2SSource(sampleRate, blockSize, sampleScale, i2sMaster)
{} {}
void initialize(int8_t i2swsPin, int8_t i2ssdPin, int8_t i2sckPin, int8_t = I2S_PIN_NO_CHANGE, int8_t = I2S_PIN_NO_CHANGE, int8_t = I2S_PIN_NO_CHANGE) { void initialize(int8_t i2swsPin, int8_t i2ssdPin, int8_t i2sckPin, int8_t = I2S_PIN_NO_CHANGE) {
DEBUGSR_PRINTLN("SPH0654:: initialize();"); DEBUGSR_PRINTLN("SPH0654:: initialize();");
I2SSource::initialize(i2swsPin, i2ssdPin, i2sckPin); I2SSource::initialize(i2swsPin, i2ssdPin, i2sckPin);
#if !defined(CONFIG_IDF_TARGET_ESP32S2) && !defined(CONFIG_IDF_TARGET_ESP32C3) && !defined(CONFIG_IDF_TARGET_ESP32S3) #if !defined(CONFIG_IDF_TARGET_ESP32S2) && !defined(CONFIG_IDF_TARGET_ESP32C3) && !defined(CONFIG_IDF_TARGET_ESP32S3)