I have an external DAC, namely a CS4344, that needs a MCLK that is 256x LRCK. Documentation states "there is no required phase relationship, but MCLK, LRCK and SCLK must be synchronous".
There are some threads here touching the subject:
https://esp32.com/viewtopic.php?t=1585
https://esp32.com/viewtopic.php?t=1521
https://esp32.com/viewtopic.php?t=1068
https://esp32.com/viewtopic.php?t=923
but none of them give any concrete answers on how to generate a MCLK for the DAC.
I'm using the example from https://github.com/espressif/esp-idf/tr ... herals/i2s and that one togheter with generating a clock using the LEDC driver, I get a tone but with a lot of extra noise and clicks, probably because the clock is not syncronized.
There are some documentation hinting that the I2S CLK can be muxed out on a GPIO to drive MCLK, but I'm unsure how to configure the PIN CTRL, and I can't find anywhere what this frequency will be.
I found that one can configure GPIO1/UOTXD to be CLK_OUT3:
PIN_FUNC_SELECT(PERIPHS_IO_MUX_U0TXD_U, FUNC_U0TXD_CLK_OUT3);
but I don't know how to configure I2S CLK to use CLK_OUT3 as output, nor to control the frequency.
This is what I use to generate the clock:
Code: Select all
static void enable_out_clock() {
periph_module_enable(PERIPH_LEDC_MODULE);
ledc_timer_bit_t bit_num = (ledc_timer_bit_t) 2; // 3 normally
int duty = pow(2, (int) bit_num) / 2;
ledc_timer_config_t timer_conf;
timer_conf.bit_num = bit_num;
timer_conf.freq_hz = 12288000; //12288000; //8192000; // 22579200
timer_conf.speed_mode = LEDC_HIGH_SPEED_MODE;
timer_conf.timer_num = LEDC_TIMER_0;
esp_err_t err = ledc_timer_config(&timer_conf);
if (err != ESP_OK) {
//ESP_LOGE(TAG, "ledc_timer_config failed, rc=%x", err);
}
ledc_channel_config_t ch_conf;
ch_conf.channel = LEDC_CHANNEL_0;
ch_conf.timer_sel = LEDC_TIMER_0;
ch_conf.intr_type = LEDC_INTR_DISABLE;
ch_conf.duty = duty;
ch_conf.speed_mode = LEDC_HIGH_SPEED_MODE;
ch_conf.gpio_num = MCLK_GPIO; //s_config.pin_xclk;
err = ledc_channel_config(&ch_conf);
if (err != ESP_OK) {
//ESP_LOGE(TAG, "ledc_channel_config failed, rc=%x", err);
}
// Set the PWM to the duty specified
ledc_set_duty(LEDC_HIGH_SPEED_MODE, LEDC_CHANNEL_0, duty);
ledc_update_duty(LEDC_HIGH_SPEED_MODE, LEDC_CHANNEL_0);
}