mirror of
https://github.com/espressif/esp-idf.git
synced 2024-10-05 20:47:46 -04:00
Merge branch 'feature/add_i2s_es8311_example_and_loop_unit_test' into 'master'
example/i2s: add es8311 example and i2s unit-test Closes IDF-3412 See merge request espressif/esp-idf!14459
This commit is contained in:
commit
dc20768913
@ -1,8 +1,9 @@
|
||||
/*
|
||||
* SPDX-FileCopyrightText: 2021 Espressif Systems (Shanghai) CO LTD
|
||||
*
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
* SPDX-License-Identifier: CC0-1.0
|
||||
*/
|
||||
|
||||
/**
|
||||
* I2S test environment UT_T1_I2S:
|
||||
* We use internal signals instead of external wiring, but please keep the following IO connections, or connect nothing to prevent the signal from being disturbed.
|
||||
@ -14,6 +15,7 @@
|
||||
#include <string.h>
|
||||
#include "freertos/FreeRTOS.h"
|
||||
#include "freertos/task.h"
|
||||
#include "freertos/queue.h"
|
||||
#include "driver/i2s.h"
|
||||
#include "driver/gpio.h"
|
||||
#include "hal/gpio_hal.h"
|
||||
@ -157,12 +159,15 @@ TEST_CASE("I2S basic driver install, uninstall, set pin test", "[i2s]")
|
||||
|
||||
// normal i2s
|
||||
i2s_pin_config_t pin_config = {
|
||||
.mck_io_num = -1,
|
||||
.bck_io_num = MASTER_BCK_IO,
|
||||
.ws_io_num = MASTER_WS_IO,
|
||||
.data_out_num = DATA_OUT_IO,
|
||||
.data_in_num = -1
|
||||
};
|
||||
TEST_ESP_OK(i2s_driver_install(I2S_NUM_0, &i2s_config, 0, NULL));
|
||||
QueueHandle_t evt_que;
|
||||
TEST_ESP_OK(i2s_driver_install(I2S_NUM_0, &i2s_config, 16, &evt_que));
|
||||
TEST_ASSERT(evt_que);
|
||||
TEST_ESP_OK(i2s_set_pin(I2S_NUM_0, &pin_config));
|
||||
TEST_ESP_OK(i2s_driver_uninstall(I2S_NUM_0));
|
||||
|
||||
@ -199,6 +204,7 @@ TEST_CASE("I2S Loopback test(master tx and rx)", "[i2s]")
|
||||
#endif
|
||||
};
|
||||
i2s_pin_config_t master_pin_config = {
|
||||
.mck_io_num = -1,
|
||||
.bck_io_num = MASTER_BCK_IO,
|
||||
.ws_io_num = MASTER_WS_IO,
|
||||
.data_out_num = DATA_OUT_IO,
|
||||
@ -247,6 +253,74 @@ TEST_CASE("I2S Loopback test(master tx and rx)", "[i2s]")
|
||||
i2s_driver_uninstall(I2S_NUM_0);
|
||||
}
|
||||
|
||||
#if SOC_I2S_SUPPORTS_TDM
|
||||
TEST_CASE("I2S TDM Loopback test(master tx and rx)", "[i2s]")
|
||||
{
|
||||
// master driver installed and send data
|
||||
i2s_config_t master_i2s_config = {
|
||||
.mode = I2S_MODE_MASTER | I2S_MODE_TX | I2S_MODE_RX,
|
||||
.sample_rate = SAMPLE_RATE,
|
||||
.bits_per_sample = SAMPLE_BITS,
|
||||
.channel_format = I2S_CHANNEL_FMT_MULTIPLE,
|
||||
.communication_format = I2S_COMM_FORMAT_STAND_I2S,
|
||||
.total_chan = 4,
|
||||
.chan_mask = I2S_TDM_ACTIVE_CH0 | I2S_TDM_ACTIVE_CH1 | I2S_TDM_ACTIVE_CH2 | I2S_TDM_ACTIVE_CH3,
|
||||
.dma_buf_count = 6,
|
||||
.dma_buf_len = 100,
|
||||
.use_apll = 0,
|
||||
.intr_alloc_flags = ESP_INTR_FLAG_LEVEL1,
|
||||
};
|
||||
i2s_pin_config_t master_pin_config = {
|
||||
.mck_io_num = -1,
|
||||
.bck_io_num = MASTER_BCK_IO,
|
||||
.ws_io_num = MASTER_WS_IO,
|
||||
.data_out_num = DATA_OUT_IO,
|
||||
.data_in_num = DATA_IN_IO
|
||||
};
|
||||
TEST_ESP_OK(i2s_driver_install(I2S_NUM_0, &master_i2s_config, 0, NULL));
|
||||
TEST_ESP_OK(i2s_set_pin(I2S_NUM_0, &master_pin_config));
|
||||
i2s_test_io_config(I2S_TEST_MODE_LOOPBACK);
|
||||
printf("\r\nheap size: %d\n", esp_get_free_heap_size());
|
||||
|
||||
uint8_t *data_wr = (uint8_t *)malloc(sizeof(uint8_t) * 400);
|
||||
size_t i2s_bytes_write = 0;
|
||||
size_t bytes_read = 0;
|
||||
int length = 0;
|
||||
uint8_t *i2s_read_buff = (uint8_t *)malloc(sizeof(uint8_t) * 10000);
|
||||
|
||||
for (int i = 0; i < 100; i++) {
|
||||
data_wr[i] = i + 1;
|
||||
}
|
||||
int flag = 0; // break loop flag
|
||||
int end_position = 0;
|
||||
// write data to slave
|
||||
i2s_write(I2S_NUM_0, data_wr, sizeof(uint8_t) * 400, &i2s_bytes_write, 1000 / portTICK_PERIOD_MS);
|
||||
while (!flag) {
|
||||
if (length >= 10000 - 500) {
|
||||
break;
|
||||
}
|
||||
i2s_read(I2S_NUM_0, i2s_read_buff + length, sizeof(uint8_t) * 500, &bytes_read, 1000 / portMAX_DELAY);
|
||||
if (bytes_read > 0) {
|
||||
for (int i = length; i < length + bytes_read; i++) {
|
||||
if (i2s_read_buff[i] == 100) {
|
||||
flag = 1;
|
||||
end_position = i;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
length = length + bytes_read;
|
||||
}
|
||||
// test the read data right or not
|
||||
for (int i = end_position - 99; i <= end_position; i++) {
|
||||
TEST_ASSERT_EQUAL_UINT8((i - end_position + 100), *(i2s_read_buff + i));
|
||||
}
|
||||
free(data_wr);
|
||||
free(i2s_read_buff);
|
||||
i2s_driver_uninstall(I2S_NUM_0);
|
||||
}
|
||||
#endif
|
||||
|
||||
#if SOC_I2S_NUM > 1
|
||||
/* ESP32S2 and ESP32C3 has only single I2S port and hence following test cases are not applicable */
|
||||
TEST_CASE("I2S write and read test(master tx and slave rx)", "[i2s]")
|
||||
@ -272,6 +346,7 @@ TEST_CASE("I2S write and read test(master tx and slave rx)", "[i2s]")
|
||||
#endif
|
||||
};
|
||||
i2s_pin_config_t master_pin_config = {
|
||||
.mck_io_num = -1,
|
||||
.bck_io_num = MASTER_BCK_IO,
|
||||
.ws_io_num = MASTER_WS_IO,
|
||||
.data_out_num = DATA_OUT_IO,
|
||||
@ -302,6 +377,7 @@ TEST_CASE("I2S write and read test(master tx and slave rx)", "[i2s]")
|
||||
#endif
|
||||
};
|
||||
i2s_pin_config_t slave_pin_config = {
|
||||
.mck_io_num = -1,
|
||||
.bck_io_num = SLAVE_BCK_IO,
|
||||
.ws_io_num = SLAVE_WS_IO,
|
||||
.data_out_num = -1,
|
||||
@ -374,6 +450,7 @@ TEST_CASE("I2S write and read test(master rx and slave tx)", "[i2s]")
|
||||
#endif
|
||||
};
|
||||
i2s_pin_config_t master_pin_config = {
|
||||
.mck_io_num = -1,
|
||||
.bck_io_num = MASTER_BCK_IO,
|
||||
.ws_io_num = MASTER_WS_IO,
|
||||
.data_out_num = -1,
|
||||
@ -404,6 +481,7 @@ TEST_CASE("I2S write and read test(master rx and slave tx)", "[i2s]")
|
||||
#endif
|
||||
};
|
||||
i2s_pin_config_t slave_pin_config = {
|
||||
.mck_io_num = -1,
|
||||
.bck_io_num = SLAVE_BCK_IO,
|
||||
.ws_io_num = SLAVE_WS_IO,
|
||||
.data_out_num = DATA_OUT_IO,
|
||||
@ -477,6 +555,7 @@ TEST_CASE("I2S memory leaking test", "[i2s]")
|
||||
#endif
|
||||
};
|
||||
i2s_pin_config_t master_pin_config = {
|
||||
.mck_io_num = -1,
|
||||
.bck_io_num = MASTER_BCK_IO,
|
||||
.ws_io_num = MASTER_WS_IO,
|
||||
.data_out_num = -1,
|
||||
@ -507,6 +586,7 @@ TEST_CASE("I2S memory leaking test", "[i2s]")
|
||||
TEST_CASE("I2S APLL clock variation test", "[i2s]")
|
||||
{
|
||||
i2s_pin_config_t pin_config = {
|
||||
.mck_io_num = -1,
|
||||
.bck_io_num = MASTER_BCK_IO,
|
||||
.ws_io_num = MASTER_WS_IO,
|
||||
.data_out_num = DATA_OUT_IO,
|
||||
|
6
examples/peripherals/i2s/i2s_es8311/CMakeLists.txt
Normal file
6
examples/peripherals/i2s/i2s_es8311/CMakeLists.txt
Normal file
@ -0,0 +1,6 @@
|
||||
# The following lines of boilerplate have to be in your project's CMakeLists
|
||||
# in this exact order for cmake to work correctly
|
||||
cmake_minimum_required(VERSION 3.5)
|
||||
|
||||
include($ENV{IDF_PATH}/tools/cmake/project.cmake)
|
||||
project(i2s-es8311-example)
|
147
examples/peripherals/i2s/i2s_es8311/README.md
Normal file
147
examples/peripherals/i2s/i2s_es8311/README.md
Normal file
@ -0,0 +1,147 @@
|
||||
# I2S ES8311 Example
|
||||
|
||||
(See the README.md file in the upper level 'examples' directory for more information about examples.)
|
||||
|
||||
In this example, you can choose music mode or echo mode in menuconfig. In music mode, the example will play a piece of music in 'canon.pcm', and in echo mode, you can hear what you said in earphone.
|
||||
|
||||
## ES8311 brief
|
||||
|
||||
ES8311 low power mono audio codec features:
|
||||
|
||||
- High performance and low power multi-bit delta-sigma audio ADC and DAC
|
||||
- I2S/PCM master or slave serial data port
|
||||
- I2C interface for configuration
|
||||
- ADC: 24-bit, 8 to 96 kHz sampling frequency
|
||||
- ADC: 100 dB signal to noise ratio, -93 dB THD+N
|
||||
- DAC: 24-bit, 8 to 96 kHz sampling frequency
|
||||
- DAC: 110 dB signal to noise ratio, -80 dB THD+N
|
||||
|
||||
For more details, see [ES8311 datasheet](http://www.everest-semi.com/pdf/ES8311%20PB.pdf)
|
||||
|
||||
## How to Use Example
|
||||
|
||||
### Hardware Required
|
||||
|
||||
* An ESP development board that support I2S.
|
||||
* A USB cable for power supply and programming.
|
||||
* A board with ES8311 codec, mic and earphone interface(e.g. ESP-LyraT-8311A extension board).
|
||||
|
||||
### Connection
|
||||
```
|
||||
┌─────────────────┐ ┌──────────────────────────┐
|
||||
│ ESP │ │ ES8311 │
|
||||
│ │ │ │
|
||||
│ MCLK-GPIO 0 ├──────────►│PIN2-MCLK │
|
||||
│ │ │ │ ┌─────────┐
|
||||
│ BCLK-GPIO 4 ├──────────►│PIN6-BCLK PIN12-OUTP├───────────┤ │
|
||||
│ │ │ │ │ EARPHONE│
|
||||
│ WS-GPIO 5 ├──────────►│PIN8-LRCK PIN13-OUTN├───────────┤ │
|
||||
│ │ │ │ └─────────┘
|
||||
│ SDOUT-GPIO 18├──────────►│PIN9-SDIN │
|
||||
│ │ │ │
|
||||
│ SDIN-GPIO 19│◄──────────┤PIN7-SDOUT │
|
||||
│ │ │ │ ┌─────────┐
|
||||
│ │ │ PIN18-MIC1P├───────────┤ │
|
||||
│ SCL-GPIO 16├──────────►│PIN1 -CCLK │ │ MIC │
|
||||
│ (GPIO 7)│ │ PIN17-MIC1N├───────────┤ │
|
||||
│ SDA-GPIO 17│◄─────────►│PIN19-CDATA │ └─────────┘
|
||||
│ (GPIO 8)│ │ │
|
||||
│ VCC 3.3├───────────┤VCC │
|
||||
│ │ │ │
|
||||
│ GND├───────────┤GND │
|
||||
└─────────────────┘ └──────────────────────────┘
|
||||
```
|
||||
Note: Since ESP32-C3 board does not have GPIO 16/17, you can use other available GPIOs instead. In this example, we set GPIO 7/8 as I2C pins for ESP32-C3 and GPIO 16/17 for other chips.
|
||||
|
||||
### Dependency
|
||||
|
||||
This example is based on [es8311 component](https://components.espressif.com/component/espressif/es8311)
|
||||
|
||||
The component can be installed by esp component manager. Since this example already installed it, no need to re-installed it again, but if you want to install this component in your own project, you can input the following command:
|
||||
```
|
||||
idf.py add-dependency espressif/es8311==0.0.2-alpha
|
||||
```
|
||||
|
||||
If dependency is added, you can check `idf_component.yml` for more detail. When building this example or other project with managed-component in it, the component manager will search the componet online and download it under `managed_componets` folder.
|
||||
|
||||
### Configure the Project
|
||||
|
||||
```
|
||||
idf.py menuconfig
|
||||
```
|
||||
You can find configurations for this example in 'Example Configutation' tag.
|
||||
|
||||
* In 'Example mode' subtag, you can set the example mode to 'music' or 'echo'. You can hear a piece of music in 'music' mode and echo the sound sampled by mic in 'echo' mode. You can also customize you own music to play as shown below.
|
||||
|
||||
* In 'Set MIC gain' subtag, you can set the mic gain for echo mode.
|
||||
|
||||
* In 'Voice volume', you can set the volum between 0 to 100.
|
||||
|
||||
### Build and Flash
|
||||
|
||||
Build the project and flash it to the board, then run monitor tool to view serial output:
|
||||
|
||||
```
|
||||
idf.py -p PORT flash monitor
|
||||
```
|
||||
|
||||
(To exit the serial monitor, type ``Ctrl-]``.)
|
||||
|
||||
See the Getting Started Guide for full steps to configure and use ESP-IDF to build projects.
|
||||
|
||||
## Example Output
|
||||
|
||||
Running this example in music mode, you can hear a piece of music (canon), the log is shown as follow:
|
||||
|
||||
```
|
||||
I (348) I2S: DMA Malloc info, datalen=blocksize=1200, dma_buf_count=6
|
||||
I (348) I2S: DMA Malloc info, datalen=blocksize=1200, dma_buf_count=6
|
||||
I (358) I2S: I2S0, MCLK output by GPIO0
|
||||
I (368) DRV8311: ES8311 in Slave mode
|
||||
I (378) gpio: GPIO[10]| InputEn: 0| OutputEn: 1| OpenDrain: 0| Pullup: 0| Pulldown: 0| Intr:0
|
||||
I (3718) i2s_es8311: I2S music played, 213996 bytes are written.
|
||||
I (7948) i2s_es8311: I2S music played, 213996 bytes are written.
|
||||
......
|
||||
```
|
||||
|
||||
Running this example in echo mode, you can hear the sound in earphone that collected by mic.
|
||||
```
|
||||
I (312) I2S: DMA Malloc info, datalen=blocksize=1200, dma_buf_count=6
|
||||
I (312) I2S: DMA Malloc info, datalen=blocksize=1200, dma_buf_count=6
|
||||
I (322) I2S: I2S0, MCLK output by GPIO0
|
||||
I (332) DRV8311: ES8311 in Slave mode
|
||||
I (342) gpio: GPIO[10]| InputEn: 0| OutputEn: 1| OpenDrain: 0| Pullup: 0| Pulldown: 0| Intr:0
|
||||
```
|
||||
|
||||
If you have a logic analyzer, you can use a logic analyzer to grab GPIO signal directly. The following table describes the pins we use by default (Note that you can also use other pins for the same purpose).
|
||||
|
||||
| pin name| function | gpio_num |
|
||||
|:---:|:---:|:---:|
|
||||
| MCLK |module clock | GPIO_NUM_0|
|
||||
| BCLK |bit clock | GPIO_NUM_4 |
|
||||
| WS |word select | GPIO_NUM_5 |
|
||||
| SDOUT |serial data out| GPIO_NUM_18 |
|
||||
| SDIN |serial data in | GPIO_NUM_19 |
|
||||
|
||||
### Customize your own music
|
||||
|
||||
The example have contained a piece of music in canon.pcm, if you want to play your own music, you can follow these steps:
|
||||
|
||||
1. Choose the music in any format you want to play (e.g. a.mp3)
|
||||
2. Install 'ffmpeg' tool
|
||||
3. Check your music format using ```ffprobe a.mp3```, you can get the stream format (e.g. Stream #0.0: Audio: mp3, 44100Hz, stereo, s16p, 64kb/s)
|
||||
4. Cut your music since there is no enough space for the whole piece of music. ```ffmpeg -i a.mp3 -ss 00:00:00 -t 00:00:20 a_cut.mp3```
|
||||
5. Transfer the music format into .pcm. ```ffmpeg -i a_cut.mp3 -f s16ls -ar 16000 -ac -1 -acodec pcm_s16le a.pcm```
|
||||
6. Move 'a.pcm' under 'main' directory
|
||||
7. Replace 'canon.pcm' with 'a.pcm' in 'CMakeLists.txt' under 'main' directory
|
||||
8. Replace '_binary_canon_pcm_start' and '_binary_canon_pcm_end' with '_binary_a_pcm_start' and '_binary_a_pcm_end' in `i2s_es9311_example.c`(line 46/47)
|
||||
9. Download the example and enjoy your own music
|
||||
|
||||
## Troubleshooting
|
||||
|
||||
* Program upload failure
|
||||
|
||||
* Hardware connection is not correct: run `idf.py -p PORT monitor`, and reboot your board to see if there are any output logs.
|
||||
* The baud rate for downloading is too high: lower your baud rate in the `menuconfig` menu, and try again.
|
||||
|
||||
For any technical queries, please open an [issue](https://github.com/espressif/esp-idf/issues) on GitHub. We will get back to you soon.
|
2
examples/peripherals/i2s/i2s_es8311/main/CMakeLists.txt
Normal file
2
examples/peripherals/i2s/i2s_es8311/main/CMakeLists.txt
Normal file
@ -0,0 +1,2 @@
|
||||
idf_component_register(SRCS "i2s_es8311_example.c"
|
||||
EMBED_FILES "canon.pcm")
|
58
examples/peripherals/i2s/i2s_es8311/main/Kconfig.projbuild
Normal file
58
examples/peripherals/i2s/i2s_es8311/main/Kconfig.projbuild
Normal file
@ -0,0 +1,58 @@
|
||||
menu "Example Configuration"
|
||||
|
||||
choice EXAMPLE_MODE
|
||||
prompt "Example mode"
|
||||
default EXAMPLE_MODE_MUSIC
|
||||
help
|
||||
Select example work mode
|
||||
|
||||
config EXAMPLE_MODE_MUSIC
|
||||
bool "music"
|
||||
config EXAMPLE_MODE_ECHO
|
||||
bool "echo"
|
||||
endchoice
|
||||
|
||||
choice EXAMPLE_SELECT_MIC_GAIN
|
||||
prompt "Set MIC gain"
|
||||
depends on EXAMPLE_MODE_ECHO
|
||||
default MIC_GAIN_18DB
|
||||
help
|
||||
Select mic gain for echo mode
|
||||
|
||||
config MIC_GAIN_0DB
|
||||
bool "0dB"
|
||||
config MIC_GAIN_6DB
|
||||
bool "6dB"
|
||||
config MIC_GAIN_12DB
|
||||
bool "12dB"
|
||||
config MIC_GAIN_18DB
|
||||
bool "18dB"
|
||||
config MIC_GAIN_24DB
|
||||
bool "24dB"
|
||||
config MIC_GAIN_30DB
|
||||
bool "30dB"
|
||||
config MIC_GAIN_36DB
|
||||
bool "36dB"
|
||||
config MIC_GAIN_42DB
|
||||
bool "42dB"
|
||||
endchoice
|
||||
|
||||
config EXAMPLE_MIC_GAIN
|
||||
int
|
||||
default 0 if MIC_GAIN_0DB
|
||||
default 1 if MIC_GAIN_6DB
|
||||
default 2 if MIC_GAIN_12DB
|
||||
default 3 if MIC_GAIN_18DB
|
||||
default 4 if MIC_GAIN_24DB
|
||||
default 5 if MIC_GAIN_30DB
|
||||
default 6 if MIC_GAIN_36DB
|
||||
default 7 if MIC_GAIN_42DB
|
||||
|
||||
config EXAMPLE_VOICE_VOLUME
|
||||
int "Voice volume"
|
||||
range 0 100
|
||||
default 60
|
||||
help
|
||||
Set voice volume
|
||||
|
||||
endmenu
|
BIN
examples/peripherals/i2s/i2s_es8311/main/canon.pcm
Normal file
BIN
examples/peripherals/i2s/i2s_es8311/main/canon.pcm
Normal file
Binary file not shown.
204
examples/peripherals/i2s/i2s_es8311/main/i2s_es8311_example.c
Normal file
204
examples/peripherals/i2s/i2s_es8311/main/i2s_es8311_example.c
Normal file
@ -0,0 +1,204 @@
|
||||
/*
|
||||
* SPDX-FileCopyrightText: 2021 Espressif Systems (Shanghai) CO LTD
|
||||
*
|
||||
* SPDX-License-Identifier: CC0-1.0
|
||||
*/
|
||||
|
||||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
#include "freertos/FreeRTOS.h"
|
||||
#include "freertos/task.h"
|
||||
#include "driver/i2s.h"
|
||||
#include "esp_system.h"
|
||||
#include "esp_check.h"
|
||||
#include "es8311.h"
|
||||
|
||||
/* I2C port and GPIOs */
|
||||
#define I2C_NUM (0)
|
||||
#ifdef CONFIG_IDF_TARGET_ESP32C3
|
||||
#define I2C_SDA_IO (GPIO_NUM_17)
|
||||
#define I2C_SCL_IO (GPIO_NUM_16)
|
||||
#else
|
||||
#define I2C_SDA_IO (GPIO_NUM_15)
|
||||
#define I2C_SCL_IO (GPIO_NUM_14)
|
||||
#endif
|
||||
|
||||
/* I2S port and GPIOs */
|
||||
#define I2S_NUM (0)
|
||||
#define I2S_MCK_IO (GPIO_NUM_0)
|
||||
#define I2S_BCK_IO (GPIO_NUM_4)
|
||||
#define I2S_WS_IO (GPIO_NUM_5)
|
||||
#define I2S_DO_IO (GPIO_NUM_18)
|
||||
#define I2S_DI_IO (GPIO_NUM_19)
|
||||
|
||||
/* Example configurations */
|
||||
#define EXAMPLE_RECV_BUF_SIZE (2048)
|
||||
#define EXAMPLE_SAMPLE_RATE (16000)
|
||||
#define EXAMPLE_MCLK_MULTIPLE I2S_MCLK_MULTIPLE_256
|
||||
#define EXAMPLE_VOICE_VOLUME CONFIG_EXAMPLE_VOICE_VOLUME
|
||||
#if CONFIG_EXAMPLE_MODE_ECHO
|
||||
#define EXAMPLE_MIC_GAIN CONFIG_EXAMPLE_MIC_GAIN
|
||||
#endif
|
||||
|
||||
static const char *TAG = "i2s_es8311";
|
||||
static const char err_reason[][30] = {"input param is invalid",
|
||||
"operation timeout"
|
||||
};
|
||||
|
||||
/* Import music file as buffer */
|
||||
#if CONFIG_EXAMPLE_MODE_MUSIC
|
||||
extern const uint8_t music_pcm_start[] asm("_binary_canon_pcm_start");
|
||||
extern const uint8_t music_pcm_end[] asm("_binary_canon_pcm_end");
|
||||
#endif
|
||||
|
||||
static esp_err_t es8311_codec_init(void)
|
||||
{
|
||||
/* Initialize I2C peripheral */
|
||||
i2c_config_t es_i2c_cfg = {
|
||||
.sda_io_num = I2C_SDA_IO,
|
||||
.scl_io_num = I2C_SCL_IO,
|
||||
.mode = I2C_MODE_MASTER,
|
||||
.sda_pullup_en = GPIO_PULLUP_ENABLE,
|
||||
.scl_pullup_en = GPIO_PULLUP_ENABLE,
|
||||
.master.clk_speed = 100000,
|
||||
};
|
||||
ESP_RETURN_ON_ERROR(i2c_param_config(I2C_NUM, &es_i2c_cfg), TAG, "config i2c failed");
|
||||
ESP_RETURN_ON_ERROR(i2c_driver_install(I2C_NUM, I2C_MODE_MASTER, 0, 0, 0), TAG, "install i2c driver failed");
|
||||
|
||||
/* Initialize es8311 codec */
|
||||
es8311_handle_t es_handle = es8311_create(I2C_NUM, ES8311_ADDRRES_0);
|
||||
ESP_RETURN_ON_FALSE(es_handle, ESP_FAIL, TAG, "es8311 create failed");
|
||||
es8311_clock_config_t es_clk = {
|
||||
.mclk_from_mclk_pin = true,
|
||||
.sample_frequency = EXAMPLE_SAMPLE_RATE
|
||||
};
|
||||
|
||||
es8311_init(es_handle, &es_clk, ES8311_RESOLUTION_16, ES8311_RESOLUTION_16);
|
||||
ESP_RETURN_ON_ERROR(es8311_sample_frequency_config(es_handle, EXAMPLE_SAMPLE_RATE * EXAMPLE_MCLK_MULTIPLE, EXAMPLE_SAMPLE_RATE), TAG, "set es8311 sample frequency failed");
|
||||
ESP_RETURN_ON_ERROR(es8311_voice_volume_set(es_handle, EXAMPLE_VOICE_VOLUME, NULL), TAG, "set es8311 volume failed");
|
||||
ESP_RETURN_ON_ERROR(es8311_microphone_config(es_handle, false), TAG, "set es8311 microphone failed");
|
||||
#if CONFIG_EXAMPLE_MODE_ECHO
|
||||
ESP_RETURN_ON_ERROR(es8311_microphone_gain_set(es_handle, EXAMPLE_MIC_GAIN), TAG, "set es8311 microphone gain faield");
|
||||
#endif
|
||||
return ESP_OK;
|
||||
}
|
||||
|
||||
static esp_err_t i2s_driver_init(void)
|
||||
{
|
||||
i2s_config_t i2s_cfg = {
|
||||
.mode = I2S_MODE_MASTER | I2S_MODE_TX | I2S_MODE_RX,
|
||||
.sample_rate = EXAMPLE_SAMPLE_RATE,
|
||||
.bits_per_sample = I2S_BITS_PER_SAMPLE_16BIT,
|
||||
.channel_format = I2S_CHANNEL_FMT_RIGHT_LEFT,
|
||||
.communication_format = I2S_COMM_FORMAT_STAND_I2S,
|
||||
.tx_desc_auto_clear = true,
|
||||
#if SOC_I2S_SUPPORTS_TDM
|
||||
.total_chan = 2,
|
||||
.chan_mask = I2S_TDM_ACTIVE_CH0 | I2S_TDM_ACTIVE_CH1,
|
||||
.left_align = false,
|
||||
.big_edin = false,
|
||||
.bit_order_msb = false,
|
||||
.skip_msk = false,
|
||||
#endif
|
||||
.dma_buf_count = 8,
|
||||
.dma_buf_len = 64,
|
||||
.use_apll = false,
|
||||
.mclk_multiple = EXAMPLE_MCLK_MULTIPLE,
|
||||
.intr_alloc_flags = ESP_INTR_FLAG_LEVEL1,
|
||||
};
|
||||
|
||||
ESP_RETURN_ON_ERROR(i2s_driver_install(I2S_NUM, &i2s_cfg, 0, NULL), TAG, "install i2s failed");
|
||||
i2s_pin_config_t i2s_pin_cfg = {
|
||||
.mck_io_num = I2S_MCK_IO,
|
||||
.bck_io_num = I2S_BCK_IO,
|
||||
.ws_io_num = I2S_WS_IO,
|
||||
.data_out_num = I2S_DO_IO,
|
||||
.data_in_num = I2S_DI_IO
|
||||
};
|
||||
ESP_RETURN_ON_ERROR(i2s_set_pin(I2S_NUM, &i2s_pin_cfg), TAG, "set i2s pins failed");
|
||||
return ESP_OK;
|
||||
}
|
||||
|
||||
#if CONFIG_EXAMPLE_MODE_MUSIC
|
||||
static void i2s_music(void *args)
|
||||
{
|
||||
esp_err_t ret = ESP_OK;
|
||||
size_t bytes_write = 0;
|
||||
while (1) {
|
||||
/* Write music to earphone */
|
||||
ret = i2s_write(I2S_NUM, music_pcm_start, music_pcm_end - music_pcm_start, &bytes_write, portMAX_DELAY);
|
||||
if (ret != ESP_OK) {
|
||||
/* Since we set timeout to 'portMAX_DELAY' in 'i2s_write'
|
||||
so you won't reach here unless you set other timeout value,
|
||||
if timeout detected, it means write operation failed. */
|
||||
ESP_LOGE(TAG, "[music] i2s read failed, %s", err_reason[ret == ESP_ERR_TIMEOUT]);
|
||||
abort();
|
||||
}
|
||||
/* Clear DMA buffer to avoid noise from legacy data in buffer */
|
||||
i2s_zero_dma_buffer(I2S_NUM);
|
||||
if (bytes_write > 0) {
|
||||
ESP_LOGI(TAG, "[music] i2s music played, %d bytes are written.", bytes_write);
|
||||
} else {
|
||||
ESP_LOGE(TAG, "[music] i2s music play falied.");
|
||||
abort();
|
||||
}
|
||||
vTaskDelay(1000 / portTICK_RATE_MS);
|
||||
}
|
||||
vTaskDelete(NULL);
|
||||
}
|
||||
|
||||
#else
|
||||
static void i2s_echo(void *args)
|
||||
{
|
||||
int *mic_data = malloc(EXAMPLE_RECV_BUF_SIZE);
|
||||
if (!mic_data) {
|
||||
ESP_LOGE(TAG, "[echo] No memory for read data buffer");
|
||||
abort();
|
||||
}
|
||||
esp_err_t ret = ESP_OK;
|
||||
size_t bytes_read = 0;
|
||||
size_t bytes_write = 0;
|
||||
ESP_LOGI(TAG, "[echo] Echo start");
|
||||
|
||||
while (1) {
|
||||
memset(mic_data, 0, EXAMPLE_RECV_BUF_SIZE);
|
||||
/* Read sample data from mic */
|
||||
ret = i2s_read(I2S_NUM, mic_data, EXAMPLE_RECV_BUF_SIZE, &bytes_read, 100);
|
||||
if (ret != ESP_OK) {
|
||||
ESP_LOGE(TAG, "[echo] i2s read failed, %s", err_reason[ret == ESP_ERR_TIMEOUT]);
|
||||
abort();
|
||||
}
|
||||
/* Write sample data to earphone */
|
||||
ret = i2s_write(I2S_NUM, mic_data, EXAMPLE_RECV_BUF_SIZE, &bytes_write, 100);
|
||||
if (ret != ESP_OK) {
|
||||
ESP_LOGE(TAG, "[echo] i2s write failed, %s", err_reason[ret == ESP_ERR_TIMEOUT]);
|
||||
abort();
|
||||
}
|
||||
if (bytes_read != bytes_write) {
|
||||
ESP_LOGW(TAG, "[echo] %d bytes read but only %d bytes are written", bytes_read, bytes_write);
|
||||
}
|
||||
}
|
||||
vTaskDelete(NULL);
|
||||
}
|
||||
#endif
|
||||
|
||||
void app_main(void)
|
||||
{
|
||||
/* Initialize i2s peripheral */
|
||||
if (i2s_driver_init() != ESP_OK) {
|
||||
ESP_LOGE(TAG, "i2s driver init failed");
|
||||
abort();
|
||||
}
|
||||
/* Initialize i2c peripheral and config es8311 codec by i2c */
|
||||
if (es8311_codec_init() != ESP_OK) {
|
||||
ESP_LOGE(TAG, "es8311 codec init failed");
|
||||
abort();
|
||||
}
|
||||
#if CONFIG_EXAMPLE_MODE_MUSIC
|
||||
/* Play a piece of music in music mode */
|
||||
xTaskCreate(i2s_music, "i2s_music", 4096, NULL, 5, NULL);
|
||||
#else
|
||||
/* Echo the sound from MIC in echo mode */
|
||||
xTaskCreate(i2s_echo, "i2s_echo", 8192, NULL, 5, NULL);
|
||||
#endif
|
||||
}
|
16
examples/peripherals/i2s/i2s_es8311/main/idf_component.yml
Normal file
16
examples/peripherals/i2s/i2s_es8311/main/idf_component.yml
Normal file
@ -0,0 +1,16 @@
|
||||
## IDF Component Manager Manifest File
|
||||
## Version of your project. Should conform Semantic Versioning 2.0 rules https://semver.org/
|
||||
version: "1.0.0"
|
||||
|
||||
dependencies:
|
||||
espressif/es8311: "==0.0.2-alpha"
|
||||
## Required IDF version
|
||||
idf:
|
||||
version: "^4.4"
|
||||
# # Put list of dependencies here
|
||||
# # For components maintained by Espressif:
|
||||
# component:
|
||||
# version: "~1.0.0"
|
||||
# # For 3rd party components:
|
||||
# username/component:
|
||||
# version: "~1.0.0"
|
@ -7,3 +7,4 @@ build_system/cmake/
|
||||
mb_example_common/
|
||||
examples/cxx/experimental/blink_cxx
|
||||
examples/peripherals/lcd/lvgl
|
||||
examples/peripherals/i2s/i2s_es8311
|
||||
|
Loading…
x
Reference in New Issue
Block a user