Add initial board, HAL, and executor modules
This commit is contained in:
1 parent
3b9e129c88
commit
0b2eebe76d
82 files changed
+20611
No files matched your search
@@ -0,0 +1,247 @@
|
||||
#include "audio_codec.h"
|
||||
#include "esp_log.h"
|
||||
#include "es7210.h"
|
||||
#include "freertos/FreeRTOS.h"
|
||||
#include "freertos/task.h"
|
||||
#include "freertos/semphr.h"
|
||||
|
||||
static const char *TAG = "AudioCodec";
|
||||
|
||||
// 静态成员初始化
|
||||
AudioCodec* AudioCodec::instance_ = nullptr;
|
||||
SemaphoreHandle_t AudioCodec::mutex_ = nullptr;
|
||||
|
||||
AudioCodec::AudioCodec()
|
||||
: board_handle_(nullptr),
|
||||
is_initialized_(false),
|
||||
current_mode_(AUDIO_CODEC_MODE_DECODE),
|
||||
current_volume_(100)
|
||||
{
|
||||
}
|
||||
|
||||
AudioCodec::~AudioCodec() {
|
||||
Deinitialize();
|
||||
}
|
||||
|
||||
AudioCodec* AudioCodec::GetInstance() {
|
||||
// 双重检查锁定模式确保线程安全
|
||||
if (instance_ == nullptr) {
|
||||
if (mutex_ == nullptr) {
|
||||
mutex_ = xSemaphoreCreateMutex();
|
||||
}
|
||||
|
||||
if (xSemaphoreTake(mutex_, portMAX_DELAY) == pdTRUE) {
|
||||
if (instance_ == nullptr) {
|
||||
instance_ = new AudioCodec();
|
||||
}
|
||||
xSemaphoreGive(mutex_);
|
||||
}
|
||||
}
|
||||
return instance_;
|
||||
}
|
||||
|
||||
esp_err_t AudioCodec::Initialize() {
|
||||
if (is_initialized_) {
|
||||
ESP_LOGW(TAG, "AudioCodec already initialized");
|
||||
return ESP_OK;
|
||||
}
|
||||
|
||||
ESP_LOGI(TAG, "Initializing AudioCodec");
|
||||
|
||||
esp_err_t ret = InitializeBoard();
|
||||
if (ret != ESP_OK) {
|
||||
ESP_LOGE(TAG, "Failed to initialize audio board: %s", esp_err_to_name(ret));
|
||||
return ret;
|
||||
}
|
||||
|
||||
// 先设置初始化标志,然后启动编解码器
|
||||
is_initialized_ = true;
|
||||
|
||||
// 默认启用双向模式,同时支持播放和录音
|
||||
ret = StartCodec(AUDIO_CODEC_MODE_BOTH);
|
||||
if (ret != ESP_OK) {
|
||||
ESP_LOGE(TAG, "Failed to start codec in both mode: %s", esp_err_to_name(ret));
|
||||
is_initialized_ = false; // 如果启动失败,重置标志
|
||||
return ret;
|
||||
}
|
||||
|
||||
ESP_LOGI(TAG, "AudioCodec initialized successfully with both encode and decode enabled");
|
||||
return ESP_OK;
|
||||
}
|
||||
|
||||
esp_err_t AudioCodec::InitializeBoard() {
|
||||
// 初始化音频板
|
||||
board_handle_ = audio_board_init();
|
||||
if (board_handle_ == nullptr) {
|
||||
ESP_LOGE(TAG, "Failed to initialize audio board");
|
||||
return ESP_FAIL;
|
||||
}
|
||||
|
||||
ESP_LOGI(TAG, "Audio board initialized successfully");
|
||||
return ESP_OK;
|
||||
}
|
||||
|
||||
esp_err_t AudioCodec::StartCodec(audio_codec_mode_t mode) {
|
||||
// 检查音频板是否已初始化,而不是检查整体初始化状态
|
||||
if (board_handle_ == nullptr) {
|
||||
ESP_LOGE(TAG, "Audio board not initialized");
|
||||
return ESP_ERR_INVALID_STATE;
|
||||
}
|
||||
|
||||
esp_err_t ret = ESP_OK;
|
||||
|
||||
switch (mode) {
|
||||
case AUDIO_CODEC_MODE_DECODE:
|
||||
ESP_LOGI(TAG, "Starting codec in decode mode");
|
||||
ret = audio_hal_ctrl_codec(board_handle_->audio_hal, AUDIO_HAL_CODEC_MODE_DECODE, AUDIO_HAL_CTRL_START);
|
||||
break;
|
||||
|
||||
case AUDIO_CODEC_MODE_ENCODE:
|
||||
ESP_LOGI(TAG, "Starting codec in encode mode");
|
||||
ret = audio_hal_ctrl_codec(board_handle_->audio_hal, AUDIO_HAL_CODEC_MODE_ENCODE, AUDIO_HAL_CTRL_START);
|
||||
if (ret == ESP_OK) {
|
||||
// 设置ADC音量
|
||||
ret = audio_hal_set_volume(board_handle_->adc_hal, 100);
|
||||
if (ret != ESP_OK) {
|
||||
ESP_LOGW(TAG, "Failed to set ADC volume: %s", esp_err_to_name(ret));
|
||||
}
|
||||
|
||||
// 设置ES7210麦克风增益
|
||||
ret = es7210_adc_set_gain((es7210_input_mics_t)(ES7210_INPUT_MIC1 | ES7210_INPUT_MIC2 | ES7210_INPUT_MIC3), GAIN_37_5DB);
|
||||
if (ret != ESP_OK) {
|
||||
ESP_LOGW(TAG, "Failed to set ES7210 gain: %s", esp_err_to_name(ret));
|
||||
} else {
|
||||
ESP_LOGI(TAG, "ES7210 gain set to 37.5dB");
|
||||
}
|
||||
}
|
||||
break;
|
||||
|
||||
case AUDIO_CODEC_MODE_BOTH:
|
||||
ESP_LOGI(TAG, "Starting codec in both modes");
|
||||
ret = audio_hal_ctrl_codec(board_handle_->audio_hal, AUDIO_HAL_CODEC_MODE_BOTH, AUDIO_HAL_CTRL_START);
|
||||
if (ret == ESP_OK) {
|
||||
// 同时设置播放和录音参数
|
||||
audio_hal_set_volume(board_handle_->adc_hal, 100);
|
||||
es7210_adc_set_gain((es7210_input_mics_t)(ES7210_INPUT_MIC1 | ES7210_INPUT_MIC2 | ES7210_INPUT_MIC3), GAIN_37_5DB);
|
||||
}
|
||||
break;
|
||||
|
||||
default:
|
||||
ESP_LOGE(TAG, "Invalid codec mode: %d", mode);
|
||||
return ESP_ERR_INVALID_ARG;
|
||||
}
|
||||
|
||||
if (ret != ESP_OK) {
|
||||
ESP_LOGE(TAG, "Failed to start codec: %s", esp_err_to_name(ret));
|
||||
return ret;
|
||||
}
|
||||
|
||||
current_mode_ = mode;
|
||||
|
||||
// 设置初始音量(仅在播放模式下)
|
||||
if (mode == AUDIO_CODEC_MODE_DECODE || mode == AUDIO_CODEC_MODE_BOTH) {
|
||||
SetVolume(current_volume_);
|
||||
}
|
||||
|
||||
ESP_LOGI(TAG, "Codec started successfully in mode %d", mode);
|
||||
return ESP_OK;
|
||||
}
|
||||
|
||||
esp_err_t AudioCodec::StopCodec() {
|
||||
if (!is_initialized_) {
|
||||
ESP_LOGW(TAG, "AudioCodec not initialized");
|
||||
return ESP_OK;
|
||||
}
|
||||
|
||||
ESP_LOGI(TAG, "Stopping codec");
|
||||
// 修复:直接使用audio_hal_codec_mode_t类型
|
||||
esp_err_t ret = audio_hal_ctrl_codec(board_handle_->audio_hal, (audio_hal_codec_mode_t)current_mode_, AUDIO_HAL_CTRL_STOP);
|
||||
if (ret != ESP_OK) {
|
||||
ESP_LOGW(TAG, "Failed to stop codec: %s", esp_err_to_name(ret));
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
esp_err_t AudioCodec::SetVolume(uint8_t volume) {
|
||||
if (!is_initialized_) {
|
||||
ESP_LOGE(TAG, "AudioCodec not initialized");
|
||||
return ESP_ERR_INVALID_STATE;
|
||||
}
|
||||
|
||||
if (volume > 100) {
|
||||
ESP_LOGW(TAG, "Volume %d exceeds maximum, setting to 100", volume);
|
||||
volume = 100;
|
||||
}
|
||||
|
||||
// 转换为HAL音量范围 (0-63)
|
||||
int hal_volume = (volume * 63) / 100;
|
||||
esp_err_t ret = audio_hal_set_volume(board_handle_->audio_hal, hal_volume);
|
||||
if (ret != ESP_OK) {
|
||||
ESP_LOGE(TAG, "Failed to set volume: %s", esp_err_to_name(ret));
|
||||
return ret;
|
||||
}
|
||||
|
||||
current_volume_ = volume;
|
||||
ESP_LOGI(TAG, "Volume set to %d%% (HAL volume: %d)", volume, hal_volume);
|
||||
return ESP_OK;
|
||||
}
|
||||
|
||||
esp_err_t AudioCodec::GetVolume(uint8_t* volume) {
|
||||
if (!volume) {
|
||||
return ESP_ERR_INVALID_ARG;
|
||||
}
|
||||
|
||||
*volume = current_volume_;
|
||||
return ESP_OK;
|
||||
}
|
||||
|
||||
esp_err_t AudioCodec::SetAdcVolume(uint8_t volume) {
|
||||
if (!is_initialized_) {
|
||||
ESP_LOGE(TAG, "AudioCodec not initialized");
|
||||
return ESP_ERR_INVALID_STATE;
|
||||
}
|
||||
|
||||
if (volume > 100) {
|
||||
volume = 100;
|
||||
}
|
||||
|
||||
esp_err_t ret = audio_hal_set_volume(board_handle_->adc_hal, volume);
|
||||
if (ret != ESP_OK) {
|
||||
ESP_LOGE(TAG, "Failed to set ADC volume: %s", esp_err_to_name(ret));
|
||||
return ret;
|
||||
}
|
||||
|
||||
ESP_LOGI(TAG, "ADC volume set to %d", volume);
|
||||
return ESP_OK;
|
||||
}
|
||||
|
||||
audio_board_handle_t AudioCodec::GetBoardHandle() {
|
||||
return board_handle_;
|
||||
}
|
||||
|
||||
bool AudioCodec::IsInitialized() {
|
||||
return is_initialized_;
|
||||
}
|
||||
|
||||
esp_err_t AudioCodec::Deinitialize() {
|
||||
if (!is_initialized_) {
|
||||
return ESP_OK;
|
||||
}
|
||||
|
||||
ESP_LOGI(TAG, "Deinitializing AudioCodec");
|
||||
|
||||
StopCodec();
|
||||
Cleanup();
|
||||
|
||||
is_initialized_ = false;
|
||||
ESP_LOGI(TAG, "AudioCodec deinitialized");
|
||||
return ESP_OK;
|
||||
}
|
||||
|
||||
void AudioCodec::Cleanup() {
|
||||
if (board_handle_) {
|
||||
audio_board_deinit(board_handle_);
|
||||
board_handle_ = nullptr;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,74 @@
|
||||
#ifndef AUDIO_CODEC_H
|
||||
#define AUDIO_CODEC_H
|
||||
|
||||
#include "esp_err.h"
|
||||
#include "audio_hal.h"
|
||||
#include "board.h"
|
||||
#include "esp_peripherals.h"
|
||||
#include "freertos/FreeRTOS.h"
|
||||
#include "freertos/semphr.h"
|
||||
#include <stdint.h>
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
// 使用audio_hal中已定义的模式类型,避免重复定义
|
||||
typedef audio_hal_codec_mode_t audio_codec_mode_t;
|
||||
|
||||
// 为了代码可读性,定义别名
|
||||
#define AUDIO_CODEC_MODE_DECODE AUDIO_HAL_CODEC_MODE_DECODE
|
||||
#define AUDIO_CODEC_MODE_ENCODE AUDIO_HAL_CODEC_MODE_ENCODE
|
||||
#define AUDIO_CODEC_MODE_BOTH AUDIO_HAL_CODEC_MODE_BOTH
|
||||
|
||||
class AudioCodec {
|
||||
public:
|
||||
// 获取单例实例
|
||||
static AudioCodec* GetInstance();
|
||||
|
||||
// 初始化音频编解码器(默认启用双向模式)
|
||||
esp_err_t Initialize();
|
||||
|
||||
// 音量控制
|
||||
esp_err_t SetVolume(uint8_t volume);
|
||||
esp_err_t GetVolume(uint8_t* volume);
|
||||
|
||||
// ADC音量控制(录音)
|
||||
esp_err_t SetAdcVolume(uint8_t volume);
|
||||
|
||||
// 获取音频板句柄
|
||||
audio_board_handle_t GetBoardHandle();
|
||||
|
||||
// 检查是否已初始化
|
||||
bool IsInitialized();
|
||||
|
||||
// 反初始化
|
||||
esp_err_t Deinitialize();
|
||||
|
||||
private:
|
||||
AudioCodec(); // 私有构造函数
|
||||
~AudioCodec();
|
||||
|
||||
// 禁止拷贝构造和赋值
|
||||
AudioCodec(const AudioCodec&) = delete;
|
||||
AudioCodec& operator=(const AudioCodec&) = delete;
|
||||
|
||||
static AudioCodec* instance_;
|
||||
static SemaphoreHandle_t mutex_;
|
||||
|
||||
audio_board_handle_t board_handle_;
|
||||
bool is_initialized_;
|
||||
audio_codec_mode_t current_mode_;
|
||||
uint8_t current_volume_;
|
||||
|
||||
esp_err_t InitializeBoard();
|
||||
void Cleanup();
|
||||
esp_err_t StartCodec(audio_codec_mode_t mode);
|
||||
esp_err_t StopCodec();
|
||||
};
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif // AUDIO_CODEC_H
|
||||
@@ -0,0 +1,16 @@
|
||||
# main/04_hal/audio_codec/module.cmake
|
||||
|
||||
|
||||
# 判断 menuconfig 中的开关
|
||||
if(NOT CONFIG_ENABLE_HAL_AUDIO_CODEC AND NOT EARLY_EXPANSION)
|
||||
message(STATUS " [Skip] audio_codec module disabled by menuconfig.")
|
||||
return()
|
||||
endif()
|
||||
|
||||
list(APPEND MODULE_SRCS
|
||||
"04_hal/audio_codec/audio_codec.cc"
|
||||
)
|
||||
|
||||
list(APPEND MODULE_INCLUDE_DIRS
|
||||
"04_hal/audio_codec"
|
||||
)
|
||||
Reference in new issue
Block a user