mirror of
https://github.com/espressif/esp-idf.git
synced 2024-10-05 20:47:46 -04:00
refactor(dac): make dac driver as component
This commit is contained in:
parent
581824d1f2
commit
ef7772eee0
@ -10,7 +10,6 @@ set(srcs)
|
||||
# Always included headers
|
||||
set(includes "include"
|
||||
"deprecated"
|
||||
"dac/include"
|
||||
"i2c/include"
|
||||
"ledc/include"
|
||||
"parlio/include"
|
||||
@ -36,12 +35,7 @@ endif()
|
||||
|
||||
# DAC related source files
|
||||
if(CONFIG_SOC_DAC_SUPPORTED)
|
||||
list(APPEND srcs "dac/dac_oneshot.c"
|
||||
"dac/dac_cosine.c"
|
||||
"dac/dac_continuous.c"
|
||||
"dac/dac_common.c"
|
||||
"dac/${target}/dac_dma.c"
|
||||
"deprecated/dac_common_legacy.c"
|
||||
list(APPEND srcs "deprecated/dac_common_legacy.c"
|
||||
"deprecated/${target}/dac_legacy.c")
|
||||
endif()
|
||||
|
||||
@ -159,6 +153,7 @@ else()
|
||||
# have a public dependency on other "esp_driver_foo" components
|
||||
esp_driver_gpio esp_driver_pcnt esp_driver_gptimer esp_driver_spi esp_driver_mcpwm
|
||||
esp_driver_ana_cmpr esp_driver_i2s esp_driver_sdmmc esp_driver_sdspi esp_driver_sdio
|
||||
esp_driver_dac
|
||||
LDFRAGMENTS ${ldfragments}
|
||||
)
|
||||
endif()
|
||||
|
@ -122,52 +122,6 @@ menu "Driver Configurations"
|
||||
|
||||
orsource "./rmt/Kconfig.rmt"
|
||||
|
||||
menu "DAC Configuration"
|
||||
depends on SOC_DAC_SUPPORTED
|
||||
config DAC_CTRL_FUNC_IN_IRAM
|
||||
bool "Place DAC control functions into IRAM"
|
||||
default n
|
||||
help
|
||||
Place DAC control functions (e.g. 'dac_oneshot_output_voltage') into IRAM,
|
||||
so that this function can be IRAM-safe and able to be called in the other IRAM interrupt context.
|
||||
Enabling this option can improve driver performance as well.
|
||||
|
||||
config DAC_ISR_IRAM_SAFE
|
||||
bool "DAC ISR IRAM-Safe"
|
||||
default n
|
||||
help
|
||||
Ensure the DAC interrupt is IRAM-Safe by allowing the interrupt handler to be
|
||||
executable when the cache is disabled (e.g. SPI Flash write).
|
||||
|
||||
config DAC_SUPPRESS_DEPRECATE_WARN
|
||||
bool "Suppress legacy driver deprecated warning"
|
||||
default n
|
||||
help
|
||||
Wether to suppress the deprecation warnings when using legacy DAC driver (driver/dac.h).
|
||||
If you want to continue using the legacy driver, and don't want to see related deprecation warnings,
|
||||
you can enable this option.
|
||||
|
||||
config DAC_ENABLE_DEBUG_LOG
|
||||
bool "Enable debug log"
|
||||
default n
|
||||
help
|
||||
Wether to enable the debug log message for DAC driver.
|
||||
Note that, this option only controls the DAC driver log, won't affect other drivers.
|
||||
|
||||
config DAC_DMA_AUTO_16BIT_ALIGN
|
||||
bool "Align the continuous data to 16 bit automatically"
|
||||
depends on SOC_DAC_DMA_16BIT_ALIGN
|
||||
default y
|
||||
help
|
||||
Whether to left shift the continuous data to align every bytes to 16 bits in the driver.
|
||||
On ESP32, although the DAC resolution is only 8 bits,
|
||||
the hardware requires 16 bits data in continuous mode.
|
||||
By enabling this option, the driver will left shift 8 bits for the input data automatically.
|
||||
Only disable this option when you decide to do this step by yourself.
|
||||
Note that the driver will allocate a new piece of memory to save the converted data.
|
||||
|
||||
endmenu # DAC Configuration
|
||||
|
||||
menu "USB Serial/JTAG Configuration"
|
||||
depends on SOC_USB_SERIAL_JTAG_SUPPORTED
|
||||
config USJ_NO_AUTO_LS_ON_CONNECTION
|
||||
|
@ -3,6 +3,3 @@ archive: libdriver.a
|
||||
entries:
|
||||
if SDM_CTRL_FUNC_IN_IRAM = y:
|
||||
sdm: sdm_channel_set_pulse_density (noflash)
|
||||
if DAC_CTRL_FUNC_IN_IRAM = y:
|
||||
dac_oneshot: dac_oneshot_output_voltage (noflash)
|
||||
dac_continuous: dac_continuous_write_asynchronously (noflash)
|
||||
|
@ -1,12 +1,10 @@
|
||||
# Documentation: .gitlab/ci/README.md#manifest-file-to-control-the-buildtest-apps
|
||||
|
||||
components/driver/test_apps/dac_test_apps/dac:
|
||||
disable:
|
||||
- if: SOC_DAC_SUPPORTED != 1
|
||||
|
||||
components/driver/test_apps/dac_test_apps/legacy_dac_driver:
|
||||
disable:
|
||||
- if: SOC_DAC_SUPPORTED != 1
|
||||
depends_components:
|
||||
- esp_adc
|
||||
|
||||
components/driver/test_apps/i2c_test_apps:
|
||||
disable:
|
||||
|
32
components/esp_driver_dac/CMakeLists.txt
Normal file
32
components/esp_driver_dac/CMakeLists.txt
Normal file
@ -0,0 +1,32 @@
|
||||
idf_build_get_property(target IDF_TARGET)
|
||||
|
||||
set(srcs)
|
||||
set(priv_req esp_pm esp_driver_gpio)
|
||||
|
||||
if(${target} STREQUAL "linux")
|
||||
return() # This component is not supported by the POSIX/Linux simulator
|
||||
elseif(${target} STREQUAL "esp32")
|
||||
list(APPEND priv_req esp_driver_i2s)
|
||||
elseif(${target} STREQUAL "esp32s2")
|
||||
list(APPEND priv_req esp_driver_spi)
|
||||
endif()
|
||||
|
||||
if(CONFIG_SOC_DAC_SUPPORTED)
|
||||
list(APPEND srcs "dac_oneshot.c"
|
||||
"dac_cosine.c"
|
||||
"dac_continuous.c"
|
||||
"dac_common.c")
|
||||
|
||||
if(${target} STREQUAL "esp32")
|
||||
list(APPEND srcs "esp32/dac_dma.c")
|
||||
elseif(${target} STREQUAL "esp32s2")
|
||||
list(APPEND srcs "esp32s2/dac_dma.c")
|
||||
endif()
|
||||
|
||||
endif()
|
||||
|
||||
idf_component_register(SRCS ${srcs}
|
||||
INCLUDE_DIRS "./include"
|
||||
PRIV_REQUIRES ${priv_req}
|
||||
LDFRAGMENTS "linker.lf"
|
||||
)
|
45
components/esp_driver_dac/Kconfig
Normal file
45
components/esp_driver_dac/Kconfig
Normal file
@ -0,0 +1,45 @@
|
||||
menu "ESP-Driver:DAC Configurations"
|
||||
depends on SOC_DAC_SUPPORTED
|
||||
config DAC_CTRL_FUNC_IN_IRAM
|
||||
bool "Place DAC control functions into IRAM"
|
||||
default n
|
||||
help
|
||||
Place DAC control functions (e.g. 'dac_oneshot_output_voltage') into IRAM,
|
||||
so that this function can be IRAM-safe and able to be called in the other IRAM interrupt context.
|
||||
Enabling this option can improve driver performance as well.
|
||||
|
||||
config DAC_ISR_IRAM_SAFE
|
||||
bool "DAC ISR IRAM-Safe"
|
||||
default n
|
||||
help
|
||||
Ensure the DAC interrupt is IRAM-Safe by allowing the interrupt handler to be
|
||||
executable when the cache is disabled (e.g. SPI Flash write).
|
||||
|
||||
config DAC_SUPPRESS_DEPRECATE_WARN
|
||||
bool "Suppress legacy driver deprecated warning"
|
||||
default n
|
||||
help
|
||||
Wether to suppress the deprecation warnings when using legacy DAC driver (driver/dac.h).
|
||||
If you want to continue using the legacy driver, and don't want to see related deprecation warnings,
|
||||
you can enable this option.
|
||||
|
||||
config DAC_ENABLE_DEBUG_LOG
|
||||
bool "Enable debug log"
|
||||
default n
|
||||
help
|
||||
Wether to enable the debug log message for DAC driver.
|
||||
Note that, this option only controls the DAC driver log, won't affect other drivers.
|
||||
|
||||
config DAC_DMA_AUTO_16BIT_ALIGN
|
||||
bool "Align the continuous data to 16 bit automatically"
|
||||
depends on SOC_DAC_DMA_16BIT_ALIGN
|
||||
default y
|
||||
help
|
||||
Whether to left shift the continuous data to align every bytes to 16 bits in the driver.
|
||||
On ESP32, although the DAC resolution is only 8 bits,
|
||||
the hardware requires 16 bits data in continuous mode.
|
||||
By enabling this option, the driver will left shift 8 bits for the input data automatically.
|
||||
Only disable this option when you decide to do this step by yourself.
|
||||
Note that the driver will allocate a new piece of memory to save the converted data.
|
||||
|
||||
endmenu # DAC Configuration
|
@ -194,7 +194,6 @@ static void IRAM_ATTR s_dac_default_intr_handler(void *arg)
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
esp_err_t dac_continuous_new_channels(const dac_continuous_config_t *cont_cfg, dac_continuous_handle_t *ret_handle)
|
||||
{
|
||||
#if CONFIG_DAC_ENABLE_DEBUG_LOG
|
@ -9,7 +9,6 @@
|
||||
#include "esp_err.h"
|
||||
#include "esp_intr_alloc.h"
|
||||
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
@ -71,7 +71,8 @@ static uint32_t s_dac_set_apll_freq(uint32_t expt_freq)
|
||||
* - ESP_OK config success
|
||||
* - ESP_ERR_INVALID_ARG invalid frequency
|
||||
*/
|
||||
static esp_err_t s_dac_dma_periph_set_clock(uint32_t freq_hz, bool is_apll){
|
||||
static esp_err_t s_dac_dma_periph_set_clock(uint32_t freq_hz, bool is_apll)
|
||||
{
|
||||
/* Step 1: Determine the digital clock source frequency */
|
||||
uint32_t digi_ctrl_freq; // Digital controller clock
|
||||
if (is_apll) {
|
@ -59,7 +59,6 @@ typedef struct {
|
||||
dac_continuous_channel_mode_t chan_mode; /*!< The channel mode of continuous mode, only take effect when multiple channels enabled, depends converting the buffer alternately or simultaneously */
|
||||
} dac_continuous_config_t;
|
||||
|
||||
|
||||
/**
|
||||
* @brief Event structure used in DAC event queue
|
||||
*/
|
||||
@ -96,7 +95,6 @@ typedef struct {
|
||||
*/
|
||||
} dac_event_callbacks_t;
|
||||
|
||||
|
||||
/**
|
||||
* @brief Allocate new DAC channels in continuous mode
|
||||
* @note The DAC channels can't be registered to continuous mode separately
|
6
components/esp_driver_dac/linker.lf
Normal file
6
components/esp_driver_dac/linker.lf
Normal file
@ -0,0 +1,6 @@
|
||||
[mapping:dac_driver]
|
||||
archive: libesp_driver_dac.a
|
||||
entries:
|
||||
if DAC_CTRL_FUNC_IN_IRAM = y:
|
||||
dac_oneshot: dac_oneshot_output_voltage (noflash)
|
||||
dac_continuous: dac_continuous_write_asynchronously (noflash)
|
@ -0,0 +1,9 @@
|
||||
# Documentation: .gitlab/ci/README.md#manifest-file-to-control-the-buildtest-apps
|
||||
|
||||
components/esp_driver_dac/test_apps/dac:
|
||||
disable:
|
||||
- if: SOC_DAC_SUPPORTED != 1
|
||||
depends_components:
|
||||
- esp_driver_i2s
|
||||
- esp_driver_spi
|
||||
- esp_adc
|
@ -10,7 +10,7 @@ project(dac_test)
|
||||
if(CONFIG_COMPILER_DUMP_RTL_FILES)
|
||||
add_custom_target(check_test_app_sections ALL
|
||||
COMMAND ${PYTHON} $ENV{IDF_PATH}/tools/ci/check_callgraph.py
|
||||
--rtl-dirs ${CMAKE_BINARY_DIR}/esp-idf/driver/,${CMAKE_BINARY_DIR}/esp-idf/hal/
|
||||
--rtl-dirs ${CMAKE_BINARY_DIR}/esp-idf/esp_driver_dac/,${CMAKE_BINARY_DIR}/esp-idf/hal/
|
||||
--elf-file ${CMAKE_BINARY_DIR}/dac_test.elf
|
||||
find-refs
|
||||
--from-sections=.iram0.text
|
@ -9,5 +9,5 @@ endif()
|
||||
# the component can be registered as WHOLE_ARCHIVE
|
||||
idf_component_register(SRCS ${srcs}
|
||||
PRIV_REQUIRES unity esp_driver_pcnt esp_adc
|
||||
driver # TODO: IDF-8370 remove driver when esp_driver_dac created
|
||||
esp_driver_dac esp_driver_gpio esp_driver_i2s esp_driver_spi
|
||||
WHOLE_ARCHIVE)
|
@ -39,11 +39,15 @@ TEST_CASE("DAC_API_basic_logic_test", "[dac]")
|
||||
{
|
||||
/* Constant API test */
|
||||
dac_oneshot_handle_t oneshot_chan0_handle;
|
||||
TEST_ESP_OK(dac_oneshot_new_channel(&(dac_oneshot_config_t){.chan_id = DAC_CHAN_0}, &oneshot_chan0_handle));
|
||||
TEST_ESP_OK(dac_oneshot_new_channel(&(dac_oneshot_config_t) {
|
||||
.chan_id = DAC_CHAN_0
|
||||
}, &oneshot_chan0_handle));
|
||||
TEST_ESP_OK(dac_oneshot_output_voltage(oneshot_chan0_handle, 128));
|
||||
TEST_ESP_OK(dac_oneshot_del_channel(oneshot_chan0_handle));
|
||||
dac_oneshot_handle_t oneshot_chan1_handle;
|
||||
TEST_ESP_OK(dac_oneshot_new_channel(&(dac_oneshot_config_t){.chan_id = DAC_CHAN_1}, &oneshot_chan1_handle));
|
||||
TEST_ESP_OK(dac_oneshot_new_channel(&(dac_oneshot_config_t) {
|
||||
.chan_id = DAC_CHAN_1
|
||||
}, &oneshot_chan1_handle));
|
||||
TEST_ESP_OK(dac_oneshot_output_voltage(oneshot_chan1_handle, 100));
|
||||
TEST_ESP_OK(dac_oneshot_del_channel(oneshot_chan1_handle));
|
||||
|
@ -53,7 +53,9 @@ static bool IRAM_ATTR test_dac_on_convert_done_cb(dac_continuous_handle_t handle
|
||||
TEST_CASE("DAC_IRAM_safe_test", "[dac]")
|
||||
{
|
||||
dac_oneshot_handle_t oneshot_handle;
|
||||
TEST_ESP_OK(dac_oneshot_new_channel(&(dac_oneshot_config_t){.chan_id = DAC_CHAN_0}, &oneshot_handle));
|
||||
TEST_ESP_OK(dac_oneshot_new_channel(&(dac_oneshot_config_t) {
|
||||
.chan_id = DAC_CHAN_0
|
||||
}, &oneshot_handle));
|
||||
|
||||
/* Test direct voltage setting safety */
|
||||
unity_utils_run_cache_disable_stub(test_dac_direct_set_safety, oneshot_handle);
|
@ -73,10 +73,6 @@ INPUT = \
|
||||
$(PROJECT_PATH)/components/bt/host/bluedroid/api/include/api/esp_spp_api.h \
|
||||
$(PROJECT_PATH)/components/bt/host/nimble/esp-hci/include/esp_nimble_hci.h \
|
||||
$(PROJECT_PATH)/components/console/esp_console.h \
|
||||
$(PROJECT_PATH)/components/driver/dac/include/driver/dac_continuous.h \
|
||||
$(PROJECT_PATH)/components/driver/dac/include/driver/dac_cosine.h \
|
||||
$(PROJECT_PATH)/components/driver/dac/include/driver/dac_oneshot.h \
|
||||
$(PROJECT_PATH)/components/driver/dac/include/driver/dac_types.h \
|
||||
$(PROJECT_PATH)/components/driver/i2c/include/driver/i2c_master.h \
|
||||
$(PROJECT_PATH)/components/driver/i2c/include/driver/i2c_slave.h \
|
||||
$(PROJECT_PATH)/components/driver/i2c/include/driver/i2c_types.h \
|
||||
@ -110,6 +106,10 @@ INPUT = \
|
||||
$(PROJECT_PATH)/components/esp_driver_ana_cmpr/include/driver/ana_cmpr.h \
|
||||
$(PROJECT_PATH)/components/esp_driver_ana_cmpr/include/driver/ana_cmpr_etm.h \
|
||||
$(PROJECT_PATH)/components/esp_driver_ana_cmpr/include/driver/ana_cmpr_types.h \
|
||||
$(PROJECT_PATH)/components/esp_driver_dac/include/driver/dac_continuous.h \
|
||||
$(PROJECT_PATH)/components/esp_driver_dac/include/driver/dac_cosine.h \
|
||||
$(PROJECT_PATH)/components/esp_driver_dac/include/driver/dac_oneshot.h \
|
||||
$(PROJECT_PATH)/components/esp_driver_dac/include/driver/dac_types.h \
|
||||
$(PROJECT_PATH)/components/esp_driver_gpio/include/driver/dedic_gpio.h \
|
||||
$(PROJECT_PATH)/components/esp_driver_gpio/include/driver/gpio.h \
|
||||
$(PROJECT_PATH)/components/esp_driver_gpio/include/driver/gpio_etm.h \
|
||||
|
@ -142,5 +142,5 @@ API Reference
|
||||
.. include-build-file:: inc/dac_oneshot.inc
|
||||
.. include-build-file:: inc/dac_cosine.inc
|
||||
.. include-build-file:: inc/dac_continuous.inc
|
||||
.. include-build-file:: inc/components/driver/dac/include/driver/dac_types.inc
|
||||
.. include-build-file:: inc/components/esp_driver_dac/include/driver/dac_types.inc
|
||||
.. include-build-file:: inc/components/hal/include/hal/dac_types.inc
|
||||
|
@ -15,6 +15,7 @@ In order to control the dependence of other components on drivers at a smaller g
|
||||
- `esp_driver_sdio` - Driver for SDIO
|
||||
- `esp_driver_ana_cmpr` - Driver for Analog Comparator
|
||||
- `esp_driver_i2s` - Driver for I2S
|
||||
- `esp_driver_dac` - Driver for DAC
|
||||
|
||||
For compatibility, the original `driver`` component is still treated as an all-in-one component by registering these `esp_driver_xyz`` components as its public dependencies. In other words, you do not need to modify the CMake file of an existing project, but you now have a way to specify the specific peripheral driver that your project depends on.
|
||||
|
||||
|
@ -142,5 +142,5 @@ API 参考
|
||||
.. include-build-file:: inc/dac_oneshot.inc
|
||||
.. include-build-file:: inc/dac_cosine.inc
|
||||
.. include-build-file:: inc/dac_continuous.inc
|
||||
.. include-build-file:: inc/components/driver/dac/include/driver/dac_types.inc
|
||||
.. include-build-file:: inc/components/esp_driver_dac/include/driver/dac_types.inc
|
||||
.. include-build-file:: inc/components/hal/include/hal/dac_types.inc
|
||||
|
@ -15,6 +15,7 @@
|
||||
- `esp_driver_sdio` - SDIO 驱动
|
||||
- `esp_driver_ana_cmpr` - 模拟比较器驱动
|
||||
- `esp_driver_i2s` - I2S 驱动
|
||||
- `esp_driver_dac` - DAC 驱动
|
||||
|
||||
为了兼容性,原来的 `driver` 组件仍然存在,并作为一个 “all-in-one" 的组件,将以上这些 `esp_driver_xyz` 组件注册成自己的公共依赖。换句话说,你无需修改既有项目的 CMake 文件,但是你现在多了一个途径去指定你项目依赖的具体的外设驱动。
|
||||
|
||||
|
@ -1,6 +1,5 @@
|
||||
idf_component_register(SRCS "bt_app_av.c"
|
||||
"bt_app_core.c"
|
||||
"main.c"
|
||||
PRIV_REQUIRES esp_driver_i2s bt nvs_flash esp_ringbuf
|
||||
driver # TODO: IDF-8370 remove driver when esp_driver_dac created
|
||||
PRIV_REQUIRES esp_driver_i2s bt nvs_flash esp_ringbuf esp_driver_dac
|
||||
INCLUDE_DIRS ".")
|
||||
|
@ -1,6 +1,5 @@
|
||||
idf_component_register(SRCS "bt_app_av.c"
|
||||
"bt_app_core.c"
|
||||
"main.c"
|
||||
PRIV_REQUIRES esp_driver_i2s bt nvs_flash esp_ringbuf
|
||||
driver # TODO: IDF-8370 remove driver when esp_driver_dac created
|
||||
PRIV_REQUIRES esp_driver_i2s bt nvs_flash esp_ringbuf esp_driver_dac
|
||||
INCLUDE_DIRS ".")
|
||||
|
@ -2,5 +2,8 @@
|
||||
# in this exact order for cmake to work correctly
|
||||
cmake_minimum_required(VERSION 3.16)
|
||||
|
||||
# "Trim" the build. Include the minimal set of components, main, and anything it depends on.
|
||||
set(COMPONENTS main)
|
||||
|
||||
include($ENV{IDF_PATH}/tools/cmake/project.cmake)
|
||||
project(dac_audio)
|
||||
|
@ -1,2 +1,3 @@
|
||||
idf_component_register(SRCS "dac_audio_example_main.c"
|
||||
INCLUDE_DIRS ".")
|
||||
INCLUDE_DIRS "."
|
||||
PRIV_REQUIRES esp_driver_dac)
|
||||
|
@ -2,5 +2,8 @@
|
||||
# in this exact order for cmake to work correctly
|
||||
cmake_minimum_required(VERSION 3.16)
|
||||
|
||||
# "Trim" the build. Include the minimal set of components, main, and anything it depends on.
|
||||
set(COMPONENTS main)
|
||||
|
||||
include($ENV{IDF_PATH}/tools/cmake/project.cmake)
|
||||
project(signal_generator)
|
||||
|
@ -3,4 +3,5 @@ set(srcs "dac_continuous_example_main.c"
|
||||
"dac_continuous_example_timer.c")
|
||||
|
||||
idf_component_register(SRCS "${srcs}"
|
||||
INCLUDE_DIRS ".")
|
||||
INCLUDE_DIRS "."
|
||||
PRIV_REQUIRES esp_driver_dac esp_driver_gpio esp_driver_gptimer esp_adc)
|
||||
|
@ -2,5 +2,8 @@
|
||||
# in this exact order for cmake to work correctly
|
||||
cmake_minimum_required(VERSION 3.16)
|
||||
|
||||
# "Trim" the build. Include the minimal set of components, main, and anything it depends on.
|
||||
set(COMPONENTS main)
|
||||
|
||||
include($ENV{IDF_PATH}/tools/cmake/project.cmake)
|
||||
project(dac_cosine_wave)
|
||||
|
@ -1,2 +1,3 @@
|
||||
idf_component_register(SRCS "dac_cosine_example_main.c"
|
||||
INCLUDE_DIRS ".")
|
||||
INCLUDE_DIRS "."
|
||||
PRIV_REQUIRES esp_driver_dac esp_adc)
|
||||
|
@ -2,5 +2,8 @@
|
||||
# in this exact order for cmake to work correctly
|
||||
cmake_minimum_required(VERSION 3.16)
|
||||
|
||||
# "Trim" the build. Include the minimal set of components, main, and anything it depends on.
|
||||
set(COMPONENTS main)
|
||||
|
||||
include($ENV{IDF_PATH}/tools/cmake/project.cmake)
|
||||
project(dac_oneshot)
|
||||
|
@ -1,2 +1,3 @@
|
||||
idf_component_register(SRCS "dac_oneshot_example_main.c"
|
||||
INCLUDE_DIRS ".")
|
||||
INCLUDE_DIRS "."
|
||||
PRIV_REQUIRES esp_driver_dac esp_adc)
|
||||
|
Loading…
Reference in New Issue
Block a user