void i2s_init(void)
{
i2s_chan_config_t chan_cfg = I2S_CHANNEL_DEFAULT_CONFIG(I2S_PORT, I2S_ROLE_MASTER);
chan_cfg.dma_desc_num = i2s_dma_setting.count;
chan_cfg.dma_frame_num = i2s_dma_setting.frame_size;
chan_cfg.intr_priority = i2s_dma_setting.intr_priority;
chan_cfg.auto_clear_after_cb = true;
//chan_cfg.auto_clear = true;
//chan_cfg.queue_size = 8;
ESP_ERROR_CHECK(i2s_new_channel(&chan_cfg, &tx_handle, NULL));
i2s_std_config_t std_cfg = {
.clk_cfg = I2S_STD_CLK_DEFAULT_CONFIG(uac_as_quality.sample_rate),
.slot_cfg = I2S_STD_PHILIPS_SLOT_DEFAULT_CONFIG(I2S_DATA_BIT_WIDTH_16BIT, I2S_SLOT_MODE_STEREO),
.gpio_cfg = {
.mclk = PIN_MCK,
.bclk = PIN_BCK,
.ws = PIN_LRCK,
.dout = PIN_DOUT,
.din = I2S_GPIO_UNUSED,
.invert_flags = {
.mclk_inv = false,
.bclk_inv = false,
.ws_inv = false,
},
},
};
if (uac_as_quality.resolution_bits == 24) {
std_cfg.slot_cfg.data_bit_width = I2S_DATA_BIT_WIDTH_24BIT;
} else if (uac_as_quality.resolution_bits == 32) {
std_cfg.slot_cfg.data_bit_width = I2S_DATA_BIT_WIDTH_32BIT;
}
std_cfg.slot_cfg.ws_width = I2S_SLOT_BIT_WIDTH_32BIT;
std_cfg.slot_cfg.slot_bit_width = I2S_SLOT_BIT_WIDTH_32BIT;
if (std_cfg.slot_cfg.slot_bit_width == I2S_SLOT_BIT_WIDTH_24BIT) {
if (uac_as_quality.sample_rate > 96000)
std_cfg.clk_cfg.mclk_multiple = I2S_MCLK_MULTIPLE_192;
else
std_cfg.clk_cfg.mclk_multiple = I2S_MCLK_MULTIPLE_384;
}
ESP_LOGI(TAG, "i2s slotcfg data=%d, ws=%d, slot=%d, mode=%d"
, std_cfg.slot_cfg.data_bit_width, std_cfg.slot_cfg.ws_width, std_cfg.slot_cfg.slot_bit_width, std_cfg.slot_cfg.slot_mode);
g_clk.src_clk = std_cfg.clk_cfg.clk_src == I2S_CLK_SRC_PLL_160M?SRC_CLK_160MHZ:SRC_CLK_40MHZ;
g_cnt_ideal.src = g_clk.src_clk;
g_cnt_ideal.mclk_multiple = std_cfg.clk_cfg.mclk_multiple;
g_cnt_ideal.mclk = g_cnt_ideal.mclk_multiple * std_cfg.clk_cfg.sample_rate_hz;
g_cnt_ideal.bclk = std_cfg.clk_cfg.sample_rate_hz * std_cfg.slot_cfg.slot_bit_width * std_cfg.slot_cfg.slot_mode;
g_cnt_ideal.bclk_divn = g_cnt_ideal.mclk / g_cnt_ideal.bclk;
g_cnt_ideal.bclk_divi = g_cnt_ideal.mclk % g_cnt_ideal.bclk;
g_cnt_ideal.pcnt_fs = std_cfg.clk_cfg.sample_rate_hz;
g_cnt_ideal.pcnt_warmup = 0;
g_cnt_ideal.pcnt_fs_max = g_cnt_ideal.pcnt_fs * FEEDBACK_AVAILABLE_RANGE;
g_cnt_ideal.pcnt_fs_min = g_cnt_ideal.pcnt_fs / FEEDBACK_AVAILABLE_RANGE;
g_cnt_ideal.pcnt_fs_factor = 1000.0f / (float)g_cnt_ideal.mclk_multiple;
std_cfg.clk_cfg.bclk_div = g_cnt_ideal.bclk_divn;
ESP_LOGI(TAG, "i2s request mclk=%d, mclk_multi=%d blck=%d, blck_div=%d.%d"
, g_cnt_ideal.mclk, g_cnt_ideal.mclk_multiple, g_cnt_ideal.bclk, g_cnt_ideal.bclk_divn, g_cnt_ideal.bclk_divi);
ESP_ERROR_CHECK(i2s_channel_init_std_mode(tx_handle, &std_cfg));
#ifdef I2S_PIN_DRIVE_CAP
gpio_set_drive_capability(PIN_MCK, I2S_PIN_DRIVE_CAP);
gpio_set_drive_capability(PIN_BCK, I2S_PIN_DRIVE_CAP);
gpio_set_drive_capability(PIN_LRCK, I2S_PIN_DRIVE_CAP);
gpio_set_drive_capability(PIN_DOUT, I2S_PIN_DRIVE_CAP);
#endif
i2s_current_clock(I2S_PORT, &g_clk);
ESP_LOGI(TAG, "i2s(1) sel=%d src=%d mlck=%.2f num=%d x=%d y=%d z=%d yn1=%d"
, g_clk.clk_sel, g_clk.src_clk, g_clk.mclk, g_clk.div_num, g_clk.div_x, g_clk.div_y, g_clk.div_z, g_clk.div_yn1);
ESP_LOGI(TAG, "i2s(1) en=%d, act=%d bits=%d bck_div=%d"
, g_clk.clk_enable, g_clk.clk_active, g_clk.bits_mod, g_clk.bck_div);
ESP_LOGI(TAG, "i2s(1) latency %dus/1ms", CALC_US_LATENCY(g_cnt_ideal.mclk, g_clk.mclk));
if (fabs(g_clk.mclk-(double)g_cnt_ideal.mclk) > 1000) {
clock_info_t cur_clk = g_clk;
for (int i=100; i<256; i ) {
clock_info_t tmp_clk = cur_clk;
if (i2s_scan_div(g_clk.src_clk, g_cnt_ideal.mclk, round(g_clk.src_clk/g_cnt_ideal.mclk), i, &tmp_clk)) {
if (fabs((double)g_cnt_ideal.mclk - tmp_clk.mclk) < fabs((double)g_cnt_ideal.mclk - cur_clk.mclk)) {
cur_clk = tmp_clk;
}
}
}
ESP_LOGI(TAG, "i2s(2) sel=%d src=%d mlck=%.2f num=%d x=%d y=%d z=%d, yn1=%d"
, cur_clk.clk_sel, cur_clk.src_clk, cur_clk.mclk, cur_clk.div_num, cur_clk.div_x, cur_clk.div_y, cur_clk.div_z, cur_clk.div_yn1);
ESP_LOGI(TAG, "i2s(2) en=%d, act=%d bits=%d bck_div=%d"
, cur_clk.clk_enable, cur_clk.clk_active, cur_clk.bits_mod, cur_clk.bck_div);
ESP_LOGI(TAG, "i2s(2) latency %dus/1ms", CALC_US_LATENCY(g_cnt_ideal.mclk, cur_clk.mclk));
i2s_set_clock_div(I2S_PORT, &cur_clk);
i2s_current_clock(I2S_PORT, &g_clk);
ESP_LOGI(TAG, "i2s(3) sel=%d src=%d mlck=%.2f num=%d x=%d y=%d z=%d, yn1=%d"
, g_clk.clk_sel, g_clk.src_clk, g_clk.mclk, g_clk.div_num, g_clk.div_x, g_clk.div_y, g_clk.div_z, g_clk.div_yn1);
ESP_LOGI(TAG, "i2s(3) en=%d, act=%d bits=%d bck_div=%d"
, g_clk.clk_enable, g_clk.clk_active, g_clk.bits_mod, g_clk.bck_div);
ESP_LOGI(TAG, "i2s(3) latency %dus/1ms", CALC_US_LATENCY(g_cnt_ideal.mclk, g_clk.mclk));
}
if (uac_as_quality.resolution_bits == 32) {
g_data_functions.pSRC = linearSRC32;
g_data_functions.padjustVolume = adjust_volume32;
g_data_functions.pcalcRms = calc_rms32;
} else if (uac_as_quality.resolution_bits == 24) {
g_data_functions.pSRC = linearSRC24;
g_data_functions.padjustVolume = adjust_volume24;
g_data_functions.pcalcRms = calc_rms24;
} else {
g_data_functions.pSRC = linearSRC16;
g_data_functions.padjustVolume = adjust_volume16;
g_data_functions.pcalcRms = calc_rms16;
}
}