diff --git a/main/boards/esp-hi/adc_pdm_audio_codec.cc b/main/boards/esp-hi/adc_pdm_audio_codec.cc index 3487bf94..db5d8e17 100644 --- a/main/boards/esp-hi/adc_pdm_audio_codec.cc +++ b/main/boards/esp-hi/adc_pdm_audio_codec.cc @@ -1,6 +1,7 @@ #include "adc_pdm_audio_codec.h" #include +#include #include #include #include @@ -11,6 +12,7 @@ #include "hal/rtc_io_hal.h" #include "hal/gpio_ll.h" #include "settings.h" +#include "config.h" static const char TAG[] = "AdcPdmAudioCodec"; @@ -71,7 +73,7 @@ AdcPdmAudioCodec::AdcPdmAudioCodec(int input_sample_rate, int output_sample_rate ESP_ERROR_CHECK(i2s_new_channel(&chan_cfg, &tx_handle_, NULL)); i2s_pdm_tx_config_t pdm_cfg_default = BSP_I2S_DUPLEX_MONO_CFG((uint32_t)output_sample_rate, pdm_speak_p); - pdm_cfg_default.clk_cfg.up_sample_fs = output_sample_rate / 100; + pdm_cfg_default.clk_cfg.up_sample_fs = AUDIO_PDM_UPSAMPLE_FS; pdm_cfg_default.slot_cfg.sd_scale = I2S_PDM_SIG_SCALING_MUL_4; pdm_cfg_default.slot_cfg.hp_scale = I2S_PDM_SIG_SCALING_MUL_4; pdm_cfg_default.slot_cfg.lp_scale = I2S_PDM_SIG_SCALING_MUL_4; @@ -112,10 +114,27 @@ AdcPdmAudioCodec::AdcPdmAudioCodec(int input_sample_rate, int output_sample_rate esp_rom_gpio_connect_out_signal(pdm_speak_n, I2SO_SD_OUT_IDX, 1, 0); //反转输出 SD OUT 信号 gpio_set_drive_capability(pdm_speak_n, GPIO_DRIVE_CAP_0); } + + // 初始化输出定时器 + esp_timer_create_args_t output_timer_args = { + .callback = &AdcPdmAudioCodec::OutputTimerCallback, + .arg = this, + .dispatch_method = ESP_TIMER_TASK, + .name = "output_timer" + }; + ESP_ERROR_CHECK(esp_timer_create(&output_timer_args, &output_timer_)); + ESP_LOGI(TAG, "AdcPdmAudioCodec initialized"); } AdcPdmAudioCodec::~AdcPdmAudioCodec() { + // 删除定时器 + if (output_timer_) { + esp_timer_stop(output_timer_); + esp_timer_delete(output_timer_); + output_timer_ = nullptr; + } + ESP_ERROR_CHECK(esp_codec_dev_close(output_dev_)); esp_codec_dev_delete(output_dev_); ESP_ERROR_CHECK(esp_codec_dev_close(input_dev_)); @@ -161,11 +180,27 @@ void AdcPdmAudioCodec::EnableOutput(bool enable) { }; ESP_ERROR_CHECK(esp_codec_dev_open(output_dev_, &fs)); ESP_ERROR_CHECK(esp_codec_dev_set_out_vol(output_dev_, output_volume_)); + + // 强制按板卡配置重配PDM TX时钟,覆盖第三方库在set_fmt中的默认up_sample_fs + // 若通道已启用,先禁用再重配,最后再启用 + ESP_ERROR_CHECK_WITHOUT_ABORT(i2s_channel_disable(tx_handle_)); + i2s_pdm_tx_clk_config_t clk_cfg = I2S_PDM_TX_CLK_DEFAULT_CONFIG((uint32_t)output_sample_rate_); + clk_cfg.up_sample_fs = AUDIO_PDM_UPSAMPLE_FS; + ESP_ERROR_CHECK(i2s_channel_reconfig_pdm_tx_clock(tx_handle_, &clk_cfg)); + ESP_ERROR_CHECK(i2s_channel_enable(tx_handle_)); if(pa_ctrl_pin_ != GPIO_NUM_NC){ gpio_set_level(pa_ctrl_pin_, 1); } + // 启用输出时启动定时器 + if (output_timer_) { + esp_timer_start_once(output_timer_, TIMER_TIMEOUT_US); + } } else { + // 禁用输出时停止定时器 + if (output_timer_) { + esp_timer_stop(output_timer_); + } if(pa_ctrl_pin_ != GPIO_NUM_NC){ gpio_set_level(pa_ctrl_pin_, 0); } @@ -183,6 +218,11 @@ int AdcPdmAudioCodec::Read(int16_t* dest, int samples) { int AdcPdmAudioCodec::Write(const int16_t* data, int samples) { if (output_enabled_) { ESP_ERROR_CHECK_WITHOUT_ABORT(esp_codec_dev_write(output_dev_, (void*)data, samples * sizeof(int16_t))); + // 重置输出定时器 + if (output_timer_) { + esp_timer_stop(output_timer_); + esp_timer_start_once(output_timer_, TIMER_TIMEOUT_US); + } } return samples; } @@ -195,9 +235,15 @@ void AdcPdmAudioCodec::Start() { output_volume_ = 10; } - ESP_ERROR_CHECK(i2s_channel_enable(tx_handle_)); - EnableInput(true); EnableOutput(true); ESP_LOGI(TAG, "Audio codec started"); } + +// 定时器回调函数实现 +void AdcPdmAudioCodec::OutputTimerCallback(void* arg) { + AdcPdmAudioCodec* codec = static_cast(arg); + if (codec && codec->output_enabled_) { + codec->EnableOutput(false); + } +} diff --git a/main/boards/esp-hi/adc_pdm_audio_codec.h b/main/boards/esp-hi/adc_pdm_audio_codec.h index cab1a2bf..8c9e8363 100644 --- a/main/boards/esp-hi/adc_pdm_audio_codec.h +++ b/main/boards/esp-hi/adc_pdm_audio_codec.h @@ -5,6 +5,7 @@ #include #include +#include class AdcPdmAudioCodec : public AudioCodec { private: @@ -12,6 +13,13 @@ private: esp_codec_dev_handle_t input_dev_ = nullptr; gpio_num_t pa_ctrl_pin_ = GPIO_NUM_NC; + // 定时器相关成员变量 + esp_timer_handle_t output_timer_ = nullptr; + static constexpr uint64_t TIMER_TIMEOUT_US = 120000; // 120ms = 120000us + + // 定时器回调函数 + static void OutputTimerCallback(void* arg); + virtual int Read(int16_t* dest, int samples) override; virtual int Write(const int16_t* data, int samples) override; diff --git a/main/boards/esp-hi/config.h b/main/boards/esp-hi/config.h index 9ea9ba74..8ea4ffc3 100644 --- a/main/boards/esp-hi/config.h +++ b/main/boards/esp-hi/config.h @@ -6,6 +6,9 @@ #define AUDIO_INPUT_SAMPLE_RATE 16000 #define AUDIO_OUTPUT_SAMPLE_RATE 24000 +// 配置PDM上采样fs参数(取值范围<=480)。部分设备在441时表现更稳定 +#define AUDIO_PDM_UPSAMPLE_FS 441 + #define AUDIO_ADC_MIC_CHANNEL 2 #define AUDIO_PDM_SPEAK_P_GPIO GPIO_NUM_6 #define AUDIO_PDM_SPEAK_N_GPIO GPIO_NUM_7 diff --git a/main/boards/esp-hi/config.json b/main/boards/esp-hi/config.json index dec5d5ef..3770f0b9 100644 --- a/main/boards/esp-hi/config.json +++ b/main/boards/esp-hi/config.json @@ -25,7 +25,6 @@ "CONFIG_LWIP_TCPIP_TASK_STACK_SIZE=2048", "CONFIG_MBEDTLS_DYNAMIC_FREE_CONFIG_DATA=y", "CONFIG_NEWLIB_NANO_FORMAT=y", - "CONFIG_MMAP_FILE_NAME_LENGTH=25", "CONFIG_ESP_CONSOLE_NONE=y", "CONFIG_USE_ESP_WAKE_WORD=y", "CONFIG_COMPILER_OPTIMIZATION_SIZE=y" diff --git a/main/boards/esp-hi/emoji_display.cc b/main/boards/esp-hi/emoji_display.cc index ab356538..c4943371 100644 --- a/main/boards/esp-hi/emoji_display.cc +++ b/main/boards/esp-hi/emoji_display.cc @@ -53,6 +53,8 @@ EmojiPlayer::EmojiPlayer(esp_lcd_panel_handle_t panel, esp_lcd_panel_io_handle_t .task = ANIM_PLAYER_INIT_CONFIG() }; + player_cfg.task.task_priority = 1; + player_cfg.task.task_stack = 4096; player_handle_ = anim_player_init(&player_cfg); const esp_lcd_panel_io_callbacks_t cbs = { diff --git a/main/boards/esp-hi/emoji_display.h b/main/boards/esp-hi/emoji_display.h index d991a7db..d4faab71 100644 --- a/main/boards/esp-hi/emoji_display.h +++ b/main/boards/esp-hi/emoji_display.h @@ -37,6 +37,8 @@ public: virtual void SetEmotion(const char* emotion) override; virtual void SetStatus(const char* status) override; + virtual void SetChatMessage(const char* role, const char* content) override {} + anim::EmojiPlayer* GetPlayer() { return player_.get(); diff --git a/main/boards/esp-hi/esp_hi.cc b/main/boards/esp-hi/esp_hi.cc index ed47b80a..0da56a48 100644 --- a/main/boards/esp-hi/esp_hi.cc +++ b/main/boards/esp-hi/esp_hi.cc @@ -397,11 +397,6 @@ public: InitializeSpi(); InitializeLcdDisplay(); InitializeTools(); - - DeviceStateEventManager::GetInstance().RegisterStateChangeCallback([this](DeviceState previous_state, DeviceState current_state) { - ESP_LOGD(TAG, "Device state changed from %d to %d", previous_state, current_state); - this->GetAudioCodec()->EnableOutput(current_state == kDeviceStateSpeaking); - }); } virtual AudioCodec* GetAudioCodec() override