|
|
@ -38,7 +38,7 @@ auto AudioDac::create(GpioExpander* expander) |
|
|
|
channel_config.dma_frame_num = 1024; |
|
|
|
channel_config.dma_frame_num = 1024; |
|
|
|
// Triple buffering should be enough to keep samples flowing smoothly.
|
|
|
|
// Triple buffering should be enough to keep samples flowing smoothly.
|
|
|
|
// TODO(jacqueline): verify this with 192kHz 32bps.
|
|
|
|
// TODO(jacqueline): verify this with 192kHz 32bps.
|
|
|
|
channel_config.dma_desc_num = 8; |
|
|
|
channel_config.dma_desc_num = 4; |
|
|
|
// channel_config.auto_clear = true;
|
|
|
|
// channel_config.auto_clear = true;
|
|
|
|
|
|
|
|
|
|
|
|
ESP_ERROR_CHECK(i2s_new_channel(&channel_config, &i2s_handle, NULL)); |
|
|
|
ESP_ERROR_CHECK(i2s_new_channel(&channel_config, &i2s_handle, NULL)); |
|
|
@ -53,7 +53,7 @@ auto AudioDac::create(GpioExpander* expander) |
|
|
|
i2s_std_config_t i2s_config = { |
|
|
|
i2s_std_config_t i2s_config = { |
|
|
|
.clk_cfg = dac->clock_config_, |
|
|
|
.clk_cfg = dac->clock_config_, |
|
|
|
.slot_cfg = dac->slot_config_, |
|
|
|
.slot_cfg = dac->slot_config_, |
|
|
|
.gpio_cfg = {.mclk = I2S_GPIO_UNUSED, |
|
|
|
.gpio_cfg = {.mclk = GPIO_NUM_0, |
|
|
|
.bclk = GPIO_NUM_26, |
|
|
|
.bclk = GPIO_NUM_26, |
|
|
|
.ws = GPIO_NUM_27, |
|
|
|
.ws = GPIO_NUM_27, |
|
|
|
.dout = GPIO_NUM_5, |
|
|
|
.dout = GPIO_NUM_5, |
|
|
@ -167,6 +167,8 @@ bool AudioDac::WaitForPowerState( |
|
|
|
|
|
|
|
|
|
|
|
auto AudioDac::Reconfigure(BitsPerSample bps, SampleRate rate) -> void { |
|
|
|
auto AudioDac::Reconfigure(BitsPerSample bps, SampleRate rate) -> void { |
|
|
|
if (i2s_active_) { |
|
|
|
if (i2s_active_) { |
|
|
|
|
|
|
|
WriteRegister(pcm512x::MUTE, 0b10001); |
|
|
|
|
|
|
|
vTaskDelay(1); |
|
|
|
WriteRegister(pcm512x::POWER, 1 << 4); |
|
|
|
WriteRegister(pcm512x::POWER, 1 << 4); |
|
|
|
i2s_channel_disable(i2s_handle_); |
|
|
|
i2s_channel_disable(i2s_handle_); |
|
|
|
} |
|
|
|
} |
|
|
@ -198,10 +200,10 @@ auto AudioDac::Reconfigure(BitsPerSample bps, SampleRate rate) -> void { |
|
|
|
ESP_ERROR_CHECK(i2s_channel_reconfig_std_clock(i2s_handle_, &clock_config_)); |
|
|
|
ESP_ERROR_CHECK(i2s_channel_reconfig_std_clock(i2s_handle_, &clock_config_)); |
|
|
|
|
|
|
|
|
|
|
|
// DAC reconfiguration.
|
|
|
|
// DAC reconfiguration.
|
|
|
|
//See here : https://e2e.ti.com/support/data_converters/audio_converters/f/64/t/428281
|
|
|
|
// Inspired heavily by https://github.com/tommag/PCM51xx_Arduino (MIT).
|
|
|
|
// for a config example
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
// Check that the bit clock (PLL input) is between 1MHz and 50MHz
|
|
|
|
// Check that the bit clock (PLL input) is between 1MHz and 50MHz. It always
|
|
|
|
|
|
|
|
// should be.
|
|
|
|
uint32_t bckFreq = rate * bps * 2; |
|
|
|
uint32_t bckFreq = rate * bps * 2; |
|
|
|
if (bckFreq < 1000000 || bckFreq > 50000000) { |
|
|
|
if (bckFreq < 1000000 || bckFreq > 50000000) { |
|
|
|
ESP_LOGE(kTag, "bck freq out of range"); |
|
|
|
ESP_LOGE(kTag, "bck freq out of range"); |
|
|
@ -210,15 +212,19 @@ auto AudioDac::Reconfigure(BitsPerSample bps, SampleRate rate) -> void { |
|
|
|
|
|
|
|
|
|
|
|
// 24 bits is not supported for 44.1kHz and 48kHz.
|
|
|
|
// 24 bits is not supported for 44.1kHz and 48kHz.
|
|
|
|
if ((rate == SAMPLE_RATE_44_1 || rate == SAMPLE_RATE_48) && bps == BPS_24) { |
|
|
|
if ((rate == SAMPLE_RATE_44_1 || rate == SAMPLE_RATE_48) && bps == BPS_24) { |
|
|
|
// TODO(jacqueline): implement
|
|
|
|
// TODO(jacqueline): I think this *can* be implemented, but requires a bunch
|
|
|
|
|
|
|
|
// of maths.
|
|
|
|
ESP_LOGE(kTag, "sample rate and bps mismatch"); |
|
|
|
ESP_LOGE(kTag, "sample rate and bps mismatch"); |
|
|
|
return; |
|
|
|
return; |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
// Initialize system clock from the I2S BCK input
|
|
|
|
// Initialize system clock from the I2S BCK input
|
|
|
|
WriteRegister(pcm512x::ERROR_DETECT, 0x1A); // Disable clock autoset and ignore SCK detection
|
|
|
|
// Disable clock autoset and ignore SCK detection
|
|
|
|
WriteRegister(pcm512x::PLL_REF, 0x10); // Set PLL clock source to BCK
|
|
|
|
WriteRegister(pcm512x::ERROR_DETECT, 0x1A); |
|
|
|
WriteRegister(pcm512x::DAC_REF, 0x10); // Set DAC clock source to PLL output
|
|
|
|
// Set PLL clock source to BCK
|
|
|
|
|
|
|
|
WriteRegister(pcm512x::PLL_REF, 0x10); |
|
|
|
|
|
|
|
// Set DAC clock source to PLL output
|
|
|
|
|
|
|
|
WriteRegister(pcm512x::DAC_REF, 0x10); |
|
|
|
|
|
|
|
|
|
|
|
// PLL configuration
|
|
|
|
// PLL configuration
|
|
|
|
int p, j, d, r; |
|
|
|
int p, j, d, r; |
|
|
@ -226,8 +232,8 @@ auto AudioDac::Reconfigure(BitsPerSample bps, SampleRate rate) -> void { |
|
|
|
// Clock dividers
|
|
|
|
// Clock dividers
|
|
|
|
int nmac, ndac, ncp, dosr, idac; |
|
|
|
int nmac, ndac, ncp, dosr, idac; |
|
|
|
|
|
|
|
|
|
|
|
if (rate == SAMPLE_RATE_11_025 || rate == SAMPLE_RATE_22_05 || rate == SAMPLE_RATE_44_1) |
|
|
|
if (rate == SAMPLE_RATE_11_025 || rate == SAMPLE_RATE_22_05 || |
|
|
|
{ |
|
|
|
rate == SAMPLE_RATE_44_1) { |
|
|
|
// 44.1kHz and derivatives.
|
|
|
|
// 44.1kHz and derivatives.
|
|
|
|
// P = 1, R = 2, D = 0 for all supported combinations.
|
|
|
|
// P = 1, R = 2, D = 0 for all supported combinations.
|
|
|
|
// Set J to have PLL clk = 90.3168 MHz
|
|
|
|
// Set J to have PLL clk = 90.3168 MHz
|
|
|
@ -242,9 +248,7 @@ auto AudioDac::Reconfigure(BitsPerSample bps, SampleRate rate) -> void { |
|
|
|
ncp = 4; |
|
|
|
ncp = 4; |
|
|
|
dosr = 8; |
|
|
|
dosr = 8; |
|
|
|
idac = 1024; // DSP clock / sample rate
|
|
|
|
idac = 1024; // DSP clock / sample rate
|
|
|
|
} |
|
|
|
} else { |
|
|
|
else |
|
|
|
|
|
|
|
{ |
|
|
|
|
|
|
|
// 8kHz and multiples.
|
|
|
|
// 8kHz and multiples.
|
|
|
|
// PLL config for a 98.304 MHz PLL clk
|
|
|
|
// PLL config for a 98.304 MHz PLL clk
|
|
|
|
if (bps == BPS_24 && bckFreq > 1536000) { |
|
|
|
if (bps == BPS_24 && bckFreq > 1536000) { |
|
|
@ -261,9 +265,15 @@ auto AudioDac::Reconfigure(BitsPerSample bps, SampleRate rate) -> void { |
|
|
|
|
|
|
|
|
|
|
|
// Derive clocks from the 98.304MHz PLL
|
|
|
|
// Derive clocks from the 98.304MHz PLL
|
|
|
|
switch (rate) { |
|
|
|
switch (rate) { |
|
|
|
case SAMPLE_RATE_16: nmac = 6; break; |
|
|
|
case SAMPLE_RATE_16: |
|
|
|
case SAMPLE_RATE_32: nmac = 3; break; |
|
|
|
nmac = 6; |
|
|
|
default: nmac = 2; break; |
|
|
|
break; |
|
|
|
|
|
|
|
case SAMPLE_RATE_32: |
|
|
|
|
|
|
|
nmac = 3; |
|
|
|
|
|
|
|
break; |
|
|
|
|
|
|
|
default: |
|
|
|
|
|
|
|
nmac = 2; |
|
|
|
|
|
|
|
break; |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
ndac = 16; |
|
|
|
ndac = 16; |
|
|
@ -272,7 +282,6 @@ auto AudioDac::Reconfigure(BitsPerSample bps, SampleRate rate) -> void { |
|
|
|
idac = 98304000 / nmac / rate; // DSP clock / sample rate
|
|
|
|
idac = 98304000 / nmac / rate; // DSP clock / sample rate
|
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
// Configure PLL
|
|
|
|
// Configure PLL
|
|
|
|
WriteRegister(pcm512x::PLL_COEFF_0, p - 1); |
|
|
|
WriteRegister(pcm512x::PLL_COEFF_0, p - 1); |
|
|
|
WriteRegister(pcm512x::PLL_COEFF_1, j); |
|
|
|
WriteRegister(pcm512x::PLL_COEFF_1, j); |
|
|
@ -311,6 +320,11 @@ auto AudioDac::Reconfigure(BitsPerSample bps, SampleRate rate) -> void { |
|
|
|
// shut itself down.
|
|
|
|
// shut itself down.
|
|
|
|
ESP_ERROR_CHECK(i2s_channel_enable(i2s_handle_)); |
|
|
|
ESP_ERROR_CHECK(i2s_channel_enable(i2s_handle_)); |
|
|
|
WriteRegister(pcm512x::POWER, 0); |
|
|
|
WriteRegister(pcm512x::POWER, 0); |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
if (i2s_active_) { |
|
|
|
|
|
|
|
vTaskDelay(1); |
|
|
|
|
|
|
|
WriteRegister(pcm512x::MUTE, 0); |
|
|
|
|
|
|
|
} |
|
|
|
i2s_active_ = true; |
|
|
|
i2s_active_ = true; |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|