diff --git a/src/AudioOutputI2S.cpp b/src/AudioOutputI2S.cpp index c4e0c3aa..9cdab0e7 100644 --- a/src/AudioOutputI2S.cpp +++ b/src/AudioOutputI2S.cpp @@ -29,7 +29,7 @@ #include "AudioOutputI2S.h" #if defined(ESP32) || defined(ESP8266) -AudioOutputI2S::AudioOutputI2S(int port, int output_mode, int dma_buf_count, int use_apll) +AudioOutputI2S::AudioOutputI2S(int port, int output_mode, int dma_buf_count, int use_apll, uint8_t mult, uint32_t freq) { this->portNo = port; this->i2sOn = false; @@ -49,6 +49,8 @@ AudioOutputI2S::AudioOutputI2S(int port, int output_mode, int dma_buf_count, int bclkPin = 26; wclkPin = 25; doutPin = 22; + mcmult = mult; + mclk_freq = freq; SetGain(1.0); } @@ -88,11 +90,12 @@ bool AudioOutputI2S::SetPinout() return false; // Not allowed i2s_pin_config_t pins = { - .mck_io_num = 0, // Unused + .mck_io_num = mclkPin, .bck_io_num = bclkPin, .ws_io_num = wclkPin, .data_out_num = doutPin, - .data_in_num = I2S_PIN_NO_CHANGE}; + .data_in_num = dinPin}; + i2s_set_pin((i2s_port_t)portNo, &pins); return true; #else @@ -103,11 +106,14 @@ bool AudioOutputI2S::SetPinout() #endif } -bool AudioOutputI2S::SetPinout(int bclk, int wclk, int dout) +bool AudioOutputI2S::SetPinout(int bclk, int wclk, int dout, int mclk, int din) { bclkPin = bclk; wclkPin = wclk; doutPin = dout; + mclkPin = mclk; + dinPin = din; + if (i2sOn) return SetPinout(); @@ -216,6 +222,14 @@ bool AudioOutputI2S::begin(bool txDAC) comm_fmt = (i2s_comm_format_t) (I2S_COMM_FORMAT_I2S | I2S_COMM_FORMAT_I2S_MSB); #endif } + + if (mclkPin != I2S_PIN_NO_CHANGE) { + use_apll = false; + } + + if (dinPin != I2S_PIN_NO_CHANGE) { + mode = (i2s_mode_t) (I2S_MODE_MASTER | I2S_MODE_TX | I2S_MODE_RX); + } i2s_config_t i2s_config_dac = { .mode = mode, @@ -228,8 +242,10 @@ bool AudioOutputI2S::begin(bool txDAC) .dma_buf_len = 128, .use_apll = use_apll, // Use audio PLL .tx_desc_auto_clear = true, // Silence on underflow - .fixed_mclk = 0, // Unused - .mclk_multiple = I2S_MCLK_MULTIPLE_DEFAULT, // Unused +#ifdef ESP32 + .fixed_mclk = (int)mclk_freq, + .mclk_multiple = (i2s_mclk_multiple_t)mcmult, +#endif .bits_per_chan = I2S_BITS_PER_CHAN_DEFAULT // Use bits per sample }; audioLogger->printf("+%d %p\n", portNo, &i2s_config_dac); diff --git a/src/AudioOutputI2S.h b/src/AudioOutputI2S.h index 33e784bd..890cd7d8 100644 --- a/src/AudioOutputI2S.h +++ b/src/AudioOutputI2S.h @@ -27,17 +27,21 @@ #include #endif +#ifdef ESP8266 +#define I2S_MCLK_MULTIPLE_DEFAULT 0 +#endif + class AudioOutputI2S : public AudioOutput { public: #if defined(ESP32) || defined(ESP8266) - AudioOutputI2S(int port=0, int output_mode=EXTERNAL_I2S, int dma_buf_count = 8, int use_apll=APLL_DISABLE); + AudioOutputI2S(int port=0, int output_mode=EXTERNAL_I2S, int dma_buf_count = 8, int use_apll=APLL_DISABLE, uint8_t mult=I2S_MCLK_MULTIPLE_DEFAULT, uint32_t freq=0); enum : int { APLL_AUTO = -1, APLL_ENABLE = 1, APLL_DISABLE = 0 }; enum : int { EXTERNAL_I2S = 0, INTERNAL_DAC = 1, INTERNAL_PDM = 2 }; #elif defined(ARDUINO_ARCH_RP2040) AudioOutputI2S(long sampleRate = 44100, pin_size_t sck = 26, pin_size_t data = 28); #endif - bool SetPinout(int bclkPin, int wclkPin, int doutPin); + bool SetPinout(int bclkPin, int wclkPin, int doutPin, int mclk = I2S_PIN_NO_CHANGE, int din = I2S_PIN_NO_CHANGE); virtual ~AudioOutputI2S() override; virtual bool SetRate(int hz) override; virtual bool SetBitsPerSample(int bits) override; @@ -68,7 +72,11 @@ class AudioOutputI2S : public AudioOutput uint8_t bclkPin; uint8_t wclkPin; uint8_t doutPin; - + int8_t dinPin; + int8_t mclkPin; + uint8_t mcmult; + uint32_t mclk_freq; + #if defined(ARDUINO_ARCH_RP2040) I2S i2s; #endif