语音对话
This commit is contained in:
@@ -22,6 +22,9 @@
|
||||
#endif
|
||||
|
||||
static const char *TAG = "voice_audio";
|
||||
static const uint32_t VOICE_CODEC_I2C_PROBE_TIMEOUT_MS = 50;
|
||||
|
||||
#define ES8311_CODEC_ALT_ADDR ((uint8_t)(ES8311_CODEC_DEFAULT_ADDR + 0x02))
|
||||
|
||||
#ifdef CONFIG_TQ_VOICE_CODEC_PA_PIN_REVERSED
|
||||
#define VOICE_CODEC_PA_REVERSED true
|
||||
@@ -56,6 +59,66 @@ static void fill_err(char *err, size_t err_len, const char *msg) {
|
||||
}
|
||||
}
|
||||
|
||||
static bool voice_audio_i2c_probe_addr(uint8_t addr_8bit) {
|
||||
#ifdef VOICE_USE_IDF_I2C_MASTER
|
||||
if (s_i2c_bus == NULL || addr_8bit == 0) {
|
||||
return false;
|
||||
}
|
||||
uint16_t addr_7bit = (uint16_t)(addr_8bit >> 1);
|
||||
return i2c_master_probe(s_i2c_bus, addr_7bit, (int)VOICE_CODEC_I2C_PROBE_TIMEOUT_MS) == ESP_OK;
|
||||
#else
|
||||
if (addr_8bit == 0) {
|
||||
return false;
|
||||
}
|
||||
|
||||
i2c_cmd_handle_t cmd = i2c_cmd_link_create();
|
||||
if (cmd == NULL) {
|
||||
return false;
|
||||
}
|
||||
|
||||
i2c_master_start(cmd);
|
||||
i2c_master_write_byte(cmd, addr_8bit, true);
|
||||
i2c_master_stop(cmd);
|
||||
|
||||
esp_err_t err = i2c_master_cmd_begin(CONFIG_TQ_VOICE_I2C_PORT,
|
||||
cmd,
|
||||
pdMS_TO_TICKS(VOICE_CODEC_I2C_PROBE_TIMEOUT_MS));
|
||||
i2c_cmd_link_delete(cmd);
|
||||
return err == ESP_OK;
|
||||
#endif
|
||||
}
|
||||
|
||||
static uint8_t voice_audio_resolve_codec_addr(uint8_t preferred_addr) {
|
||||
uint8_t candidates[3] = {preferred_addr, ES8311_CODEC_DEFAULT_ADDR, ES8311_CODEC_ALT_ADDR};
|
||||
for (size_t i = 0; i < 3; ++i) {
|
||||
uint8_t addr = candidates[i];
|
||||
bool duplicate = false;
|
||||
for (size_t j = 0; j < i; ++j) {
|
||||
if (candidates[j] == addr) {
|
||||
duplicate = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (duplicate) {
|
||||
continue;
|
||||
}
|
||||
|
||||
if (voice_audio_i2c_probe_addr(addr)) {
|
||||
return addr;
|
||||
}
|
||||
}
|
||||
|
||||
ESP_LOGW(TAG,
|
||||
"ES8311 not found on I2C(port=%d,sda=%d,scl=%d), tried addrs:0x%02x/0x%02x/0x%02x",
|
||||
CONFIG_TQ_VOICE_I2C_PORT,
|
||||
CONFIG_TQ_VOICE_I2C_SDA_PIN,
|
||||
CONFIG_TQ_VOICE_I2C_SCL_PIN,
|
||||
(unsigned)preferred_addr,
|
||||
(unsigned)ES8311_CODEC_DEFAULT_ADDR,
|
||||
(unsigned)ES8311_CODEC_ALT_ADDR);
|
||||
return preferred_addr;
|
||||
}
|
||||
|
||||
static esp_err_t voice_audio_init_i2c(void) {
|
||||
#ifdef VOICE_USE_IDF_I2C_MASTER
|
||||
if (s_i2c_bus != NULL) {
|
||||
@@ -71,7 +134,15 @@ static esp_err_t voice_audio_init_i2c(void) {
|
||||
.flags.enable_internal_pullup = true,
|
||||
};
|
||||
|
||||
return i2c_new_master_bus(&bus_cfg, &s_i2c_bus);
|
||||
esp_err_t err = i2c_new_master_bus(&bus_cfg, &s_i2c_bus);
|
||||
if (err == ESP_OK) {
|
||||
ESP_LOGI(TAG,
|
||||
"voice i2c ready: port=%d sda=%d scl=%d",
|
||||
CONFIG_TQ_VOICE_I2C_PORT,
|
||||
CONFIG_TQ_VOICE_I2C_SDA_PIN,
|
||||
CONFIG_TQ_VOICE_I2C_SCL_PIN);
|
||||
}
|
||||
return err;
|
||||
#else
|
||||
i2c_config_t i2c_cfg = {
|
||||
.mode = I2C_MODE_MASTER,
|
||||
@@ -83,7 +154,15 @@ static esp_err_t voice_audio_init_i2c(void) {
|
||||
};
|
||||
|
||||
ESP_RETURN_ON_ERROR(i2c_param_config(CONFIG_TQ_VOICE_I2C_PORT, &i2c_cfg), TAG, "i2c_param_config failed");
|
||||
return i2c_driver_install(CONFIG_TQ_VOICE_I2C_PORT, i2c_cfg.mode, 0, 0, 0);
|
||||
esp_err_t err = i2c_driver_install(CONFIG_TQ_VOICE_I2C_PORT, i2c_cfg.mode, 0, 0, 0);
|
||||
if (err == ESP_OK) {
|
||||
ESP_LOGI(TAG,
|
||||
"voice i2c ready: port=%d sda=%d scl=%d",
|
||||
CONFIG_TQ_VOICE_I2C_PORT,
|
||||
CONFIG_TQ_VOICE_I2C_SDA_PIN,
|
||||
CONFIG_TQ_VOICE_I2C_SCL_PIN);
|
||||
}
|
||||
return err;
|
||||
#endif
|
||||
}
|
||||
|
||||
@@ -136,9 +215,27 @@ static esp_err_t voice_audio_build_codec_dev(void) {
|
||||
return ESP_OK;
|
||||
}
|
||||
|
||||
uint8_t codec_addr = voice_audio_resolve_codec_addr((uint8_t)CONFIG_TQ_VOICE_CODEC_ADDR);
|
||||
if (codec_addr != (uint8_t)CONFIG_TQ_VOICE_CODEC_ADDR) {
|
||||
ESP_LOGW(TAG,
|
||||
"override ES8311 I2C addr 0x%02x -> 0x%02x",
|
||||
(unsigned)CONFIG_TQ_VOICE_CODEC_ADDR,
|
||||
(unsigned)codec_addr);
|
||||
}
|
||||
ESP_LOGI(TAG,
|
||||
"voice codec cfg: i2c_port=%d addr=0x%02x i2s_port=%d mclk=%d bclk=%d ws=%d dout=%d din=%d",
|
||||
CONFIG_TQ_VOICE_I2C_PORT,
|
||||
(unsigned)codec_addr,
|
||||
CONFIG_TQ_VOICE_I2S_PORT,
|
||||
CONFIG_TQ_VOICE_I2S_MCLK_PIN,
|
||||
CONFIG_TQ_VOICE_I2S_BCLK_PIN,
|
||||
CONFIG_TQ_VOICE_I2S_WS_PIN,
|
||||
CONFIG_TQ_VOICE_I2S_DOUT_PIN,
|
||||
CONFIG_TQ_VOICE_I2S_DIN_PIN);
|
||||
|
||||
audio_codec_i2c_cfg_t i2c_cfg = {
|
||||
.port = (uint8_t)CONFIG_TQ_VOICE_I2C_PORT,
|
||||
.addr = (uint8_t)CONFIG_TQ_VOICE_CODEC_ADDR,
|
||||
.addr = codec_addr,
|
||||
#ifdef VOICE_USE_IDF_I2C_MASTER
|
||||
.bus_handle = s_i2c_bus,
|
||||
#endif
|
||||
@@ -180,7 +277,8 @@ static esp_err_t voice_audio_build_codec_dev(void) {
|
||||
|
||||
s_codec_if = es8311_codec_new(&codec_cfg);
|
||||
if (s_codec_if == NULL) {
|
||||
return ESP_ERR_NO_MEM;
|
||||
ESP_LOGE(TAG, "es8311_codec_new failed, check I2C wiring/pull-up/address");
|
||||
return ESP_FAIL;
|
||||
}
|
||||
|
||||
esp_codec_dev_cfg_t dev_cfg = {
|
||||
@@ -230,7 +328,11 @@ esp_err_t voice_audio_open(const voice_audio_open_config_t *cfg, char *err, size
|
||||
|
||||
esp_err_t init_err = voice_audio_prepare(cfg);
|
||||
if (init_err != ESP_OK) {
|
||||
fill_err(err, err_len, "voice audio peripheral init failed");
|
||||
if (init_err == ESP_FAIL) {
|
||||
fill_err(err, err_len, "es8311 init failed, check i2c wiring/address");
|
||||
} else {
|
||||
fill_err(err, err_len, "voice audio peripheral init failed");
|
||||
}
|
||||
xSemaphoreGive(s_lock);
|
||||
return init_err;
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user