Skip to content

Commit

Permalink
Merge branch 'feature/esp_codec_dev_for_idfv53' into 'master'
Browse files Browse the repository at this point in the history
esp_codec_dev: Support IDFv5.3 use esp_driver_i2c

See merge request adf/esp-adf-internal!1305
  • Loading branch information
jason-mao committed Jun 12, 2024
2 parents 2c6b060 + 4329fe0 commit a47f0c6
Show file tree
Hide file tree
Showing 19 changed files with 277 additions and 45 deletions.
52 changes: 52 additions & 0 deletions components/esp_codec_dev/CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,52 @@
# Changelog

## v1.2.0

### Features

- Add IDF v5.3 support
Using new i2c driver `esp_driver_i2c`, add `bus_handle` configuration for `audio_codec_i2c_cfg_t`.
User need create the `bus_handle` using API `i2c_new_master_bus` instead of `i2c_driver_install`.
- Change test code to standalone application, user can directly build it under folder [codec_dev_test](test_apps/codec_dev_test)

### Bug Fixes

- Fix I2S work in PDM mode record or play mono channel audio wrongly


## v1.1.0

### Features

- Add driver for AW88298, see detail datasheet [AW88298](https://datasheetspdf.com/download_new.php?id=1513778)

### Bug Fixes

- Fix ES8311 playback fade in for long time


## v1.0.3

### Bug Fixes

- Fix I2S TX and RX work in share mode, need enable TX before RX


## v1.0.2

### Features

- Add I2S TDM support
- Add API to `esp_codec_dev_set_in_channel_gain` to set input channel gain dependently


## v1.0.1

### Bug Fixes

- Fix ES8388 volume register set incorrectly


## v1.0.0

- Initial version of `esp_codec_dev`
4 changes: 2 additions & 2 deletions components/esp_codec_dev/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -159,7 +159,7 @@ To balance the speaker's loudness across different platforms when playing the sa
## Usage

The steps below take the ES8311 codec as an example to illustrate how to play and record audio.
1. Install the driver for codec control and data bus referring to [test_board.c](test/test_board.c)
1. Install the driver for codec control and data bus referring to [test_board.c](test_apps/codec_dev_test/main/test_board.c)
```c
ut_i2c_init(0);
ut_i2s_init(0);
Expand Down Expand Up @@ -235,4 +235,4 @@ The steps below take the ES8311 codec as an example to illustrate how to play an
const audio_codec_if_t *my_codec_new(my_codec_cfg_t *codec_cfg);
```

For details, refer to the sample code [my_codec.c](test/my_codec.c).
For details, refer to the sample code [my_codec.c](test_apps/codec_dev_test/main/my_codec.c).
4 changes: 2 additions & 2 deletions components/esp_codec_dev/README_CN.md
Original file line number Diff line number Diff line change
Expand Up @@ -158,7 +158,7 @@ audio_codec_data_if_t ..> esp_codec_dev
## 使用方法

以 ES8311 为例,下面将演示播放和录音的具体步骤
1. 为编解码器设备的控制和数据总线安装驱动,可参考[test_board.c](test/test_board.c)
1. 为编解码器设备的控制和数据总线安装驱动,可参考[test_board.c](test_apps/codec_dev_test/main/test_board.c)
```c
ut_i2c_init(0);
ut_i2s_init(0);
Expand Down Expand Up @@ -234,4 +234,4 @@ audio_codec_data_if_t ..> esp_codec_dev
const audio_codec_if_t *my_codec_new(my_codec_cfg_t *codec_cfg);
```

更细节的实现可以参考测试代码 [my_codec.c](test/my_codec.c)
更细节的实现可以参考测试代码 [my_codec.c](test_apps/codec_dev_test/main/my_codec.c)
2 changes: 1 addition & 1 deletion components/esp_codec_dev/idf_component.yml
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
version: 1.1.0
version: 1.2.0
description: Audio codec device support for Espressif SOC
url: https://github.com/espressif/esp-adf/tree/master/components/esp_codec_dev

Expand Down
5 changes: 3 additions & 2 deletions components/esp_codec_dev/include/esp_codec_dev_defaults.h
Original file line number Diff line number Diff line change
Expand Up @@ -50,8 +50,9 @@ extern "C" {
* @brief Codec I2C configuration
*/
typedef struct {
uint8_t port; /*!< I2C port, this port need pre-installed by other modules */
uint8_t addr; /*!< I2C address, default address can be gotten from codec head files */
uint8_t port; /*!< I2C port, this port need pre-installed by other modules */
uint8_t addr; /*!< I2C address, default address can be gotten from codec head files */
void *bus_handle; /*!< I2C Master bus handle (for IDFv5.3 or higher version) */
} audio_codec_i2c_cfg_t;

/**
Expand Down
2 changes: 1 addition & 1 deletion components/esp_codec_dev/include/esp_codec_dev_types.h
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@
extern "C" {
#endif

#define ESP_CODEC_DEV_VERSION "1.1.0"
#define ESP_CODEC_DEV_VERSION "1.2.0"

/**
* @brief Define error number of codec device module
Expand Down
92 changes: 83 additions & 9 deletions components/esp_codec_dev/platform/audio_codec_ctrl_i2c.c
Original file line number Diff line number Diff line change
Expand Up @@ -5,22 +5,32 @@
*/
#include "audio_codec_ctrl_if.h"
#include "esp_codec_dev_defaults.h"
#include "driver/i2c.h"
#include "esp_log.h"
#include "esp_idf_version.h"
#if ESP_IDF_VERSION >= ESP_IDF_VERSION_VAL(5, 0, 0)
#define TICK_PER_MS portTICK_PERIOD_MS
#else
#define TICK_PER_MS portTICK_RATE_MS
#endif
#define DEFAULT_I2C_CLOCK (100000)
#define DEFAULT_I2C_TRANS_TIMEOUT (100)

#define TAG "I2C_If"
#if ESP_IDF_VERSION >= ESP_IDF_VERSION_VAL(5, 3, 0)
#include "driver/i2c_master.h"
#define USE_IDF_I2C_MASTER
#else
#include "driver/i2c.h"
#endif

#define TAG "I2C_If"
typedef struct {
audio_codec_ctrl_if_t base;
bool is_open;
uint8_t port;
uint8_t addr;
audio_codec_ctrl_if_t base;
bool is_open;
uint8_t port;
uint8_t addr;
#ifdef USE_IDF_I2C_MASTER
i2c_master_dev_handle_t dev_handle;
#endif
} i2c_ctrl_t;

static int _i2c_ctrl_open(const audio_codec_ctrl_if_t *ctrl, void *cfg, int cfg_size)
Expand All @@ -32,7 +42,20 @@ static int _i2c_ctrl_open(const audio_codec_ctrl_if_t *ctrl, void *cfg, int cfg_
audio_codec_i2c_cfg_t *i2c_cfg = (audio_codec_i2c_cfg_t *) cfg;
i2c_ctrl->port = i2c_cfg->port;
i2c_ctrl->addr = i2c_cfg->addr;
#ifdef USE_IDF_I2C_MASTER
if (i2c_cfg->bus_handle == NULL) {
return ESP_CODEC_DEV_INVALID_ARG;
}
i2c_device_config_t dev_cfg = {
.dev_addr_length = I2C_ADDR_BIT_LEN_7,
.device_address = (i2c_cfg->addr >> 1),
.scl_speed_hz = DEFAULT_I2C_CLOCK,
};
int ret = i2c_master_bus_add_device(i2c_cfg->bus_handle, &dev_cfg, &i2c_ctrl->dev_handle);
return (ret == ESP_OK) ? 0 : ESP_CODEC_DEV_DRV_ERR;
#else
return 0;
#endif
}

static bool _i2c_ctrl_is_open(const audio_codec_ctrl_if_t *ctrl)
Expand All @@ -44,6 +67,44 @@ static bool _i2c_ctrl_is_open(const audio_codec_ctrl_if_t *ctrl)
return false;
}

#ifdef USE_IDF_I2C_MASTER
static int _i2c_master_read_reg(i2c_ctrl_t *i2c_ctrl, int addr, int addr_len, void *data, int data_len)
{
uint8_t addr_data[2] = {0};
addr_data[0] = addr & 0xff;
addr_data[1] = addr >> 8;
int ret = i2c_master_transmit_receive(i2c_ctrl->dev_handle, addr_data, addr_len, data, data_len, DEFAULT_I2C_TRANS_TIMEOUT);
if (ret != ESP_OK) {
ESP_LOGE(TAG, "Fail to read from dev %x", i2c_ctrl->addr);
}
return ret ? ESP_CODEC_DEV_READ_FAIL : ESP_CODEC_DEV_OK;
}

static int _i2c_master_write_reg(i2c_ctrl_t *i2c_ctrl, int addr, int addr_len, void *data, int data_len)
{
esp_err_t ret = ESP_CODEC_DEV_NOT_SUPPORT;
int len = addr_len + data_len;
if (len <= 4) {
// Not support write huge data
uint8_t write_data[4] = {0};
int i = 0;
write_data[i++] = addr & 0xff;
if (addr_len > 1) {
write_data[i++] = addr >> 8;
}
uint8_t *w = (uint8_t*)data;
while (i < len) {
write_data[i++] = *(w++);
}
ret = i2c_master_transmit(i2c_ctrl->dev_handle, write_data, len, DEFAULT_I2C_TRANS_TIMEOUT);
}
if (ret != 0) {
ESP_LOGE(TAG, "Fail to write to dev %x", i2c_ctrl->addr);
}
return ret ? ESP_CODEC_DEV_WRITE_FAIL : ESP_CODEC_DEV_OK;
}
#endif

static int _i2c_ctrl_read_reg(const audio_codec_ctrl_if_t *ctrl, int addr, int addr_len, void *data, int data_len)
{
if (ctrl == NULL || data == NULL) {
Expand All @@ -53,14 +114,17 @@ static int _i2c_ctrl_read_reg(const audio_codec_ctrl_if_t *ctrl, int addr, int a
if (i2c_ctrl->is_open == false) {
return ESP_CODEC_DEV_WRONG_STATE;
}
#ifdef USE_IDF_I2C_MASTER
return _i2c_master_read_reg(i2c_ctrl, addr, addr_len, data, data_len);
#else
esp_err_t ret = ESP_OK;
i2c_cmd_handle_t cmd;
cmd = i2c_cmd_link_create();
ret |= i2c_master_start(cmd);
ret |= i2c_master_write_byte(cmd, i2c_ctrl->addr, 1);
ret |= i2c_master_write(cmd, (uint8_t *) &addr, addr_len, 1);
ret |= i2c_master_stop(cmd);
ret |= i2c_master_cmd_begin(i2c_ctrl->port, cmd, 1000 / TICK_PER_MS);
ret |= i2c_master_cmd_begin(i2c_ctrl->port, cmd, DEFAULT_I2C_TRANS_TIMEOUT / TICK_PER_MS);
i2c_cmd_link_delete(cmd);

cmd = i2c_cmd_link_create();
Expand All @@ -73,12 +137,13 @@ static int _i2c_ctrl_read_reg(const audio_codec_ctrl_if_t *ctrl, int addr, int a
ret |= i2c_master_read_byte(cmd, (uint8_t *) data + (data_len - 1), 1);

ret |= i2c_master_stop(cmd);
ret |= i2c_master_cmd_begin(i2c_ctrl->port, cmd, 1000 / TICK_PER_MS);
ret |= i2c_master_cmd_begin(i2c_ctrl->port, cmd, DEFAULT_I2C_TRANS_TIMEOUT / TICK_PER_MS);
i2c_cmd_link_delete(cmd);
if (ret != ESP_OK) {
ESP_LOGE(TAG, "Fail to read from dev %x", i2c_ctrl->addr);
}
return ret ? ESP_CODEC_DEV_READ_FAIL : ESP_CODEC_DEV_OK;
#endif
}

static int _i2c_ctrl_write_reg(const audio_codec_ctrl_if_t *ctrl, int addr, int addr_len, void *data, int data_len)
Expand All @@ -90,6 +155,9 @@ static int _i2c_ctrl_write_reg(const audio_codec_ctrl_if_t *ctrl, int addr, int
if (i2c_ctrl->is_open == false) {
return ESP_CODEC_DEV_WRONG_STATE;
}
#ifdef USE_IDF_I2C_MASTER
return _i2c_master_write_reg(i2c_ctrl, addr, addr_len, data, data_len);
#else
esp_err_t ret = ESP_OK;
i2c_cmd_handle_t cmd = i2c_cmd_link_create();
ret |= i2c_master_start(cmd);
Expand All @@ -99,12 +167,13 @@ static int _i2c_ctrl_write_reg(const audio_codec_ctrl_if_t *ctrl, int addr, int
ret |= i2c_master_write(cmd, data, data_len, 1);
}
ret |= i2c_master_stop(cmd);
ret |= i2c_master_cmd_begin(i2c_ctrl->port, cmd, 1000 / TICK_PER_MS);
ret |= i2c_master_cmd_begin(i2c_ctrl->port, cmd, DEFAULT_I2C_TRANS_TIMEOUT / TICK_PER_MS);
if (ret != 0) {
ESP_LOGE(TAG, "Fail to write to dev %x", i2c_ctrl->addr);
}
i2c_cmd_link_delete(cmd);
return ret ? ESP_CODEC_DEV_WRITE_FAIL : ESP_CODEC_DEV_OK;
#endif
}

static int _i2c_ctrl_close(const audio_codec_ctrl_if_t *ctrl)
Expand All @@ -113,6 +182,11 @@ static int _i2c_ctrl_close(const audio_codec_ctrl_if_t *ctrl)
return ESP_CODEC_DEV_INVALID_ARG;
}
i2c_ctrl_t *i2c_ctrl = (i2c_ctrl_t *) ctrl;
#if ESP_IDF_VERSION >= ESP_IDF_VERSION_VAL(5, 3, 0)
if (i2c_ctrl->dev_handle) {
i2c_master_bus_rm_device(i2c_ctrl->dev_handle);
}
#endif
i2c_ctrl->is_open = false;
return 0;
}
Expand Down
8 changes: 8 additions & 0 deletions components/esp_codec_dev/platform/audio_codec_data_i2s.c
Original file line number Diff line number Diff line change
Expand Up @@ -154,6 +154,10 @@ static int set_drv_fs(i2s_chan_handle_t channel, bool playback, uint8_t slot_bit
i2s_pdm_rx_slot_config_t slot_cfg = I2S_PDM_RX_SLOT_DEFAULT_CONFIG(slot_bits, I2S_SLOT_MODE_STEREO);
i2s_pdm_slot_mask_t slot_mask = fs->channel_mask ?
(i2s_pdm_slot_mask_t) fs->channel_mask : I2S_PDM_SLOT_BOTH;
// Stereo channel mask is ignored in driver, need use mono instead
if (fs->channel_mask && fs->channel_mask < 3) {
slot_cfg.slot_mode = I2S_SLOT_MODE_MONO;
}
slot_cfg.slot_mask = slot_mask;
if (slot_bits > fs->bits_per_sample) {
slot_cfg.data_bit_width = fs->bits_per_sample;
Expand All @@ -175,6 +179,10 @@ static int set_drv_fs(i2s_chan_handle_t channel, bool playback, uint8_t slot_bit
#if SOC_I2S_SUPPORTS_PDM_TX
i2s_pdm_tx_clk_config_t clk_cfg = I2S_PDM_TX_CLK_DEFAULT_CONFIG(fs->sample_rate);
i2s_pdm_tx_slot_config_t slot_cfg = I2S_PDM_TX_SLOT_DEFAULT_CONFIG(slot_bits, I2S_SLOT_MODE_STEREO);
// Stereo channel mask is ignored, need use mono instead
if (fs->channel_mask && fs->channel_mask < 3) {
slot_cfg.slot_mode = I2S_SLOT_MODE_MONO;
}
#if SOC_I2S_HW_VERSION_1
i2s_pdm_slot_mask_t slot_mask = fs->channel_mask ?
(i2s_pdm_slot_mask_t) fs->channel_mask : I2S_PDM_SLOT_BOTH;
Expand Down
4 changes: 0 additions & 4 deletions components/esp_codec_dev/test/CMakeLists.txt

This file was deleted.

Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
cmake_minimum_required(VERSION 3.16)

list(APPEND EXTRA_COMPONENT_DIRS "$ENV{IDF_PATH}/tools/unit-test-app/components")

set(COMPONENTS main)

include($ENV{IDF_PATH}/tools/cmake/project.cmake)
project(codec_dev_test)
Original file line number Diff line number Diff line change
@@ -1,10 +1,10 @@
| Supported Targets | ESP32 | ESP32-C2 | ESP32-C3 | ESP32-C6 | ESP32-S2 | ESP32-S3 |
| ----------------- | ----- | -------- | -------- | -------- | -------- | -------- |
| Supported Targets | ESP32 | ESP32-C2 | ESP32-C3 | ESP32-C6 | ESP32-S2 | ESP32-S3 | ESP32-P4 |
| ----------------- | ----- | -------- | -------- | -------- | -------- | -------- | -------- |

# esp_codec_dev: Codec device test application

There are two sets of tests in this application:
1. Using customized codec to test all related API
2. Test codec device on special board

The default test board is ESP32S3_KORVO2_V3, if you are using other board, please change definition in [test_boards.h](main/test_board.h) and realization code is [test_board.c](test_board.c).
The default test board is ESP32S3_KORVO2_V3, if you are using other board, please change definition in [test_boards.h](main/test_board.h) and realization code is [test_board.c](main/test_board.c).
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@

set(priv_requires
unity
driver
esp_codec_dev
)

idf_component_register(SRC_DIRS .
PRIV_INCLUDE_DIRS .
PRIV_REQUIRES unity esp_codec_dev
PRIV_REQUIRES ${priv_requires}
WHOLE_ARCHIVE TRUE
)
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
description: Codec Device Test

dependencies:
esp_codec_dev:
version: ">=1.1"
override_path: "../../../"
Original file line number Diff line number Diff line change
Expand Up @@ -57,7 +57,8 @@ static bool my_codec_data_is_open(const audio_codec_data_if_t *h)
return data_if->is_open;
}

static int my_codec_data_set_fmt(const audio_codec_data_if_t *h, esp_codec_dev_sample_info_t *fs)
static int my_codec_data_set_fmt(const audio_codec_data_if_t *h, esp_codec_dev_type_t dev_caps,
esp_codec_dev_sample_info_t *fs)
{
my_codec_data_t *data_if = (my_codec_data_t *) h;
memcpy(&data_if->fmt, fs, sizeof(esp_codec_dev_sample_info_t));
Expand Down
File renamed without changes.
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
/*
* SPDX-FileCopyrightText: 2024 Espressif Systems (Shanghai) CO LTD
*
* SPDX-License-Identifier: CC0-1.0
*/

#include "unity.h"
#include "unity_test_utils.h"
#include "esp_heap_caps.h"
#include "sdkconfig.h"

#define TEST_MEMORY_LEAK_THRESHOLD (400)

void setUp(void)
{
unity_utils_record_free_mem();
}

void tearDown(void)
{
unity_utils_evaluate_leaks_direct(TEST_MEMORY_LEAK_THRESHOLD);
}

void app_main(void)
{
unity_run_menu();
}
Loading

0 comments on commit a47f0c6

Please sign in to comment.