From 7cc0008837f557afa3ad337f797c8f0954b2af07 Mon Sep 17 00:00:00 2001 From: Keith Burzinski Date: Mon, 16 Jun 2025 02:36:49 -0500 Subject: [PATCH] [i2s_audio] Add ``dump_config`` methods, shorten log messages (#9099) --- esphome/components/i2s_audio/i2s_audio.cpp | 2 +- .../microphone/i2s_audio_microphone.cpp | 51 +++++++++++-------- .../microphone/i2s_audio_microphone.h | 1 + .../i2s_audio/speaker/i2s_audio_speaker.cpp | 38 ++++++++++---- .../i2s_audio/speaker/i2s_audio_speaker.h | 1 + 5 files changed, 61 insertions(+), 32 deletions(-) diff --git a/esphome/components/i2s_audio/i2s_audio.cpp b/esphome/components/i2s_audio/i2s_audio.cpp index 2de3f1d9f8..0f2995b4bd 100644 --- a/esphome/components/i2s_audio/i2s_audio.cpp +++ b/esphome/components/i2s_audio/i2s_audio.cpp @@ -18,7 +18,7 @@ void I2SAudioComponent::setup() { static i2s_port_t next_port_num = I2S_NUM_0; if (next_port_num >= I2S_NUM_MAX) { - ESP_LOGE(TAG, "Too many I2S Audio components"); + ESP_LOGE(TAG, "Too many components"); this->mark_failed(); return; } diff --git a/esphome/components/i2s_audio/microphone/i2s_audio_microphone.cpp b/esphome/components/i2s_audio/microphone/i2s_audio_microphone.cpp index 52d0ae34fb..2cd004ffaa 100644 --- a/esphome/components/i2s_audio/microphone/i2s_audio_microphone.cpp +++ b/esphome/components/i2s_audio/microphone/i2s_audio_microphone.cpp @@ -45,7 +45,7 @@ void I2SAudioMicrophone::setup() { #if SOC_I2S_SUPPORTS_ADC if (this->adc_) { if (this->parent_->get_port() != I2S_NUM_0) { - ESP_LOGE(TAG, "Internal ADC only works on I2S0!"); + ESP_LOGE(TAG, "Internal ADC only works on I2S0"); this->mark_failed(); return; } @@ -55,7 +55,7 @@ void I2SAudioMicrophone::setup() { { if (this->pdm_) { if (this->parent_->get_port() != I2S_NUM_0) { - ESP_LOGE(TAG, "PDM only works on I2S0!"); + ESP_LOGE(TAG, "PDM only works on I2S0"); this->mark_failed(); return; } @@ -64,14 +64,14 @@ void I2SAudioMicrophone::setup() { this->active_listeners_semaphore_ = xSemaphoreCreateCounting(MAX_LISTENERS, MAX_LISTENERS); if (this->active_listeners_semaphore_ == nullptr) { - ESP_LOGE(TAG, "Failed to create semaphore"); + ESP_LOGE(TAG, "Creating semaphore failed"); this->mark_failed(); return; } this->event_group_ = xEventGroupCreate(); if (this->event_group_ == nullptr) { - ESP_LOGE(TAG, "Failed to create event group"); + ESP_LOGE(TAG, "Creating event group failed"); this->mark_failed(); return; } @@ -79,6 +79,15 @@ void I2SAudioMicrophone::setup() { this->configure_stream_settings_(); } +void I2SAudioMicrophone::dump_config() { + ESP_LOGCONFIG(TAG, + "Microphone:\n" + " Pin: %d\n" + " PDM: %s\n" + " DC offset correction: %s", + static_cast(this->din_pin_), YESNO(this->pdm_), YESNO(this->correct_dc_offset_)); +} + void I2SAudioMicrophone::configure_stream_settings_() { uint8_t channel_count = 1; #ifdef USE_I2S_LEGACY @@ -151,7 +160,7 @@ bool I2SAudioMicrophone::start_driver_() { config.mode = (i2s_mode_t) (config.mode | I2S_MODE_ADC_BUILT_IN); err = i2s_driver_install(this->parent_->get_port(), &config, 0, nullptr); if (err != ESP_OK) { - ESP_LOGE(TAG, "Error installing I2S driver: %s", esp_err_to_name(err)); + ESP_LOGE(TAG, "Error installing driver: %s", esp_err_to_name(err)); return false; } @@ -174,7 +183,7 @@ bool I2SAudioMicrophone::start_driver_() { err = i2s_driver_install(this->parent_->get_port(), &config, 0, nullptr); if (err != ESP_OK) { - ESP_LOGE(TAG, "Error installing I2S driver: %s", esp_err_to_name(err)); + ESP_LOGE(TAG, "Error installing driver: %s", esp_err_to_name(err)); return false; } @@ -183,7 +192,7 @@ bool I2SAudioMicrophone::start_driver_() { err = i2s_set_pin(this->parent_->get_port(), &pin_config); if (err != ESP_OK) { - ESP_LOGE(TAG, "Error setting I2S pin: %s", esp_err_to_name(err)); + ESP_LOGE(TAG, "Error setting pin: %s", esp_err_to_name(err)); return false; } } @@ -198,7 +207,7 @@ bool I2SAudioMicrophone::start_driver_() { /* Allocate a new RX channel and get the handle of this channel */ err = i2s_new_channel(&chan_cfg, NULL, &this->rx_handle_); if (err != ESP_OK) { - ESP_LOGE(TAG, "Error creating new I2S channel: %s", esp_err_to_name(err)); + ESP_LOGE(TAG, "Error creating channel: %s", esp_err_to_name(err)); return false; } @@ -270,14 +279,14 @@ bool I2SAudioMicrophone::start_driver_() { err = i2s_channel_init_std_mode(this->rx_handle_, &std_cfg); } if (err != ESP_OK) { - ESP_LOGE(TAG, "Error initializing I2S channel: %s", esp_err_to_name(err)); + ESP_LOGE(TAG, "Error initializing channel: %s", esp_err_to_name(err)); return false; } /* Before reading data, start the RX channel first */ i2s_channel_enable(this->rx_handle_); if (err != ESP_OK) { - ESP_LOGE(TAG, "Error enabling I2S Microphone: %s", esp_err_to_name(err)); + ESP_LOGE(TAG, "Enabling failed: %s", esp_err_to_name(err)); return false; } #endif @@ -304,29 +313,29 @@ void I2SAudioMicrophone::stop_driver_() { if (this->adc_) { err = i2s_adc_disable(this->parent_->get_port()); if (err != ESP_OK) { - ESP_LOGW(TAG, "Error disabling ADC - it may not have started: %s", esp_err_to_name(err)); + ESP_LOGW(TAG, "Error disabling ADC: %s", esp_err_to_name(err)); } } #endif err = i2s_stop(this->parent_->get_port()); if (err != ESP_OK) { - ESP_LOGW(TAG, "Error stopping I2S microphone - it may not have started: %s", esp_err_to_name(err)); + ESP_LOGW(TAG, "Error stopping: %s", esp_err_to_name(err)); } err = i2s_driver_uninstall(this->parent_->get_port()); if (err != ESP_OK) { - ESP_LOGW(TAG, "Error uninstalling I2S driver - it may not have started: %s", esp_err_to_name(err)); + ESP_LOGW(TAG, "Error uninstalling driver: %s", esp_err_to_name(err)); } #else if (this->rx_handle_ != nullptr) { /* Have to stop the channel before deleting it */ err = i2s_channel_disable(this->rx_handle_); if (err != ESP_OK) { - ESP_LOGW(TAG, "Error stopping I2S microphone - it may not have started: %s", esp_err_to_name(err)); + ESP_LOGW(TAG, "Error stopping: %s", esp_err_to_name(err)); } /* If the handle is not needed any more, delete it to release the channel resources */ err = i2s_del_channel(this->rx_handle_); if (err != ESP_OK) { - ESP_LOGW(TAG, "Error deleting I2S channel - it may not have started: %s", esp_err_to_name(err)); + ESP_LOGW(TAG, "Error deleting channel: %s", esp_err_to_name(err)); } this->rx_handle_ = nullptr; } @@ -403,7 +412,7 @@ size_t I2SAudioMicrophone::read_(uint8_t *buf, size_t len, TickType_t ticks_to_w // Ignore ESP_ERR_TIMEOUT if ticks_to_wait = 0, as it will read the data on the next call if (!this->status_has_warning()) { // Avoid spamming the logs with the error message if its repeated - ESP_LOGW(TAG, "Error reading from I2S microphone: %s", esp_err_to_name(err)); + ESP_LOGW(TAG, "Read error: %s", esp_err_to_name(err)); } this->status_set_warning(); return 0; @@ -431,19 +440,19 @@ void I2SAudioMicrophone::loop() { uint32_t event_group_bits = xEventGroupGetBits(this->event_group_); if (event_group_bits & MicrophoneEventGroupBits::TASK_STARTING) { - ESP_LOGD(TAG, "Task started, attempting to allocate buffer"); + ESP_LOGV(TAG, "Task started, attempting to allocate buffer"); xEventGroupClearBits(this->event_group_, MicrophoneEventGroupBits::TASK_STARTING); } if (event_group_bits & MicrophoneEventGroupBits::TASK_RUNNING) { - ESP_LOGD(TAG, "Task is running and reading data"); + ESP_LOGV(TAG, "Task is running and reading data"); xEventGroupClearBits(this->event_group_, MicrophoneEventGroupBits::TASK_RUNNING); this->state_ = microphone::STATE_RUNNING; } if ((event_group_bits & MicrophoneEventGroupBits::TASK_STOPPED)) { - ESP_LOGD(TAG, "Task finished, freeing resources and uninstalling I2S driver"); + ESP_LOGV(TAG, "Task finished, freeing resources and uninstalling driver"); vTaskDelete(this->task_handle_); this->task_handle_ = nullptr; @@ -473,7 +482,7 @@ void I2SAudioMicrophone::loop() { } if (!this->start_driver_()) { - this->status_momentary_error("I2S driver failed to start, unloading it and attempting again in 1 second", 1000); + this->status_momentary_error("Driver failed to start; retrying in 1 second", 1000); this->stop_driver_(); // Stop/frees whatever possibly started break; } @@ -483,7 +492,7 @@ void I2SAudioMicrophone::loop() { &this->task_handle_); if (this->task_handle_ == nullptr) { - this->status_momentary_error("Task failed to start, attempting again in 1 second", 1000); + this->status_momentary_error("Task failed to start, retrying in 1 second", 1000); this->stop_driver_(); // Stops the driver to return the lock; will be reloaded in next attempt } } diff --git a/esphome/components/i2s_audio/microphone/i2s_audio_microphone.h b/esphome/components/i2s_audio/microphone/i2s_audio_microphone.h index c35f88f8ee..4c384ba963 100644 --- a/esphome/components/i2s_audio/microphone/i2s_audio_microphone.h +++ b/esphome/components/i2s_audio/microphone/i2s_audio_microphone.h @@ -18,6 +18,7 @@ namespace i2s_audio { class I2SAudioMicrophone : public I2SAudioIn, public microphone::Microphone, public Component { public: void setup() override; + void dump_config() override; void start() override; void stop() override; diff --git a/esphome/components/i2s_audio/speaker/i2s_audio_speaker.cpp b/esphome/components/i2s_audio/speaker/i2s_audio_speaker.cpp index f4c761ecc0..41da8a4642 100644 --- a/esphome/components/i2s_audio/speaker/i2s_audio_speaker.cpp +++ b/esphome/components/i2s_audio/speaker/i2s_audio_speaker.cpp @@ -110,29 +110,48 @@ void I2SAudioSpeaker::setup() { } } +void I2SAudioSpeaker::dump_config() { + ESP_LOGCONFIG(TAG, + "Speaker:\n" + " Pin: %d\n" + " Buffer duration: %" PRIu32, + static_cast(this->dout_pin_), this->buffer_duration_ms_); + if (this->timeout_.has_value()) { + ESP_LOGCONFIG(TAG, " Timeout: %" PRIu32 " ms", this->timeout_.value()); + } +#ifdef USE_I2S_LEGACY +#if SOC_I2S_SUPPORTS_DAC + ESP_LOGCONFIG(TAG, " Internal DAC mode: %d", static_cast(this->internal_dac_mode_)); +#endif + ESP_LOGCONFIG(TAG, " Communication format: %d", static_cast(this->i2s_comm_fmt_)); +#else + ESP_LOGCONFIG(TAG, " Communication format: %s", this->i2s_comm_fmt_.c_str()); +#endif +} + void I2SAudioSpeaker::loop() { uint32_t event_group_bits = xEventGroupGetBits(this->event_group_); if (event_group_bits & SpeakerEventGroupBits::STATE_STARTING) { - ESP_LOGD(TAG, "Starting Speaker"); + ESP_LOGD(TAG, "Starting"); this->state_ = speaker::STATE_STARTING; xEventGroupClearBits(this->event_group_, SpeakerEventGroupBits::STATE_STARTING); } if (event_group_bits & SpeakerEventGroupBits::STATE_RUNNING) { - ESP_LOGD(TAG, "Started Speaker"); + ESP_LOGD(TAG, "Started"); this->state_ = speaker::STATE_RUNNING; xEventGroupClearBits(this->event_group_, SpeakerEventGroupBits::STATE_RUNNING); this->status_clear_warning(); this->status_clear_error(); } if (event_group_bits & SpeakerEventGroupBits::STATE_STOPPING) { - ESP_LOGD(TAG, "Stopping Speaker"); + ESP_LOGD(TAG, "Stopping"); this->state_ = speaker::STATE_STOPPING; xEventGroupClearBits(this->event_group_, SpeakerEventGroupBits::STATE_STOPPING); } if (event_group_bits & SpeakerEventGroupBits::STATE_STOPPED) { if (!this->task_created_) { - ESP_LOGD(TAG, "Stopped Speaker"); + ESP_LOGD(TAG, "Stopped"); this->state_ = speaker::STATE_STOPPED; xEventGroupClearBits(this->event_group_, SpeakerEventGroupBits::ALL_BITS); this->speaker_task_handle_ = nullptr; @@ -140,20 +159,19 @@ void I2SAudioSpeaker::loop() { } if (event_group_bits & SpeakerEventGroupBits::ERR_TASK_FAILED_TO_START) { - this->status_set_error("Failed to start speaker task"); + this->status_set_error("Failed to start task"); xEventGroupClearBits(this->event_group_, SpeakerEventGroupBits::ERR_TASK_FAILED_TO_START); } if (event_group_bits & SpeakerEventGroupBits::ALL_ERR_ESP_BITS) { uint32_t error_bits = event_group_bits & SpeakerEventGroupBits::ALL_ERR_ESP_BITS; - ESP_LOGW(TAG, "Error writing to I2S: %s", esp_err_to_name(err_bit_to_esp_err(error_bits))); + ESP_LOGW(TAG, "Writing failed: %s", esp_err_to_name(err_bit_to_esp_err(error_bits))); this->status_set_warning(); } if (event_group_bits & SpeakerEventGroupBits::ERR_ESP_NOT_SUPPORTED) { - this->status_set_error("Failed to adjust I2S bus to match the incoming audio"); - ESP_LOGE(TAG, - "Incompatible audio format: sample rate = %" PRIu32 ", channels = %" PRIu8 ", bits per sample = %" PRIu8, + this->status_set_error("Failed to adjust bus to match incoming audio"); + ESP_LOGE(TAG, "Incompatible audio format: sample rate = %" PRIu32 ", channels = %u, bits per sample = %u", this->audio_stream_info_.get_sample_rate(), this->audio_stream_info_.get_channels(), this->audio_stream_info_.get_bits_per_sample()); } @@ -202,7 +220,7 @@ void I2SAudioSpeaker::set_mute_state(bool mute_state) { size_t I2SAudioSpeaker::play(const uint8_t *data, size_t length, TickType_t ticks_to_wait) { if (this->is_failed()) { - ESP_LOGE(TAG, "Cannot play audio, speaker failed to setup"); + ESP_LOGE(TAG, "Setup failed; cannot play audio"); return 0; } if (this->state_ != speaker::STATE_RUNNING && this->state_ != speaker::STATE_STARTING) { diff --git a/esphome/components/i2s_audio/speaker/i2s_audio_speaker.h b/esphome/components/i2s_audio/speaker/i2s_audio_speaker.h index b5e4b94bc4..eb2a0ae756 100644 --- a/esphome/components/i2s_audio/speaker/i2s_audio_speaker.h +++ b/esphome/components/i2s_audio/speaker/i2s_audio_speaker.h @@ -24,6 +24,7 @@ class I2SAudioSpeaker : public I2SAudioOut, public speaker::Speaker, public Comp float get_setup_priority() const override { return esphome::setup_priority::PROCESSOR; } void setup() override; + void dump_config() override; void loop() override; void set_buffer_duration(uint32_t buffer_duration_ms) { this->buffer_duration_ms_ = buffer_duration_ms; }