diff --git a/Documentation/platforms/xtensa/esp32s3/boards/lckfb-szpi-esp32s3/index.rst b/Documentation/platforms/xtensa/esp32s3/boards/lckfb-szpi-esp32s3/index.rst index 70a492c1286..cb770388f5a 100644 --- a/Documentation/platforms/xtensa/esp32s3/boards/lckfb-szpi-esp32s3/index.rst +++ b/Documentation/platforms/xtensa/esp32s3/boards/lckfb-szpi-esp32s3/index.rst @@ -116,6 +116,43 @@ Then run the adb command:: nsh> uname -a NuttX 0.0.0 Mar 21 2025 14:25:36 xtensa lckfb-szpi-esp32s3 +es7210 +------ + +Basic NuttShell configuration with ES7210 4-channel ADC audio codec support +over USB ADB. The ES7210 is connected via I2C0 (address 0x41) and I2S0 RX, +enabling audio recording through the on-board microphones. + +The I2S0 RX pin mapping is as follows: + +======= ====== +Signal GPIO +======= ====== +BCLK GPIO14 +DIN GPIO12 +MCLK GPIO38 +WS GPIO13 +======= ====== + +You can run the configuration and compilation procedure:: + + $ ./tools/configure.sh lckfb-szpi-esp32s3:es7210 + $ make flash ESPTOOL_PORT=/dev/ttyUSB0 -j + +Then record audio using nxrecorder:: + + $ adb -s 1234 shell + nsh> nxrecorder + nxrecorder> device /dev/audio/pcm_in0 + nxrecorder> recordraw /tmp/test.pcm 2 16 48000 + nxrecorder> stop + nxrecorder> q + +Pull the recorded file to the host and convert to WAV:: + + $ adb -s 1234 pull /tmp/test.pcm . + $ ffmpeg -f s16le -ar 48000 -ac 2 -i test.pcm test.wav + txtable ------- diff --git a/boards/xtensa/esp32s3/lckfb-szpi-esp32s3/configs/es7210/defconfig b/boards/xtensa/esp32s3/lckfb-szpi-esp32s3/configs/es7210/defconfig new file mode 100644 index 00000000000..d6a3b9fe664 --- /dev/null +++ b/boards/xtensa/esp32s3/lckfb-szpi-esp32s3/configs/es7210/defconfig @@ -0,0 +1,105 @@ +# +# This file is autogenerated: PLEASE DO NOT EDIT IT. +# +# You can use "make menuconfig" to make any modifications to the installed .config file. +# You can then do "make savedefconfig" to generate a new defconfig file that includes your +# modifications. +# +# CONFIG_ARCH_LEDS is not set +# CONFIG_ESPRESSIF_I2S0_TX is not set +# CONFIG_NSH_ARGCAT is not set +# CONFIG_NSH_CMDOPT_HEXDUMP is not set +CONFIG_ADBD_FILE_SERVICE=y +CONFIG_ADBD_SHELL_SERVICE=y +CONFIG_ADBD_STACKSIZE=8192 +CONFIG_ADBD_USB_BOARDCTL=y +CONFIG_ADBD_USB_SERVER=y +CONFIG_ARCH="xtensa" +CONFIG_ARCH_BOARD="lckfb-szpi-esp32s3" +CONFIG_ARCH_BOARD_COMMON=y +CONFIG_ARCH_BOARD_ESP32S3_LCKFB_SZPI=y +CONFIG_ARCH_CHIP="esp32s3" +CONFIG_ARCH_CHIP_ESP32S3=y +CONFIG_ARCH_CHIP_ESP32S3WROOM1N16R8=y +CONFIG_ARCH_INTERRUPTSTACK=2048 +CONFIG_ARCH_IRQ_TO_NDX=y +CONFIG_ARCH_MINIMAL_VECTORTABLE_DYNAMIC=y +CONFIG_ARCH_NUSER_INTERRUPTS=2 +CONFIG_ARCH_STACKDUMP=y +CONFIG_ARCH_XTENSA=y +CONFIG_AUDIO=y +CONFIG_AUDIO_ES7210=y +CONFIG_AUDIO_EXCLUDE_BALANCE=y +CONFIG_AUDIO_EXCLUDE_FFORWARD=y +CONFIG_AUDIO_EXCLUDE_TONE=y +CONFIG_AUDIO_I2S=y +CONFIG_BOARDCTL_RESET=y +CONFIG_BOARD_LOOPSPERMSEC=16717 +CONFIG_BUILTIN=y +CONFIG_DRIVERS_AUDIO=y +CONFIG_ESP32S3_I2C0=y +CONFIG_ESP32S3_OTG=y +CONFIG_ESP32S3_OTG_ENDPOINT_NUM=2 +CONFIG_ESP32S3_SPIRAM=y +CONFIG_ESP32S3_SPIRAM_MODE_OCT=y +CONFIG_ESP32S3_UART0=y +CONFIG_ESPRESSIF_I2S0=y +CONFIG_ESPRESSIF_I2S0_BCLKPIN=14 +CONFIG_ESPRESSIF_I2S0_DINPIN=12 +CONFIG_ESPRESSIF_I2S0_MCLK=y +CONFIG_ESPRESSIF_I2S0_MCLKPIN=38 +CONFIG_ESPRESSIF_I2S0_SAMPLE_RATE=48000 +CONFIG_ESPRESSIF_I2S0_WSPIN=13 +CONFIG_ETC_ROMFS=y +CONFIG_FS_PROCFS=y +CONFIG_FS_ROMFS=y +CONFIG_FS_TMPFS=y +CONFIG_HAVE_CXX=y +CONFIG_HAVE_CXXINITIALIZE=y +CONFIG_I2C_DRIVER=y +CONFIG_I2C_POLLED=y +CONFIG_I2S_DMADESC_NUM=16 +CONFIG_IDLETHREAD_STACKSIZE=3072 +CONFIG_INIT_ENTRYPOINT="nsh_main" +CONFIG_INIT_STACKSIZE=4096 +CONFIG_INTELHEX_BINARY=y +CONFIG_LIBC_EXECFUNCS=y +CONFIG_LIBUV=y +CONFIG_LINE_MAX=64 +CONFIG_MM_BACKTRACE=0 +CONFIG_MM_REGIONS=2 +CONFIG_NSH_ARCHINIT=y +CONFIG_NSH_BUILTIN_APPS=y +CONFIG_NSH_FILEIOSIZE=512 +CONFIG_NSH_READLINE=y +CONFIG_NXRECORDER_RECORDTHREAD_STACKSIZE=16384 +CONFIG_POSIX_SPAWN_DEFAULT_STACKSIZE=4096 +CONFIG_PREALLOC_TIMERS=4 +CONFIG_PSEUDOTERM=y +CONFIG_PTHREAD_MUTEX_TYPES=y +CONFIG_RAM_SIZE=114688 +CONFIG_RAM_START=0x20000000 +CONFIG_RR_INTERVAL=200 +CONFIG_SCHED_BACKTRACE=y +CONFIG_SCHED_CHILD_STATUS=y +CONFIG_SCHED_HAVE_PARENT=y +CONFIG_SCHED_HPWORKSTACKSIZE=8192 +CONFIG_SCHED_LPWORK=y +CONFIG_SCHED_LPWORKSTACKSIZE=8192 +CONFIG_SCHED_WAITPID=y +CONFIG_STACK_COLORATION=y +CONFIG_STACK_USAGE=y +CONFIG_START_DAY=6 +CONFIG_START_MONTH=12 +CONFIG_START_YEAR=2011 +CONFIG_SYSLOG_BUFFER=y +CONFIG_SYSLOG_CHARDEV=y +CONFIG_SYSLOG_CONSOLE=y +CONFIG_SYSTEM_ADBD=y +CONFIG_SYSTEM_NSH=y +CONFIG_SYSTEM_NXRECORDER=y +CONFIG_TLS_NCLEANUP=4 +CONFIG_TLS_NELEM=4 +CONFIG_TLS_TASK_NELEM=4 +CONFIG_UART0_SERIAL_CONSOLE=y +CONFIG_USBADB=y diff --git a/boards/xtensa/esp32s3/lckfb-szpi-esp32s3/src/Make.defs b/boards/xtensa/esp32s3/lckfb-szpi-esp32s3/src/Make.defs index 7bca8ccd973..8c0dace9727 100644 --- a/boards/xtensa/esp32s3/lckfb-szpi-esp32s3/src/Make.defs +++ b/boards/xtensa/esp32s3/lckfb-szpi-esp32s3/src/Make.defs @@ -60,3 +60,7 @@ endif ifeq ($(CONFIG_ESP32S3_CAM),y) CSRCS += esp32s3_board_camera.c endif + +ifeq ($(CONFIG_AUDIO_ES7210),y) +CSRCS += esp32s3_board_es7210.c +endif diff --git a/boards/xtensa/esp32s3/lckfb-szpi-esp32s3/src/esp32s3-szpi.h b/boards/xtensa/esp32s3/lckfb-szpi-esp32s3/src/esp32s3-szpi.h index 6a060cef4d5..544c15586f0 100644 --- a/boards/xtensa/esp32s3/lckfb-szpi-esp32s3/src/esp32s3-szpi.h +++ b/boards/xtensa/esp32s3/lckfb-szpi-esp32s3/src/esp32s3-szpi.h @@ -49,6 +49,10 @@ #define QMI8658_I2C_PORT (0) #define QMI8658_I2C_ADDR (0x6A) +#define ES7210_I2C_ADDR (0x41) +#define ES7210_I2C_FREQ (100000) +#define ES7210_DEVPATH "/dev/audio/pcm_in0" + /**************************************************************************** * Public Types ****************************************************************************/ @@ -167,5 +171,9 @@ int esp32s3_qmi8658_initialize(void); int esp32s3_camera_initialize(void); #endif +#ifdef CONFIG_AUDIO_ES7210 +int esp32s3_es7210_initialize(int i2c_port, int i2s_port); +#endif + #endif /* __ASSEMBLY__ */ #endif /* __BOARDS_XTENSA_ESP32S3_LCKFB_SZPI_ESP32S3_SRC_ESP32S3_DEVKIT_H */ diff --git a/boards/xtensa/esp32s3/lckfb-szpi-esp32s3/src/esp32s3_board_es7210.c b/boards/xtensa/esp32s3/lckfb-szpi-esp32s3/src/esp32s3_board_es7210.c new file mode 100644 index 00000000000..ed8a54cb3e3 --- /dev/null +++ b/boards/xtensa/esp32s3/lckfb-szpi-esp32s3/src/esp32s3_board_es7210.c @@ -0,0 +1,126 @@ +/**************************************************************************** + * boards/xtensa/esp32s3/lckfb-szpi-esp32s3/src/esp32s3_board_es7210.c + * + * SPDX-License-Identifier: Apache-2.0 + * + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. The + * ASF licenses this file to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance with the + * License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT + * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the + * License for the specific language governing permissions and limitations + * under the License. + * + ****************************************************************************/ + +/**************************************************************************** + * Included Files + ****************************************************************************/ + +#include + +#include +#include +#include +#include +#include + +#include +#include +#include +#include + +#include + +#include "esp32s3_i2c.h" +#include "espressif/esp_i2s.h" +#include "esp32s3-szpi.h" + +/**************************************************************************** + * Public Functions + ****************************************************************************/ + +/**************************************************************************** + * Name: esp32s3_es7210_initialize + * + * Description: + * This function is called by board-specific setup logic to configure + * and register the ES7210 audio ADC device. + * + * Input Parameters: + * i2c_port - The I2C port number for the ES7210 control interface + * i2s_port - The I2S port number for the ES7210 audio data interface + * + * Returned Value: + * Zero is returned on success. Otherwise, a negated errno value is + * returned to indicate the nature of the failure. + * + ****************************************************************************/ + +int esp32s3_es7210_initialize(int i2c_port, int i2s_port) +{ + FAR struct i2c_master_s *i2c; + FAR struct i2s_dev_s *i2s; + FAR struct audio_lowerhalf_s *es7210; + struct es7210_lower_s lower; + static bool initialized = false; + char devname[] = "pcm_in0"; + int ret; + + if (initialized) + { + return OK; + } + + /* Get I2C bus instance */ + + i2c = esp32s3_i2cbus_initialize(i2c_port); + if (i2c == NULL) + { + auderr("ERROR: Failed to initialize I2C%d\n", i2c_port); + return -ENODEV; + } + + /* Get I2S bus instance (RX only) */ + + i2s = esp_i2sbus_initialize(i2s_port); + if (i2s == NULL) + { + auderr("ERROR: Failed to initialize I2S%d\n", i2s_port); + return -ENODEV; + } + + /* Configure ES7210 lower half */ + + lower.frequency = ES7210_I2C_FREQ; + lower.address = ES7210_I2C_ADDR; + + /* Initialize the ES7210 codec */ + + es7210 = es7210_initialize(i2c, i2s, &lower); + if (es7210 == NULL) + { + auderr("ERROR: Failed to initialize ES7210\n"); + return -ENODEV; + } + + /* Register the audio device as /dev/audio/pcm_in0 */ + + ret = audio_register(devname, es7210); + if (ret < 0) + { + auderr("ERROR: Failed to register %s: %d\n", devname, ret); + return ret; + } + + initialized = true; + audinfo("ES7210 registered as %s\n", devname); + return OK; +} diff --git a/boards/xtensa/esp32s3/lckfb-szpi-esp32s3/src/esp32s3_bringup.c b/boards/xtensa/esp32s3/lckfb-szpi-esp32s3/src/esp32s3_bringup.c index 26bbb4641b7..88f6ddc2113 100644 --- a/boards/xtensa/esp32s3/lckfb-szpi-esp32s3/src/esp32s3_bringup.c +++ b/boards/xtensa/esp32s3/lckfb-szpi-esp32s3/src/esp32s3_bringup.c @@ -173,7 +173,7 @@ int esp32s3_bringup(void) } #endif -#if defined(CONFIG_ESPRESSIF_I2S0) || defined(CONFIG_ESPRESSIF_I2S1) +#ifdef CONFIG_ESPRESSIF_I2S1 bool i2s_enable_tx; bool i2s_enable_rx; #endif @@ -345,25 +345,20 @@ int esp32s3_bringup(void) #endif #ifdef CONFIG_ESPRESSIF_I2S -#ifdef CONFIG_ESPRESSIF_I2S0_TX - i2s_enable_tx = true; -#else - i2s_enable_tx = false; -#endif /* CONFIG_ESPRESSIF_I2S0_TX */ -#ifdef CONFIG_ESPRESSIF_I2S0_RX - i2s_enable_rx = true; -#else - i2s_enable_rx = false; -#endif /* CONFIG_ESPRESSIF_I2S0_RX */ + /* On lckfb-szpi-esp32s3, I2S0 is wired to dedicated codec chips + * (ES7210 ADC + ES8311 DAC) which register their own audio devices. + * Generic audio_i2s is not used on I2S0 — skip board_i2sdev_initialize + * for port 0. + */ - /* Configure I2S generic audio on I2S0 */ - - ret = board_i2sdev_initialize(ESP32S3_I2S0, i2s_enable_tx, i2s_enable_rx); +#ifdef CONFIG_AUDIO_ES7210 + ret = esp32s3_es7210_initialize(0, 0); if (ret < 0) { - syslog(LOG_ERR, "Failed to initialize I2S0 driver: %d\n", ret); + syslog(LOG_ERR, "ERROR: Failed to initialize ES7210: %d\n", ret); } +#endif #ifdef CONFIG_ESPRESSIF_I2S1