From bd477624f0127b7357cc7c4f22ef7749f62b3855 Mon Sep 17 00:00:00 2001 From: TroyHacks <5659019+troyhacks@users.noreply.github.com> Date: Mon, 3 Apr 2023 22:41:29 -0400 Subject: [PATCH 1/5] Working proof of concept for ES8388 --- usermods/audioreactive/audio_source.h | 338 +++++++++++++++++++++++--- 1 file changed, 308 insertions(+), 30 deletions(-) diff --git a/usermods/audioreactive/audio_source.h b/usermods/audioreactive/audio_source.h index 2bcab435..84eb8df8 100644 --- a/usermods/audioreactive/audio_source.h +++ b/usermods/audioreactive/audio_source.h @@ -485,35 +485,19 @@ public: int8_t pin_ES7243_SCL; }; +/* ES8388 Microphone + This is an I2S microphone that requires ininitialization over + I2C before I2S data can be received +*/ + class ES8388Source : public I2SSource { - private: - - void _es8388InitAdc() { - DEBUGSR_PRINTF("\nAR: _es8388InitAdc\n"); - - if (!es8388.init()) { - Serial.println("_es8388InitAdc init Fail\n"); - return; - } - es8388.inputSelect(IN2); // IN2 Line-In - es8388.setInputGain(8); - es8388.outputSelect(OUT1); // OUT1 - Headphones - es8388.setOutputVolume(12); - es8388.mixerSourceSelect(MIXADC, MIXADC); - es8388.mixerSourceControl(DACOUT); - es8388.setALCmode(MUSIC); - es8388.analogBypass(true); - uint8_t *reg; - for (uint8_t i = 0; i < 53; i++) { - reg = es8388.readAllReg(); - DEBUGSR_PRINTF("Reg-%02d = 0x%02x\r\n", i, reg[i]); - } - } public: ES8388Source(int sampleRate, int blockSize, int sdaPin, int sclPin) : I2SSource(sampleRate, blockSize) { _config.channel_format = I2S_CHANNEL_FMT_ONLY_LEFT; + // _config.mode = (i2s_mode_t)(I2S_MODE_MASTER | I2S_MODE_TX | I2S_MODE_RX), + // _config.channel_format = I2S_CHANNEL_FMT_RIGHT_LEFT; pin_ES8388_SDA = sdaPin; pin_ES8388_SCL = sclPin; DEBUGSR_PRINTF("\nAR: ES8388Source\n"); @@ -529,14 +513,57 @@ public: return; } - _es8388InitAdc(); - // i2s - // PIN_FUNC_SELECT(PERIPHS_IO_MUX_GPIO0_U, FUNC_GPIO0_CLK_OUT1); - // WRITE_PERI_REG(PIN_CTRL, 0xFFF0); - // i2s_set_sample_rates(I2S_NUM_0, 22050); + ES8388 es8388 = ES8388(pin_ES8388_SDA, pin_ES8388_SCL, 400000); + + if (!es8388.init()) { + Serial.println("_es8388InitAdc init Fail\n"); + return; + } + + es8388.inputSelect(IN2); + es8388.setInputGain(8); + es8388.outputSelect(OUT2); + es8388.setOutputVolume(12); + es8388.mixerSourceSelect(MIXIN2, MIXIN2); + es8388.mixerSourceControl(DACOUT); + es8388.setALCmode(DISABLE); + es8388.analogBypass(true); + + bool pf = es8388.pub_write_reg(0x09, 0x00); // mutes onboard microphones (a bit) and highly reduces distortion + + uint8_t *reg; + for (uint8_t i = 0; i < 53; i++) { + reg = es8388.readAllReg(); + DEBUGSR_PRINTF("Reg-%02d = 0x%02x\r\n", i, reg[i]); + } + + PIN_FUNC_SELECT(PERIPHS_IO_MUX_GPIO0_U, FUNC_GPIO0_CLK_OUT1); + WRITE_PERI_REG(PIN_CTRL, 0xFFF0); DEBUGSR_PRINTF("\nAR: ES8388Source calling I2SSource::initialize\n"); - I2SSource::initialize(i2swsPin, i2ssdPin, i2sckPin, mclkPin); + // I2SSource::initialize(i2swsPin, i2ssdPin, i2sckPin, mclkPin); + + i2s_config_t i2s_config = { + .mode = (i2s_mode_t)(I2S_MODE_MASTER | I2S_MODE_RX), + .sample_rate = 22050, + .bits_per_sample = I2S_SAMPLE_RESOLUTION, + .channel_format = I2S_MIC_CHANNEL, + .communication_format = I2S_COMM_FORMAT_I2S, + .intr_alloc_flags = 0, + .dma_buf_count = 8, + .dma_buf_len = 512, + .use_apll = false, + .tx_desc_auto_clear = true, + .fixed_mclk = 0}; + + i2s_pin_config_t pin_config = { + .bck_io_num = 27, .ws_io_num = 25, .data_out_num = 26, .data_in_num = 35}; + + i2s_driver_install(I2S_NUM_0, &i2s_config, 0, NULL); + i2s_set_pin(I2S_NUM_0, &pin_config); + + _initialized = true; + } void deinitialize() { @@ -549,9 +576,260 @@ public: private: int8_t pin_ES8388_SDA; int8_t pin_ES8388_SCL; - ES8388 es8388 = ES8388(18, 23, 400000); + }; +// class ES8388Source : public I2SSource { +// private: +// // I2C initialization functions for ES8388 +// void _es8388I2cBegin() { +// bool i2c_initialized = Wire.begin(pin_ES8388_SDA, pin_ES8388_SCL, 100000U); +// if (i2c_initialized == false) { +// ERRORSR_PRINTLN(F("AR: ES8388 failed to initialize I2C bus driver.")); +// } +// } + +// void _es8388I2cWrite(uint8_t reg, uint8_t val) { +// #ifndef ES8388_ADDR +// Wire.beginTransmission(0x10); +// #define ES8388_ADDR 0x10 // default address +// #else +// Wire.beginTransmission(ES7243_ADDR); +// #endif +// Wire.write((uint8_t)reg); +// Wire.write((uint8_t)val); +// uint8_t i2cErr = Wire.endTransmission(); // i2cErr == 0 means OK +// if (i2cErr != 0) { +// DEBUGSR_PRINTF("AR: ES8388 I2C write failed with error=%d (addr=0x%X, reg 0x%X, val 0x%X).\n", i2cErr, ES8388_ADDR, reg, val); +// } +// } + +// void _es8388InitAdc() { + +// // _es8388I2cBegin(); + +// // _es8388I2cWrite(0x08, 0x00); +// // _es8388I2cWrite(0x02, 0xFF); +// // _es8388I2cWrite(0x2B, 0x80); +// // _es8388I2cWrite(0x00, 0x05); +// // _es8388I2cWrite(0x01, 0x40); + +// // _es8388I2cWrite(0x03, 0x00); +// // _es8388I2cWrite(0x0a, 0x50); +// // _es8388I2cWrite(0x0b, 0x80); +// // _es8388I2cWrite(0x09, 0x77); +// // _es8388I2cWrite(0x0c, 0x0C); +// // _es8388I2cWrite(0x0d, 0x02); +// // _es8388I2cWrite(0x10, 0x00); +// // _es8388I2cWrite(0x11, 0x00); + +// // _es8388I2cWrite(0x12, 0xEA); +// // _es8388I2cWrite(0x13, 0xC0); +// // _es8388I2cWrite(0x14, 0x12); +// // _es8388I2cWrite(0x15, 0x06); +// // _es8388I2cWrite(0x16, 0xC3); + +// // _es8388I2cWrite(0x04, 0x3C); +// // _es8388I2cWrite(0x17, 0x18); +// // _es8388I2cWrite(0x18, 0x02); +// // _es8388I2cWrite(0x19, 0x00); +// // _es8388I2cWrite(0x1a, 0x00); +// // _es8388I2cWrite(0x1b, 0x00); + +// // _es8388I2cWrite(0x26, 0x09); +// // _es8388I2cWrite(0x27, 0x50); +// // _es8388I2cWrite(0x28, 0x38); +// // _es8388I2cWrite(0x29, 0x38); +// // _es8388I2cWrite(0x2a, 0x50); + +// // _es8388I2cWrite(0x2e, 0x00); +// // _es8388I2cWrite(0x2f, 0x00); +// // _es8388I2cWrite(0x30, 0x00); +// // _es8388I2cWrite(0x31, 0x00); + +// // ... and now the "config", lol + +// // _es8388I2cWrite(0x09, 0x00); +// // _es8388I2cWrite(0x04, 0x0C); +// // _es8388I2cWrite(0x30, 12); +// // _es8388I2cWrite(0x31, 12); + +// // _es8388I2cWrite(0x26, (1<<3)|1); + +// // _es8388I2cWrite(0x27, (false << 7) | (true << 6) | (2 << 3)); +// // _es8388I2cWrite(0x28, (false << 7) | (true << 6) | (2 << 3)); + +// // _es8388I2cWrite(0x12, 0x00); + +// // _es8388I2cWrite(0x09, 0x00); + +// #include "ES8388.h" + +// ES8388 es8388 = ES8388(pin_ES8388_SDA, pin_ES8388_SCL, 400000); + +// if (!es8388.init()) { +// Serial.println("_es8388InitAdc init Fail\n"); +// return; +// } + +// es8388.inputSelect(IN2); +// es8388.setInputGain(0); +// es8388.outputSelect(OUT2); +// es8388.setOutputVolume(8); +// es8388.mixerSourceSelect(MIXIN2, MIXIN2); +// es8388.mixerSourceControl(DACOUT); +// es8388.setALCmode(MUSIC); +// es8388.analogBypass(true); + +// bool pf = es8388.pub_write_reg(0x09, 0x00); // mutes onboard microphones (a bit) and highly reduces distortion + +// uint8_t *reg; +// for (uint8_t i = 0; i < 53; i++) { +// reg = es8388.readAllReg(); +// DEBUGSR_PRINTF("Reg-%02d = 0x%02x\r\n", i, reg[i]); +// } + +// } + +// public: +// ES8388Source(SRate_t sampleRate, int blockSize, float sampleScale = 1.0f, bool i2sMaster=true) : +// I2SSource(sampleRate, blockSize, sampleScale, i2sMaster) { +// _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) { + +// // 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 ((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 +// _es8388InitAdc(); +// // I2SSource::initialize(i2swsPin, i2ssdPin, i2sckPin, mclkPin); + +// PIN_FUNC_SELECT(PERIPHS_IO_MUX_GPIO0_U, FUNC_GPIO0_CLK_OUT1); +// WRITE_PERI_REG(PIN_CTRL, 0xFFF0); + +// i2s_config_t i2s_config = { +// .mode = (i2s_mode_t)(I2S_MODE_MASTER | I2S_MODE_RX), +// .sample_rate = 22050, +// .bits_per_sample = I2S_SAMPLE_RESOLUTION, +// .channel_format = I2S_MIC_CHANNEL, +// .communication_format = I2S_COMM_FORMAT_I2S, +// .intr_alloc_flags = 0, +// .dma_buf_count = 8, +// .dma_buf_len = 512, +// .use_apll = false, +// .tx_desc_auto_clear = true, +// .fixed_mclk = 0}; + +// i2s_pin_config_t pin_config = { +// .bck_io_num = 27, .ws_io_num = 25, .data_out_num = 26, .data_in_num = 35}; + +// i2s_driver_install(I2S_NUM_0, &i2s_config, 0, NULL); +// i2s_set_pin(I2S_NUM_0, &pin_config); + +// _initialized = true; + +// } + +// 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(); +// } + +// private: +// int8_t pin_ES8388_SDA; +// int8_t pin_ES8388_SCL; +// }; + +// class ES8388Source : public I2SSource { +// private: + +// void _es8388InitAdc() { +// DEBUGSR_PRINTF("\nAR: _es8388InitAdc\n"); + +// if (!es8388.init()) { +// Serial.println("_es8388InitAdc init Fail\n"); +// return; +// } +// es8388.inputSelect(IN2); // IN2 Line-In +// es8388.setInputGain(8); +// es8388.outputSelect(OUT1); // OUT1 - Headphones +// es8388.setOutputVolume(12); +// es8388.mixerSourceSelect(MIXADC, MIXADC); +// es8388.mixerSourceControl(DACOUT); +// es8388.setALCmode(MUSIC); +// es8388.analogBypass(true); +// uint8_t *reg; +// for (uint8_t i = 0; i < 53; i++) { +// reg = es8388.readAllReg(); +// DEBUGSR_PRINTF("Reg-%02d = 0x%02x\r\n", i, reg[i]); +// } +// } + +// public: +// ES8388Source(int sampleRate, int blockSize, int sdaPin, int sclPin) : +// I2SSource(sampleRate, blockSize) { +// _config.channel_format = I2S_CHANNEL_FMT_ONLY_LEFT; +// pin_ES8388_SDA = sdaPin; +// pin_ES8388_SCL = sclPin; +// DEBUGSR_PRINTF("\nAR: ES8388Source\n"); +// }; + +// void initialize(int8_t i2swsPin, int8_t i2ssdPin, int8_t i2sckPin, int8_t mclkPin, int8_t = I2S_PIN_NO_CHANGE, int8_t = I2S_PIN_NO_CHANGE) { +// DEBUGSR_PRINTF("\nAR: ES8388Source initialize called\n"); +// // Reserve SDA and SCL pins of the I2C interface +// PinManagerPinType pins[2] = { { pin_ES8388_SDA, true }, { pin_ES8388_SCL, true } }; +// if (!pinManager.allocateMultiplePins(pins, 2, PinOwner::HW_I2C)) { +// pinManager.deallocateMultiplePins(pins, 2, PinOwner::HW_I2C); +// ERRORSR_PRINTF("\nAR: Failed to allocate ES8388 I2C pins: SDA=%d, SCL=%d\n", pin_ES8388_SDA, pin_ES8388_SCL); +// return; +// } + +// _es8388InitAdc(); +// // i2s +// // PIN_FUNC_SELECT(PERIPHS_IO_MUX_GPIO0_U, FUNC_GPIO0_CLK_OUT1); +// // WRITE_PERI_REG(PIN_CTRL, 0xFFF0); +// // i2s_set_sample_rates(I2S_NUM_0, 22050); + +// DEBUGSR_PRINTF("\nAR: ES8388Source calling I2SSource::initialize\n"); +// I2SSource::initialize(i2swsPin, i2ssdPin, i2sckPin, mclkPin); +// } + +// void deinitialize() { +// // Release SDA and SCL pins of the I2C interface +// pinManager.deallocatePin(pin_ES8388_SDA, PinOwner::HW_I2C); +// pinManager.deallocatePin(pin_ES8388_SCL, PinOwner::HW_I2C); +// I2SSource::deinitialize(); +// } + +// private: +// int8_t pin_ES8388_SDA; +// int8_t pin_ES8388_SCL; +// ES8388 es8388 = ES8388(18, 23, 400000); +// }; + #if ESP_IDF_VERSION >= ESP_IDF_VERSION_VAL(4, 2, 0) From d775f7fb2884e20cc921e7b323b906f95673b9dd Mon Sep 17 00:00:00 2001 From: TroyHacks <5659019+troyhacks@users.noreply.github.com> Date: Tue, 4 Apr 2023 14:01:47 -0400 Subject: [PATCH 2/5] Removed reliance on the ES8388 library and made things more in line with similar boards with I2C init. --- lib/ES8388 | 1 + usermods/audioreactive/audio_reactive.h | 4 +- usermods/audioreactive/audio_source.h | 430 ++++++------------------ 3 files changed, 111 insertions(+), 324 deletions(-) create mode 160000 lib/ES8388 diff --git a/lib/ES8388 b/lib/ES8388 new file mode 160000 index 00000000..f589ddfe --- /dev/null +++ b/lib/ES8388 @@ -0,0 +1 @@ +Subproject commit f589ddfe7cc27f294e00644dc510e64bff677f0b diff --git a/usermods/audioreactive/audio_reactive.h b/usermods/audioreactive/audio_reactive.h index ca9f221a..2f9a0482 100644 --- a/usermods/audioreactive/audio_reactive.h +++ b/usermods/audioreactive/audio_reactive.h @@ -1273,9 +1273,9 @@ class AudioReactive : public Usermod { #endif case 6: DEBUGSR_PRINTLN(F("AR: ES8388 Source")); - audioSource = new ES8388Source(SAMPLE_RATE, BLOCK_SIZE, sdaPin, sclPin); + audioSource = new ES8388Source(SAMPLE_RATE, BLOCK_SIZE); delay(100); - if (audioSource) audioSource->initialize(i2swsPin, i2ssdPin, i2sckPin, mclkPin); + if (audioSource) audioSource->initialize(sdaPin, sclPin, i2swsPin, i2ssdPin, i2sckPin, mclkPin); break; #if !defined(CONFIG_IDF_TARGET_ESP32S2) && !defined(CONFIG_IDF_TARGET_ESP32C3) && !defined(CONFIG_IDF_TARGET_ESP32S3) diff --git a/usermods/audioreactive/audio_source.h b/usermods/audioreactive/audio_source.h index 84eb8df8..a1cd1eda 100644 --- a/usermods/audioreactive/audio_source.h +++ b/usermods/audioreactive/audio_source.h @@ -15,7 +15,7 @@ #else #define SRate_t int #endif -#include "ES8388.h" +// #include "ES8388.h" //#include //#include @@ -489,349 +489,135 @@ public: This is an I2S microphone that requires ininitialization over I2C before I2S data can be received */ - class ES8388Source : public I2SSource { + private: + // I2C initialization functions for ES8388 + void _es8388I2cBegin() { + bool i2c_initialized = Wire.begin(pin_ES8388_SDA, pin_ES8388_SCL, 100000U); + if (i2c_initialized == false) { + ERRORSR_PRINTLN(F("AR: ES8388 failed to initialize I2C bus driver.")); + } + } -public: - ES8388Source(int sampleRate, int blockSize, int sdaPin, int sclPin) : - I2SSource(sampleRate, blockSize) { + void _es8388I2cWrite(uint8_t reg, uint8_t val) { +#ifndef ES8388_ADDR + Wire.beginTransmission(0x10); + #define ES8388_ADDR 0x10 // default address +#else + Wire.beginTransmission(ES7243_ADDR); +#endif + Wire.write((uint8_t)reg); + Wire.write((uint8_t)val); + uint8_t i2cErr = Wire.endTransmission(); // i2cErr == 0 means OK + if (i2cErr != 0) { + DEBUGSR_PRINTF("AR: ES8388 I2C write failed with error=%d (addr=0x%X, reg 0x%X, val 0x%X).\n", i2cErr, ES8388_ADDR, reg, val); + } + } + + void _es8388InitAdc() { + // This is by no means 100% figured but it's working for line-in + // with a little too much noise for my liking... + _es8388I2cBegin(); + _es8388I2cWrite(0x08,0x00); + _es8388I2cWrite(0x02,0xff); + _es8388I2cWrite(0x2b,0x80); + _es8388I2cWrite(0x00,0x05); + _es8388I2cWrite(0x01,0x40); + _es8388I2cWrite(0x03,0x00); + _es8388I2cWrite(0x0a,0x50); + _es8388I2cWrite(0x0b,0x80); + _es8388I2cWrite(0x09,0x77); + _es8388I2cWrite(0x0c,0x0c); + _es8388I2cWrite(0x0d,0x02); + _es8388I2cWrite(0x10,0x00); + _es8388I2cWrite(0x11,0x00); + _es8388I2cWrite(0x12,0xea); + _es8388I2cWrite(0x13,0xc0); + _es8388I2cWrite(0x14,0x12); + _es8388I2cWrite(0x15,0x06); + _es8388I2cWrite(0x16,0xc3); + _es8388I2cWrite(0x04,0x3c); + _es8388I2cWrite(0x17,0x18); + _es8388I2cWrite(0x18,0x02); + _es8388I2cWrite(0x19,0x00); + _es8388I2cWrite(0x1a,0x00); + _es8388I2cWrite(0x1b,0x00); + _es8388I2cWrite(0x26,0x09); + _es8388I2cWrite(0x27,0x50); + _es8388I2cWrite(0x28,0x38); + _es8388I2cWrite(0x29,0x38); + _es8388I2cWrite(0x2a,0x50); + _es8388I2cWrite(0x2e,0x00); + _es8388I2cWrite(0x2f,0x00); + _es8388I2cWrite(0x30,0x00); + _es8388I2cWrite(0x31,0x00); + _es8388I2cWrite(0x02,0x00); + _es8388I2cWrite(0x0a,0x50); + _es8388I2cWrite(0x09,0x00); + _es8388I2cWrite(0x04,0x0c); + _es8388I2cWrite(0x30,0x21); + _es8388I2cWrite(0x31,0x21); + _es8388I2cWrite(0x26,0x09); + _es8388I2cWrite(0x27,0x90); + _es8388I2cWrite(0x2a,0x90); + _es8388I2cWrite(0x12,0x38); + _es8388I2cWrite(0x13,0x30); + _es8388I2cWrite(0x14,0x57); + _es8388I2cWrite(0x15,0x06); + _es8388I2cWrite(0x16,0x89); + _es8388I2cWrite(0x26,0x09); + _es8388I2cWrite(0x27,0x50); + _es8388I2cWrite(0x2a,0x50); + _es8388I2cWrite(0x09,0x00); + } + + public: + ES8388Source(SRate_t sampleRate, int blockSize, float sampleScale = 1.0f, bool i2sMaster=true) : + I2SSource(sampleRate, blockSize, sampleScale, i2sMaster) { _config.channel_format = I2S_CHANNEL_FMT_ONLY_LEFT; - // _config.mode = (i2s_mode_t)(I2S_MODE_MASTER | I2S_MODE_TX | I2S_MODE_RX), - // _config.channel_format = I2S_CHANNEL_FMT_RIGHT_LEFT; - pin_ES8388_SDA = sdaPin; - pin_ES8388_SCL = sclPin; - DEBUGSR_PRINTF("\nAR: ES8388Source\n"); }; - void initialize(int8_t i2swsPin, int8_t i2ssdPin, int8_t i2sckPin, int8_t mclkPin, int8_t = I2S_PIN_NO_CHANGE, int8_t = I2S_PIN_NO_CHANGE) { - DEBUGSR_PRINTF("\nAR: ES8388Source initialize called\n"); + void initialize(int8_t sdaPin, int8_t sclPin, int8_t i2swsPin, int8_t i2ssdPin, int8_t i2sckPin, int8_t mclkPin) { + + // 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 ((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 pins[2] = { { pin_ES8388_SDA, true }, { pin_ES8388_SCL, true } }; - if (!pinManager.allocateMultiplePins(pins, 2, PinOwner::HW_I2C)) { - pinManager.deallocateMultiplePins(pins, 2, PinOwner::HW_I2C); - ERRORSR_PRINTF("\nAR: Failed to allocate ES8388 I2C pins: SDA=%d, SCL=%d\n", pin_ES8388_SDA, pin_ES8388_SCL); + 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; } - ES8388 es8388 = ES8388(pin_ES8388_SDA, pin_ES8388_SCL, 400000); + pin_ES8388_SDA = sdaPin; + pin_ES8388_SCL = sclPin; - if (!es8388.init()) { - Serial.println("_es8388InitAdc init Fail\n"); - return; - } - - es8388.inputSelect(IN2); - es8388.setInputGain(8); - es8388.outputSelect(OUT2); - es8388.setOutputVolume(12); - es8388.mixerSourceSelect(MIXIN2, MIXIN2); - es8388.mixerSourceControl(DACOUT); - es8388.setALCmode(DISABLE); - es8388.analogBypass(true); - - bool pf = es8388.pub_write_reg(0x09, 0x00); // mutes onboard microphones (a bit) and highly reduces distortion - - uint8_t *reg; - for (uint8_t i = 0; i < 53; i++) { - reg = es8388.readAllReg(); - DEBUGSR_PRINTF("Reg-%02d = 0x%02x\r\n", i, reg[i]); - } - - PIN_FUNC_SELECT(PERIPHS_IO_MUX_GPIO0_U, FUNC_GPIO0_CLK_OUT1); - WRITE_PERI_REG(PIN_CTRL, 0xFFF0); - - DEBUGSR_PRINTF("\nAR: ES8388Source calling I2SSource::initialize\n"); - // I2SSource::initialize(i2swsPin, i2ssdPin, i2sckPin, mclkPin); - - i2s_config_t i2s_config = { - .mode = (i2s_mode_t)(I2S_MODE_MASTER | I2S_MODE_RX), - .sample_rate = 22050, - .bits_per_sample = I2S_SAMPLE_RESOLUTION, - .channel_format = I2S_MIC_CHANNEL, - .communication_format = I2S_COMM_FORMAT_I2S, - .intr_alloc_flags = 0, - .dma_buf_count = 8, - .dma_buf_len = 512, - .use_apll = false, - .tx_desc_auto_clear = true, - .fixed_mclk = 0}; - - i2s_pin_config_t pin_config = { - .bck_io_num = 27, .ws_io_num = 25, .data_out_num = 26, .data_in_num = 35}; - - i2s_driver_install(I2S_NUM_0, &i2s_config, 0, NULL); - i2s_set_pin(I2S_NUM_0, &pin_config); - - _initialized = true; - + // First route mclk, then configure ADC over I2C, then configure I2S + _es8388InitAdc(); + I2SSource::initialize(i2swsPin, i2ssdPin, i2sckPin, mclkPin); } void deinitialize() { // Release SDA and SCL pins of the I2C interface - pinManager.deallocatePin(pin_ES8388_SDA, PinOwner::HW_I2C); - pinManager.deallocatePin(pin_ES8388_SCL, PinOwner::HW_I2C); + PinManagerPinType es8388Pins[2] = { { pin_ES8388_SDA, true }, { pin_ES8388_SCL, true } }; + pinManager.deallocateMultiplePins(es8388Pins, 2, PinOwner::HW_I2C); I2SSource::deinitialize(); } private: int8_t pin_ES8388_SDA; int8_t pin_ES8388_SCL; - }; -// class ES8388Source : public I2SSource { -// private: -// // I2C initialization functions for ES8388 -// void _es8388I2cBegin() { -// bool i2c_initialized = Wire.begin(pin_ES8388_SDA, pin_ES8388_SCL, 100000U); -// if (i2c_initialized == false) { -// ERRORSR_PRINTLN(F("AR: ES8388 failed to initialize I2C bus driver.")); -// } -// } - -// void _es8388I2cWrite(uint8_t reg, uint8_t val) { -// #ifndef ES8388_ADDR -// Wire.beginTransmission(0x10); -// #define ES8388_ADDR 0x10 // default address -// #else -// Wire.beginTransmission(ES7243_ADDR); -// #endif -// Wire.write((uint8_t)reg); -// Wire.write((uint8_t)val); -// uint8_t i2cErr = Wire.endTransmission(); // i2cErr == 0 means OK -// if (i2cErr != 0) { -// DEBUGSR_PRINTF("AR: ES8388 I2C write failed with error=%d (addr=0x%X, reg 0x%X, val 0x%X).\n", i2cErr, ES8388_ADDR, reg, val); -// } -// } - -// void _es8388InitAdc() { - -// // _es8388I2cBegin(); - -// // _es8388I2cWrite(0x08, 0x00); -// // _es8388I2cWrite(0x02, 0xFF); -// // _es8388I2cWrite(0x2B, 0x80); -// // _es8388I2cWrite(0x00, 0x05); -// // _es8388I2cWrite(0x01, 0x40); - -// // _es8388I2cWrite(0x03, 0x00); -// // _es8388I2cWrite(0x0a, 0x50); -// // _es8388I2cWrite(0x0b, 0x80); -// // _es8388I2cWrite(0x09, 0x77); -// // _es8388I2cWrite(0x0c, 0x0C); -// // _es8388I2cWrite(0x0d, 0x02); -// // _es8388I2cWrite(0x10, 0x00); -// // _es8388I2cWrite(0x11, 0x00); - -// // _es8388I2cWrite(0x12, 0xEA); -// // _es8388I2cWrite(0x13, 0xC0); -// // _es8388I2cWrite(0x14, 0x12); -// // _es8388I2cWrite(0x15, 0x06); -// // _es8388I2cWrite(0x16, 0xC3); - -// // _es8388I2cWrite(0x04, 0x3C); -// // _es8388I2cWrite(0x17, 0x18); -// // _es8388I2cWrite(0x18, 0x02); -// // _es8388I2cWrite(0x19, 0x00); -// // _es8388I2cWrite(0x1a, 0x00); -// // _es8388I2cWrite(0x1b, 0x00); - -// // _es8388I2cWrite(0x26, 0x09); -// // _es8388I2cWrite(0x27, 0x50); -// // _es8388I2cWrite(0x28, 0x38); -// // _es8388I2cWrite(0x29, 0x38); -// // _es8388I2cWrite(0x2a, 0x50); - -// // _es8388I2cWrite(0x2e, 0x00); -// // _es8388I2cWrite(0x2f, 0x00); -// // _es8388I2cWrite(0x30, 0x00); -// // _es8388I2cWrite(0x31, 0x00); - -// // ... and now the "config", lol - -// // _es8388I2cWrite(0x09, 0x00); -// // _es8388I2cWrite(0x04, 0x0C); -// // _es8388I2cWrite(0x30, 12); -// // _es8388I2cWrite(0x31, 12); - -// // _es8388I2cWrite(0x26, (1<<3)|1); - -// // _es8388I2cWrite(0x27, (false << 7) | (true << 6) | (2 << 3)); -// // _es8388I2cWrite(0x28, (false << 7) | (true << 6) | (2 << 3)); - -// // _es8388I2cWrite(0x12, 0x00); - -// // _es8388I2cWrite(0x09, 0x00); - -// #include "ES8388.h" - -// ES8388 es8388 = ES8388(pin_ES8388_SDA, pin_ES8388_SCL, 400000); - -// if (!es8388.init()) { -// Serial.println("_es8388InitAdc init Fail\n"); -// return; -// } - -// es8388.inputSelect(IN2); -// es8388.setInputGain(0); -// es8388.outputSelect(OUT2); -// es8388.setOutputVolume(8); -// es8388.mixerSourceSelect(MIXIN2, MIXIN2); -// es8388.mixerSourceControl(DACOUT); -// es8388.setALCmode(MUSIC); -// es8388.analogBypass(true); - -// bool pf = es8388.pub_write_reg(0x09, 0x00); // mutes onboard microphones (a bit) and highly reduces distortion - -// uint8_t *reg; -// for (uint8_t i = 0; i < 53; i++) { -// reg = es8388.readAllReg(); -// DEBUGSR_PRINTF("Reg-%02d = 0x%02x\r\n", i, reg[i]); -// } - -// } - -// public: -// ES8388Source(SRate_t sampleRate, int blockSize, float sampleScale = 1.0f, bool i2sMaster=true) : -// I2SSource(sampleRate, blockSize, sampleScale, i2sMaster) { -// _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) { - -// // 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 ((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 -// _es8388InitAdc(); -// // I2SSource::initialize(i2swsPin, i2ssdPin, i2sckPin, mclkPin); - -// PIN_FUNC_SELECT(PERIPHS_IO_MUX_GPIO0_U, FUNC_GPIO0_CLK_OUT1); -// WRITE_PERI_REG(PIN_CTRL, 0xFFF0); - -// i2s_config_t i2s_config = { -// .mode = (i2s_mode_t)(I2S_MODE_MASTER | I2S_MODE_RX), -// .sample_rate = 22050, -// .bits_per_sample = I2S_SAMPLE_RESOLUTION, -// .channel_format = I2S_MIC_CHANNEL, -// .communication_format = I2S_COMM_FORMAT_I2S, -// .intr_alloc_flags = 0, -// .dma_buf_count = 8, -// .dma_buf_len = 512, -// .use_apll = false, -// .tx_desc_auto_clear = true, -// .fixed_mclk = 0}; - -// i2s_pin_config_t pin_config = { -// .bck_io_num = 27, .ws_io_num = 25, .data_out_num = 26, .data_in_num = 35}; - -// i2s_driver_install(I2S_NUM_0, &i2s_config, 0, NULL); -// i2s_set_pin(I2S_NUM_0, &pin_config); - -// _initialized = true; - -// } - -// 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(); -// } - -// private: -// int8_t pin_ES8388_SDA; -// int8_t pin_ES8388_SCL; -// }; - -// class ES8388Source : public I2SSource { -// private: - -// void _es8388InitAdc() { -// DEBUGSR_PRINTF("\nAR: _es8388InitAdc\n"); - -// if (!es8388.init()) { -// Serial.println("_es8388InitAdc init Fail\n"); -// return; -// } -// es8388.inputSelect(IN2); // IN2 Line-In -// es8388.setInputGain(8); -// es8388.outputSelect(OUT1); // OUT1 - Headphones -// es8388.setOutputVolume(12); -// es8388.mixerSourceSelect(MIXADC, MIXADC); -// es8388.mixerSourceControl(DACOUT); -// es8388.setALCmode(MUSIC); -// es8388.analogBypass(true); -// uint8_t *reg; -// for (uint8_t i = 0; i < 53; i++) { -// reg = es8388.readAllReg(); -// DEBUGSR_PRINTF("Reg-%02d = 0x%02x\r\n", i, reg[i]); -// } -// } - -// public: -// ES8388Source(int sampleRate, int blockSize, int sdaPin, int sclPin) : -// I2SSource(sampleRate, blockSize) { -// _config.channel_format = I2S_CHANNEL_FMT_ONLY_LEFT; -// pin_ES8388_SDA = sdaPin; -// pin_ES8388_SCL = sclPin; -// DEBUGSR_PRINTF("\nAR: ES8388Source\n"); -// }; - -// void initialize(int8_t i2swsPin, int8_t i2ssdPin, int8_t i2sckPin, int8_t mclkPin, int8_t = I2S_PIN_NO_CHANGE, int8_t = I2S_PIN_NO_CHANGE) { -// DEBUGSR_PRINTF("\nAR: ES8388Source initialize called\n"); -// // Reserve SDA and SCL pins of the I2C interface -// PinManagerPinType pins[2] = { { pin_ES8388_SDA, true }, { pin_ES8388_SCL, true } }; -// if (!pinManager.allocateMultiplePins(pins, 2, PinOwner::HW_I2C)) { -// pinManager.deallocateMultiplePins(pins, 2, PinOwner::HW_I2C); -// ERRORSR_PRINTF("\nAR: Failed to allocate ES8388 I2C pins: SDA=%d, SCL=%d\n", pin_ES8388_SDA, pin_ES8388_SCL); -// return; -// } - -// _es8388InitAdc(); -// // i2s -// // PIN_FUNC_SELECT(PERIPHS_IO_MUX_GPIO0_U, FUNC_GPIO0_CLK_OUT1); -// // WRITE_PERI_REG(PIN_CTRL, 0xFFF0); -// // i2s_set_sample_rates(I2S_NUM_0, 22050); - -// DEBUGSR_PRINTF("\nAR: ES8388Source calling I2SSource::initialize\n"); -// I2SSource::initialize(i2swsPin, i2ssdPin, i2sckPin, mclkPin); -// } - -// void deinitialize() { -// // Release SDA and SCL pins of the I2C interface -// pinManager.deallocatePin(pin_ES8388_SDA, PinOwner::HW_I2C); -// pinManager.deallocatePin(pin_ES8388_SCL, PinOwner::HW_I2C); -// I2SSource::deinitialize(); -// } - -// private: -// int8_t pin_ES8388_SDA; -// int8_t pin_ES8388_SCL; -// ES8388 es8388 = ES8388(18, 23, 400000); -// }; - - - #if ESP_IDF_VERSION >= ESP_IDF_VERSION_VAL(4, 2, 0) #if !defined(SOC_I2S_SUPPORTS_ADC) && !defined(SOC_I2S_SUPPORTS_ADC_DAC) #warning this MCU does not support analog sound input From c38baf90b508d1b78d71549f502b98a82ea84c72 Mon Sep 17 00:00:00 2001 From: TroyHacks <5659019+troyhacks@users.noreply.github.com> Date: Tue, 4 Apr 2023 14:04:02 -0400 Subject: [PATCH 3/5] Removing local lib copy --- lib/ES8388 | 1 - 1 file changed, 1 deletion(-) delete mode 160000 lib/ES8388 diff --git a/lib/ES8388 b/lib/ES8388 deleted file mode 160000 index f589ddfe..00000000 --- a/lib/ES8388 +++ /dev/null @@ -1 +0,0 @@ -Subproject commit f589ddfe7cc27f294e00644dc510e64bff677f0b From a6a1bbabeb5d3a662740dc7d58a478d3727b9200 Mon Sep 17 00:00:00 2001 From: TroyHacks <5659019+troyhacks@users.noreply.github.com> Date: Tue, 4 Apr 2023 14:07:09 -0400 Subject: [PATCH 4/5] Remove platform.ini entry for ES8388 --- platformio.ini | 1 - 1 file changed, 1 deletion(-) diff --git a/platformio.ini b/platformio.ini index 991ac91b..2d5035f0 100644 --- a/platformio.ini +++ b/platformio.ini @@ -587,7 +587,6 @@ build_flags_min = lib_deps_min = https://github.com/kosme/arduinoFFT#develop @ 1.9.2 ; used for USERMOD_AUDIOREACTIVE - https://github.com/netmindz/es8388arduino.git @ 0.0.1 ; used for USERMOD_AUDIOREACTIVE ES8388 source ; monitor_filters = esp32_exception_decoder ; used to show crash details From f44f307f89766416e1f35558ded07a7718adfe3e Mon Sep 17 00:00:00 2001 From: TroyHacks <5659019+troyhacks@users.noreply.github.com> Date: Tue, 4 Apr 2023 17:04:18 -0400 Subject: [PATCH 5/5] Comments and typos, init optimization and shortening. --- usermods/audioreactive/audio_source.h | 93 +++++++++++---------------- 1 file changed, 37 insertions(+), 56 deletions(-) diff --git a/usermods/audioreactive/audio_source.h b/usermods/audioreactive/audio_source.h index a1cd1eda..0d173698 100644 --- a/usermods/audioreactive/audio_source.h +++ b/usermods/audioreactive/audio_source.h @@ -15,7 +15,6 @@ #else #define SRate_t int #endif -// #include "ES8388.h" //#include //#include @@ -485,9 +484,9 @@ public: int8_t pin_ES7243_SCL; }; -/* ES8388 Microphone - This is an I2S microphone that requires ininitialization over - I2C before I2S data can be received +/* ES8388 Sound Modude + This is an I2S sound processing unit that requires ininitialization over + I2C before I2S data can be received. */ class ES8388Source : public I2SSource { private: @@ -504,7 +503,7 @@ class ES8388Source : public I2SSource { Wire.beginTransmission(0x10); #define ES8388_ADDR 0x10 // default address #else - Wire.beginTransmission(ES7243_ADDR); + Wire.beginTransmission(ES8388_ADDR); #endif Wire.write((uint8_t)reg); Wire.write((uint8_t)val); @@ -517,58 +516,40 @@ class ES8388Source : public I2SSource { void _es8388InitAdc() { // This is by no means 100% figured but it's working for line-in // with a little too much noise for my liking... + // https://dl.radxa.com/rock2/docs/hw/ds/ES8388%20user%20Guide.pdf Section 10.1 + // https://docs.google.com/spreadsheets/d/1CN3MvhkcPVESuxKyx1xRYqfUit5hOdsG45St9BCUm-g/edit#gid=0 generally _es8388I2cBegin(); - _es8388I2cWrite(0x08,0x00); - _es8388I2cWrite(0x02,0xff); - _es8388I2cWrite(0x2b,0x80); - _es8388I2cWrite(0x00,0x05); - _es8388I2cWrite(0x01,0x40); - _es8388I2cWrite(0x03,0x00); - _es8388I2cWrite(0x0a,0x50); - _es8388I2cWrite(0x0b,0x80); - _es8388I2cWrite(0x09,0x77); - _es8388I2cWrite(0x0c,0x0c); - _es8388I2cWrite(0x0d,0x02); - _es8388I2cWrite(0x10,0x00); - _es8388I2cWrite(0x11,0x00); - _es8388I2cWrite(0x12,0xea); - _es8388I2cWrite(0x13,0xc0); - _es8388I2cWrite(0x14,0x12); - _es8388I2cWrite(0x15,0x06); - _es8388I2cWrite(0x16,0xc3); - _es8388I2cWrite(0x04,0x3c); - _es8388I2cWrite(0x17,0x18); - _es8388I2cWrite(0x18,0x02); - _es8388I2cWrite(0x19,0x00); - _es8388I2cWrite(0x1a,0x00); - _es8388I2cWrite(0x1b,0x00); - _es8388I2cWrite(0x26,0x09); - _es8388I2cWrite(0x27,0x50); - _es8388I2cWrite(0x28,0x38); - _es8388I2cWrite(0x29,0x38); - _es8388I2cWrite(0x2a,0x50); - _es8388I2cWrite(0x2e,0x00); - _es8388I2cWrite(0x2f,0x00); - _es8388I2cWrite(0x30,0x00); - _es8388I2cWrite(0x31,0x00); - _es8388I2cWrite(0x02,0x00); - _es8388I2cWrite(0x0a,0x50); - _es8388I2cWrite(0x09,0x00); - _es8388I2cWrite(0x04,0x0c); - _es8388I2cWrite(0x30,0x21); - _es8388I2cWrite(0x31,0x21); - _es8388I2cWrite(0x26,0x09); - _es8388I2cWrite(0x27,0x90); - _es8388I2cWrite(0x2a,0x90); - _es8388I2cWrite(0x12,0x38); - _es8388I2cWrite(0x13,0x30); - _es8388I2cWrite(0x14,0x57); - _es8388I2cWrite(0x15,0x06); - _es8388I2cWrite(0x16,0x89); - _es8388I2cWrite(0x26,0x09); - _es8388I2cWrite(0x27,0x50); - _es8388I2cWrite(0x2a,0x50); - _es8388I2cWrite(0x09,0x00); + _es8388I2cWrite(0x08,0x00); // I2S to slave + _es8388I2cWrite(0x02,0xf3); // Power down DEM and STM + _es8388I2cWrite(0x2b,0x80); // Set same LRCK + _es8388I2cWrite(0x00,0x05); // Set chip to Play & Record Mode + _es8388I2cWrite(0x01,0x40); // Power up Analog and lbias ... These 5 (to here) need to be done in order + _es8388I2cWrite(0x03,0x00); // Power up ADC, Analog Input, and Mic Bias + _es8388I2cWrite(0x04,0x3C); // ** In guide, not in working example tho. ** + _es8388I2cWrite(0x0a,0x50); // Use Lin2/Rin2 for ADC input + _es8388I2cWrite(0x09,0x00); // Select Analog Input PGA Gain for ADC to 0dB ** + _es8388I2cWrite(0x0c,0x0c); // I2S format, 24-bit + _es8388I2cWrite(0x0d,0x02); // Set MCLK/LRCK ratio to 256 + _es8388I2cWrite(0x10,0x00); // Set ADC digital volume attenuation to 0dB (left) + _es8388I2cWrite(0x11,0x00); // Set ADC digital volume attenuation to 0dB (right) + _es8388I2cWrite(0x17,0x18); // Set format for DAC (I2S, 24bit) + _es8388I2cWrite(0x18,0x02); // Set DAC MCLK/LRCK ratio to 256 + _es8388I2cWrite(0x1a,0x00); // DAC Volume attenuation 0dB (left) + _es8388I2cWrite(0x1b,0x00); // DAC Volume attenuation 0dB (right) + _es8388I2cWrite(0x2e,0x00); // LOUT1 volume - 00 = -45dB + _es8388I2cWrite(0x2f,0x00); // ROUT1 volume - 00 = -45dB + _es8388I2cWrite(0x0C,0b00000001); // ADC digital format - I2S + Left Justified + _es8388I2cWrite(0x17,0b00000010); // DAC digital format - I2S + Left Justified + _es8388I2cWrite(0x02,0x00); // Power up DEM and STM + // end of guide init ^^^ + _es8388I2cWrite(0x02,0b01000000); // Power. Guide says it's only 6 bits but that 1 means "turn on sometthing for line-out voltage" + _es8388I2cWrite(0x04,0x0c); // LOUT2 an ROUT2 powered + _es8388I2cWrite(0x30,0b00011110); // LOUT2VOL - 0 = -45dB, 0b00011110 = +0dB + _es8388I2cWrite(0x31,0b00011110); // ROUT2VOL - 0 = -45dB, 0b00011110 = +0dB + _es8388I2cWrite(0x26,0x09); // Mixer + _es8388I2cWrite(0x27,0x50); // Mixer + _es8388I2cWrite(0x2a,0x50); // Mixer + _es8388I2cWrite(0x03,0x00); // Power } public: