2021-06-15 03:53:44 -04:00
/*
* 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 = {
2022-10-26 06:28:30 -04:00
. mclk_inverted = false ,
. sclk_inverted = false ,
2021-06-15 03:53:44 -04:00
. mclk_from_mclk_pin = true ,
2022-10-26 06:28:30 -04:00
. mclk_frequency = EXAMPLE_SAMPLE_RATE * EXAMPLE_MCLK_MULTIPLE ,
2021-06-15 03:53:44 -04:00
. 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
}