diff --git a/components/audio_board/CMakeLists.txt b/components/audio_board/CMakeLists.txt index 82bba4c80..4476f6444 100644 --- a/components/audio_board/CMakeLists.txt +++ b/components/audio_board/CMakeLists.txt @@ -79,6 +79,15 @@ set(COMPONENT_SRCS ) endif() +if (CONFIG_ESP32_S3_CUSTOM_BOARD) +message(STATUS "Current board name is " CONFIG_ESP32_S3_CUSTOM_BOARD) +list(APPEND COMPONENT_ADD_INCLUDEDIRS ./esp32_s3_custom) +set(COMPONENT_SRCS +./esp32_s3_custom/board.c +./esp32_s3_custom/board_pins_config.c +) +endif() + if (CONFIG_ESP32_S3_KORVO2L_V1_BOARD) message(STATUS "Current board name is " CONFIG_ESP32_S3_KORVO2L_V1_BOARD) list(APPEND COMPONENT_ADD_INCLUDEDIRS ./esp32_s3_korvo2l_v1) diff --git a/components/audio_board/Kconfig.projbuild b/components/audio_board/Kconfig.projbuild index ba68fb09a..74e9cee27 100644 --- a/components/audio_board/Kconfig.projbuild +++ b/components/audio_board/Kconfig.projbuild @@ -23,6 +23,8 @@ config ESP32_S2_KALUGA_1_V1_2_BOARD bool "ESP32-S2-Kaluga-1 v1.2" config ESP32_S3_KORVO2_V3_BOARD bool "ESP32-S3-Korvo-2 v3" +config ESP32_S3_CUSTOM_BOARD + bool "ESP32-S3-custom" config ESP32_S3_KORVO2L_V1_BOARD bool "ESP32-S3-Korvo-2L v1" config ESP32_S3_BOX_LITE_BOARD diff --git a/components/audio_board/component.mk b/components/audio_board/component.mk index 61cf50f35..8289aa803 100644 --- a/components/audio_board/component.mk +++ b/components/audio_board/component.mk @@ -47,6 +47,11 @@ COMPONENT_ADD_INCLUDEDIRS += ./esp32_s3_korvo2_v3 COMPONENT_SRCDIRS += ./esp32_s3_korvo2_v3 endif +ifdef CONFIG_ESP32_S3_CUSTOM_BOARD +COMPONENT_ADD_INCLUDEDIRS += ./esp32_s3_custom +COMPONENT_SRCDIRS += ./esp32_s3_custom +endif + ifdef CONFIG_ESP32_C3_LYRA_V2_BOARD COMPONENT_ADD_INCLUDEDIRS += ./esp32_c3_lyra COMPONENT_SRCDIRS += ./esp32_c3_lyra diff --git a/components/audio_board/esp32_s3_box/board_def.h b/components/audio_board/esp32_s3_box/board_def.h index f9df7cba0..d24c0945a 100644 --- a/components/audio_board/esp32_s3_box/board_def.h +++ b/components/audio_board/esp32_s3_box/board_def.h @@ -29,8 +29,8 @@ * @brief LCD SCREEN Function Definition */ #define FUNC_LCD_SCREEN_EN (1) -#define LCD_CTRL_GPIO GPIO_NUM_45 -#define LCD_RST_GPIO GPIO_NUM_48 +#define LCD_CTRL_GPIO GPIO_NUM_35 +#define LCD_RST_GPIO GPIO_NUM_38 #define LCD_DC_GPIO GPIO_NUM_4 #define LCD_CS_GPIO GPIO_NUM_5 #define LCD_CLK_GPIO GPIO_NUM_7 @@ -84,7 +84,7 @@ #define CODEC_ADC_SAMPLE_RATE (48000) #define RECORD_HARDWARE_AEC (true) #define BOARD_PA_GAIN (0) /* Power amplifier gain defined by board (dB) */ -#define PA_ENABLE_GPIO GPIO_NUM_46 +#define PA_ENABLE_GPIO GPIO_NUM_36 #define HEADPHONE_DETECT -1 #define ES7210_MIC_SELECT (ES7210_INPUT_MIC1 | ES7210_INPUT_MIC2 | ES7210_INPUT_MIC3) diff --git a/components/audio_board/esp32_s3_box/board_pins_config.c b/components/audio_board/esp32_s3_box/board_pins_config.c index 249b5fea1..a6efa5f89 100644 --- a/components/audio_board/esp32_s3_box/board_pins_config.c +++ b/components/audio_board/esp32_s3_box/board_pins_config.c @@ -52,7 +52,7 @@ esp_err_t get_i2s_pins(int port, board_i2s_pin_t *i2s_config) AUDIO_NULL_CHECK(TAG, i2s_config, return ESP_FAIL); if (port == 0) { i2s_config->bck_io_num = GPIO_NUM_17; - i2s_config->ws_io_num = GPIO_NUM_47; + i2s_config->ws_io_num = GPIO_NUM_37; i2s_config->data_out_num = GPIO_NUM_15; i2s_config->data_in_num = GPIO_NUM_16; i2s_config->mck_io_num = GPIO_NUM_2; diff --git a/components/audio_board/esp32_s3_custom/CMakeLists.txt b/components/audio_board/esp32_s3_custom/CMakeLists.txt new file mode 100644 index 000000000..58bb8c792 --- /dev/null +++ b/components/audio_board/esp32_s3_custom/CMakeLists.txt @@ -0,0 +1,164 @@ +set(COMPONENT_ADD_INCLUDEDIRS ./include) + +# Edit following two lines to set component requirements (see docs) +set(COMPONENT_REQUIRES ) +set(COMPONENT_PRIV_REQUIRES esp_peripherals audio_sal audio_hal esp_dispatcher display_service) + + +if (CONFIG_ESP_LYRAT_V4_2_BOARD) +message(STATUS "Current board name is " CONFIG_ESP_LYRAT_V4_2_BOARD) +list(APPEND COMPONENT_ADD_INCLUDEDIRS ./lyrat_v4_2) +set(COMPONENT_SRCS +./lyrat_v4_2/board.c +./lyrat_v4_2/board_pins_config.c +) +endif() + +if (CONFIG_ESP_LYRAT_V4_3_BOARD) +message(STATUS "Current board name is " CONFIG_ESP_LYRAT_V4_3_BOARD) +list(APPEND COMPONENT_ADD_INCLUDEDIRS ./lyrat_v4_3) +set(COMPONENT_SRCS +./lyrat_v4_3/board.c +./lyrat_v4_3/board_pins_config.c +) +endif() + +if (CONFIG_ESP_LYRAT_MINI_V1_1_BOARD) +message(STATUS "Current board name is " CONFIG_ESP_LYRAT_MINI_V1_1_BOARD) +list(APPEND COMPONENT_ADD_INCLUDEDIRS ./lyrat_mini_v1_1) +set(COMPONENT_SRCS +./lyrat_mini_v1_1/board.c +./lyrat_mini_v1_1/board_pins_config.c +) +endif() + + +if (CONFIG_ESP_LYRATD_MSC_V2_1_BOARD) +message(STATUS "Current board name is " CONFIG_ESP_LYRATD_MSC_V2_1_BOARD) +list(APPEND COMPONENT_ADD_INCLUDEDIRS ./lyratd_msc_v2_1) +set(COMPONENT_SRCS +./lyratd_msc_v2_1/board.c +./lyratd_msc_v2_1/board_pins_config.c +) +endif() + +if (CONFIG_ESP_LYRATD_MSC_V2_2_BOARD) +message(STATUS "Current board name is " CONFIG_ESP_LYRATD_MSC_V2_2_BOARD) +list(APPEND COMPONENT_ADD_INCLUDEDIRS ./lyratd_msc_v2_2) +set(COMPONENT_SRCS +./lyratd_msc_v2_2/board.c +./lyratd_msc_v2_2/board_pins_config.c +) +endif() + +if (CONFIG_ESP32_KORVO_DU1906_BOARD) +message(STATUS "Current board name is " CONFIG_ESP32_KORVO_DU1906_BOARD) +list(APPEND COMPONENT_ADD_INCLUDEDIRS ./esp32_korvo_du1906) +set(COMPONENT_SRCS +./esp32_korvo_du1906/board.c +./esp32_korvo_du1906/board_pins_config.c +./esp32_korvo_du1906/du1906_bar_pattern.c +) +endif() + +if (CONFIG_ESP32_S2_KALUGA_1_V1_2_BOARD) +message(STATUS "Current board name is " CONFIG_ESP32_S2_KALUGA_1_V1_2_BOARD) +list(APPEND COMPONENT_ADD_INCLUDEDIRS ./esp32_s2_kaluga_1_v1_2) +set(COMPONENT_SRCS +./esp32_s2_kaluga_1_v1_2/board.c +./esp32_s2_kaluga_1_v1_2/board_pins_config.c +) +endif() + +if (CONFIG_ESP32_S3_KORVO2_V3_BOARD) +message(STATUS "Current board name is " CONFIG_ESP32_S3_KORVO2_V3_BOARD) +list(APPEND COMPONENT_ADD_INCLUDEDIRS ./esp32_s3_korvo2_v3) +set(COMPONENT_SRCS +./esp32_s3_korvo2_v3/board.c +./esp32_s3_korvo2_v3/board_pins_config.c +) +endif() + +if (CONFIG_ESP32_S3_CUSTOM_BOARD) +message(STATUS "Current board name is " CONFIG_ESP32_S3_CUSTOM_BOARD) +list(APPEND COMPONENT_ADD_INCLUDEDIRS ./esp32_s3_custom) +set(COMPONENT_SRCS +./esp32_s3_custom/board.c +./esp32_s3_custom/board_pins_config.c +) +endif() + +if (CONFIG_ESP32_S3_KORVO2L_V1_BOARD) +message(STATUS "Current board name is " CONFIG_ESP32_S3_KORVO2L_V1_BOARD) +list(APPEND COMPONENT_ADD_INCLUDEDIRS ./esp32_s3_korvo2l_v1) +set(COMPONENT_SRCS +./esp32_s3_korvo2l_v1/board.c +./esp32_s3_korvo2l_v1/board_pins_config.c +) +endif() + +if (CONFIG_ESP32_S3_BOX_LITE_BOARD) +message(STATUS "Current board name is " CONFIG_ESP32_S3_BOX_LITE_BOARD) +list(APPEND COMPONENT_ADD_INCLUDEDIRS ./esp32_s3_box_lite) +set(COMPONENT_SRCS +./esp32_s3_box_lite/board.c +./esp32_s3_box_lite/board_pins_config.c +) +endif() + +if (CONFIG_ESP32_S3_BOX_BOARD) +message(STATUS "Current board name is " CONFIG_ESP32_S3_BOX_BOARD) +list(APPEND COMPONENT_ADD_INCLUDEDIRS ./esp32_s3_box) +set(COMPONENT_SRCS +./esp32_s3_box/board.c +./esp32_s3_box/board_pins_config.c +) +endif() + +if (CONFIG_ESP32_S3_BOX_3_BOARD) +message(STATUS "Current board name is " CONFIG_ESP32_S3_BOX_3_BOARD) +list(APPEND COMPONENT_ADD_INCLUDEDIRS ./esp32_s3_box_3) +set(COMPONENT_SRCS +./esp32_s3_box_3/board.c +./esp32_s3_box_3/board_pins_config.c +) +endif() + +if (CONFIG_M5STACK_ATOMS3R_BOARD) +message(STATUS "Current board name is " CONFIG_M5STACK_ATOMS3R_BOARD) +list(APPEND COMPONENT_ADD_INCLUDEDIRS ./m5stack_atoms3r) +set(COMPONENT_SRCS +./m5stack_atoms3r/board.c +./m5stack_atoms3r/board_pins_config.c +) +endif() + +if (CONFIG_ESP32_C3_LYRA_V2_BOARD) +message(STATUS "Current board name is " CONFIG_ESP32_C3_LYRA_V2_BOARD) +list(APPEND COMPONENT_ADD_INCLUDEDIRS ./esp32_c3_lyra) +set(COMPONENT_SRCS +./esp32_c3_lyra/board.c +./esp32_c3_lyra/board_pins_config.c +./esp32_c3_lyra/C3_lyra_sys_pattern.c +) +endif() + +if (CONFIG_ESP32_C6_DEVKIT_BOARD) +message(STATUS "Current board name is " CONFIG_ESP32_C6_DEVKIT_BOARD) +list(APPEND COMPONENT_ADD_INCLUDEDIRS ./esp32_c6_devkit) +set(COMPONENT_SRCS +./esp32_c6_devkit/board.c +./esp32_c6_devkit/board_pins_config.c +) +endif() + +if (CONFIG_ESP32_P4_FUNCTION_EV_BOARD) +message(STATUS "Current board name is " CONFIG_ESP32_P4_FUNCTION_EV_BOARD) +list(APPEND COMPONENT_ADD_INCLUDEDIRS ./esp32_p4_function_ev_board) +set(COMPONENT_SRCS +./esp32_p4_function_ev_board/board.c +./esp32_p4_function_ev_board/board_pins_config.c +) +endif() + +register_component() diff --git a/components/audio_board/esp32_s3_custom/Kconfig.projbuild b/components/audio_board/esp32_s3_custom/Kconfig.projbuild new file mode 100644 index 000000000..dbd421189 --- /dev/null +++ b/components/audio_board/esp32_s3_custom/Kconfig.projbuild @@ -0,0 +1,73 @@ +menu "Audio HAL" + +choice AUDIO_BOARD + prompt "Audio board" + default ESP_LYRAT_V4_3_BOARD + help + Select an audio board to use with the ESP-ADF +config AUDIO_BOARD_CUSTOM + bool "Custom audio board" +config ESP_LYRAT_V4_3_BOARD + bool "ESP32-Lyrat V4.3" +config ESP_LYRAT_V4_2_BOARD + bool "ESP32-Lyrat V4.2" +config ESP_LYRATD_MSC_V2_1_BOARD + bool "ESP32-LyraTD-MSC V2.1" +config ESP_LYRATD_MSC_V2_2_BOARD + bool "ESP32-LyraTD-MSC V2.2" +config ESP_LYRAT_MINI_V1_1_BOARD + bool "ESP32-Lyrat-Mini V1.1" +config ESP32_KORVO_DU1906_BOARD + bool "ESP32_KORVO_DU1906" +config ESP32_S2_KALUGA_1_V1_2_BOARD + bool "ESP32-S2-Kaluga-1 v1.2" +config ESP32_S3_KORVO2_V3_BOARD + bool "ESP32-S3-Korvo-2 v3" +config ESP32_S3_CUSTOM_BOARD + bool "ESP32-S3-custom" +config ESP32_S3_KORVO2L_V1_BOARD + bool "ESP32-S3-Korvo-2L v1" +config ESP32_S3_BOX_LITE_BOARD + bool "ESP32-S3-BOX-Lite" +config ESP32_S3_BOX_BOARD + bool "ESP32-S3-BOX" +config ESP32_S3_BOX_3_BOARD + bool "ESP32-S3-BOX-3" +config M5STACK_ATOMS3R_BOARD + bool "M5STACK-ATOMS3R" +config ESP32_C3_LYRA_V2_BOARD + bool "ESP32-C3-Lyra-v2.0" +config ESP32_C6_DEVKIT_BOARD + bool "ESP32-C6-DEVKIT" +config ESP32_P4_FUNCTION_EV_BOARD + bool "ESP32-P4-FUNCTION-EV-BOARD" + +endchoice + +choice ESP32_KORVO_DU1906_DAC + prompt "ESP32 KORVO DU1906 Board DAC chip" + depends on ESP32_KORVO_DU1906_BOARD + default ESP32_KORVO_DU1906_DAC_TAS5805M + help + Select DAC chip to use on ESP32_KORVO_DU1906 board + +config ESP32_KORVO_DU1906_DAC_TAS5805M + bool "ESP32_KORVO_DU1906_DAC_TAS5805M" +config ESP32_KORVO_DU1906_DAC_ES7148 + bool "ESP32_KORVO_DU1906_DAC_ES7148" + +endchoice + +choice ESP32_KORVO_DU1906_ADC + prompt "ESP32 KORVO DU1906 Board ADC chip" + depends on ESP32_KORVO_DU1906_BOARD + default ESP32_KORVO_DU1906_ADC_ES7243 + help + Select ADC chip to use on ESP32_KORVO_DU1906 board + +config ESP32_KORVO_DU1906_ADC_ES7243 + bool "ESP32_KORVO_DU1906_ADC_ES7243" +endchoice + +endmenu + diff --git a/components/audio_board/esp32_s3_custom/board.c b/components/audio_board/esp32_s3_custom/board.c new file mode 100644 index 000000000..88e250ab4 --- /dev/null +++ b/components/audio_board/esp32_s3_custom/board.c @@ -0,0 +1,213 @@ +/* + * ESPRESSIF MIT License + * + * Copyright (c) 2021 + * + * Permission is hereby granted for use on all ESPRESSIF SYSTEMS products, in which case, + * it is free of charge, to any person obtaining a copy of this software and associated + * documentation files (the "Software"), to deal in the Software without restriction, including + * without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the Software is furnished + * to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in all copies or + * substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS + * FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR + * COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER + * IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN + * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + * + */ + +#include "esp_log.h" +#include "board.h" +#include "audio_mem.h" +#include "periph_sdcard.h" +#include "periph_adc_button.h" +#include "tca9554.h" + +static const char *TAG = "AUDIO_BOARD"; + +static audio_board_handle_t board_handle = 0; + +audio_board_handle_t audio_board_init(void) +{ + if (board_handle) { + ESP_LOGW(TAG, "The board has already been initialized!"); + return board_handle; + } + board_handle = (audio_board_handle_t) audio_calloc(1, sizeof(struct audio_board_handle)); + AUDIO_MEM_CHECK(TAG, board_handle, return NULL); + board_handle->audio_hal = audio_board_codec_init(); + return board_handle; +} + +audio_hal_handle_t audio_board_adc_init(void) +{ + audio_hal_codec_config_t audio_codec_cfg = AUDIO_CODEC_DEFAULT_CONFIG(); + audio_codec_cfg.codec_mode = AUDIO_HAL_CODEC_MODE_BOTH; + audio_hal_handle_t adc_hal = NULL; + adc_hal = audio_hal_init(&audio_codec_cfg, &AUDIO_CODEC_TLV320_DEFAULT_HANDLE); + AUDIO_NULL_CHECK(TAG, adc_hal, return NULL); + return adc_hal; +} + +audio_hal_handle_t audio_board_codec_init(void) +{ + audio_hal_codec_config_t audio_codec_cfg = AUDIO_CODEC_DEFAULT_CONFIG(); + audio_hal_handle_t codec_hal = audio_hal_init(&audio_codec_cfg, &AUDIO_CODEC_TLV320_DEFAULT_HANDLE); + AUDIO_NULL_CHECK(TAG, codec_hal, return NULL); + return codec_hal; +} + +esp_err_t _lcd_rest(esp_periph_handle_t self, void *ctx) +{ + // Reset the LCD + tca9554_set_output_state(LCD_RST_GPIO, TCA9554_IO_LOW); + vTaskDelay(100 / portTICK_PERIOD_MS); + tca9554_set_output_state(LCD_RST_GPIO, TCA9554_IO_HIGH); + vTaskDelay(200 / portTICK_PERIOD_MS); + return ESP_OK; +} + +esp_err_t _get_lcd_io_bus (void *bus, esp_lcd_panel_io_spi_config_t *io_config, + esp_lcd_panel_io_handle_t *out_panel_io) +{ + return esp_lcd_new_panel_io_spi((esp_lcd_spi_bus_handle_t)bus, io_config, out_panel_io); +} + +display_service_handle_t audio_board_led_init(void) +{ + return NULL; +} + +void *audio_board_lcd_init(esp_periph_set_handle_t set, void *cb) +{ + esp_tca9554_config_t pca_cfg = { + .i2c_scl = GPIO_NUM_1, + .i2c_sda = GPIO_NUM_2, + .interrupt_output = -1, + }; + tca9554_init(&pca_cfg); + // Set LCD_BL_CTRL output + tca9554_set_io_config(LCD_CTRL_GPIO, TCA9554_IO_OUTPUT); + // Set LCD_RST output + tca9554_set_io_config(LCD_RST_GPIO, TCA9554_IO_OUTPUT); + // Set LCD_CS pin output + tca9554_set_io_config(LCD_CS_GPIO, TCA9554_IO_OUTPUT); + + tca9554_set_output_state(LCD_CTRL_GPIO, TCA9554_IO_HIGH); + tca9554_set_output_state(LCD_CS_GPIO, TCA9554_IO_HIGH); + vTaskDelay(10 / portTICK_PERIOD_MS); + tca9554_set_output_state(LCD_CS_GPIO, TCA9554_IO_LOW); + vTaskDelay(10 / portTICK_PERIOD_MS); + + spi_bus_config_t buscfg = { + .sclk_io_num = LCD_CLK_GPIO, + .mosi_io_num = LCD_MOSI_GPIO, + .miso_io_num = -1, + .quadwp_io_num = -1, + .quadhd_io_num = -1, + .max_transfer_sz = LCD_V_RES * LCD_H_RES * 2 + }; + ESP_ERROR_CHECK(spi_bus_initialize(SPI2_HOST, &buscfg, SPI_DMA_CH_AUTO)); + + esp_lcd_panel_io_spi_config_t io_config = { + .dc_gpio_num = LCD_DC_GPIO, + .cs_gpio_num = -1, + .pclk_hz = 60 * 1000 * 1000, + .lcd_cmd_bits = 8, + .lcd_param_bits = 8, + .spi_mode = 0, + .trans_queue_depth = 10, + .on_color_trans_done = cb, + .user_ctx = NULL, + }; + esp_lcd_panel_dev_config_t panel_config = { + .reset_gpio_num = -1, + .color_space = ESP_LCD_COLOR_SPACE_BGR, + .bits_per_pixel = 16, + }; + periph_lcd_cfg_t cfg = { + .io_bus = (void *)SPI2_HOST, + .new_panel_io = _get_lcd_io_bus, + .lcd_io_cfg = &io_config, + .new_lcd_panel = esp_lcd_new_panel_st7789, + .lcd_dev_cfg = &panel_config, + .rest_cb = _lcd_rest, + .rest_cb_ctx = NULL, + .lcd_swap_xy = LCD_SWAP_XY, + .lcd_mirror_x = LCD_MIRROR_X, + .lcd_mirror_y = LCD_MIRROR_Y, + .lcd_color_invert = LCD_COLOR_INV, + }; + esp_periph_handle_t periph_lcd = periph_lcd_init(&cfg); + AUDIO_NULL_CHECK(TAG, periph_lcd, return NULL); + esp_periph_start(set, periph_lcd); + return (void *)periph_lcd_get_panel_handle(periph_lcd); +} + +esp_err_t audio_board_key_init(esp_periph_set_handle_t set) +{ + periph_adc_button_cfg_t adc_btn_cfg = PERIPH_ADC_BUTTON_DEFAULT_CONFIG(); + adc_arr_t adc_btn_tag = ADC_DEFAULT_ARR(); + adc_btn_tag.total_steps = 6; + adc_btn_tag.adc_ch = ADC1_CHANNEL_4; + int btn_array[7] = {190, 600, 1000, 1375, 1775, 2195, 3000}; + adc_btn_tag.adc_level_step = btn_array; + adc_btn_cfg.arr = &adc_btn_tag; + adc_btn_cfg.arr_size = 1; + if (audio_mem_spiram_stack_is_enabled()) { + adc_btn_cfg.task_cfg.ext_stack = true; + } + esp_periph_handle_t adc_btn_handle = periph_adc_button_init(&adc_btn_cfg); + AUDIO_NULL_CHECK(TAG, adc_btn_handle, return ESP_ERR_ADF_MEMORY_LACK); + return esp_periph_start(set, adc_btn_handle); +} + +esp_err_t audio_board_sdcard_init(esp_periph_set_handle_t set, periph_sdcard_mode_t mode) +{ + if (mode != SD_MODE_1_LINE) { + ESP_LOGE(TAG, "Current board only support 1-line SD mode!"); + return ESP_FAIL; + } + periph_sdcard_cfg_t sdcard_cfg = { + .root = "/sdcard", + .card_detect_pin = get_sdcard_intr_gpio(), + .mode = mode + }; + esp_periph_handle_t sdcard_handle = periph_sdcard_init(&sdcard_cfg); + esp_err_t ret = esp_periph_start(set, sdcard_handle); + int retry_time = 5; + bool mount_flag = false; + while (retry_time --) { + if (periph_sdcard_is_mounted(sdcard_handle)) { + mount_flag = true; + break; + } else { + vTaskDelay(500 / portTICK_PERIOD_MS); + } + } + if (mount_flag == false) { + ESP_LOGE(TAG, "Sdcard mount failed"); + return ESP_FAIL; + } + return ret; +} + +audio_board_handle_t audio_board_get_handle(void) +{ + return board_handle; +} + +esp_err_t audio_board_deinit(audio_board_handle_t audio_board) +{ + esp_err_t ret = ESP_OK; + ret |= audio_hal_deinit(audio_board->audio_hal); + audio_free(audio_board); + board_handle = NULL; + return ret; +} diff --git a/components/audio_board/esp32_s3_custom/board.h b/components/audio_board/esp32_s3_custom/board.h new file mode 100644 index 000000000..723627655 --- /dev/null +++ b/components/audio_board/esp32_s3_custom/board.h @@ -0,0 +1,137 @@ +/* + * ESPRESSIF MIT License + * + * Copyright (c) 2021 + * + * Permission is hereby granted for use on all ESPRESSIF SYSTEMS products, in which case, + * it is free of charge, to any person obtaining a copy of this software and associated + * documentation files (the "Software"), to deal in the Software without restriction, including + * without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the Software is furnished + * to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in all copies or + * substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS + * FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR + * COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER + * IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN + * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + * + */ + +#ifndef _AUDIO_BOARD_H_ +#define _AUDIO_BOARD_H_ + +#include "audio_hal.h" +#include "board_def.h" +#include "board_pins_config.h" +#include "esp_peripherals.h" +#include "display_service.h" +#include "periph_sdcard.h" +#include "periph_lcd.h" + +#ifdef __cplusplus +extern "C" { +#endif + +/** + * @brief Audio board handle + */ +struct audio_board_handle { + audio_hal_handle_t audio_hal; /*!< audio hardware abstract layer handle */ +}; + +typedef struct audio_board_handle *audio_board_handle_t; + +/** + * @brief Initialize audio board + * + * @return The audio board handle + */ +audio_board_handle_t audio_board_init(void); + +/** + * @brief Initialize codec chip + * + * @return The audio hal handle + */ +audio_hal_handle_t audio_board_codec_init(void); + +/** + * @brief Initialize adc + * + * @return The adc hal handle + */ +audio_hal_handle_t audio_board_adc_init(void); + +/** + * @brief Initialize lcd peripheral + * + * @param set The handle of esp_periph_set_handle_t + * @param cb The `on_color_trans_done` callback in `esp_lcd_panel_io_spi_config_t` + * + * @return The `esp_lcd_panel_handle_t` handle + */ +void *audio_board_lcd_init(esp_periph_set_handle_t set, void *cb); + +/** + * @brief Initialize led peripheral and display service + * + * @return The audio display service handle + */ +display_service_handle_t audio_board_led_init(void); + +/** + * @brief Initialize led peripheral and display service + * + * @return The audio display service handle + */ +display_service_handle_t audio_board_blue_led_init(void); + +/** + * @brief Initialize key peripheral + * + * @param set The handle of esp_periph_set_handle_t + * + * @return + * - ESP_OK, success + * - Others, fail + */ +esp_err_t audio_board_key_init(esp_periph_set_handle_t set); + +/** + * @brief Initialize sdcard peripheral + * + * @param set The handle of esp_periph_set_handle_t + * + * @return + * - ESP_OK, success + * - Others, fail + */ +esp_err_t audio_board_sdcard_init(esp_periph_set_handle_t set, periph_sdcard_mode_t mode); + +/** + * @brief Query audio_board_handle + * + * @return The audio board handle + */ +audio_board_handle_t audio_board_get_handle(void); + +/** + * @brief Uninitialize the audio board + * + * @param audio_board The handle of audio board + * + * @return 0 success, + * others fail + */ +esp_err_t audio_board_deinit(audio_board_handle_t audio_board); + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/components/audio_board/esp32_s3_custom/board_def.h b/components/audio_board/esp32_s3_custom/board_def.h new file mode 100644 index 000000000..aff40d435 --- /dev/null +++ b/components/audio_board/esp32_s3_custom/board_def.h @@ -0,0 +1,190 @@ +/* + * ESPRESSIF MIT License + * + * Copyright (c) 2021 + * + * Permission is hereby granted for use on all ESPRESSIF SYSTEMS products, in which case, + * it is free of charge, to any person obtaining a copy of this software and associated + * documentation files (the "Software"), to deal in the Software without restriction, including + * without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the Software is furnished + * to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in all copies or + * substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS + * FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR + * COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER + * IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN + * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + * + */ + +#ifndef _AUDIO_BOARD_DEFINITION_H_ +#define _AUDIO_BOARD_DEFINITION_H_ + +/** + * @brief LED Function Definition + */ +#define GREEN_LED_GPIO -1 +#define BLUE_LED_GPIO BIT(7) // TCA9554_GPIO_NUM_7 +#define RED_LED_GPIO BIT(6) // TCA9554_GPIO_NUM_6 + + +/** + * @brief LCD SCREEN Function Definition + */ +#define FUNC_LCD_SCREEN_EN (1) +#define LCD_CTRL_GPIO BIT(1) // TCA9554_GPIO_NUM_1 +#define LCD_RST_GPIO BIT(2) // TCA9554_GPIO_NUM_2 +#define LCD_CS_GPIO BIT(3) // TCA9554_GPIO_NUM_3 +// LCD SPI Pins +#define LCD_DC_GPIO GPIO_NUM_2 +#define LCD_CLK_GPIO GPIO_NUM_1 +#define LCD_MOSI_GPIO GPIO_NUM_0 +// The LCD pixel number in horizontal and vertical +#define LCD_H_RES 320 +#define LCD_V_RES 240 +#define LCD_SWAP_XY (false) +#define LCD_MIRROR_X (true) +#define LCD_MIRROR_Y (true) +#define LCD_COLOR_INV (false) + + +/** + * @brief SDCARD Function Definition + */ +#define FUNC_SDCARD_EN (1) +#define SDCARD_OPEN_FILE_NUM_MAX 5 +#define SDCARD_INTR_GPIO -1 +#define SDCARD_PWR_CTRL -1 + +#define ESP_SD_PIN_CLK -1 //GPIO_NUM_15 +#define ESP_SD_PIN_CMD -1 //GPIO_NUM_7 +#define ESP_SD_PIN_D0 -1 //GPIO_NUM_4 +#define ESP_SD_PIN_D1 -1 +#define ESP_SD_PIN_D2 -1 +#define ESP_SD_PIN_D3 -1 +#define ESP_SD_PIN_D4 -1 +#define ESP_SD_PIN_D5 -1 +#define ESP_SD_PIN_D6 -1 +#define ESP_SD_PIN_D7 -1 +#define ESP_SD_PIN_CD -1 +#define ESP_SD_PIN_WP -1 + + +/** + * @brief Camera Function Definition + */ +#define FUNC_CAMERA_EN (1) +#define CAM_PIN_PWDN -1 +#define CAM_PIN_RESET -1 +#define CAM_PIN_XCLK -1 //GPIO_NUM_40 +#define CAM_PIN_SIOD -1 //GPIO_NUM_17 +#define CAM_PIN_SIOC -1 //GPIO_NUM_18 + +#define CAM_PIN_D7 -1 //GPIO_NUM_39 +#define CAM_PIN_D6 -1 //GPIO_NUM_41 +#define CAM_PIN_D5 -1 //GPIO_NUM_42 +#define CAM_PIN_D4 -1 //GPIO_NUM_12 +#define CAM_PIN_D3 -1 //GPIO_NUM_3 +#define CAM_PIN_D2 -1 //GPIO_NUM_14 +#define CAM_PIN_D1 -1 //GPIO_NUM_47 +#define CAM_PIN_D0 -1 //GPIO_NUM_13 +#define CAM_PIN_VSYNC -1 //GPIO_NUM_21 +#define CAM_PIN_HREF -1 //GPIO_NUM_38 +#define CAM_PIN_PCLK -1 //GPIO_NUM_11 + + +/** + * @brief LCD TOUCH PANEL Function Definition + */ +#define FUNC_LCD_TOUCH_EN (1) +#define TOUCH_PANEL_SWAP_XY (0) +#define TOUCH_PANEL_INVERSE_X (1) +#define TOUCH_PANEL_INVERSE_Y (0) + +/** + * @brief Audio Codec Chip Function Definition + */ +#define FUNC_AUDIO_CODEC_EN (1) +#define CODEC_ADC_I2S_PORT ((i2s_port_t)0) +#define CODEC_ADC_BITS_PER_SAMPLE ((i2s_data_bit_width_t)16) /* 32bit */ +#define CODEC_ADC_SAMPLE_RATE (8000) +#define RECORD_HARDWARE_AEC (true) +#define BOARD_PA_GAIN (0) /* Power amplifier gain defined by board (dB) */ +#define HEADPHONE_DETECT (-1) +#define PA_ENABLE_GPIO GPIO_NUM_38 +#define TLV320_MCLK_SOURCE (0) /* 0 From MCLK of esp32 1 From BCLK */ +#define ES7210_MIC_SELECT (ES7210_INPUT_MIC1 | ES7210_INPUT_MIC2 | ES7210_INPUT_MIC3) + +/** + * @brief ADC input data format + */ +#define AUDIO_ADC_INPUT_CH_FORMAT "RM" + +extern audio_hal_func_t AUDIO_CODEC_TLV320_DEFAULT_HANDLE; +extern audio_hal_func_t AUDIO_CODEC_ES7210_DEFAULT_HANDLE; + + +// edit sample 48 to 8 +#define AUDIO_CODEC_DEFAULT_CONFIG(){ \ + .adc_input = AUDIO_HAL_ADC_INPUT_ALL, \ + .dac_output = AUDIO_HAL_DAC_OUTPUT_ALL, \ + .codec_mode = AUDIO_HAL_CODEC_MODE_BOTH, \ + .i2s_iface = { \ + .mode = AUDIO_HAL_MODE_SLAVE, \ + .fmt = AUDIO_HAL_I2S_NORMAL, \ + .samples = AUDIO_HAL_08K_SAMPLES, \ + .bits = AUDIO_HAL_BIT_LENGTH_16BITS, \ + }, \ +}; + +/** + * @brief Button Function Definition + */ +#define FUNC_BUTTON_EN (1) +#define INPUT_KEY_NUM 6 +#define BUTTON_VOLUP_ID 0 +#define BUTTON_VOLDOWN_ID 1 +#define BUTTON_SET_ID 2 +#define BUTTON_PLAY_ID 3 +#define BUTTON_MODE_ID 4 +#define BUTTON_REC_ID 5 + +#define INPUT_KEY_DEFAULT_INFO() { \ + { \ + .type = PERIPH_ID_ADC_BTN, \ + .user_id = INPUT_KEY_USER_ID_REC, \ + .act_id = BUTTON_REC_ID, \ + }, \ + { \ + .type = PERIPH_ID_ADC_BTN, \ + .user_id = INPUT_KEY_USER_ID_MUTE, \ + .act_id = BUTTON_MODE_ID, \ + }, \ + { \ + .type = PERIPH_ID_ADC_BTN, \ + .user_id = INPUT_KEY_USER_ID_SET, \ + .act_id = BUTTON_SET_ID, \ + }, \ + { \ + .type = PERIPH_ID_ADC_BTN, \ + .user_id = INPUT_KEY_USER_ID_PLAY, \ + .act_id = BUTTON_PLAY_ID, \ + }, \ + { \ + .type = PERIPH_ID_ADC_BTN, \ + .user_id = INPUT_KEY_USER_ID_VOLUP, \ + .act_id = BUTTON_VOLUP_ID, \ + }, \ + { \ + .type = PERIPH_ID_ADC_BTN, \ + .user_id = INPUT_KEY_USER_ID_VOLDOWN, \ + .act_id = BUTTON_VOLDOWN_ID, \ + } \ +} + +#endif diff --git a/components/audio_board/esp32_s3_custom/board_pins_config.c b/components/audio_board/esp32_s3_custom/board_pins_config.c new file mode 100644 index 000000000..fe381d9f8 --- /dev/null +++ b/components/audio_board/esp32_s3_custom/board_pins_config.c @@ -0,0 +1,167 @@ +/* + * ESPRESSIF MIT License + * + * Copyright (c) 2021 + * + * Permission is hereby granted for use on all ESPRESSIF SYSTEMS products, in which case, + * it is free of charge, to any person obtaining a copy of this software and associated + * documentation files (the "Software"), to deal in the Software without restriction, including + * without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the Software is furnished + * to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in all copies or + * substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS + * FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR + * COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER + * IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN + * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + * + */ + +#include "esp_log.h" +#include "driver/gpio.h" +#include +#include "board.h" +#include "audio_error.h" +#include "audio_mem.h" +#include "soc/soc_caps.h" + +static const char *TAG = "ESP32_S3_CUSTOM"; + +esp_err_t get_i2c_pins(i2c_port_t port, i2c_config_t *i2c_config) +{ + AUDIO_NULL_CHECK(TAG, i2c_config, return ESP_FAIL); + if (port == I2C_NUM_0 || port == I2C_NUM_1) { + i2c_config->sda_io_num = GPIO_NUM_2; //GPIO_NUM_17 + i2c_config->scl_io_num = GPIO_NUM_1; //GPIO_NUM_18 + } else { + i2c_config->sda_io_num = -1; + i2c_config->scl_io_num = -1; + ESP_LOGE(TAG, "i2c port %d is not supported", port); + return ESP_FAIL; + } + return ESP_OK; +} + +esp_err_t get_i2s_pins(int port, board_i2s_pin_t *i2s_config) +{ + AUDIO_NULL_CHECK(TAG, i2s_config, return ESP_FAIL); + if (port == 0) { + i2s_config->bck_io_num = GPIO_NUM_39; //GPIO_NUM_9; + i2s_config->ws_io_num = GPIO_NUM_40; //GPIO_NUM_35; + i2s_config->data_out_num = GPIO_NUM_41; //GPIO_NUM_8; + i2s_config->data_in_num = GPIO_NUM_42; //GPIO_NUM_10; + i2s_config->mck_io_num = GPIO_NUM_38; //GPIO_NUM_16; + } else if (port == 1) { + i2s_config->bck_io_num = -1; + i2s_config->ws_io_num = -1; + i2s_config->data_out_num = -1; + i2s_config->data_in_num = -1; + i2s_config->mck_io_num = -1; + } else { + memset(i2s_config, -1, sizeof(board_i2s_pin_t)); + ESP_LOGE(TAG, "i2s port %d is not supported", port); + return ESP_FAIL; + } + + return ESP_OK; +} + +esp_err_t get_spi_pins(spi_bus_config_t *spi_config, spi_device_interface_config_t *spi_device_interface_config) +{ + AUDIO_NULL_CHECK(TAG, spi_config, return ESP_FAIL); + AUDIO_NULL_CHECK(TAG, spi_device_interface_config, return ESP_FAIL); + + spi_config->mosi_io_num = -1; + spi_config->miso_io_num = -1; + spi_config->sclk_io_num = -1; + spi_config->quadwp_io_num = -1; + spi_config->quadhd_io_num = -1; + + spi_device_interface_config->spics_io_num = -1; + + ESP_LOGW(TAG, "SPI interface is not supported"); + return ESP_OK; +} + +// sdcard + +int8_t get_sdcard_intr_gpio(void) +{ + return SDCARD_INTR_GPIO; +} + +int8_t get_sdcard_open_file_num_max(void) +{ + return SDCARD_OPEN_FILE_NUM_MAX; +} + +int8_t get_sdcard_power_ctrl_gpio(void) +{ + return SDCARD_PWR_CTRL; +} + +// input-output pins + +int8_t get_headphone_detect_gpio(void) +{ + return HEADPHONE_DETECT; +} + +int8_t get_pa_enable_gpio(void) +{ + return PA_ENABLE_GPIO; +} + +// adc button id + +int8_t get_input_rec_id(void) +{ + return BUTTON_REC_ID; +} + +int8_t get_input_mode_id(void) +{ + return BUTTON_MODE_ID; +} + +int8_t get_input_set_id(void) +{ + return BUTTON_SET_ID; +} + +int8_t get_input_play_id(void) +{ + return BUTTON_PLAY_ID; +} + +int8_t get_input_volup_id(void) +{ + return BUTTON_VOLUP_ID; +} + +int8_t get_input_voldown_id(void) +{ + return BUTTON_VOLDOWN_ID; +} + +// led pins + +int8_t get_green_led_gpio(void) +{ + return GREEN_LED_GPIO; +} + +int8_t get_blue_led_gpio(void) +{ + return BLUE_LED_GPIO; +} + +int8_t get_tlv320_mclk_src(void) +{ + return TLV320_MCLK_SOURCE; +} diff --git a/components/audio_board/esp32_s3_custom/component.mk b/components/audio_board/esp32_s3_custom/component.mk new file mode 100644 index 000000000..8289aa803 --- /dev/null +++ b/components/audio_board/esp32_s3_custom/component.mk @@ -0,0 +1,58 @@ +# +# "main" pseudo-component makefile. +# +# (Uses default behaviour of compiling all source files in directory, adding 'include' to include path.) + +COMPONENT_ADD_INCLUDEDIRS := ./include + +ifdef CONFIG_ESP_LYRAT_V4_3_BOARD +COMPONENT_ADD_INCLUDEDIRS += ./lyrat_v4_3 +COMPONENT_SRCDIRS += ./lyrat_v4_3 +endif + +ifdef CONFIG_ESP_LYRAT_V4_2_BOARD +COMPONENT_ADD_INCLUDEDIRS += ./lyrat_v4_2 +COMPONENT_SRCDIRS += ./lyrat_v4_2 +endif + +ifdef CONFIG_ESP_LYRATD_MSC_V2_1_BOARD +COMPONENT_ADD_INCLUDEDIRS += ./lyratd_msc_v2_1 +COMPONENT_SRCDIRS += ./lyratd_msc_v2_1 +COMPONENT_ADD_LDFLAGS += -L$(COMPONENT_PATH)/../audio_hal/driver/zl38063/firmware -lfirmware +endif + +ifdef CONFIG_ESP_LYRATD_MSC_V2_2_BOARD +COMPONENT_ADD_INCLUDEDIRS += ./lyratd_msc_v2_2 +COMPONENT_SRCDIRS += ./lyratd_msc_v2_2 +COMPONENT_ADD_LDFLAGS += -L$(COMPONENT_PATH)/../audio_hal/driver/zl38063/firmware -lfirmware +endif + +ifdef CONFIG_ESP_LYRAT_MINI_V1_1_BOARD +COMPONENT_ADD_INCLUDEDIRS += ./lyrat_mini_v1_1 +COMPONENT_SRCDIRS += ./lyrat_mini_v1_1 +endif + +ifdef CONFIG_ESP32_KORVO_DU1906_BOARD +COMPONENT_ADD_INCLUDEDIRS += ./esp32_korvo_du1906 +COMPONENT_SRCDIRS += ./esp32_korvo_du1906 +endif + +ifdef CONFIG_ESP32_S2_KALUGA_1_V1_2_BOARD +COMPONENT_ADD_INCLUDEDIRS += ./esp32_s2_kaluga_1_v1_2 +COMPONENT_SRCDIRS += ./esp32_s2_kaluga_1_v1_2 +endif + +ifdef CONFIG_ESP32_S3_KORVO2_V3_BOARD +COMPONENT_ADD_INCLUDEDIRS += ./esp32_s3_korvo2_v3 +COMPONENT_SRCDIRS += ./esp32_s3_korvo2_v3 +endif + +ifdef CONFIG_ESP32_S3_CUSTOM_BOARD +COMPONENT_ADD_INCLUDEDIRS += ./esp32_s3_custom +COMPONENT_SRCDIRS += ./esp32_s3_custom +endif + +ifdef CONFIG_ESP32_C3_LYRA_V2_BOARD +COMPONENT_ADD_INCLUDEDIRS += ./esp32_c3_lyra +COMPONENT_SRCDIRS += ./esp32_c3_lyra +endif \ No newline at end of file diff --git a/components/audio_board/esp32_s3_korvo2_v3/board.c b/components/audio_board/esp32_s3_korvo2_v3/board.c index c18fbde07..c513ef37e 100644 --- a/components/audio_board/esp32_s3_korvo2_v3/board.c +++ b/components/audio_board/esp32_s3_korvo2_v3/board.c @@ -89,8 +89,8 @@ display_service_handle_t audio_board_led_init(void) void *audio_board_lcd_init(esp_periph_set_handle_t set, void *cb) { esp_tca9554_config_t pca_cfg = { - .i2c_scl = GPIO_NUM_18, - .i2c_sda = GPIO_NUM_17, + .i2c_scl = GPIO_NUM_1, + .i2c_sda = GPIO_NUM_2, .interrupt_output = -1, }; tca9554_init(&pca_cfg); diff --git a/components/audio_board/esp32_s3_korvo2_v3/board_def.h b/components/audio_board/esp32_s3_korvo2_v3/board_def.h index c7d3300e9..a3a1e26cd 100644 --- a/components/audio_board/esp32_s3_korvo2_v3/board_def.h +++ b/components/audio_board/esp32_s3_korvo2_v3/board_def.h @@ -116,7 +116,7 @@ #define RECORD_HARDWARE_AEC (true) #define BOARD_PA_GAIN (6) /* Power amplifier gain defined by board (dB) */ #define HEADPHONE_DETECT (-1) -#define PA_ENABLE_GPIO GPIO_NUM_48 +#define PA_ENABLE_GPIO GPIO_NUM_38 #define ES8311_MCLK_SOURCE (0) /* 0 From MCLK of esp32 1 From BCLK */ #define ES7210_MIC_SELECT (ES7210_INPUT_MIC1 | ES7210_INPUT_MIC2 | ES7210_INPUT_MIC3) diff --git a/components/audio_board/esp32_s3_korvo2_v3/board_pins_config.c b/components/audio_board/esp32_s3_korvo2_v3/board_pins_config.c index be01c354d..6df96abbe 100644 --- a/components/audio_board/esp32_s3_korvo2_v3/board_pins_config.c +++ b/components/audio_board/esp32_s3_korvo2_v3/board_pins_config.c @@ -36,8 +36,8 @@ esp_err_t get_i2c_pins(i2c_port_t port, i2c_config_t *i2c_config) { AUDIO_NULL_CHECK(TAG, i2c_config, return ESP_FAIL); if (port == I2C_NUM_0 || port == I2C_NUM_1) { - i2c_config->sda_io_num = GPIO_NUM_17; - i2c_config->scl_io_num = GPIO_NUM_18; + i2c_config->sda_io_num = GPIO_NUM_17; //GPIO_NUM_17 + i2c_config->scl_io_num = GPIO_NUM_18; //GPIO_NUM_18 } else { i2c_config->sda_io_num = -1; i2c_config->scl_io_num = -1; @@ -51,11 +51,11 @@ esp_err_t get_i2s_pins(int port, board_i2s_pin_t *i2s_config) { AUDIO_NULL_CHECK(TAG, i2s_config, return ESP_FAIL); if (port == 0) { - i2s_config->bck_io_num = GPIO_NUM_9; - i2s_config->ws_io_num = GPIO_NUM_45; - i2s_config->data_out_num = GPIO_NUM_8; - i2s_config->data_in_num = GPIO_NUM_10; - i2s_config->mck_io_num = GPIO_NUM_16; + i2s_config->bck_io_num = GPIO_NUM_9; //GPIO_NUM_39; + i2s_config->ws_io_num = GPIO_NUM_35; // GPIO_NUM_40; + i2s_config->data_out_num = GPIO_NUM_8; //GPIO_NUM_42; + i2s_config->data_in_num = GPIO_NUM_10; // GPIO_NUM_41; + i2s_config->mck_io_num = GPIO_NUM_16; // GPIO_NUM_38; } else if (port == 1) { i2s_config->bck_io_num = -1; i2s_config->ws_io_num = -1; diff --git a/components/audio_hal/CMakeLists.txt b/components/audio_hal/CMakeLists.txt index 9d465106d..08d7ed889 100644 --- a/components/audio_hal/CMakeLists.txt +++ b/components/audio_hal/CMakeLists.txt @@ -8,6 +8,7 @@ set(COMPONENT_ADD_INCLUDEDIRS ./include ./driver/es7210 ./driver/es7243e ./driver/tas5805m + ./driver/tlv320 ./driver/include) IF (NOT ((CONFIG_IDF_TARGET STREQUAL "esp32c3") OR (CONFIG_IDF_TARGET STREQUAL "esp32c6"))) list(APPEND COMPONENT_ADD_INCLUDEDIRS @@ -33,6 +34,7 @@ set(COMPONENT_SRCS ./audio_hal.c ./driver/es7210/es7210.c ./driver/es7243e/es7243e.c ./driver/tas5805m/tas5805m.c + ./driver/tlv320/tlv320.c ) IF (NOT ((CONFIG_IDF_TARGET STREQUAL "esp32c3") OR (CONFIG_IDF_TARGET STREQUAL "esp32c6") OR (CONFIG_IDF_TARGET STREQUAL "esp32p4") OR (CONFIG_IDF_TARGET STREQUAL "esp32c5"))) diff --git a/components/audio_hal/component.mk b/components/audio_hal/component.mk index d794d0e7f..6cf487d78 100644 --- a/components/audio_hal/component.mk +++ b/components/audio_hal/component.mk @@ -10,8 +10,8 @@ COMPONENT_PRIV_INCLUDEDIRS := ./driver/include COMPONENT_ADD_INCLUDEDIRS += ./driver/es8388 ./driver/es8374 COMPONENT_SRCDIRS += ./driver/es8388 ./driver/es8374 -COMPONENT_ADD_INCLUDEDIRS += ./driver/es8311 ./driver/es7243 -COMPONENT_SRCDIRS += ./driver/es8311 ./driver/es7243 +COMPONENT_ADD_INCLUDEDIRS += ./driver/es8311 ./driver/es7243 ./driver/tlv320 +COMPONENT_SRCDIRS += ./driver/es8311 ./driver/es7243 ./driver/tlv320 COMPONENT_ADD_INCLUDEDIRS += ./driver/zl38063 ./driver/zl38063/api_lib ./driver/zl38063/example_apps ./driver/zl38063/firmware COMPONENT_SRCDIRS += ./driver/zl38063 ./driver/zl38063/api_lib ./driver/zl38063/example_apps ./driver/zl38063/firmware diff --git a/components/audio_hal/driver/tlv320/tlv320.c b/components/audio_hal/driver/tlv320/tlv320.c new file mode 100644 index 000000000..3c08fc90d --- /dev/null +++ b/components/audio_hal/driver/tlv320/tlv320.c @@ -0,0 +1,434 @@ +/* + * ESPRESSIF MIT License + * + * Copyright (c) 2018 + * + * Permission is hereby granted for use on all ESPRESSIF SYSTEMS products, in which case, + * it is free of charge, to any person obtaining a copy of this software and associated + * documentation files (the "Software"), to deal in the Software without restriction, including + * without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the Software is furnished + * to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in all copies or + * substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS + * FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR + * COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER + * IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN + * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + * + */ + +#include +#include "esp_log.h" +#include "i2c_bus.h" +#include "tlv320.h" +#include "board.h" +#include "audio_volume.h" + +static const char *TAG = "TLV320_DRIVER"; + +static i2c_bus_handle_t i2c_handle; +static codec_dac_volume_config_t *dac_vol_handle; + +#define TLV320_I2C_ADDR 0x18 + +#define CHECK(x) do { if ((x) != ESP_OK) return ESP_FAIL; } while (0) + + +#define TLV320_DAC_VOL_CFG_DEFAULT() { \ + .max_dac_volume = 0, \ + .min_dac_volume = -96, \ + .board_pa_gain = BOARD_PA_GAIN, \ + .volume_accuracy = 0.5, \ + .dac_vol_symbol = -1, \ + .zero_volume_reg = 0, \ + .reg_value = 0, \ + .user_volume = 0, \ + .offset_conv_volume = NULL, \ +} + +#define ES_ASSERT(a, format, b, ...) \ + if ((a) != 0) { \ + ESP_LOGE(TAG, format, ##__VA_ARGS__); \ + return b;\ + } + +audio_hal_func_t AUDIO_CODEC_TLV320_DEFAULT_HANDLE = { + .audio_codec_initialize = tlv320_init, + .audio_codec_deinitialize = tlv320_deinit, + .audio_codec_ctrl = tlv320_ctrl_state, + .audio_codec_config_iface = tlv320_config_i2s, + .audio_codec_set_mute = tlv320_set_voice_mute, + .audio_codec_set_volume = tlv320_set_voice_volume, + .audio_codec_get_volume = tlv320_get_voice_volume, + .audio_codec_enable_pa = tlv320_pa_power, + .audio_hal_lock = NULL, + .handle = NULL, +}; + +esp_err_t tlv320_write_reg(uint8_t reg_addr, uint8_t data) { + // return i2c_bus_write_bytes(i2c_handle, TLV320_I2C_ADDR, ®_addr, sizeof(reg_addr), &data, sizeof(data)); + + i2c_cmd_handle_t cmd = i2c_cmd_link_create(); + i2c_master_start(cmd); + + i2c_master_write_byte(cmd, (0x18 << 1) | I2C_MASTER_WRITE, true); // آدرس دستگاه + i2c_master_write_byte(cmd, reg_addr, true); // آدرس رجیستر + i2c_master_write_byte(cmd, data, true); // دیتا + + i2c_master_stop(cmd); + + esp_err_t ret = i2c_master_cmd_begin(I2C_NUM_0, cmd, pdMS_TO_TICKS(1000)); + i2c_cmd_link_delete(cmd); + return ret; +} + +void tlv320_read_reg(uint8_t reg_addr ,uint8_t *data) { + // uint8_t data; + // i2c_bus_read_bytes(i2c_handle, TLV320_I2C_ADDR, ®_addr, sizeof(reg_addr), &data, sizeof(data)); + // return (int)data; + + i2c_cmd_handle_t cmd = i2c_cmd_link_create(); + + // مرحله نوشتن: تعیین آدرس رجیستر + i2c_master_start(cmd); + i2c_master_write_byte(cmd, (0x18 << 1) | I2C_MASTER_WRITE, true); + i2c_master_write_byte(cmd, reg_addr, true); + + // مرحله خواندن + i2c_master_start(cmd); // repeated start + i2c_master_write_byte(cmd, (0x18 << 1) | I2C_MASTER_READ, true); + i2c_master_read_byte(cmd, data, I2C_MASTER_NACK); // فقط یک بایت می‌خونیم + + i2c_master_stop(cmd); + + esp_err_t ret = i2c_master_cmd_begin(I2C_NUM_0, cmd, pdMS_TO_TICKS(1000)); + i2c_cmd_link_delete(cmd); +} + +static int i2c_init() +{ + // int res = 0; + // i2c_config_t es_i2c_cfg = { + // .mode = I2C_MODE_MASTER, + // .sda_pullup_en = GPIO_PULLUP_DISABLE, + // .scl_pullup_en = GPIO_PULLUP_DISABLE, + // .master.clk_speed = 100000, + // }; + + // res = get_i2c_pins(I2C_NUM_1, &es_i2c_cfg); + // ESP_LOGE(TAG, "Config i2c -> SDA: %d ,SCL: %d", es_i2c_cfg.sda_io_num ,es_i2c_cfg.scl_io_num); + + // ES_ASSERT(res, "getting i2c pins error", -1); + // i2c_handle = i2c_bus_create(I2C_NUM_1, &es_i2c_cfg); + + // i2c_param_config(I2C_NUM_1, &es_i2c_cfg); + // i2c_driver_install(I2C_NUM_1, es_i2c_cfg.mode, 0, 0, 0); + + i2c_config_t conf = { + .mode = I2C_MODE_MASTER, + .sda_io_num = GPIO_NUM_2, + .scl_io_num = GPIO_NUM_1, + .sda_pullup_en = GPIO_PULLUP_DISABLE, + .scl_pullup_en = GPIO_PULLUP_DISABLE + }; + conf.master.clk_speed = 100000, + + i2c_param_config(I2C_NUM_0, &conf); + i2c_driver_install(I2C_NUM_0, conf.mode, 0, 0, 0); + + // i2c_handle = i2c_bus_create(I2C_NUM_0, &conf); + + return 1; +} + +bool i2c_check_address(uint8_t address) +{ + i2c_cmd_handle_t cmd = i2c_cmd_link_create(); + i2c_master_start(cmd); + i2c_master_write_byte(cmd, (address << 1) | I2C_MASTER_WRITE, true); // فقط آدرس + بیت write + i2c_master_stop(cmd); + + esp_err_t ret = i2c_master_cmd_begin(I2C_NUM_0, cmd, pdMS_TO_TICKS(100)); + i2c_cmd_link_delete(cmd); + + return ret == ESP_OK; // اگر ACK گرفتیم یعنی دستگاه موجوده +} + +esp_err_t tlv320_init(audio_hal_codec_config_t *codec_cfg) { + ESP_LOGI(TAG, "Initializing TLV320 codec..."); + + int res = i2c_init(); + ESP_LOGE(TAG, "Start I2C : %d", res); + + for (size_t i = 1; i < 127; i++) { + if (i2c_check_address(i)) { + printf("✅ find 0x%02X\n", i); + } + vTaskDelay(pdMS_TO_TICKS(1)); + } + + //(1) software reset + if (tlv320_write_reg(0x00, 0x00) == ESP_FAIL) { + ESP_LOGE(TAG, "Write Register Failed"); + } + + tlv320_write_reg(0x01, 0b10000000); + vTaskDelay(10); + + tlv320_write_reg(0x00, 0x00); + //(2) codec ADC/DAC sample rate + tlv320_write_reg(0x02, 0b00000000); + + //(3)We want fs_ref=48kHz, MCLK = 12.288 MHz, CODEC_CLK=fs_ref*256=12.288MHz, with CODEC_CLK = MCLK*2/Q -> Q=2 + //tlv320_write_reg(0x03, 0b01000000); + tlv320_write_reg(0x03, 0b00010001); + + //(7) fs=48kHz, ADC-DAC dual rate OFF, left-DAC data path plays left-channel input data, right-DAC data path plays right-channel input data + tlv320_write_reg(0x07, 0b00001010); + + //(9) Frame bits + // tlv320_write_reg(0x09, 0b00110000); + + //(12) Input HP filter disabled, DAC filters bypassed + tlv320_write_reg(0x0c, 0b11110000); + + //(14) high-power outputs ac-coupled driver configuration, pseudo-differential + tlv320_write_reg(0x0e, 0b10001000); + + //(15) un-mute left ADC PGA (6dB) (TESTED, WITH HIGHER GAIN SATURATES) + tlv320_write_reg(0x0f, 0b00000000); + // tlv320_write_reg(0x0f, 0b10000000); + + //(16) un-mute right ADC PGA (6dB) (TESTED, WITH HIGHER GAIN SATURATES) + tlv320_write_reg(0x10, 0b00000000); + + //(17) MIC2L connected to LEFT ADC (0dB), MIC2R not connected to LEFT ADC + // tlv320_write_reg(0x11, 0b00001111); + tlv320_write_reg(0x11, 0b11111000); + + //(18) MIC2R connected to RIGTH ADC (0dB), MIC2L not connected to RIGHT ADC + tlv320_write_reg(0x12, 0b11111000); + // tlv320_write_reg(0x12, 0b11111111); + + //(19) Turn ON LEFT ADC - PGA soft stepping disabled + tlv320_write_reg(0x13, 0b01111111); + + //(22) Turn ON RIGHT ADC - PGA soft stepping disabled + tlv320_write_reg(0x16, 0b01111111); + // tlv320_write_reg(0x16, 0b10000111); + + // (25) + // tlv320_write_reg(0x19, 0b01000000); + + // (26) + tlv320_write_reg(0x1A, 0b11110011); + // (28) + tlv320_write_reg(0x1C, 0b10111110); + + + // (29) + tlv320_write_reg(0x1D, 0b11110011); + // (31) + tlv320_write_reg(0x1F, 0b10111110); + + // (32) + // tlv320_write_reg(0x20, 0b00111100); + // tlv320_write_reg(0x20, 0b00000000); + // (33) + // tlv320_write_reg(0x21, 0b00111100); + // tlv320_write_reg(0x21, 0b00000000); + + // (34) + // tlv320_write_reg(0x22, 0b00111111); + // (35) + // tlv320_write_reg(0x23, 0b00111111); + + //(37) Turn ON RIGHT and LEFT DACs, HPLCOM set as independent VCM output + // tlv320_write_reg(0x25, 0b11010000); + tlv320_write_reg(0x25, 0b11100000);//Gieff + + //(38) HPRCOM set as independent VCM output, short circuit protection activated with curr limit + // tlv320_write_reg(0x26, 0b00001100); + tlv320_write_reg(0x26, 0b00010000);//Gieff + + //(40) output common-mode voltage = 1.65 V - output soft stepping each fs + tlv320_write_reg(0x28, 0b10000010); + + //(41) set DAC path, DAC_L2 to left high power, DAC_R2 to right high power, independent volume + tlv320_write_reg(0x29, 0b10100000); + //if commented, DAC_L1/DAC_R1 is used to HPLOUT, HPROUT + + //(42) Pop-reduction register, voltage divider + tlv320_write_reg(0x2a, 0b00010100); + + //(43) un-mute left DAC, gain 0dB + tlv320_write_reg(0x2b, 0b00000000); + + //(44) un-mute right DAC, gain 0dB + tlv320_write_reg(0x2c, 0b00000000); + + //(46) PGA_L to HPLOUT ON, volume control 0dB + //tlv320_write_reg(0x2e, 0b10000000); + + //(47) DAC_L1 to HPLOUT ON, volume control 0dB + // tlv320_write_reg(0x2f, 0b10000000); + + //(51) un-mute HPLOUT, 9dB, high impedance when powered down, HPLOUT fully powered + tlv320_write_reg(0x33, 0b10011101); + // tlv320_write_reg(0x33, 0b00001101);//Gieff + + // (53) PGA_L to HPLCOM + // tlv320_write_reg(0x35, 0b10000000); + // (56) PGA_R to HPLCOM + // tlv320_write_reg(0x38, 0b10000000); + // (60) PGA_L to HPROUT + // tlv320_write_reg(0x3C, 0b10000000); + // (63) PGA_R to HPROUT + // tlv320_write_reg(0x3F, 0b10000000); + // (67) PGA_L to HPRCOM + // tlv320_write_reg(0x43, 0b10000000); + // (70) PGA_R to HPRCOM + // tlv320_write_reg(0x46, 0b10000000); + + // (58) un-mute HPLCOM, high impedance when powered down, HPLCOM ON + tlv320_write_reg(0x3A, 0b10011101); + + //(63) PGA_R to HPROUT ON, volume control 0dB + //tlv320_write_reg(0x3f, 0b10000000); + + //(64) DAC_R1 to HPROUT Om, volume control 0dB + // tlv320_write_reg(0x3f, 0b10000000); + + //(65) un-mute HPROUT, 9dB, high impedance when powered down, HPROUT fully powered + tlv320_write_reg(0x41, 0b10011101); + //tlv320_write_reg(0x41, 0b00001101); //gieff + + //(72) un-mute HPRCOM, high impedance when powered down, HPRCOM fully powered + tlv320_write_reg(0x48, 0b10011101); + + //(101) CLK source selection, CLKDIV_OUT + tlv320_write_reg(0x65, 0b00000001); + + //(102) CLK source selection, MCLK + tlv320_write_reg(0x66, 0b00000010); + + //(109) DAC quiescent current 50% increase + tlv320_write_reg(0x6d, 0b00000000); + + + + + + audio_hal_codec_i2s_iface_t *i2s_cfg = &(codec_cfg->i2s_iface); + switch (i2s_cfg->mode) { + case AUDIO_HAL_MODE_MASTER: /* MASTER MODE */ + ESP_LOGI(TAG, "TLV320 in Master mode"); + break; + case AUDIO_HAL_MODE_SLAVE: /* SLAVE MODE */ + ESP_LOGI(TAG, "TLV320 in Slave mode"); + break; + default: + ESP_LOGI(TAG, "TLV320 in Default mode"); + } + + // switch (get_es8311_mclk_src()) { + // case FROM_MCLK_PIN: + + // break; + // case FROM_SCLK_PIN: + + // break; + // default: + + // break; + // } + + int sample_fre = 0; + switch (i2s_cfg->samples) { + case AUDIO_HAL_08K_SAMPLES: + ESP_LOGI(TAG, "TLV320 Sample Rate: 8KHz"); + sample_fre = 8000; + break; + case AUDIO_HAL_11K_SAMPLES: + ESP_LOGI(TAG, "TLV320 Sample Rate: 11KHz"); + sample_fre = 11025; + break; + case AUDIO_HAL_16K_SAMPLES: + ESP_LOGI(TAG, "TLV320 Sample Rate: 16KHz"); + sample_fre = 16000; + break; + case AUDIO_HAL_22K_SAMPLES: + ESP_LOGI(TAG, "TLV320 Sample Rate: 22KHz"); + sample_fre = 22050; + break; + case AUDIO_HAL_24K_SAMPLES: + ESP_LOGI(TAG, "TLV320 Sample Rate: 24KHz"); + sample_fre = 24000; + break; + case AUDIO_HAL_32K_SAMPLES: + ESP_LOGI(TAG, "TLV320 Sample Rate: 32KHz"); + sample_fre = 32000; + break; + case AUDIO_HAL_44K_SAMPLES: + ESP_LOGI(TAG, "TLV320 Sample Rate: 44.1KHz"); + sample_fre = 44100; + break; + case AUDIO_HAL_48K_SAMPLES: + ESP_LOGI(TAG, "TLV320 Sample Rate: 48KHz"); + sample_fre = 48000; + break; + default: + ESP_LOGE(TAG, "Unable to configure sample rate %dHz", sample_fre); + break; + } + + + return ESP_OK; +} + +esp_err_t tlv320_deinit(void) { + i2c_bus_delete(i2c_handle); + audio_codec_volume_deinit(dac_vol_handle); + + return ESP_OK; +} + +esp_err_t tlv320_set_voice_volume(int volume) { + ESP_LOGI(TAG, "Setting TLV320 volume to: %d", volume); + + // dac_vol_handle->user_volume = volume; + return ESP_OK; +} + +esp_err_t tlv320_get_voice_volume(int *volume) { + ESP_LOGI(TAG, "Getting TLV320 volume"); + + *volume = dac_vol_handle->user_volume; + return ESP_OK; +} + +esp_err_t tlv320_set_voice_mute(bool enable) { + ESP_LOGI(TAG, "Setting TLV320 mute to: %s", enable ? "ON" : "OFF"); + return ESP_OK; +} + +esp_err_t tlv320_config_i2s(audio_hal_codec_mode_t mode, audio_hal_codec_i2s_iface_t *iface) { + ESP_LOGI(TAG, "Configuring TLV320 I2S interface"); + + return ESP_OK; +} + +esp_err_t tlv320_ctrl_state(audio_hal_codec_mode_t mode, audio_hal_ctrl_t ctrl_state) { + ESP_LOGI(TAG, "Controlling TLV320 state: mode=%d, ctrl_state=%d", mode, ctrl_state); + return ESP_OK; +} + +esp_err_t tlv320_pa_power(bool enable) { + ESP_LOGI(TAG, "Setting TLV320 PA power to: %s", enable ? "ON" : "OFF"); + return ESP_OK; +} diff --git a/components/audio_hal/driver/tlv320/tlv320.h b/components/audio_hal/driver/tlv320/tlv320.h new file mode 100644 index 000000000..51152deb0 --- /dev/null +++ b/components/audio_hal/driver/tlv320/tlv320.h @@ -0,0 +1,104 @@ +#ifndef __TLV320_H__ +#define __TLV320_H__ + +#include "esp_types.h" +#include "audio_hal.h" +#include "driver/i2c.h" +#include "esxxx_common.h" + +#ifdef __cplusplus +extern "C" { +#endif + +/** + * @brief I2C address of TLV320AIC3101 + */ +#define TLV320_ADDR 0x18 /*!< Default I2C address if ADDR0 is low */ + +/** + * @brief Register Definitions for TLV320AIC3101 (Page 0 only — primary use) + */ +#define TLV320_PAGE_SELECT 0x00 +#define TLV320_SOFTWARE_RESET 0x01 + +#define TLV320_PLL_P_R 0x05 +#define TLV320_PLL_J 0x06 +#define TLV320_PLL_D_MSB 0x07 +#define TLV320_PLL_D_LSB 0x08 + +#define TLV320_NDAC 0x0B +#define TLV320_MDAC 0x0C +#define TLV320_DOSR_MSB 0x0D +#define TLV320_DOSR_LSB 0x0E + +#define TLV320_IFACE_CTRL_1 0x1B +#define TLV320_IFACE_CTRL_2 0x1C +#define TLV320_IFACE_CTRL_3 0x1D + +#define TLV320_DAC_PWR_CTRL 0x3F +#define TLV320_DAC_MUTE 0x40 +#define TLV320_DAC_VOL_LEFT 0x41 +#define TLV320_DAC_VOL_RIGHT 0x42 + +#define TLV320_ADC_PWR_CTRL 0x51 +#define TLV320_ADC_VOL_LEFT 0x53 +#define TLV320_ADC_VOL_RIGHT 0x54 + +// Page 1 for DAC Routing & Output Driver +#define TLV320_PAGE1_DAC_ROUTING_LEFT 0x0C +#define TLV320_PAGE1_DAC_ROUTING_RIGHT 0x0D +#define TLV320_PAGE1_HP_DRIVER_LEFT 0x0F +#define TLV320_PAGE1_HP_DRIVER_RIGHT 0x10 +#define TLV320_PAGE1_OUTPUT_DRV_PWR_CTRL 0x01 + + +/** + * @brief Initialize TLV320 codec + */ +esp_err_t tlv320_init(audio_hal_codec_config_t *cfg); + +/** + * @brief Deinitialize TLV320 codec + */ +esp_err_t tlv320_deinit(void); + +/** + * @brief Set DAC volume (0–100) + */ +esp_err_t tlv320_set_voice_volume(int volume); + +/** + * @brief Get DAC volume + */ +esp_err_t tlv320_get_voice_volume(int *volume); + +/** + * @brief Enable or disable mute + */ +esp_err_t tlv320_set_voice_mute(bool enable); + +/** + * @brief Direct register write + */ +esp_err_t tlv320_write_reg(uint8_t reg_addr, uint8_t data); + +/** + * @brief Configure codec I2S interface + */ +esp_err_t tlv320_config_i2s(audio_hal_codec_mode_t mode, audio_hal_codec_i2s_iface_t *iface); + +/** + * @brief Start/Stop codec in encode/decode/both mode + */ +int tlv320_ctrl_state(audio_hal_codec_mode_t mode, audio_hal_ctrl_t ctrl_state); + +/** + * @brief Set PA (Power Amp) control GPIO + */ +esp_err_t tlv320_pa_power(bool enable); + +#ifdef __cplusplus +} +#endif + +#endif // __TLV320_H__ diff --git a/components/audio_hal/test/test_audio_hal.c b/components/audio_hal/test/test_audio_hal.c index d7219d8e1..4d15d82a6 100644 --- a/components/audio_hal/test/test_audio_hal.c +++ b/components/audio_hal/test/test_audio_hal.c @@ -30,6 +30,7 @@ #include "driver/gpio.h" #include "unity.h" #include "es8311.h" +#include "tlv320.h" #include "es8388.h" #include "zl38063.h" diff --git a/components/audio_stream/i2s_stream_idf5.c b/components/audio_stream/i2s_stream_idf5.c index b26b6d64e..f3d39ad33 100644 --- a/components/audio_stream/i2s_stream_idf5.c +++ b/components/audio_stream/i2s_stream_idf5.c @@ -114,6 +114,11 @@ static int i2s_driver_startup(audio_element_handle_t self, i2s_stream_cfg_t *i2s i2s_key_slot[i2s->port].chan_cfg.auto_clear = true; ret = i2s_new_channel(&i2s_key_slot[i2s->port].chan_cfg, i2s_key_slot[i2s->port].dir & I2S_DIR_TX ? &i2s_key_slot[i2s->port].tx_handle : NULL, i2s_key_slot[i2s->port].dir & I2S_DIR_RX ? &i2s_key_slot[i2s->port].rx_handle : NULL); + + i2s_key_slot[i2s->port].tx_std_cfg.gpio_cfg.invert_flags.bclk_inv = 0; + i2s_key_slot[i2s->port].tx_std_cfg.gpio_cfg.invert_flags.mclk_inv = 0; + i2s_key_slot[i2s->port].tx_std_cfg.gpio_cfg.invert_flags.ws_inv = 0; + switch (i2s_mode) { case I2S_COMM_MODE_STD: if (i2s_key_slot[i2s->port].dir & I2S_DIR_TX) { @@ -604,6 +609,7 @@ audio_element_handle_t i2s_stream_init(i2s_stream_cfg_t *config) return NULL; } int i2s_port = config->chan_cfg.id; + ESP_LOGE(TAG, "I2s Port is : %d" ,i2s_port); i2s_dir_t i2s_dir = 0; if (i2s_port == I2S_NUM_AUTO) { ESP_LOGE(TAG, "Please specify the port number of I2S."); @@ -677,6 +683,18 @@ audio_element_handle_t i2s_stream_init(i2s_stream_cfg_t *config) i2s_channel_enable(i2s_key_slot[i2s_port].rx_handle); } + ESP_LOGE(TAG, "I2S Pins -> BCLK : %d" ,i2s_key_slot[i2s->port].tx_std_cfg.gpio_cfg.bclk); + ESP_LOGE(TAG, "I2S Pins -> MCLK : %d" ,i2s_key_slot[i2s->port].tx_std_cfg.gpio_cfg.mclk); + ESP_LOGE(TAG, "I2S Pins -> SDO : %d" ,i2s_key_slot[i2s->port].tx_std_cfg.gpio_cfg.dout); + ESP_LOGE(TAG, "I2S Pins -> SDI : %d" ,i2s_key_slot[i2s->port].tx_std_cfg.gpio_cfg.din); + ESP_LOGE(TAG, "I2S Pins -> WS : %d" ,i2s_key_slot[i2s->port].tx_std_cfg.gpio_cfg.ws); + + ESP_LOGE(TAG, "I2S Pins -> bclk_inv : %d" ,i2s_key_slot[i2s->port].tx_std_cfg.gpio_cfg.invert_flags.bclk_inv); + ESP_LOGE(TAG, "I2S Pins -> mclk_inv : %d" ,i2s_key_slot[i2s->port].tx_std_cfg.gpio_cfg.invert_flags.mclk_inv); + ESP_LOGE(TAG, "I2S Pins -> ws_inv : %d" ,i2s_key_slot[i2s->port].tx_std_cfg.gpio_cfg.invert_flags.ws_inv); + + + i2s_end: i2s_safe_unlock(s_i2s_tx_mutex[i2s_port]); i2s_safe_unlock(s_i2s_rx_mutex[i2s_port]); diff --git a/components/audio_stream/include/i2s_stream.h b/components/audio_stream/include/i2s_stream.h index 2b7eced81..31912e70a 100644 --- a/components/audio_stream/include/i2s_stream.h +++ b/components/audio_stream/include/i2s_stream.h @@ -270,7 +270,7 @@ typedef struct { }, \ }, \ .use_alc = false, \ - .volume = 0, \ + .volume = 100, \ .out_rb_size = I2S_STREAM_RINGBUFFER_SIZE, \ .task_stack = I2S_STREAM_TASK_STACK, \ .task_core = I2S_STREAM_TASK_CORE, \ diff --git a/components/esp_codec_dev/CMakeLists.txt b/components/esp_codec_dev/CMakeLists.txt index 89deacadf..7e8251b1e 100644 --- a/components/esp_codec_dev/CMakeLists.txt +++ b/components/esp_codec_dev/CMakeLists.txt @@ -55,6 +55,10 @@ if (CONFIG_CODEC_AW88298_SUPPORT) list(APPEND COMPONENT_SRCS device/aw88298/aw88298.c) endif() +if (CONFIG_CODEC_TLV320_SUPPORT) + list(APPEND COMPONENT_SRCS device/tlv320/tlv320.c) +endif() + if (CONFIG_CODEC_ZL38063_SUPPORT) list(APPEND COMPONENT_SRCS device/zl38063/zl38063.c device/zl38063/api_lib/vprocTwolf_access.c diff --git a/components/esp_codec_dev/Kconfig b/components/esp_codec_dev/Kconfig index 7f1c8193f..5c6c94151 100755 --- a/components/esp_codec_dev/Kconfig +++ b/components/esp_codec_dev/Kconfig @@ -57,6 +57,12 @@ menu "Audio Codec Device Configuration" default y help Enable this option to support codec ES8388. + + config CODEC_TLV320_SUPPORT + bool "Support TLV320 Codec Chip" + default y + help + Enable this option to support codec TLV320. config CODEC_TAS5805M_SUPPORT bool "Support TAS5805M Codec Chip" diff --git a/components/esp_codec_dev/device/include/tlv320_codec.h b/components/esp_codec_dev/device/include/tlv320_codec.h new file mode 100644 index 000000000..69e8a1ec0 --- /dev/null +++ b/components/esp_codec_dev/device/include/tlv320_codec.h @@ -0,0 +1,53 @@ +/* + * SPDX-FileCopyrightText: 2023 Espressif Systems (Shanghai) CO LTD + * + * SPDX-License-Identifier: Apache-2.0 + */ +#ifndef _TLV320_CODEC_H_ +#define _TLV320_CODEC_H_ + +#include "audio_codec_if.h" +#include "audio_codec_ctrl_if.h" +#include "audio_codec_gpio_if.h" +#include "esp_codec_dev_vol.h" +// #include "esp_codec_dev_defs.h" // For esp_codec_i2s_iface_t + +#ifdef __cplusplus +extern "C" { +#endif + +/** + * @brief TLV320AIC3101 default I2C address + * According to datasheet: address = 0b0011000 = 0x18 (if ADDR0 pin is low) + */ +#define TLV320_CODEC_I2C_ADDR (0x18) +#define TLV320_CODEC_I2C_ADDR_ALT (0x19) /*!< If ADDR0 pin is high */ + +/** + * @brief TLV320 codec configuration structure + */ +typedef struct { + const audio_codec_ctrl_if_t *ctrl_if; /*!< I2C control interface for TLV320 */ + const audio_codec_gpio_if_t *gpio_if; /*!< Optional GPIO interface (e.g. for PA pin) */ + esp_codec_dec_work_mode_t codec_mode; /*!< ADC / DAC / Both */ + // esp_codec_i2s_iface_t i2s_iface; /*!< I2S format, master/slave mode, etc. */ + bool master_mode; + int16_t pa_pin; /*!< Power Amplifier control pin (-1 if unused) */ + bool pa_reverted; /*!< true if PA is active-low */ + esp_codec_dev_hw_gain_t hw_gain; /*!< Codec internal gain in dB */ +} tlv320_codec_cfg_t; + +/** + * @brief Create a new TLV320 codec interface + * + * @param codec_cfg Codec configuration + * + * @return Pointer to audio_codec_if_t on success, NULL on failure + */ +const audio_codec_if_t *tlv320_codec_new(tlv320_codec_cfg_t *codec_cfg); + +#ifdef __cplusplus +} +#endif + +#endif // _TLV320_CODEC_H_ diff --git a/components/esp_codec_dev/device/tlv320/tlv320.c b/components/esp_codec_dev/device/tlv320/tlv320.c new file mode 100644 index 000000000..f23a8251c --- /dev/null +++ b/components/esp_codec_dev/device/tlv320/tlv320.c @@ -0,0 +1,174 @@ +#include +#include "esp_log.h" +#include "tlv320_reg.h" +#include "tlv320_codec.h" +#include "esp_codec_dev_vol.h" + +#define TAG "TLV320_CODEC" + +typedef struct { + audio_codec_if_t base; + const audio_codec_ctrl_if_t *ctrl_if; + const audio_codec_gpio_if_t *gpio_if; + bool is_open; + bool enabled; + esp_codec_dec_work_mode_t codec_mode; + int16_t pa_pin; + bool pa_reverted; + float hw_gain; +} audio_codec_tlv320_t; + +static const esp_codec_dev_vol_range_t vol_range = { + .min_vol = { .vol = 0x7F, .db_value = -63.5f }, + .max_vol = { .vol = 0x00, .db_value = 0.0f }, +}; + +static int tlv320_write_reg(audio_codec_tlv320_t *codec, uint8_t reg, uint8_t val) { + return codec->ctrl_if->write_reg(codec->ctrl_if, reg, 1, &val, 1); +} + +static int tlv320_read_reg(audio_codec_tlv320_t *codec, uint8_t reg, int *val) { + uint8_t temp = 0; + int res = codec->ctrl_if->read_reg(codec->ctrl_if, reg, 1, &temp, 1); + *val = temp; + return res; +} + +static int tlv320_set_volume(audio_codec_tlv320_t *codec, float db) { + db -= codec->hw_gain; + int volume = esp_codec_dev_vol_calc_reg(&vol_range, db); + // tlv320_write_reg(codec, TLV320_REG_DAC_VOL_LEFT, volume); + // tlv320_write_reg(codec, TLV320_REG_DAC_VOL_RIGHT, volume); + return ESP_OK; +} + +static int tlv320_set_mute(audio_codec_tlv320_t *codec, bool mute) { + // int reg = 0; + // tlv320_read_reg(codec, TLV320_REG_DAC_MUTE, ®); + // reg = mute ? (reg | 0x0C) : (reg & ~0x0C); + // tlv320_write_reg(codec, TLV320_REG_DAC_MUTE, reg); + return ESP_OK; +} + +static int tlv320_configure(audio_codec_tlv320_t *codec) { + int res = 0; + + // // Set to page 0 + // res |= tlv320_write_reg(codec, TLV320_REG_PAGE_SELECT, 0x00); + // res |= tlv320_write_reg(codec, TLV320_REG_SOFTWARE_RESET, 0x01); + + // // vTaskDelay(pdMS_TO_TICKS(10)); + + // // Configure PLL and clock + // res |= tlv320_write_reg(codec, TLV320_REG_CLK_GEN_MUX, 0x01); // PLL + // res |= tlv320_write_reg(codec, TLV320_REG_PLL_P_R, 0x91); // P=1, R=1 + // res |= tlv320_write_reg(codec, TLV320_REG_PLL_J, 0x08); // J=8 + // res |= tlv320_write_reg(codec, TLV320_REG_PLL_D_MSB, 0x00); + // res |= tlv320_write_reg(codec, TLV320_REG_PLL_D_LSB, 0x00); + + // res |= tlv320_write_reg(codec, TLV320_REG_NDAC, 0x81); // NDAC = 1 + // res |= tlv320_write_reg(codec, TLV320_REG_MDAC, 0x81); // MDAC = 1 + // res |= tlv320_write_reg(codec, TLV320_REG_DOSR_MSB, 0x00); + // res |= tlv320_write_reg(codec, TLV320_REG_DOSR_LSB, 0x80); // DOSR = 128 + + // // Audio Interface config (I2S, 16-bit) + // res |= tlv320_write_reg(codec, TLV320_REG_IFACE_CTRL_1, 0x00); // I2S, 16bit + // res |= tlv320_write_reg(codec, TLV320_REG_IFACE_CTRL_2, 0x00); + // res |= tlv320_write_reg(codec, TLV320_REG_IFACE_CTRL_3, 0x00); + + // // Power-up DAC + // res |= tlv320_write_reg(codec, TLV320_REG_DAC_PWR_CTRL, 0xD4); // Enable L/R DAC + // res |= tlv320_write_reg(codec, TLV320_REG_DAC_MUTE, 0x00); // Unmute + // res |= tlv320_set_volume(codec, 0); // 0 dB volume + + // // Power-up ADC + // res |= tlv320_write_reg(codec, TLV320_REG_ADC_PWR_CTRL, 0xC0); + // res |= tlv320_write_reg(codec, TLV320_REG_ADC_VOL_LEFT, 0x80); // 0dB + // res |= tlv320_write_reg(codec, TLV320_REG_ADC_VOL_RIGHT, 0x80); // 0dB + + // // DAC Routing + // res |= tlv320_write_reg(codec, TLV320_REG_PAGE_SELECT, 0x01); + // res |= tlv320_write_reg(codec, TLV320_PAGE1_DAC_ROUTING_LEFT, 0x08); + // res |= tlv320_write_reg(codec, TLV320_PAGE1_DAC_ROUTING_RIGHT, 0x08); + // res |= tlv320_write_reg(codec, TLV320_PAGE1_HP_DRIVER_LEFT, 0x0C); + // res |= tlv320_write_reg(codec, TLV320_PAGE1_HP_DRIVER_RIGHT, 0x0C); + // res |= tlv320_write_reg(codec, TLV320_PAGE1_OUTPUT_DRV_PWR_CTRL, 0xC0); + + // // Return to Page 0 + // res |= tlv320_write_reg(codec, TLV320_REG_PAGE_SELECT, 0x00); + + return res; +} + +static int tlv320_open(const audio_codec_if_t *h, void *cfg, int cfg_size) { + // audio_codec_tlv320_t *codec = (audio_codec_tlv320_t *) h; + // tlv320_codec_cfg_t *codec_cfg = (tlv320_codec_cfg_t *) cfg; + + // if (!codec || !codec_cfg || cfg_size != sizeof(tlv320_codec_cfg_t)) return -1; + + // codec->ctrl_if = codec_cfg->ctrl_if; + // codec->gpio_if = codec_cfg->gpio_if; + // codec->pa_pin = codec_cfg->pa_pin; + // codec->pa_reverted = codec_cfg->pa_reverted; + // codec->codec_mode = codec_cfg->codec_mode; + + // return tlv320_configure(codec); + + return ESP_OK; +} + +static int tlv320_enable(const audio_codec_if_t *h, bool enable) { + // audio_codec_tlv320_t *codec = (audio_codec_tlv320_t *) h; + // codec->enabled = enable; + return ESP_OK; +} + +static int tlv320_set_fs(const audio_codec_if_t *h, esp_codec_dev_sample_info_t *fs) { + // For now fixed sample rate. Extendable. + return ESP_OK; +} + +static int tlv320_set_vol(const audio_codec_if_t *h, float db) { + // return tlv320_set_volume((audio_codec_tlv320_t *) h, db); + return ESP_OK; +} + +static int tlv320_mute(const audio_codec_if_t *h, bool mute) { + // return tlv320_set_mute((audio_codec_tlv320_t *) h, mute); + return ESP_OK; +} + +static int tlv320_close(const audio_codec_if_t *h) { + return ESP_OK; +} + +static void tlv320_dump(const audio_codec_if_t *h) { + // audio_codec_tlv320_t *codec = (audio_codec_tlv320_t *) h; + // for (int i = 0; i <= 0x7F; ++i) { + // int val = 0; + // tlv320_read_reg(codec, i, &val); + // ESP_LOGI(TAG, "Reg 0x%02X = 0x%02X", i, val); + // } +} + +const audio_codec_if_t *tlv320_codec_new(tlv320_codec_cfg_t *cfg) { + // if (!cfg || !cfg->ctrl_if) return NULL; + audio_codec_tlv320_t *codec = calloc(1, sizeof(audio_codec_tlv320_t)); + // if (!codec) return NULL; + + // codec->base.open = tlv320_open; + // codec->base.enable = tlv320_enable; + // codec->base.set_fs = tlv320_set_fs; + // codec->base.set_vol = tlv320_set_vol; + // codec->base.mute = tlv320_mute; + // codec->base.dump_reg = tlv320_dump; + // codec->base.close = tlv320_close; + // codec->hw_gain = esp_codec_dev_col_calc_hw_gain(&cfg->hw_gain); + + // if (codec->base.open(&codec->base, cfg, sizeof(tlv320_codec_cfg_t)) != 0) { + // free(codec); + // return NULL; + // } + + return &codec->base; +} diff --git a/components/esp_codec_dev/device/tlv320/tlv320_reg.h b/components/esp_codec_dev/device/tlv320/tlv320_reg.h new file mode 100644 index 000000000..b5e87044d --- /dev/null +++ b/components/esp_codec_dev/device/tlv320/tlv320_reg.h @@ -0,0 +1,63 @@ +/* + * SPDX-FileCopyrightText: 2023 Espressif Systems (Shanghai) CO LTD + * + * SPDX-License-Identifier: Apache-2.0 + */ +#ifndef _TLV320_REG_ +#define _TLV320_REG_ + +#ifdef __cplusplus +extern "C" { +#endif + +// Page 0 Registers +#define TLV320_REG_PAGE_SELECT 0x00 +#define TLV320_REG_SOFTWARE_RESET 0x01 + +#define TLV320_REG_CLK_GEN_MUX 0x04 +#define TLV320_REG_PLL_P_R 0x05 +#define TLV320_REG_PLL_J 0x06 +#define TLV320_REG_PLL_D_MSB 0x07 +#define TLV320_REG_PLL_D_LSB 0x08 + +#define TLV320_REG_NDAC 0x0B +#define TLV320_REG_MDAC 0x0C +#define TLV320_REG_DOSR_MSB 0x0D +#define TLV320_REG_DOSR_LSB 0x0E + +#define TLV320_REG_NADC 0x12 +#define TLV320_REG_MADC 0x13 +#define TLV320_REG_AOSR 0x14 + +#define TLV320_REG_IFACE_CTRL_1 0x1B +#define TLV320_REG_IFACE_CTRL_2 0x1C +#define TLV320_REG_IFACE_CTRL_3 0x1D + +#define TLV320_REG_DAC_PWR_CTRL 0x3F +#define TLV320_REG_DAC_MUTE 0x40 +#define TLV320_REG_DAC_VOL_LEFT 0x41 +#define TLV320_REG_DAC_VOL_RIGHT 0x42 + +#define TLV320_REG_ADC_PWR_CTRL 0x51 +#define TLV320_REG_ADC_VOL_LEFT 0x53 +#define TLV320_REG_ADC_VOL_RIGHT 0x54 + +#define TLV320_REG_ADC_INPUT_ROUTING 0x52 + +// Page 1 Registers +#define TLV320_PAGE1_DAC_ROUTING_LEFT 0x0C +#define TLV320_PAGE1_DAC_ROUTING_RIGHT 0x0D +#define TLV320_PAGE1_HP_DRIVER_LEFT 0x0F +#define TLV320_PAGE1_HP_DRIVER_RIGHT 0x10 +#define TLV320_PAGE1_OUTPUT_DRV_PWR_CTRL 0x01 + +// Constants +#define TLV320_PAGE_0 0x00 +#define TLV320_PAGE_1 0x01 +#define TLV320_SOFT_RESET_CMD 0x01 + +#ifdef __cplusplus +} +#endif + +#endif //__TLV320_H__ diff --git a/components/esp_codec_dev/include/esp_codec_dev_defaults.h b/components/esp_codec_dev/include/esp_codec_dev_defaults.h index e06a06e0f..8f3f8f572 100644 --- a/components/esp_codec_dev/include/esp_codec_dev_defaults.h +++ b/components/esp_codec_dev/include/esp_codec_dev_defaults.h @@ -41,6 +41,9 @@ #ifdef CONFIG_CODEC_ZL38063_SUPPORT #include "zl38063_codec.h" #endif +#ifdef CONFIG_CODEC_TLV320_SUPPORT +#include "tlv320_codec.h" +#endif #ifdef __cplusplus extern "C" { diff --git a/examples/protocols/components/audio_flash_tone/audio_player_int_tone.c b/examples/protocols/components/audio_flash_tone/audio_player_int_tone.c index e33e327b9..00bb9cfb7 100644 --- a/examples/protocols/components/audio_flash_tone/audio_player_int_tone.c +++ b/examples/protocols/components/audio_flash_tone/audio_player_int_tone.c @@ -103,6 +103,8 @@ audio_err_t audio_player_int_tone_stop() audio_err_t audio_player_int_tone_play(const char *url) { - esp_audio_play(player, AUDIO_CODEC_TYPE_DECODER, url, 0); + audio_err_t res = ESP_OK; + res = esp_audio_play(player, AUDIO_CODEC_TYPE_DECODER, url, 0); + ESP_LOGI(TAG, "esp_audio_play : %d" ,res); return ESP_OK; } diff --git a/examples/protocols/components/av_stream/av_stream.c b/examples/protocols/components/av_stream/av_stream.c index 71bbd134a..6a4a0be50 100644 --- a/examples/protocols/components/av_stream/av_stream.c +++ b/examples/protocols/components/av_stream/av_stream.c @@ -397,7 +397,8 @@ int av_audio_enc_start(av_stream_handle_t av_stream) audio_pipeline_register(av_stream->audio_enc, av_stream->audio_enc_read, "raw"); audio_element_set_read_cb(filter, audio_read_cb, av_stream); audio_element_set_input_timeout(filter, get_audio_max_delay(av_stream, AUDIO_MAX_SIZE) / portTICK_PERIOD_MS); - const char *link_tag[2] = {"filter", "raw"}; + // const char *link_tag[2] = {"filter", "raw"}; + const char *link_tag[2] = {"raw", "filter"}; audio_pipeline_link(av_stream->audio_enc, &link_tag[0], 2); #endif } diff --git a/examples/protocols/components/av_stream/av_stream_hal/av_stream_hal.h b/examples/protocols/components/av_stream/av_stream_hal/av_stream_hal.h index 3b98f5baf..ef8c182e6 100644 --- a/examples/protocols/components/av_stream/av_stream_hal/av_stream_hal.h +++ b/examples/protocols/components/av_stream/av_stream_hal/av_stream_hal.h @@ -46,7 +46,7 @@ extern "C" { #if CONFIG_ESP32_S3_KORVO2L_V1_BOARD // ES8311 need ADCL + DACR for AEC feature #define I2S_CHANNELS I2S_CHANNEL_TYPE_RIGHT_LEFT #else -#define I2S_CHANNELS I2S_CHANNEL_TYPE_ONLY_LEFT +#define I2S_CHANNELS I2S_CHANNEL_TYPE_RIGHT_LEFT #endif #define USB_CAMERA_FRAME_INTERVAL(fps) ((10000000) / fps) diff --git a/examples/protocols/components/av_stream/av_stream_hal/av_stream_hal_audio.c b/examples/protocols/components/av_stream/av_stream_hal/av_stream_hal_audio.c index fc4ef22aa..5aea1e47d 100644 --- a/examples/protocols/components/av_stream/av_stream_hal/av_stream_hal_audio.c +++ b/examples/protocols/components/av_stream/av_stream_hal/av_stream_hal_audio.c @@ -22,189 +22,189 @@ * */ -#include "string.h" -#include "es8311.h" -#include "audio_mem.h" -#include "audio_sys.h" -#include "i2s_stream.h" -#include "algorithm_stream.h" -#include "av_stream_hal.h" - -static const char *TAG = "AV_STREAM_HAL"; - -static audio_element_handle_t i2s_io_writer; -static audio_element_handle_t i2s_io_reader; - -#if CONFIG_IDF_TARGET_ESP32 -static int uac_device_init(void *mic_cb, void *arg, uint32_t sample_rate) -{ - /* Not Support */ - return ESP_FAIL; -} -#else -#include "usb_stream.h" -/* USB Audio Descriptors Related MACROS, -the quick demo skip the standred get descriptors process, -users need to get params from camera descriptors from PC side, -eg. run `lsusb -v` in linux, -then hardcode the related MACROS below -*/ -static int uac_device_init(void *mic_cb, void *arg, uint32_t sample_rate) -{ - esp_err_t ret = ESP_FAIL; - uac_config_t uac_config = { - .mic_bit_resolution = 16, - .mic_samples_frequence = sample_rate, - .spk_bit_resolution = 16, - .spk_samples_frequence = sample_rate, - .spk_buf_size = 20*1024, - .mic_cb = mic_cb, - .mic_cb_arg = arg, - }; - ret = uac_streaming_config(&uac_config); - if (ret != ESP_OK) { - ESP_LOGE(TAG, "uac streaming config failed"); - } - return ret; -} -#endif - -static esp_err_t i2s_read_drv_init(int port, uint32_t sample_rate, i2s_channel_type_t channels) -{ - i2s_stream_cfg_t i2s_cfg = I2S_STREAM_CFG_DEFAULT_WITH_PARA(port, sample_rate, I2S_DEFAULT_BITS, AUDIO_STREAM_READER); - i2s_cfg.task_stack = -1; - i2s_stream_set_channel_type(&i2s_cfg, channels); - i2s_io_reader = i2s_stream_init(&i2s_cfg); - if (i2s_io_reader == NULL) { - ESP_LOGE(TAG, "i2s_read_drv_init failed"); - return ESP_FAIL; - } - return ESP_OK; -} - -static esp_err_t i2s_write_drv_init(int port, uint32_t sample_rate, i2s_channel_type_t channels) -{ - i2s_stream_cfg_t i2s_cfg = I2S_STREAM_CFG_DEFAULT_WITH_PARA(port, sample_rate, I2S_DEFAULT_BITS, AUDIO_STREAM_WRITER); - i2s_cfg.task_stack = -1; - i2s_cfg.need_expand = (16 != I2S_DEFAULT_BITS); - i2s_stream_set_channel_type(&i2s_cfg, channels); - i2s_io_writer = i2s_stream_init(&i2s_cfg); - if (i2s_io_writer == NULL) { - ESP_LOGE(TAG, "i2s_write_drv_init failed"); - return ESP_FAIL; - } - return ESP_OK; -} - -static audio_board_handle_t i2s_device_init(uint32_t sample_rate) -{ - i2s_write_drv_init(I2S_DEFAULT_PORT, sample_rate, I2S_CHANNELS); - -#if CONFIG_ESP_LYRAT_MINI_V1_1_BOARD - i2s_read_drv_init(CODEC_ADC_I2S_PORT, sample_rate, I2S_CHANNEL_TYPE_RIGHT_LEFT); -#else - i2s_read_drv_init(CODEC_ADC_I2S_PORT, sample_rate, I2S_CHANNELS); -#endif - - audio_board_handle_t board_handle = audio_board_init(); - audio_hal_ctrl_codec(board_handle->audio_hal, AUDIO_HAL_CODEC_MODE_BOTH, AUDIO_HAL_CTRL_START); - audio_hal_set_volume(board_handle->audio_hal, 75); - return board_handle; -} - -static int i2s_device_deinit(void *handle) -{ - esp_err_t ret = ESP_FAIL; - - AUDIO_NULL_CHECK(TAG, handle, return ESP_ERR_INVALID_ARG); - audio_board_handle_t board_handle = (audio_board_handle_t) handle; -#if RECORD_HARDWARE_AEC - ret = audio_hal_deinit(board_handle->audio_hal); -#if (CONFIG_ESP32_S3_KORVO2_V3_BOARD || CONFIG_ESP_LYRAT_MINI_V1_1_BOARD) - ret |= audio_hal_deinit(board_handle->adc_hal); -#endif -#if CONFIG_ESP_LYRAT_MINI_V1_1_BOARD - ret |= audio_element_deinit(i2s_io_reader); -#endif - free(board_handle); - board_handle = NULL; -#else - ret = audio_board_deinit(board_handle); -#endif - ret |= audio_element_deinit(i2s_io_writer); - ret |= audio_element_deinit(i2s_io_reader); - - return ret; -} - -int av_stream_audio_read(char *buf, int len, TickType_t wait_time, bool uac_en) -{ - int ret = ESP_FAIL; - size_t bytes_read = 0; - - if (uac_en) { - // TODO - // ret = uac_mic_streaming_read(buf, len, &bytes_read, wait_time); - // if (ret != ESP_OK) { - // ESP_LOGE(TAG, "uac read failed"); - // } - return ret; - } else { - ret = audio_element_input(i2s_io_reader, buf, len); - if (ret <= 0) { - ESP_LOGE(TAG, "i2s fail read ret %d", ret); - return ret; - } - #if (CONFIG_IDF_TARGET_ESP32 && !RECORD_HARDWARE_AEC) - algorithm_mono_fix((uint8_t *)buf, bytes_read); - #endif - bytes_read = ret; - } - - return bytes_read; -} - -int av_stream_audio_write(char *buf, int len, TickType_t wait_time, bool uac_en) -{ - size_t bytes_writen = 0; - - if (uac_en) { - #if !CONFIG_IDF_TARGET_ESP32 - bytes_writen = uac_spk_streaming_write(buf, len, wait_time); - #endif - } else { - #if CONFIG_IDF_TARGET_ESP32 - algorithm_mono_fix((uint8_t *)buf, len); - #endif - - int ret = audio_element_output(i2s_io_writer, buf, len); - if (ret < 0) { - ESP_LOGE(TAG, "i2s write failed"); - } else { - bytes_writen = ret; - } - } - return bytes_writen; -} - -audio_board_handle_t av_stream_audio_init(void *ctx, void *arg, av_stream_hal_config_t *config) -{ - AUDIO_NULL_CHECK(TAG, config, return NULL); - - if (config->uac_en) { - uac_device_init(ctx, arg, config->audio_samplerate); - } else { - return i2s_device_init(config->audio_samplerate); - } - return NULL; -} - -int av_stream_audio_deinit(void *ctx, bool uac_en) -{ - esp_err_t ret = ESP_OK; - - if (!uac_en) { - ret = i2s_device_deinit(ctx); - } - return ret; -} + #include "string.h" + #include "es8311.h" + #include "audio_mem.h" + #include "audio_sys.h" + #include "i2s_stream.h" + #include "algorithm_stream.h" + #include "av_stream_hal.h" + + static const char *TAG = "AV_STREAM_HAL"; + + static audio_element_handle_t i2s_io_writer; + static audio_element_handle_t i2s_io_reader; + + #if CONFIG_IDF_TARGET_ESP32 + static int uac_device_init(void *mic_cb, void *arg, uint32_t sample_rate) + { + /* Not Support */ + return ESP_FAIL; + } + #else + #include "usb_stream.h" + /* USB Audio Descriptors Related MACROS, + the quick demo skip the standred get descriptors process, + users need to get params from camera descriptors from PC side, + eg. run `lsusb -v` in linux, + then hardcode the related MACROS below + */ + static int uac_device_init(void *mic_cb, void *arg, uint32_t sample_rate) + { + esp_err_t ret = ESP_FAIL; + uac_config_t uac_config = { + .mic_bit_resolution = 16, + .mic_samples_frequence = sample_rate, + .spk_bit_resolution = 16, + .spk_samples_frequence = sample_rate, + .spk_buf_size = 20*1024, + .mic_cb = mic_cb, + .mic_cb_arg = arg, + }; + ret = uac_streaming_config(&uac_config); + if (ret != ESP_OK) { + ESP_LOGE(TAG, "uac streaming config failed"); + } + return ret; + } + #endif + + static esp_err_t i2s_read_drv_init(int port, uint32_t sample_rate, i2s_channel_type_t channels) + { + i2s_stream_cfg_t i2s_cfg = I2S_STREAM_CFG_DEFAULT_WITH_PARA(port, sample_rate, I2S_DEFAULT_BITS, AUDIO_STREAM_READER); + i2s_cfg.task_stack = -1; + i2s_stream_set_channel_type(&i2s_cfg, channels); + i2s_io_reader = i2s_stream_init(&i2s_cfg); + if (i2s_io_reader == NULL) { + ESP_LOGE(TAG, "i2s_read_drv_init failed"); + return ESP_FAIL; + } + return ESP_OK; + } + + static esp_err_t i2s_write_drv_init(int port, uint32_t sample_rate, i2s_channel_type_t channels) + { + i2s_stream_cfg_t i2s_cfg = I2S_STREAM_CFG_DEFAULT_WITH_PARA(port, sample_rate, I2S_DEFAULT_BITS, AUDIO_STREAM_WRITER); + i2s_cfg.task_stack = -1; + i2s_cfg.need_expand = (16 != I2S_DEFAULT_BITS); + i2s_stream_set_channel_type(&i2s_cfg, channels); + i2s_io_writer = i2s_stream_init(&i2s_cfg); + if (i2s_io_writer == NULL) { + ESP_LOGE(TAG, "i2s_write_drv_init failed"); + return ESP_FAIL; + } + return ESP_OK; + } + + static audio_board_handle_t i2s_device_init(uint32_t sample_rate) + { + i2s_write_drv_init(I2S_DEFAULT_PORT, sample_rate, I2S_CHANNELS); + + #if CONFIG_ESP_LYRAT_MINI_V1_1_BOARD + i2s_read_drv_init(CODEC_ADC_I2S_PORT, sample_rate, I2S_CHANNEL_TYPE_RIGHT_LEFT); + #else + i2s_read_drv_init(CODEC_ADC_I2S_PORT, sample_rate, I2S_CHANNELS); + #endif + + audio_board_handle_t board_handle = audio_board_init(); + audio_hal_ctrl_codec(board_handle->audio_hal, AUDIO_HAL_CODEC_MODE_BOTH, AUDIO_HAL_CTRL_START); + audio_hal_set_volume(board_handle->audio_hal, 75); + return board_handle; + } + + static int i2s_device_deinit(void *handle) + { + esp_err_t ret = ESP_FAIL; + + AUDIO_NULL_CHECK(TAG, handle, return ESP_ERR_INVALID_ARG); + audio_board_handle_t board_handle = (audio_board_handle_t) handle; + #if RECORD_HARDWARE_AEC + ret = audio_hal_deinit(board_handle->audio_hal); + #if (CONFIG_ESP32_S3_KORVO2_V3_BOARD || CONFIG_ESP_LYRAT_MINI_V1_1_BOARD) + ret |= audio_hal_deinit(board_handle->adc_hal); + #endif + #if CONFIG_ESP_LYRAT_MINI_V1_1_BOARD + ret |= audio_element_deinit(i2s_io_reader); + #endif + free(board_handle); + board_handle = NULL; + #else + ret = audio_board_deinit(board_handle); + #endif + ret |= audio_element_deinit(i2s_io_writer); + ret |= audio_element_deinit(i2s_io_reader); + + return ret; + } + + int av_stream_audio_read(char *buf, int len, TickType_t wait_time, bool uac_en) + { + int ret = ESP_FAIL; + size_t bytes_read = 0; + + if (uac_en) { + // TODO + // ret = uac_mic_streaming_read(buf, len, &bytes_read, wait_time); + // if (ret != ESP_OK) { + // ESP_LOGE(TAG, "uac read failed"); + // } + return ret; + } else { + ret = audio_element_input(i2s_io_reader, buf, len); + if (ret < 0) { + ESP_LOGE(TAG, "i2s read failed"); + } else { + bytes_read = ret; + } + #if (CONFIG_IDF_TARGET_ESP32 && !RECORD_HARDWARE_AEC) + algorithm_mono_fix((uint8_t *)buf, bytes_read); + #endif + } + + return bytes_read; + } + + int av_stream_audio_write(char *buf, int len, TickType_t wait_time, bool uac_en) + { + size_t bytes_writen = 0; + + if (uac_en) { + #if !CONFIG_IDF_TARGET_ESP32 + bytes_writen = uac_spk_streaming_write(buf, len, wait_time); + #endif + } else { + #if CONFIG_IDF_TARGET_ESP32 + algorithm_mono_fix((uint8_t *)buf, len); + #endif + + int ret = audio_element_output(i2s_io_writer, buf, len); + if (ret < 0) { + ESP_LOGE(TAG, "i2s write failed"); + } else { + bytes_writen = ret; + } + } + return bytes_writen; + } + + audio_board_handle_t av_stream_audio_init(void *ctx, void *arg, av_stream_hal_config_t *config) + { + AUDIO_NULL_CHECK(TAG, config, return NULL); + + if (config->uac_en) { + uac_device_init(ctx, arg, config->audio_samplerate); + } else { + return i2s_device_init(config->audio_samplerate); + } + return NULL; + } + + int av_stream_audio_deinit(void *ctx, bool uac_en) + { + esp_err_t ret = ESP_OK; + + if (!uac_en) { + ret = i2s_device_deinit(ctx); + } + return ret; + } \ No newline at end of file