mirror of
https://github.com/espressif/esp-idf.git
synced 2026-09-22 13:01:16 +03:00
refactor(dac): remove adc read back in dac example, prepare for s31
This commit is contained in:
@@ -602,7 +602,7 @@ clean_up:
|
|||||||
|
|
||||||
//////////////////////////////////// Cyclic writing ////////////////////////////////////
|
//////////////////////////////////// Cyclic writing ////////////////////////////////////
|
||||||
|
|
||||||
esp_err_t dac_continuous_write_cyclically(dac_continuous_handle_t handle, uint8_t *buf, size_t buf_size, size_t *bytes_loaded)
|
esp_err_t dac_continuous_write_cyclically(dac_continuous_handle_t handle, const uint8_t *buf, size_t buf_size, size_t *bytes_loaded)
|
||||||
{
|
{
|
||||||
DAC_NULL_POINTER_CHECK(handle);
|
DAC_NULL_POINTER_CHECK(handle);
|
||||||
DAC_NULL_POINTER_CHECK(buf);
|
DAC_NULL_POINTER_CHECK(buf);
|
||||||
@@ -687,7 +687,7 @@ esp_err_t dac_continuous_stop_cyclically(dac_continuous_handle_t handle)
|
|||||||
|
|
||||||
//////////////////////////////////// Synchronous writing ////////////////////////////////////
|
//////////////////////////////////// Synchronous writing ////////////////////////////////////
|
||||||
|
|
||||||
esp_err_t dac_continuous_write(dac_continuous_handle_t handle, uint8_t *buf, size_t buf_size, size_t *bytes_loaded, int timeout_ms)
|
esp_err_t dac_continuous_write(dac_continuous_handle_t handle, const uint8_t *buf, size_t buf_size, size_t *bytes_loaded, int timeout_ms)
|
||||||
{
|
{
|
||||||
DAC_NULL_POINTER_CHECK(handle);
|
DAC_NULL_POINTER_CHECK(handle);
|
||||||
DAC_NULL_POINTER_CHECK(buf);
|
DAC_NULL_POINTER_CHECK(buf);
|
||||||
@@ -822,3 +822,12 @@ static esp_err_t s_dac_continuous_stop_sync(dac_continuous_handle_t handle)
|
|||||||
|
|
||||||
return ESP_OK;
|
return ESP_OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
uint8_t dac_continuous_get_bitwidth(dac_continuous_handle_t handle)
|
||||||
|
{
|
||||||
|
if (!handle) {
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
return SOC_DAC_RESOLUTION;
|
||||||
|
}
|
||||||
|
|||||||
@@ -144,3 +144,12 @@ esp_err_t dac_cosine_stop(dac_cosine_handle_t handle)
|
|||||||
|
|
||||||
return ESP_OK;
|
return ESP_OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
uint8_t dac_cosine_get_bitwidth(dac_cosine_handle_t handle)
|
||||||
|
{
|
||||||
|
if (!handle) {
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
return SOC_DAC_RESOLUTION;
|
||||||
|
}
|
||||||
|
|||||||
@@ -69,3 +69,12 @@ esp_err_t dac_oneshot_output_voltage(dac_oneshot_handle_t handle, uint8_t digi_v
|
|||||||
|
|
||||||
return ESP_OK;
|
return ESP_OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
uint8_t dac_oneshot_get_bitwidth(dac_oneshot_handle_t handle)
|
||||||
|
{
|
||||||
|
if (!handle) {
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
return SOC_DAC_RESOLUTION;
|
||||||
|
}
|
||||||
|
|||||||
@@ -153,7 +153,7 @@ esp_err_t dac_continuous_disable(dac_continuous_handle_t handle);
|
|||||||
* - ESP_ERR_TIMEOUT Waiting for semaphore or message queue timeout
|
* - ESP_ERR_TIMEOUT Waiting for semaphore or message queue timeout
|
||||||
* - ESP_OK Success to output the acyclic DAC data
|
* - ESP_OK Success to output the acyclic DAC data
|
||||||
*/
|
*/
|
||||||
esp_err_t dac_continuous_write(dac_continuous_handle_t handle, uint8_t *buf, size_t buf_size, size_t *bytes_loaded, int timeout_ms);
|
esp_err_t dac_continuous_write(dac_continuous_handle_t handle, const uint8_t *buf, size_t buf_size, size_t *bytes_loaded, int timeout_ms);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @brief Write DAC continuous data cyclically
|
* @brief Write DAC continuous data cyclically
|
||||||
@@ -176,7 +176,7 @@ esp_err_t dac_continuous_write(dac_continuous_handle_t handle, uint8_t *buf, siz
|
|||||||
* - ESP_ERR_INVALID_STATE The DAC continuous mode has not been enabled yet
|
* - ESP_ERR_INVALID_STATE The DAC continuous mode has not been enabled yet
|
||||||
* - ESP_OK Success to output the cyclic DAC data
|
* - ESP_OK Success to output the cyclic DAC data
|
||||||
*/
|
*/
|
||||||
esp_err_t dac_continuous_write_cyclically(dac_continuous_handle_t handle, uint8_t *buf, size_t buf_size, size_t *bytes_loaded);
|
esp_err_t dac_continuous_write_cyclically(dac_continuous_handle_t handle, const uint8_t *buf, size_t buf_size, size_t *bytes_loaded);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @brief Stop the cyclical conversion triggered by 'dac_continuous_write_cyclically'
|
* @brief Stop the cyclical conversion triggered by 'dac_continuous_write_cyclically'
|
||||||
@@ -257,6 +257,14 @@ esp_err_t dac_continuous_write_asynchronously(dac_continuous_handle_t handle,
|
|||||||
size_t data_len,
|
size_t data_len,
|
||||||
size_t *bytes_loaded);
|
size_t *bytes_loaded);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Get the DAC code bit width of the continuous channel group
|
||||||
|
*
|
||||||
|
* @param[in] handle The DAC continuous channel handle
|
||||||
|
* @return The DAC code bit width, 0 if the input parameter is invalid
|
||||||
|
*/
|
||||||
|
uint8_t dac_continuous_get_bitwidth(dac_continuous_handle_t handle);
|
||||||
|
|
||||||
#endif // SOC_DAC_SUPPORTED
|
#endif // SOC_DAC_SUPPORTED
|
||||||
|
|
||||||
#ifdef __cplusplus
|
#ifdef __cplusplus
|
||||||
|
|||||||
@@ -1,5 +1,5 @@
|
|||||||
/*
|
/*
|
||||||
* SPDX-FileCopyrightText: 2019-2022 Espressif Systems (Shanghai) CO LTD
|
* SPDX-FileCopyrightText: 2019-2026 Espressif Systems (Shanghai) CO LTD
|
||||||
*
|
*
|
||||||
* SPDX-License-Identifier: Apache-2.0
|
* SPDX-License-Identifier: Apache-2.0
|
||||||
*/
|
*/
|
||||||
@@ -91,6 +91,14 @@ esp_err_t dac_cosine_start(dac_cosine_handle_t handle);
|
|||||||
*/
|
*/
|
||||||
esp_err_t dac_cosine_stop(dac_cosine_handle_t handle);
|
esp_err_t dac_cosine_stop(dac_cosine_handle_t handle);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Get the DAC code bit width of a cosine wave channel
|
||||||
|
*
|
||||||
|
* @param[in] handle The DAC cosine wave channel handle
|
||||||
|
* @return The DAC code bit width, 0 if the input parameter is invalid
|
||||||
|
*/
|
||||||
|
uint8_t dac_cosine_get_bitwidth(dac_cosine_handle_t handle);
|
||||||
|
|
||||||
#endif // SOC_DAC_SUPPORTED
|
#endif // SOC_DAC_SUPPORTED
|
||||||
|
|
||||||
#ifdef __cplusplus
|
#ifdef __cplusplus
|
||||||
|
|||||||
@@ -1,5 +1,5 @@
|
|||||||
/*
|
/*
|
||||||
* SPDX-FileCopyrightText: 2019-2022 Espressif Systems (Shanghai) CO LTD
|
* SPDX-FileCopyrightText: 2019-2026 Espressif Systems (Shanghai) CO LTD
|
||||||
*
|
*
|
||||||
* SPDX-License-Identifier: Apache-2.0
|
* SPDX-License-Identifier: Apache-2.0
|
||||||
*/
|
*/
|
||||||
@@ -63,6 +63,14 @@ esp_err_t dac_oneshot_del_channel(dac_oneshot_handle_t handle);
|
|||||||
*/
|
*/
|
||||||
esp_err_t dac_oneshot_output_voltage(dac_oneshot_handle_t handle, uint8_t digi_value);
|
esp_err_t dac_oneshot_output_voltage(dac_oneshot_handle_t handle, uint8_t digi_value);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Get the DAC code bit width of a oneshot channel
|
||||||
|
*
|
||||||
|
* @param[in] handle The DAC oneshot channel handle
|
||||||
|
* @return The DAC code bit width, 0 if the input parameter is invalid
|
||||||
|
*/
|
||||||
|
uint8_t dac_oneshot_get_bitwidth(dac_oneshot_handle_t handle);
|
||||||
|
|
||||||
#endif // SOC_DAC_SUPPORTED
|
#endif // SOC_DAC_SUPPORTED
|
||||||
|
|
||||||
#ifdef __cplusplus
|
#ifdef __cplusplus
|
||||||
|
|||||||
@@ -129,11 +129,11 @@ The table below provides more information on pin usage, and please note the comm
|
|||||||
-
|
-
|
||||||
-
|
-
|
||||||
* - GPIO25
|
* - GPIO25
|
||||||
- ADC2_CH8
|
- ADC2_CH8, DAC0
|
||||||
- RTC_GPIO6
|
- RTC_GPIO6
|
||||||
-
|
-
|
||||||
* - GPIO26
|
* - GPIO26
|
||||||
- ADC2_CH9
|
- ADC2_CH9, DAC1
|
||||||
- RTC_GPIO7
|
- RTC_GPIO7
|
||||||
-
|
-
|
||||||
* - GPIO27
|
* - GPIO27
|
||||||
|
|||||||
@@ -91,11 +91,11 @@ The table below provides more information on pin usage, and please note the comm
|
|||||||
- RTC_GPIO16
|
- RTC_GPIO16
|
||||||
-
|
-
|
||||||
* - GPIO17
|
* - GPIO17
|
||||||
- ADC2_CH6
|
- ADC2_CH6, DAC0
|
||||||
- RTC_GPIO17
|
- RTC_GPIO17
|
||||||
-
|
-
|
||||||
* - GPIO18
|
* - GPIO18
|
||||||
- ADC2_CH7
|
- ADC2_CH7, DAC1
|
||||||
- RTC_GPIO18
|
- RTC_GPIO18
|
||||||
-
|
-
|
||||||
* - GPIO19
|
* - GPIO19
|
||||||
|
|||||||
@@ -129,11 +129,11 @@
|
|||||||
-
|
-
|
||||||
-
|
-
|
||||||
* - GPIO25
|
* - GPIO25
|
||||||
- ADC2_CH8
|
- ADC2_CH8, DAC0
|
||||||
- RTC_GPIO6
|
- RTC_GPIO6
|
||||||
-
|
-
|
||||||
* - GPIO26
|
* - GPIO26
|
||||||
- ADC2_CH9
|
- ADC2_CH9, DAC1
|
||||||
- RTC_GPIO7
|
- RTC_GPIO7
|
||||||
-
|
-
|
||||||
* - GPIO27
|
* - GPIO27
|
||||||
|
|||||||
@@ -91,11 +91,11 @@
|
|||||||
- RTC_GPIO16
|
- RTC_GPIO16
|
||||||
-
|
-
|
||||||
* - GPIO17
|
* - GPIO17
|
||||||
- ADC2_CH6
|
- ADC2_CH6, DAC0
|
||||||
- RTC_GPIO17
|
- RTC_GPIO17
|
||||||
-
|
-
|
||||||
* - GPIO18
|
* - GPIO18
|
||||||
- ADC2_CH7
|
- ADC2_CH7, DAC1
|
||||||
- RTC_GPIO18
|
- RTC_GPIO18
|
||||||
-
|
-
|
||||||
* - GPIO19
|
* - GPIO19
|
||||||
|
|||||||
@@ -1,7 +1,7 @@
|
|||||||
| Supported Targets | ESP32 | ESP32-S2 |
|
| Supported Targets | ESP32 | ESP32-S2 |
|
||||||
| ----------------- | ----- | -------- |
|
| ----------------- | ----- | -------- |
|
||||||
|
|
||||||
# DAC Constant Example
|
# DAC Continuous Audio Example
|
||||||
|
|
||||||
(See the README.md file in the upper level 'examples' directory for more information about examples.)
|
(See the README.md file in the upper level 'examples' directory for more information about examples.)
|
||||||
|
|
||||||
@@ -14,13 +14,23 @@ This example shows how to play a piece of audio by DAC driver.
|
|||||||
### Hardware Required
|
### Hardware Required
|
||||||
|
|
||||||
* A development board with ESP32 or ESP32-S2 SoC
|
* A development board with ESP32 or ESP32-S2 SoC
|
||||||
- Note that some ESP32-S2 DevKits have LED on it which is connected to GPIO18 (same pin as DAC channel2), so the output voltage of DAC channel 1 can't go down due the this LED.
|
* DAC channel to GPIO mapping: see [GPIO Summary](https://docs.espressif.com/projects/esp-idf/en/latest/esp32/api-reference/peripherals/gpio.html#gpio-summary) (switch the chip target on the documentation page if needed)
|
||||||
|
* Note that some ESP32-S2 DevKits have an LED on the DAC1 pin, so that channel's output may not go fully low
|
||||||
* An Audio Power Amplifier like `NS4150`
|
* An Audio Power Amplifier like `NS4150`
|
||||||
* A speaker or earphone to play the audio
|
* A speaker or earphone to play the audio
|
||||||
|
|
||||||
### Configure the Project
|
### Configure the Project
|
||||||
|
|
||||||
This example uses the audio that stored in a buffer, which is put in `audio_example_file.h`. You can also create your own audio buffer by the python script `generate_audio_file.py`.
|
The audio table and sample rate are extracted at build time from a WAV file under `tools/` and written into a generated header in the build directory. In menuconfig, under ``Example Configuration``:
|
||||||
|
|
||||||
|
* ``WAV file name``: file under `tools/` (default `hi_idf_audio.wav`)
|
||||||
|
* ``DAC audio table bit width``: Please select based on the DAC channel configuration
|
||||||
|
|
||||||
|
You can also run the converter by hand to inspect the table:
|
||||||
|
|
||||||
|
```
|
||||||
|
python tools/generate_audio_file.py --bitwidth 8 -o audio_example_file.h tools/hi_idf_audio.wav
|
||||||
|
```
|
||||||
|
|
||||||
### Build and Flash
|
### Build and Flash
|
||||||
|
|
||||||
@@ -41,12 +51,12 @@ See the Getting Started Guide for full steps to configure and use ESP-IDF to bui
|
|||||||
You can see the following logs on the monitor:
|
You can see the following logs on the monitor:
|
||||||
|
|
||||||
```
|
```
|
||||||
I (277) dac audio: DAC audio example start
|
I (277) dac_audio: DAC audio example start
|
||||||
I (277) dac audio: --------------------------------------
|
I (277) dac_audio: --------------------------------------
|
||||||
I (287) dac audio: DAC initialized success, DAC DMA is ready
|
I (287) dac_audio: DAC initialized success, DAC DMA is ready
|
||||||
I (297) dac audio: Audio size 79512 bytes, played at frequency 16000 Hz
|
I (297) dac_audio: Audio size 95824 bytes, played at frequency 48000 Hz synchronously
|
||||||
I (5137) dac audio: Audio size 79512 bytes, played at frequency 16000 Hz
|
Play count: 1
|
||||||
I (9967) dac audio: Audio size 79512 bytes, played at frequency 16000 Hz
|
Play count: 2
|
||||||
...
|
...
|
||||||
```
|
```
|
||||||
|
|
||||||
|
|||||||
@@ -1,3 +1,29 @@
|
|||||||
idf_component_register(SRCS "dac_audio_example_main.c"
|
idf_component_register(SRCS "dac_audio_example_main.c"
|
||||||
INCLUDE_DIRS "."
|
INCLUDE_DIRS "."
|
||||||
PRIV_REQUIRES esp_driver_dac)
|
PRIV_REQUIRES esp_driver_dac)
|
||||||
|
|
||||||
|
# Generate the audio table header at build time
|
||||||
|
set(audio_header ${CMAKE_CURRENT_BINARY_DIR}/audio_example_file.h)
|
||||||
|
set(audio_gen_script ${CMAKE_CURRENT_SOURCE_DIR}/../tools/generate_audio_file.py)
|
||||||
|
set(audio_wav ${CMAKE_CURRENT_SOURCE_DIR}/../tools/${CONFIG_EXAMPLE_AUDIO_WAV_FILE})
|
||||||
|
|
||||||
|
idf_build_get_property(python PYTHON)
|
||||||
|
idf_build_get_property(project_dir PROJECT_DIR)
|
||||||
|
|
||||||
|
add_custom_command(
|
||||||
|
OUTPUT ${audio_header}
|
||||||
|
COMMAND ${python} ${audio_gen_script}
|
||||||
|
--bitwidth ${CONFIG_EXAMPLE_DAC_AUDIO_BITWIDTH}
|
||||||
|
-o ${audio_header}
|
||||||
|
${audio_wav}
|
||||||
|
DEPENDS ${audio_gen_script} ${audio_wav} ${project_dir}/sdkconfig
|
||||||
|
COMMENT "Generating DAC audio table from ${CONFIG_EXAMPLE_AUDIO_WAV_FILE}"
|
||||||
|
VERBATIM
|
||||||
|
)
|
||||||
|
|
||||||
|
add_custom_target(dac_audio_header DEPENDS ${audio_header})
|
||||||
|
add_dependencies(${COMPONENT_LIB} dac_audio_header)
|
||||||
|
set_source_files_properties(dac_audio_example_main.c PROPERTIES OBJECT_DEPENDS ${audio_header})
|
||||||
|
target_include_directories(${COMPONENT_LIB} PRIVATE ${CMAKE_CURRENT_BINARY_DIR})
|
||||||
|
set_property(DIRECTORY "${CMAKE_CURRENT_SOURCE_DIR}"
|
||||||
|
APPEND PROPERTY ADDITIONAL_CLEAN_FILES ${audio_header})
|
||||||
|
|||||||
@@ -12,10 +12,35 @@ menu "Example Configuration"
|
|||||||
bool "Asynchronous transmitting"
|
bool "Asynchronous transmitting"
|
||||||
endchoice
|
endchoice
|
||||||
|
|
||||||
config EXAMPLE_AUDIO_SAMPLE_RATE
|
config EXAMPLE_AUDIO_WAV_FILE
|
||||||
int "The audio sample rate (Unit: Hz)"
|
string "WAV file name"
|
||||||
default 48000
|
default "hi_idf_audio.wav"
|
||||||
help
|
help
|
||||||
The audio sample rate
|
WAV file under the example tools/ directory. It is converted to a DAC
|
||||||
|
code table at build time.
|
||||||
|
|
||||||
|
choice EXAMPLE_DAC_AUDIO_BITWIDTH_SEL
|
||||||
|
prompt "DAC audio table bit width"
|
||||||
|
default EXAMPLE_DAC_AUDIO_BITWIDTH_8 if IDF_TARGET_ESP32 || IDF_TARGET_ESP32S2
|
||||||
|
default EXAMPLE_DAC_AUDIO_BITWIDTH_12 if IDF_TARGET_ESP32S31
|
||||||
|
help
|
||||||
|
Bit width of the generated DAC codes. Must match the DAC channel configuration.
|
||||||
|
|
||||||
|
config EXAMPLE_DAC_AUDIO_BITWIDTH_8
|
||||||
|
bool "8 bits"
|
||||||
|
depends on IDF_TARGET_ESP32 || IDF_TARGET_ESP32S2
|
||||||
|
config EXAMPLE_DAC_AUDIO_BITWIDTH_10
|
||||||
|
bool "10 bits"
|
||||||
|
depends on IDF_TARGET_ESP32S31
|
||||||
|
config EXAMPLE_DAC_AUDIO_BITWIDTH_12
|
||||||
|
bool "12 bits"
|
||||||
|
depends on IDF_TARGET_ESP32S31
|
||||||
|
endchoice
|
||||||
|
|
||||||
|
config EXAMPLE_DAC_AUDIO_BITWIDTH
|
||||||
|
int
|
||||||
|
default 8 if EXAMPLE_DAC_AUDIO_BITWIDTH_8
|
||||||
|
default 10 if EXAMPLE_DAC_AUDIO_BITWIDTH_10
|
||||||
|
default 12 if EXAMPLE_DAC_AUDIO_BITWIDTH_12
|
||||||
|
|
||||||
endmenu
|
endmenu
|
||||||
|
|||||||
File diff suppressed because it is too large
Load Diff
@@ -11,15 +11,15 @@
|
|||||||
#include "freertos/queue.h"
|
#include "freertos/queue.h"
|
||||||
#include "driver/dac_continuous.h"
|
#include "driver/dac_continuous.h"
|
||||||
#include "esp_check.h"
|
#include "esp_check.h"
|
||||||
#include "audio_example_file.h"
|
#include "audio_example_file.h" // This header file is automatically generated during the build process by tools/generate_audio_file.py
|
||||||
|
|
||||||
static const char *TAG = "dac_audio";
|
static const char *TAG = "dac_audio";
|
||||||
|
|
||||||
#if CONFIG_EXAMPLE_DAC_WRITE_ASYNC
|
#if CONFIG_EXAMPLE_DAC_WRITE_ASYNC
|
||||||
static bool IRAM_ATTR dac_on_convert_done_callback(dac_continuous_handle_t handle, const dac_event_data_t *event, void *user_data)
|
static bool IRAM_ATTR example_on_convert_done_callback(dac_continuous_handle_t handle, const dac_event_data_t *event, void *user_data)
|
||||||
{
|
{
|
||||||
QueueHandle_t que = (QueueHandle_t)user_data;
|
QueueHandle_t que = (QueueHandle_t)user_data;
|
||||||
BaseType_t need_awoke;
|
BaseType_t need_awoke = pdFALSE;
|
||||||
/* When the queue is full, drop the oldest item */
|
/* When the queue is full, drop the oldest item */
|
||||||
if (xQueueIsQueueFullFromISR(que)) {
|
if (xQueueIsQueueFullFromISR(que)) {
|
||||||
dac_event_data_t dummy;
|
dac_event_data_t dummy;
|
||||||
@@ -30,9 +30,10 @@ static bool IRAM_ATTR dac_on_convert_done_callback(dac_continuous_handle_t hand
|
|||||||
return need_awoke;
|
return need_awoke;
|
||||||
}
|
}
|
||||||
|
|
||||||
static void dac_write_data_asynchronously(dac_continuous_handle_t handle, QueueHandle_t que, uint8_t *data, size_t data_size)
|
static void example_write_data_asynchronously(dac_continuous_handle_t handle, QueueHandle_t que)
|
||||||
{
|
{
|
||||||
ESP_LOGI(TAG, "Audio size %d bytes, played at frequency %d Hz asynchronously", data_size, CONFIG_EXAMPLE_AUDIO_SAMPLE_RATE);
|
size_t data_size = sizeof(audio_table);
|
||||||
|
ESP_LOGI(TAG, "Audio size %d bytes, played at frequency %d Hz asynchronously", data_size, AUDIO_SAMPLE_RATE_HZ);
|
||||||
uint32_t cnt = 1;
|
uint32_t cnt = 1;
|
||||||
while (1) {
|
while (1) {
|
||||||
printf("Play count: %"PRIu32"\n", cnt++);
|
printf("Play count: %"PRIu32"\n", cnt++);
|
||||||
@@ -43,7 +44,7 @@ static void dac_write_data_asynchronously(dac_continuous_handle_t handle, QueueH
|
|||||||
xQueueReceive(que, &evt_data, portMAX_DELAY);
|
xQueueReceive(que, &evt_data, portMAX_DELAY);
|
||||||
size_t loaded_bytes = 0;
|
size_t loaded_bytes = 0;
|
||||||
ESP_ERROR_CHECK(dac_continuous_write_asynchronously(handle, evt_data.buf, evt_data.buf_size,
|
ESP_ERROR_CHECK(dac_continuous_write_asynchronously(handle, evt_data.buf, evt_data.buf_size,
|
||||||
data + byte_written, data_size - byte_written, &loaded_bytes));
|
audio_table + byte_written, data_size - byte_written, &loaded_bytes));
|
||||||
byte_written += loaded_bytes;
|
byte_written += loaded_bytes;
|
||||||
}
|
}
|
||||||
/* Clear the legacy data in DMA, clear times equal to the 'dac_continuous_config_t::desc_num' */
|
/* Clear the legacy data in DMA, clear times equal to the 'dac_continuous_config_t::desc_num' */
|
||||||
@@ -60,13 +61,14 @@ static void dac_write_data_asynchronously(dac_continuous_handle_t handle, QueueH
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
#else
|
#else
|
||||||
static void dac_write_data_synchronously(dac_continuous_handle_t handle, uint8_t *data, size_t data_size)
|
static void example_write_data_synchronously(dac_continuous_handle_t handle)
|
||||||
{
|
{
|
||||||
ESP_LOGI(TAG, "Audio size %d bytes, played at frequency %d Hz synchronously", data_size, CONFIG_EXAMPLE_AUDIO_SAMPLE_RATE);
|
size_t data_size = sizeof(audio_table);
|
||||||
|
ESP_LOGI(TAG, "Audio size %d bytes, played at frequency %d Hz synchronously", data_size, AUDIO_SAMPLE_RATE_HZ);
|
||||||
uint32_t cnt = 1;
|
uint32_t cnt = 1;
|
||||||
while (1) {
|
while (1) {
|
||||||
printf("Play count: %"PRIu32"\n", cnt++);
|
printf("Play count: %"PRIu32"\n", cnt++);
|
||||||
ESP_ERROR_CHECK(dac_continuous_write(handle, data, data_size, NULL, -1));
|
ESP_ERROR_CHECK(dac_continuous_write(handle, audio_table, data_size, NULL, -1));
|
||||||
vTaskDelay(pdMS_TO_TICKS(1000));
|
vTaskDelay(pdMS_TO_TICKS(1000));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -77,13 +79,13 @@ void app_main(void)
|
|||||||
ESP_LOGI(TAG, "DAC audio example start");
|
ESP_LOGI(TAG, "DAC audio example start");
|
||||||
ESP_LOGI(TAG, "--------------------------------------");
|
ESP_LOGI(TAG, "--------------------------------------");
|
||||||
|
|
||||||
|
/* Allocate continuous channels */
|
||||||
dac_continuous_handle_t dac_handle;
|
dac_continuous_handle_t dac_handle;
|
||||||
dac_continuous_config_t cont_cfg = {
|
dac_continuous_config_t cont_cfg = {
|
||||||
.chan_mask = DAC_CHANNEL_MASK_ALL,
|
.chan_mask = DAC_CHANNEL_MASK_ALL,
|
||||||
.desc_num = 4,
|
.desc_num = 4,
|
||||||
.buf_size = 2048,
|
.buf_size = 2048,
|
||||||
.freq_hz = CONFIG_EXAMPLE_AUDIO_SAMPLE_RATE,
|
.freq_hz = AUDIO_SAMPLE_RATE_HZ,
|
||||||
.clk_src = DAC_DIGI_CLK_SRC_APLL, // Using APLL as clock source to get a wider frequency range
|
|
||||||
/* Assume the data in buffer is 'A B C D E F'
|
/* Assume the data in buffer is 'A B C D E F'
|
||||||
* DAC_CHANNEL_MODE_SIMUL:
|
* DAC_CHANNEL_MODE_SIMUL:
|
||||||
* - channel 0: A B C D E F
|
* - channel 0: A B C D E F
|
||||||
@@ -94,28 +96,31 @@ void app_main(void)
|
|||||||
*/
|
*/
|
||||||
.chan_mode = DAC_CHANNEL_MODE_SIMUL,
|
.chan_mode = DAC_CHANNEL_MODE_SIMUL,
|
||||||
};
|
};
|
||||||
/* Allocate continuous channels */
|
|
||||||
ESP_ERROR_CHECK(dac_continuous_new_channels(&cont_cfg, &dac_handle));
|
ESP_ERROR_CHECK(dac_continuous_new_channels(&cont_cfg, &dac_handle));
|
||||||
|
|
||||||
|
/* Ensure that the bit width configured in menuconfig matches that of the DAC channel */
|
||||||
|
assert(CONFIG_EXAMPLE_DAC_AUDIO_BITWIDTH == dac_continuous_get_bitwidth(dac_handle));
|
||||||
|
|
||||||
#if CONFIG_EXAMPLE_DAC_WRITE_ASYNC
|
#if CONFIG_EXAMPLE_DAC_WRITE_ASYNC
|
||||||
/* Create a queue to transport the interrupt event data */
|
/* Create a queue to transport the interrupt event data */
|
||||||
QueueHandle_t que = xQueueCreate(10, sizeof(dac_event_data_t));
|
QueueHandle_t que = xQueueCreate(10, sizeof(dac_event_data_t));
|
||||||
assert(que);
|
assert(que);
|
||||||
dac_event_callbacks_t cbs = {
|
dac_event_callbacks_t cbs = {
|
||||||
.on_convert_done = dac_on_convert_done_callback,
|
.on_convert_done = example_on_convert_done_callback,
|
||||||
.on_stop = NULL,
|
.on_stop = NULL,
|
||||||
};
|
};
|
||||||
/* Must register the callback if using asynchronous writing */
|
/* Must register the callback if using asynchronous writing */
|
||||||
ESP_ERROR_CHECK(dac_continuous_register_event_callback(dac_handle, &cbs, que));
|
ESP_ERROR_CHECK(dac_continuous_register_event_callback(dac_handle, &cbs, que));
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
/* Enable the continuous channels */
|
/* Enable the continuous channels */
|
||||||
ESP_ERROR_CHECK(dac_continuous_enable(dac_handle));
|
ESP_ERROR_CHECK(dac_continuous_enable(dac_handle));
|
||||||
ESP_LOGI(TAG, "DAC initialized success, DAC DMA is ready");
|
ESP_LOGI(TAG, "DAC initialized success, DAC DMA is ready");
|
||||||
|
|
||||||
size_t audio_size = sizeof(audio_table);
|
|
||||||
#if CONFIG_EXAMPLE_DAC_WRITE_ASYNC
|
#if CONFIG_EXAMPLE_DAC_WRITE_ASYNC
|
||||||
ESP_ERROR_CHECK(dac_continuous_start_async_writing(dac_handle));
|
ESP_ERROR_CHECK(dac_continuous_start_async_writing(dac_handle));
|
||||||
dac_write_data_asynchronously(dac_handle, que, (uint8_t *)audio_table, audio_size);
|
example_write_data_asynchronously(dac_handle, que);
|
||||||
#else
|
#else
|
||||||
dac_write_data_synchronously(dac_handle, (uint8_t *)audio_table, audio_size);
|
example_write_data_synchronously(dac_handle);
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,48 +1,144 @@
|
|||||||
# SPDX-FileCopyrightText: 2022 Espressif Systems (Shanghai) CO LTD
|
# SPDX-FileCopyrightText: 2022-2026 Espressif Systems (Shanghai) CO LTD
|
||||||
# SPDX-License-Identifier: Unlicense OR CC0-1.0
|
# SPDX-License-Identifier: Unlicense OR CC0-1.0
|
||||||
import os
|
"""Convert one WAV file to a C array of unsigned DAC codes.
|
||||||
|
|
||||||
|
8-bit codes are packed as uint8_t; 10-bit and 12-bit codes are packed as uint16_t.
|
||||||
|
|
||||||
|
Examples:
|
||||||
|
python generate_audio_file.py --bitwidth 12 -o audio_example_file.h hi_idf_audio.wav
|
||||||
|
"""
|
||||||
|
|
||||||
import struct
|
import struct
|
||||||
import wave
|
import wave
|
||||||
|
from collections.abc import Iterable
|
||||||
|
from collections.abc import Iterator
|
||||||
|
from itertools import islice
|
||||||
|
from pathlib import Path
|
||||||
|
from typing import NamedTuple
|
||||||
|
from typing import TypeVar
|
||||||
|
|
||||||
try:
|
import rich_click as click
|
||||||
from typing import List
|
from esp_pylib.logger import log
|
||||||
except ImportError:
|
|
||||||
pass
|
SUPPORTED_BITWIDTHS = (8, 10, 12)
|
||||||
|
C_ELEM_TYPES = {
|
||||||
|
8: 'uint8_t',
|
||||||
|
10: 'uint16_t',
|
||||||
|
12: 'uint16_t',
|
||||||
|
}
|
||||||
|
T = TypeVar('T')
|
||||||
|
|
||||||
|
|
||||||
def get_wave_array_str(filename, target_bits): # type: (str, int) -> str
|
class PcmData(NamedTuple):
|
||||||
wave_read = wave.open(filename, 'r')
|
samples: list[int]
|
||||||
array_str = ''
|
src_bits: int
|
||||||
nchannels, sampwidth, framerate, nframes, comptype, compname = wave_read.getparams()
|
sample_rate: int
|
||||||
sampwidth *= 8
|
|
||||||
for i in range(wave_read.getnframes()):
|
|
||||||
val, = struct.unpack('<H', wave_read.readframes(1))
|
|
||||||
scale_val = (1 << target_bits) - 1
|
|
||||||
cur_lim = (1 << sampwidth) - 1
|
|
||||||
# scale current data to 8-bit data
|
|
||||||
val = val * scale_val / cur_lim
|
|
||||||
val = int(val + ((scale_val + 1) // 2)) & scale_val
|
|
||||||
array_str += '0x%x, ' % (val)
|
|
||||||
if (i + 1) % 16 == 0:
|
|
||||||
array_str += '\n'
|
|
||||||
return array_str
|
|
||||||
|
|
||||||
|
|
||||||
def gen_wave_table(wav_file_list, target_file_name, scale_bits=8): # type: (List[str], str, int) -> None
|
def _read_signed_pcm(filename: Path) -> PcmData:
|
||||||
with open(target_file_name, 'w') as audio_table:
|
"""Read signed samples and their bit width from a PCM WAV file.
|
||||||
print('#include <stdio.h>', file=audio_table)
|
|
||||||
print('const unsigned char audio_table[] = {', file=audio_table)
|
Multi-channel files use the first channel only. 8-bit WAV is unsigned and is
|
||||||
for wav in wav_file_list:
|
converted to signed PCM; 16-bit WAV is treated as signed little-endian.
|
||||||
print('processing: {}'.format(wav))
|
"""
|
||||||
print(get_wave_array_str(filename=wav, target_bits=scale_bits), file=audio_table)
|
with wave.open(str(filename), 'r') as wav:
|
||||||
print('};\n', file=audio_table)
|
params = wav.getparams()
|
||||||
print('Done...')
|
raw = wav.readframes(params.nframes)
|
||||||
|
|
||||||
|
if params.sampwidth == 1:
|
||||||
|
src_bits = 8
|
||||||
|
signed = [sample - 128 for sample in raw]
|
||||||
|
elif params.sampwidth == 2:
|
||||||
|
src_bits = 16
|
||||||
|
signed = list(struct.unpack(f'<{params.nframes * params.nchannels}h', raw))
|
||||||
|
else:
|
||||||
|
raise ValueError(
|
||||||
|
f'{filename}: only 8-bit and 16-bit PCM WAV are supported (got {params.sampwidth}-byte samples)'
|
||||||
|
)
|
||||||
|
|
||||||
|
if params.nchannels > 1:
|
||||||
|
signed = signed[0 :: params.nchannels]
|
||||||
|
return PcmData(signed, src_bits, params.framerate)
|
||||||
|
|
||||||
|
|
||||||
|
def pcm_to_dac_code(pcm: int, src_bits: int, target_bits: int) -> int:
|
||||||
|
"""Map signed PCM to an unsigned DAC code with mid-scale bias."""
|
||||||
|
max_code = (1 << target_bits) - 1
|
||||||
|
mid = 1 << (target_bits - 1)
|
||||||
|
shift = src_bits - target_bits
|
||||||
|
if shift >= 0:
|
||||||
|
code = (pcm >> shift) + mid
|
||||||
|
else:
|
||||||
|
code = (pcm << -shift) + mid
|
||||||
|
return max(0, min(code, max_code))
|
||||||
|
|
||||||
|
|
||||||
|
def _chunked(iterable: Iterable[T], size: int) -> Iterator[list[T]]:
|
||||||
|
if size <= 0:
|
||||||
|
raise ValueError('chunk size must be positive')
|
||||||
|
iterator = iter(iterable)
|
||||||
|
while chunk := list(islice(iterator, size)):
|
||||||
|
yield chunk
|
||||||
|
|
||||||
|
|
||||||
|
def get_wave_array_str(pcm_data: PcmData, target_bits: int) -> str:
|
||||||
|
hex_width = (target_bits + 3) // 4
|
||||||
|
codes = (f'0x{pcm_to_dac_code(pcm, pcm_data.src_bits, target_bits):0{hex_width}x},' for pcm in pcm_data.samples)
|
||||||
|
return '\n'.join(' '.join(chunk) for chunk in _chunked(codes, 16))
|
||||||
|
|
||||||
|
|
||||||
|
def c_elem_type(bitwidth: int) -> str:
|
||||||
|
return C_ELEM_TYPES[bitwidth]
|
||||||
|
|
||||||
|
|
||||||
|
def gen_wave_table(wav_file: Path, target_file_name: Path, scale_bits: int = 8) -> None:
|
||||||
|
pcm_data = _read_signed_pcm(wav_file)
|
||||||
|
elem_type = c_elem_type(scale_bits)
|
||||||
|
with target_file_name.open('w', encoding='utf-8') as audio_table:
|
||||||
|
audio_table.write('#include <stdint.h>\n')
|
||||||
|
audio_table.write(f'#define AUDIO_SAMPLE_RATE_HZ {pcm_data.sample_rate}\n\n')
|
||||||
|
audio_table.write(f'const {elem_type} audio_table[] = {{\n')
|
||||||
|
audio_table.write(get_wave_array_str(pcm_data=pcm_data, target_bits=scale_bits))
|
||||||
|
audio_table.write('\n};\n')
|
||||||
|
|
||||||
|
|
||||||
|
@click.command(
|
||||||
|
context_settings={'help_option_names': ['-h', '--help']},
|
||||||
|
help='Generate a C array of DAC codes from one WAV file.',
|
||||||
|
)
|
||||||
|
@click.option(
|
||||||
|
'-b',
|
||||||
|
'--bitwidth',
|
||||||
|
type=click.Choice(tuple(str(bitwidth) for bitwidth in SUPPORTED_BITWIDTHS)),
|
||||||
|
default='8',
|
||||||
|
show_default=True,
|
||||||
|
help='DAC code bit width.',
|
||||||
|
)
|
||||||
|
@click.option(
|
||||||
|
'-o',
|
||||||
|
'--output',
|
||||||
|
type=click.Path(dir_okay=False, path_type=Path),
|
||||||
|
default='audio_example_file.h',
|
||||||
|
show_default=True,
|
||||||
|
help='Output header path.',
|
||||||
|
)
|
||||||
|
@click.argument(
|
||||||
|
'wav_file',
|
||||||
|
type=click.Path(exists=True, dir_okay=False, readable=True, path_type=Path),
|
||||||
|
)
|
||||||
|
def cli(bitwidth: str, output: Path, wav_file: Path) -> None:
|
||||||
|
scale_bits = int(bitwidth)
|
||||||
|
log.print(f'Generating audio array from {wav_file} (bitwidth={scale_bits})...', markup=False, soft_wrap=True)
|
||||||
|
gen_wave_table(wav_file=wav_file, target_file_name=output, scale_bits=scale_bits)
|
||||||
|
log.print(f'Wrote {output}', markup=False, soft_wrap=True)
|
||||||
|
|
||||||
|
|
||||||
|
def main() -> None:
|
||||||
|
cli()
|
||||||
|
|
||||||
|
|
||||||
if __name__ == '__main__':
|
if __name__ == '__main__':
|
||||||
print('Generating audio array...')
|
from esp_pylib.excepthook import install_exception_reporting
|
||||||
wav_list = []
|
|
||||||
for wavefile in os.listdir('./'):
|
install_exception_reporting()
|
||||||
if wavefile.endswith('.wav'):
|
main()
|
||||||
wav_list.append(wavefile)
|
|
||||||
gen_wave_table(wav_file_list=wav_list, target_file_name='audio_example_file.h')
|
|
||||||
|
|||||||
@@ -1,40 +1,43 @@
|
|||||||
| Supported Targets | ESP32 | ESP32-S2 |
|
| Supported Targets | ESP32 | ESP32-S2 |
|
||||||
| ----------------- | ----- | -------- |
|
| ----------------- | ----- | -------- |
|
||||||
|
|
||||||
# DAC Constant Example
|
# DAC Continuous Signal Generator Example
|
||||||
|
|
||||||
(See the README.md file in the upper level 'examples' directory for more information about examples.)
|
(See the README.md file in the upper level 'examples' directory for more information about examples.)
|
||||||
|
|
||||||
## Overview
|
## Overview
|
||||||
|
|
||||||
This example shows the basic usage of outputting continuous voltage by the DAC driver. There are two ways to realize continuous output, one is outputting by DMA transmission and another is by timer interrupt.
|
This example demonstrates how to continuously output waveforms using the DAC. There are two general approaches: DMA transfer and timer interrupts.
|
||||||
|
|
||||||
### Timer Interrupt
|
### DMA Transfer
|
||||||
|
|
||||||
While using timer interrupt to output the waves, it actually sets the voltage by `oneshot` API in every timer interrupt callback. Which means the conversion frequency is equal to the timer interrupt frequency. Obviously, the conversion frequency is limited by the interrupt, which relies on the CPU scheduling, thus it can't reach a high frequency in this mode. But it can be used as a supplementary way while the conversion frequency is too low to use DMA mode.
|
Waveform samples are filled into a DMA buffer and continuously transferred to the DAC by DMA. Therefore, the sample (or DAC code) update rate is equal to the DMA transfer rate. This approach reduces CPU load and supports relatively high update rates. However, due to DMA clock limitations, very low update rates may not be achievable. In addition, due to the analog performance limitations of the DAC, excessively high frequencies may result in waveform distortion.
|
||||||
|
|
||||||
### DMA transmission
|
### Timer Interrupts
|
||||||
|
|
||||||
While using DMA to transmit the wave buffers, the digital values are put into a DMA buffer waiting for transmission and conversion, that means the conversion frequency is equal to the frequency that DMA transmitting the data. We can set the DMA frequency directly, and the digital data in the buffer will be sent automatically when the buffer has been loaded into the DMA. So the conversion frequency can reach even several MHz while using DMA mode. But the wave can be distorted if the frequency is too high.
|
This approach essentially calls the DAC `oneshot` API from a timer interrupt callback. Therefore, the sample (or DAC code) update rate is determined by the timer interrupt frequency. Note that frequent interrupts can impose significant CPU overhead, so this approach is only suitable for relatively low update rates.
|
||||||
|
|
||||||
|
In general, the DMA-based approach is recommended for most applications, unless the DMA peripheral is already occupied or the required sample update rate is too low.
|
||||||
|
|
||||||
## How to use the Example
|
## How to use the Example
|
||||||
|
|
||||||
### Hardware Required
|
### Hardware Required
|
||||||
|
|
||||||
* A development board with ESP32 or ESP32-S2 SoC
|
* A development board with ESP32 or ESP32-S2 SoC
|
||||||
- Note that some ESP32-S2 DevKits have LED on it which is connected to GPIO18 (same pin as DAC channel1), so the output voltage of DAC channel 1 can't go down due the this LED.
|
* DAC channel to GPIO mapping: see [GPIO Summary](https://docs.espressif.com/projects/esp-idf/en/latest/esp32/api-reference/peripherals/gpio.html#gpio-summary) (switch the chip target on the documentation page if needed)
|
||||||
|
* Note that some ESP32-S2 DevKits have an LED on the DAC1 pin, so that channel's output may not go fully low
|
||||||
* (Optional) An oscilloscope to monitor the output wave
|
* (Optional) An oscilloscope to monitor the output wave
|
||||||
|
|
||||||
### Configure the Project
|
### Configure the Project
|
||||||
|
|
||||||
You can switch the output method by setting the macro `EXAMPLE_DAC_CONTINUOUS_MODE` to `EXAMPLE_DAC_CONTINUOUS_BY_TIMER` or `EXAMPLE_DAC_CONTINUOUS_BY_DMA`.
|
You can switch the output method in menuconfig under ``Example Configuration`` → ``Select DAC continuous example mode`` (DMA or Timer).
|
||||||
|
|
||||||
There are four waves: sine, triangle, saw tooth and square. These waves are stored in corresponding buffers, and each wave has 400 points as default, which can be modified by `EXAMPLE_ARRAY_LEN`, reduce the point number can increase the wave frequency.
|
Four waveform types are supported: sine, triangle, sawtooth, and square waves. The waveform data is generated at runtime and stored in the corresponding buffers. Each waveform buffer contains one complete period with 400 samples by default, which can be changed via `EXAMPLE_ARRAY_LEN`. The following relationship applies:
|
||||||
|
|
||||||
|
Output waveform frequency = DAC sample update rate / Number of samples
|
||||||
|
|
||||||
### Build and Flash
|
### Build and Flash
|
||||||
|
|
||||||
Note that as we use the ADC to monitor the output data, we need to set false to `CONFIG_ADC_DISABLE_DAC_OUTPUT` in the menuconfig, otherwise the ADC will shutdown the DAC power to guarantee it won't be affect by DAC.
|
|
||||||
|
|
||||||
Build the project and flash it to the board, then run monitor tool to view serial output:
|
Build the project and flash it to the board, then run monitor tool to view serial output:
|
||||||
|
|
||||||
```
|
```
|
||||||
@@ -49,107 +52,41 @@ See the Getting Started Guide for full steps to configure and use ESP-IDF to bui
|
|||||||
|
|
||||||
## Example Output
|
## Example Output
|
||||||
|
|
||||||
This example can output sine wave, triangle wave, saw tooth wave and square wave periodically, each wave will last for 3 seconds.
|
This example outputs sine, triangle, sawtooth and square waves on DAC channel 0, switching every 2 seconds. Connect an oscilloscope to the DAC channel 0 GPIO to observe the waveforms.
|
||||||
|
|
||||||
The DAC channels can be read by ADC channels internally. The ADC read period is 500 ms, the following log is the raw ADC value read from the DAC channels. But since the ADC sample-rate is lower than the DAC output-rate, the sampling value can only indicate that the voltage is changing.
|
|
||||||
|
|
||||||
### Timer Triggered Output
|
|
||||||
|
|
||||||
You can see sine wave, triangle wave, saw tooth wave and square wave at 50 Hz on the oscilloscope.
|
|
||||||
|
|
||||||
```
|
|
||||||
I (333) dac continuous: --------------------------------------------------
|
|
||||||
I (343) dac continuous: DAC continuous output by Timer
|
|
||||||
I (343) dac continuous: DAC channel 0 io: GPIO_NUM_25
|
|
||||||
I (353) dac continuous: DAC channel 1 io: GPIO_NUM_26
|
|
||||||
I (353) dac continuous: Waveform: SINE -> TRIANGLE -> SAWTOOTH -> SQUARE
|
|
||||||
I (363) dac continuous: DAC conversion frequency (Hz): 20000
|
|
||||||
I (373) dac continuous: DAC wave frequency (Hz): 50
|
|
||||||
I (373) dac continuous: --------------------------------------------------
|
|
||||||
DAC channel 0 value: 2291 DAC channel 1 value: 2331
|
|
||||||
DAC channel 0 value: 43 DAC channel 1 value: 3
|
|
||||||
DAC channel 0 value: 55 DAC channel 1 value: 32
|
|
||||||
DAC channel 0 value: 57 DAC channel 1 value: 33
|
|
||||||
DAC channel 0 value: 56 DAC channel 1 value: 34
|
|
||||||
DAC channel 0 value: 59 DAC channel 1 value: 34
|
|
||||||
DAC channel 0 value: 56 DAC channel 1 value: 33
|
|
||||||
I (3393) dac continuous(timer): triangle wave start
|
|
||||||
DAC channel 0 value: 2258 DAC channel 1 value: 2243
|
|
||||||
DAC channel 0 value: 2257 DAC channel 1 value: 2242
|
|
||||||
DAC channel 0 value: 2259 DAC channel 1 value: 2242
|
|
||||||
DAC channel 0 value: 2257 DAC channel 1 value: 2245
|
|
||||||
DAC channel 0 value: 2257 DAC channel 1 value: 2243
|
|
||||||
DAC channel 0 value: 2258 DAC channel 1 value: 2240
|
|
||||||
I (6393) dac continuous(timer): sawtooth wave start
|
|
||||||
DAC channel 0 value: 2704 DAC channel 1 value: 2735
|
|
||||||
DAC channel 0 value: 2704 DAC channel 1 value: 2735
|
|
||||||
DAC channel 0 value: 2704 DAC channel 1 value: 2736
|
|
||||||
DAC channel 0 value: 2704 DAC channel 1 value: 2717
|
|
||||||
DAC channel 0 value: 2704 DAC channel 1 value: 2734
|
|
||||||
DAC channel 0 value: 2704 DAC channel 1 value: 2736
|
|
||||||
I (9393) dac continuous(timer): square wave start
|
|
||||||
DAC channel 0 value: 0 DAC channel 1 value: 0
|
|
||||||
DAC channel 0 value: 0 DAC channel 1 value: 0
|
|
||||||
DAC channel 0 value: 0 DAC channel 1 value: 0
|
|
||||||
DAC channel 0 value: 0 DAC channel 1 value: 0
|
|
||||||
DAC channel 0 value: 0 DAC channel 1 value: 0
|
|
||||||
DAC channel 0 value: 0 DAC channel 1 value: 0
|
|
||||||
I (12393) dac continuous(timer): sine wave start
|
|
||||||
DAC channel 0 value: 82 DAC channel 1 value: 62
|
|
||||||
DAC channel 0 value: 83 DAC channel 1 value: 62
|
|
||||||
DAC channel 0 value: 82 DAC channel 1 value: 62
|
|
||||||
DAC channel 0 value: 87 DAC channel 1 value: 62
|
|
||||||
DAC channel 0 value: 84 DAC channel 1 value: 63
|
|
||||||
DAC channel 0 value: 83 DAC channel 1 value: 64
|
|
||||||
...
|
|
||||||
```
|
|
||||||
|
|
||||||
### DMA Output
|
### DMA Output
|
||||||
|
|
||||||
You can see sine wave, triangle wave, saw tooth wave and square wave at 2 KHz on the oscilloscope.
|
You can see sine wave, triangle wave, saw tooth wave and square wave at 2 KHz on the oscilloscope.
|
||||||
|
|
||||||
```
|
```
|
||||||
I (335) dac continuous: --------------------------------------------------
|
I (266) signal_generator: --------------------------------------------------
|
||||||
I (345) dac continuous: DAC continuous output by DMA
|
I (266) signal_generator: DAC continuous output by DMA
|
||||||
I (345) dac continuous: DAC channel 0 io: GPIO_NUM_25
|
I (266) signal_generator: DAC channel 0 io: GPIO_NUM_25
|
||||||
I (355) dac continuous: DAC channel 1 io: GPIO_NUM_26
|
I (276) signal_generator: Waveform: SINE -> TRIANGLE -> SAWTOOTH -> SQUARE
|
||||||
I (355) dac continuous: Waveform: SINE -> TRIANGLE -> SAWTOOTH -> SQUARE
|
I (276) signal_generator: DAC sample update rate (Hz): 800000
|
||||||
I (365) dac continuous: DAC conversion frequency (Hz): 800000
|
I (286) signal_generator: Waveform frequency (Hz): 2000
|
||||||
I (375) dac continuous: DAC wave frequency (Hz): 2000
|
I (286) signal_generator: --------------------------------------------------
|
||||||
I (375) dac continuous: --------------------------------------------------
|
I (296) signal_generator: sine wave start
|
||||||
DAC channel 0 value: 3131 DAC channel 1 value: 1634
|
I (2296) signal_generator: triangle wave start
|
||||||
DAC channel 0 value: 1712 DAC channel 1 value: 2531
|
I (4296) signal_generator: sawtooth wave start
|
||||||
DAC channel 0 value: 1716 DAC channel 1 value: 2535
|
I (6296) signal_generator: square wave start
|
||||||
DAC channel 0 value: 1715 DAC channel 1 value: 2544
|
...
|
||||||
DAC channel 0 value: 1715 DAC channel 1 value: 2533
|
```
|
||||||
DAC channel 0 value: 1712 DAC channel 1 value: 2539
|
### Timer Triggered Output
|
||||||
I (3395) dac continuous(DMA): triangle wave start
|
|
||||||
DAC channel 0 value: 592 DAC channel 1 value: 1190
|
You can see sine wave, triangle wave, saw tooth wave and square wave at 50 Hz on the oscilloscope.
|
||||||
DAC channel 0 value: 4095 DAC channel 1 value: 3518
|
|
||||||
DAC channel 0 value: 4095 DAC channel 1 value: 3515
|
```
|
||||||
DAC channel 0 value: 4095 DAC channel 1 value: 3516
|
I (265) signal_generator: --------------------------------------------------
|
||||||
DAC channel 0 value: 4095 DAC channel 1 value: 3514
|
I (265) signal_generator: DAC continuous output by timer
|
||||||
DAC channel 0 value: 4095 DAC channel 1 value: 3515
|
I (265) signal_generator: DAC channel 0 io: GPIO_NUM_25
|
||||||
I (6395) dac continuous(DMA): sawtooth wave start
|
I (275) signal_generator: Waveform: SINE -> TRIANGLE -> SAWTOOTH -> SQUARE
|
||||||
DAC channel 0 value: 294 DAC channel 1 value: 560
|
I (275) signal_generator: DAC sample update rate (Hz): 20000
|
||||||
DAC channel 0 value: 2861 DAC channel 1 value: 3227
|
I (285) signal_generator: Waveform frequency (Hz): 50
|
||||||
DAC channel 0 value: 2860 DAC channel 1 value: 3216
|
I (285) signal_generator: --------------------------------------------------
|
||||||
DAC channel 0 value: 2861 DAC channel 1 value: 3227
|
I (295) signal_generator: sine wave start
|
||||||
DAC channel 0 value: 2861 DAC channel 1 value: 3216
|
I (2295) signal_generator: triangle wave start
|
||||||
DAC channel 0 value: 2859 DAC channel 1 value: 3183
|
I (4295) signal_generator: sawtooth wave start
|
||||||
I (9395) dac continuous(DMA): square wave start
|
I (6295) signal_generator: square wave start
|
||||||
DAC channel 0 value: 4095 DAC channel 1 value: 4095
|
|
||||||
DAC channel 0 value: 0 DAC channel 1 value: 0
|
|
||||||
DAC channel 0 value: 0 DAC channel 1 value: 0
|
|
||||||
DAC channel 0 value: 0 DAC channel 1 value: 0
|
|
||||||
DAC channel 0 value: 0 DAC channel 1 value: 0
|
|
||||||
DAC channel 0 value: 0 DAC channel 1 value: 0
|
|
||||||
I (12395) dac continuous(DMA): sine wave start
|
|
||||||
DAC channel 0 value: 2864 DAC channel 1 value: 3691
|
|
||||||
DAC channel 0 value: 0 DAC channel 1 value: 204
|
|
||||||
DAC channel 0 value: 0 DAC channel 1 value: 202
|
|
||||||
DAC channel 0 value: 0 DAC channel 1 value: 193
|
|
||||||
DAC channel 0 value: 0 DAC channel 1 value: 181
|
|
||||||
DAC channel 0 value: 0 DAC channel 1 value: 194
|
|
||||||
...
|
...
|
||||||
```
|
```
|
||||||
|
|||||||
@@ -1,7 +1,5 @@
|
|||||||
set(srcs "dac_continuous_example_main.c"
|
idf_component_register(SRCS "dac_continuous_example_main.c"
|
||||||
"dac_continuous_example_dma.c"
|
"dac_continuous_example_dma.c"
|
||||||
"dac_continuous_example_timer.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)
|
PRIV_REQUIRES esp_driver_dac esp_driver_gptimer)
|
||||||
|
|||||||
@@ -1,12 +1,24 @@
|
|||||||
/*
|
/*
|
||||||
* SPDX-FileCopyrightText: 2022 Espressif Systems (Shanghai) CO LTD
|
* SPDX-FileCopyrightText: 2022-2026 Espressif Systems (Shanghai) CO LTD
|
||||||
*
|
*
|
||||||
* SPDX-License-Identifier: CC0-1.0
|
* SPDX-License-Identifier: CC0-1.0
|
||||||
*/
|
*/
|
||||||
#define CONST_PERIOD_2_PI 6.2832 // 2 * PI
|
#include <stdint.h>
|
||||||
|
#include "soc/soc_caps.h"
|
||||||
|
|
||||||
#define EXAMPLE_ARRAY_LEN 400 // Length of wave array
|
#define TAG "signal_generator"
|
||||||
#define EXAMPLE_DAC_AMPLITUDE 255 // Amplitude of DAC voltage. If it's more than 256 will causes dac_output_voltage() output 0.
|
|
||||||
|
#if SOC_IS(ESP32) || SOC_IS(ESP32S2)
|
||||||
|
/* only support 8-bit code, packed into uint8_t */
|
||||||
|
typedef uint8_t dac_example_sample_t;
|
||||||
|
#elif SOC_IS(ESP32S31)
|
||||||
|
/* support 10-bit and 12-bit codes, both packed into uint16_t */
|
||||||
|
typedef uint16_t dac_example_sample_t;
|
||||||
|
#else
|
||||||
|
#error "Define packed sample type to match selected SOC and DAC channel config"
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#define EXAMPLE_ARRAY_LEN 400 // Length of wave array
|
||||||
|
|
||||||
typedef enum {
|
typedef enum {
|
||||||
DAC_SINE_WAVE,
|
DAC_SINE_WAVE,
|
||||||
@@ -16,6 +28,16 @@ typedef enum {
|
|||||||
DAC_WAVE_MAX,
|
DAC_WAVE_MAX,
|
||||||
} dac_example_wave_type_t;
|
} dac_example_wave_type_t;
|
||||||
|
|
||||||
|
extern const char* wave_name[DAC_WAVE_MAX];
|
||||||
|
extern dac_example_sample_t wave_data[DAC_WAVE_MAX][EXAMPLE_ARRAY_LEN];
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Generate wave tables for the given bit width of the configured DAC channel
|
||||||
|
*
|
||||||
|
* @param resolution_bits The resolution bits width of the DAC channel
|
||||||
|
*/
|
||||||
|
void example_generate_wave(uint8_t resolution_bits);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @brief Use DMA to convert continuously
|
* @brief Use DMA to convert continuously
|
||||||
*
|
*
|
||||||
@@ -31,7 +53,7 @@ void example_dac_continuous_by_timer(void);
|
|||||||
/**
|
/**
|
||||||
* @brief Print the example log information
|
* @brief Print the example log information
|
||||||
*
|
*
|
||||||
* @param conv_freq DAC conversion frequency
|
* @param update_rate DAC sample update rate (Hz)
|
||||||
* @param wave_freq The frequency of the wave
|
* @param wave_freq The frequency of the wave
|
||||||
*/
|
*/
|
||||||
void example_log_info(uint32_t conv_freq, uint32_t wave_freq);
|
void example_log_info(uint32_t update_rate, uint32_t wave_freq);
|
||||||
|
|||||||
@@ -1,58 +1,31 @@
|
|||||||
/*
|
/*
|
||||||
* SPDX-FileCopyrightText: 2022-2023 Espressif Systems (Shanghai) CO LTD
|
* SPDX-FileCopyrightText: 2022-2026 Espressif Systems (Shanghai) CO LTD
|
||||||
*
|
*
|
||||||
* SPDX-License-Identifier: CC0-1.0
|
* SPDX-License-Identifier: CC0-1.0
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#include <math.h>
|
|
||||||
#include "freertos/FreeRTOS.h"
|
#include "freertos/FreeRTOS.h"
|
||||||
#include "freertos/task.h"
|
#include "freertos/task.h"
|
||||||
#include "driver/dac_continuous.h"
|
#include "driver/dac_continuous.h"
|
||||||
#include "esp_check.h"
|
#include "esp_check.h"
|
||||||
#include "dac_continuous_example.h"
|
#include "dac_continuous_example.h"
|
||||||
|
|
||||||
#define EXAMPLE_WAVE_FREQ_HZ 2000 // Default wave frequency 2000 Hz, it can't be too low
|
#define EXAMPLE_WAVE_FREQ_HZ 2000 // Default wave frequency 2000 Hz, it can't be too low
|
||||||
#define EXAMPLE_CONVERT_FREQ_HZ (EXAMPLE_ARRAY_LEN * EXAMPLE_WAVE_FREQ_HZ) // The frequency that DAC convert every data in the wave array
|
#define EXAMPLE_UPDATE_RATE_HZ (EXAMPLE_ARRAY_LEN * EXAMPLE_WAVE_FREQ_HZ) // The frequency at which the DAC samples (codes) are updated
|
||||||
|
|
||||||
extern uint8_t sin_wav[EXAMPLE_ARRAY_LEN]; // Used to store sine wave values
|
|
||||||
extern uint8_t tri_wav[EXAMPLE_ARRAY_LEN]; // Used to store triangle wave values
|
|
||||||
extern uint8_t saw_wav[EXAMPLE_ARRAY_LEN]; // Used to store sawtooth wave values
|
|
||||||
extern uint8_t squ_wav[EXAMPLE_ARRAY_LEN]; // Used to store square wave values
|
|
||||||
|
|
||||||
static const char *TAG = "dac continuous(DMA)";
|
|
||||||
static const char wav_name[DAC_WAVE_MAX][15] = {"sine", "triangle", "sawtooth", "square"};
|
|
||||||
|
|
||||||
static void dac_dma_write_task(void *args)
|
static void dac_dma_write_task(void *args)
|
||||||
{
|
{
|
||||||
dac_continuous_handle_t handle = (dac_continuous_handle_t)args;
|
dac_continuous_handle_t handle = (dac_continuous_handle_t)args;
|
||||||
dac_example_wave_type_t wav_sel = DAC_SINE_WAVE; // Start from sine wave
|
dac_example_wave_type_t wave_sel = DAC_SINE_WAVE; // Start from sine wave
|
||||||
|
|
||||||
size_t buf_len = EXAMPLE_ARRAY_LEN;
|
|
||||||
|
|
||||||
while (1) {
|
while (1) {
|
||||||
ESP_LOGI(TAG, "%s wave start", wav_name[wav_sel]);
|
ESP_LOGI(TAG, "%s wave start", wave_name[wave_sel]);
|
||||||
/* The wave in the buffer will be converted cyclically */
|
/* The wave in the buffer will be converted cyclically */
|
||||||
switch (wav_sel) {
|
ESP_ERROR_CHECK(dac_continuous_write_cyclically(handle, wave_data[wave_sel], EXAMPLE_ARRAY_LEN, NULL));
|
||||||
case DAC_SINE_WAVE:
|
|
||||||
ESP_ERROR_CHECK(dac_continuous_write_cyclically(handle, (uint8_t *)sin_wav, buf_len, NULL));
|
|
||||||
break;
|
|
||||||
case DAC_TRIANGLE_WAVE:
|
|
||||||
ESP_ERROR_CHECK(dac_continuous_write_cyclically(handle, (uint8_t *)tri_wav, buf_len, NULL));
|
|
||||||
break;
|
|
||||||
case DAC_SAWTOOTH_WAVE:
|
|
||||||
ESP_ERROR_CHECK(dac_continuous_write_cyclically(handle, (uint8_t *)saw_wav, buf_len, NULL));
|
|
||||||
break;
|
|
||||||
case DAC_SQUARE_WAVE:
|
|
||||||
ESP_ERROR_CHECK(dac_continuous_write_cyclically(handle, (uint8_t *)squ_wav, buf_len, NULL));
|
|
||||||
break;
|
|
||||||
default:
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
/* Switch wave every CONFIG_EXAMPLE_WAVE_PERIOD_SEC seconds */
|
/* Switch wave every CONFIG_EXAMPLE_WAVE_PERIOD_SEC seconds */
|
||||||
vTaskDelay(pdMS_TO_TICKS(CONFIG_EXAMPLE_WAVE_PERIOD_SEC * 1000));
|
vTaskDelay(pdMS_TO_TICKS(CONFIG_EXAMPLE_WAVE_PERIOD_SEC * 1000));
|
||||||
ESP_ERROR_CHECK(dac_continuous_stop_cyclically(handle));
|
ESP_ERROR_CHECK(dac_continuous_stop_cyclically(handle));
|
||||||
wav_sel++;
|
wave_sel = (wave_sel + 1) % DAC_WAVE_MAX;
|
||||||
wav_sel %= DAC_WAVE_MAX;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -60,26 +33,19 @@ void example_dac_continuous_by_dma(void)
|
|||||||
{
|
{
|
||||||
dac_continuous_handle_t cont_handle;
|
dac_continuous_handle_t cont_handle;
|
||||||
dac_continuous_config_t cont_cfg = {
|
dac_continuous_config_t cont_cfg = {
|
||||||
.chan_mask = DAC_CHANNEL_MASK_ALL,
|
.chan_mask = DAC_CHANNEL_MASK_CH0, // This example outputs on one channel only
|
||||||
.desc_num = 8,
|
.desc_num = 8,
|
||||||
.buf_size = 2048,
|
.buf_size = 2048,
|
||||||
.freq_hz = EXAMPLE_CONVERT_FREQ_HZ,
|
.freq_hz = EXAMPLE_UPDATE_RATE_HZ,
|
||||||
/* Assume the data in buffer is 'A B C D E F'
|
|
||||||
* DAC_CHANNEL_MODE_SIMUL:
|
|
||||||
* - channel 0: A B C D E F
|
|
||||||
* - channel 1: A B C D E F
|
|
||||||
* DAC_CHANNEL_MODE_ALTER:
|
|
||||||
* - channel 0: A C E
|
|
||||||
* - channel 1: B D F
|
|
||||||
*/
|
|
||||||
.chan_mode = DAC_CHANNEL_MODE_SIMUL,
|
|
||||||
};
|
};
|
||||||
/* Allocate continuous channel */
|
/* Allocate continuous channel */
|
||||||
ESP_ERROR_CHECK(dac_continuous_new_channels(&cont_cfg, &cont_handle));
|
ESP_ERROR_CHECK(dac_continuous_new_channels(&cont_cfg, &cont_handle));
|
||||||
|
/* Generate wave data */
|
||||||
|
example_generate_wave(dac_continuous_get_bitwidth(cont_handle));
|
||||||
/* Enable the channels in the group */
|
/* Enable the channels in the group */
|
||||||
ESP_ERROR_CHECK(dac_continuous_enable(cont_handle));
|
ESP_ERROR_CHECK(dac_continuous_enable(cont_handle));
|
||||||
|
|
||||||
example_log_info(EXAMPLE_CONVERT_FREQ_HZ, EXAMPLE_WAVE_FREQ_HZ);
|
example_log_info(EXAMPLE_UPDATE_RATE_HZ, EXAMPLE_WAVE_FREQ_HZ);
|
||||||
|
|
||||||
/* Start to convert wave */
|
/* Start to convert wave */
|
||||||
xTaskCreate(dac_dma_write_task, "dac_dma_write_task", 4096, cont_handle, 5, NULL);
|
xTaskCreate(dac_dma_write_task, "dac_dma_write_task", 4096, cont_handle, 5, NULL);
|
||||||
|
|||||||
@@ -1,67 +1,36 @@
|
|||||||
/*
|
/*
|
||||||
* SPDX-FileCopyrightText: 2022 Espressif Systems (Shanghai) CO LTD
|
* SPDX-FileCopyrightText: 2022-2026 Espressif Systems (Shanghai) CO LTD
|
||||||
*
|
*
|
||||||
* SPDX-License-Identifier: CC0-1.0
|
* SPDX-License-Identifier: CC0-1.0
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
#include <stdint.h>
|
||||||
#include <inttypes.h>
|
#include <inttypes.h>
|
||||||
#include <math.h>
|
#include <math.h>
|
||||||
#include "freertos/FreeRTOS.h"
|
#include "esp_log.h"
|
||||||
#include "freertos/task.h"
|
#include "hal/dac_types.h"
|
||||||
#include "soc/dac_channel.h"
|
#include "hal/dac_periph.h"
|
||||||
#include "esp_adc/adc_oneshot.h"
|
|
||||||
#include "esp_check.h"
|
|
||||||
#include "dac_continuous_example.h"
|
#include "dac_continuous_example.h"
|
||||||
|
|
||||||
/**
|
#define EXAMPLE_DAC_CHAN_IO dac_periph_signal.dac_channel_io_num[DAC_CHAN_0]
|
||||||
* There are two ways to convert digital data to analog signal continuously:
|
|
||||||
* - Using a timer: setting DAC voltage periodically in the timer interrupt
|
|
||||||
* in this way, DAC can achieve a relatively low conversion frequency
|
|
||||||
* but it is not a efficient way comparing to using the DMA
|
|
||||||
* - Using DMA: tansmitting the data buffer via DMA,
|
|
||||||
* the conversion frequency is controlled by how fast it is transmitted by DMA
|
|
||||||
* in this way, the conversion frequency can reach several MHz,
|
|
||||||
* but it can't achieve a very low conversion frequency because it is limited by the DMA clock source
|
|
||||||
* Generally, recommand to use DMA, if the DMA peripheral is occupied or the required conversion frequency is very low,
|
|
||||||
* then use timer instead
|
|
||||||
*/
|
|
||||||
|
|
||||||
/* ADC configuration */
|
const char* wave_name[DAC_WAVE_MAX] = {"sine", "triangle", "sawtooth", "square"};
|
||||||
#if CONFIG_IDF_TARGET_ESP32
|
dac_example_sample_t wave_data[DAC_WAVE_MAX][EXAMPLE_ARRAY_LEN];
|
||||||
#define EXAMPLE_DAC_CHAN0_ADC_CHAN ADC_CHANNEL_8 // GPIO25, same as DAC channel 0
|
|
||||||
#define EXAMPLE_DAC_CHAN1_ADC_CHAN ADC_CHANNEL_9 // GPIO26, same as DAC channel 1
|
|
||||||
#define EXAMPLE_ADC_WIDTH ADC_WIDTH_BIT_12
|
|
||||||
#elif CONFIG_IDF_TARGET_ESP32S2
|
|
||||||
#define EXAMPLE_DAC_CHAN0_ADC_CHAN ADC_CHANNEL_6 // GPIO17, same as DAC channel 0
|
|
||||||
#define EXAMPLE_DAC_CHAN1_ADC_CHAN ADC_CHANNEL_7 // GPIO18, same as DAC channel 1
|
|
||||||
#define EXAMPLE_ADC_WIDTH ADC_WIDTH_BIT_13
|
|
||||||
#endif
|
|
||||||
#define EXAMPLE_DAC_CHAN0_IO DAC_CHAN0_GPIO_NUM // DAC channel 0 io number
|
|
||||||
#define EXAMPLE_DAC_CHAN1_IO DAC_CHAN1_GPIO_NUM // DAC channel 1 io number
|
|
||||||
#define EXAMPLE_ADC_ATTEN ADC_ATTEN_DB_12
|
|
||||||
|
|
||||||
_Static_assert(EXAMPLE_DAC_AMPLITUDE < 256, "The DAC accuracy is 8 bit-width, doesn't support the amplitude beyond 255");
|
void example_generate_wave(uint8_t resolution_bits)
|
||||||
|
|
||||||
static const char *TAG = "dac continuous";
|
|
||||||
|
|
||||||
uint8_t sin_wav[EXAMPLE_ARRAY_LEN]; // Used to store sine wave values
|
|
||||||
uint8_t tri_wav[EXAMPLE_ARRAY_LEN]; // Used to store triangle wave values
|
|
||||||
uint8_t saw_wav[EXAMPLE_ARRAY_LEN]; // Used to store sawtooth wave values
|
|
||||||
uint8_t squ_wav[EXAMPLE_ARRAY_LEN]; // Used to store square wave values
|
|
||||||
|
|
||||||
static void example_generate_wave(void)
|
|
||||||
{
|
{
|
||||||
uint32_t pnt_num = EXAMPLE_ARRAY_LEN;
|
const size_t N = EXAMPLE_ARRAY_LEN;
|
||||||
|
const uint16_t max_code = (1U << resolution_bits) - 1;
|
||||||
|
|
||||||
for (int i = 0; i < pnt_num; i ++) {
|
for (size_t i = 0; i < N; i++) {
|
||||||
sin_wav[i] = (uint8_t)((sin(i * CONST_PERIOD_2_PI / pnt_num) + 1) * (double)(EXAMPLE_DAC_AMPLITUDE) / 2 + 0.5);
|
wave_data[DAC_SINE_WAVE][i] = (sin(2 * M_PI * i / N) + 1) / 2 * max_code + 0.5;
|
||||||
tri_wav[i] = (i > (pnt_num / 2)) ? (2 * EXAMPLE_DAC_AMPLITUDE * (pnt_num - i) / pnt_num) : (2 * EXAMPLE_DAC_AMPLITUDE * i / pnt_num);
|
wave_data[DAC_TRIANGLE_WAVE][i] = (i < N / 2) ? (2 * max_code * i / N) : (2 * max_code * (N - i) / N);
|
||||||
saw_wav[i] = (i == pnt_num) ? 0 : (i * EXAMPLE_DAC_AMPLITUDE / pnt_num);
|
wave_data[DAC_SAWTOOTH_WAVE][i] = max_code * i / N;
|
||||||
squ_wav[i] = (i < (pnt_num / 2)) ? EXAMPLE_DAC_AMPLITUDE : 0;
|
wave_data[DAC_SQUARE_WAVE][i] = (i < N / 2) ? max_code : 0;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void example_log_info(uint32_t conv_freq, uint32_t wave_freq)
|
void example_log_info(uint32_t update_rate, uint32_t wave_freq)
|
||||||
{
|
{
|
||||||
ESP_LOGI(TAG, "--------------------------------------------------");
|
ESP_LOGI(TAG, "--------------------------------------------------");
|
||||||
#if CONFIG_EXAMPLE_DAC_CONTINUOUS_BY_DMA
|
#if CONFIG_EXAMPLE_DAC_CONTINUOUS_BY_DMA
|
||||||
@@ -69,32 +38,15 @@ void example_log_info(uint32_t conv_freq, uint32_t wave_freq)
|
|||||||
#else
|
#else
|
||||||
ESP_LOGI(TAG, "DAC continuous output by timer");
|
ESP_LOGI(TAG, "DAC continuous output by timer");
|
||||||
#endif
|
#endif
|
||||||
ESP_LOGI(TAG, "DAC channel 0 io: GPIO_NUM_%d", EXAMPLE_DAC_CHAN0_IO);
|
ESP_LOGI(TAG, "DAC channel 0 io: GPIO_NUM_%d", EXAMPLE_DAC_CHAN_IO);
|
||||||
ESP_LOGI(TAG, "DAC channel 1 io: GPIO_NUM_%d", EXAMPLE_DAC_CHAN1_IO);
|
|
||||||
ESP_LOGI(TAG, "Waveform: SINE -> TRIANGLE -> SAWTOOTH -> SQUARE");
|
ESP_LOGI(TAG, "Waveform: SINE -> TRIANGLE -> SAWTOOTH -> SQUARE");
|
||||||
ESP_LOGI(TAG, "DAC conversion frequency (Hz): %"PRIu32, conv_freq);
|
ESP_LOGI(TAG, "DAC sample update rate (Hz): %"PRIu32, update_rate);
|
||||||
ESP_LOGI(TAG, "DAC wave frequency (Hz): %"PRIu32, wave_freq);
|
ESP_LOGI(TAG, "Waveform frequency (Hz): %"PRIu32, wave_freq);
|
||||||
ESP_LOGI(TAG, "--------------------------------------------------");
|
ESP_LOGI(TAG, "--------------------------------------------------");
|
||||||
}
|
}
|
||||||
|
|
||||||
static void adc_monitor_task(void *args)
|
|
||||||
{
|
|
||||||
adc_oneshot_unit_handle_t adc2_handle = (adc_oneshot_unit_handle_t)args;
|
|
||||||
|
|
||||||
int chan0_val = 0;
|
|
||||||
int chan1_val = 0;
|
|
||||||
while (1) {
|
|
||||||
/* Read the DAC output voltage */
|
|
||||||
ESP_ERROR_CHECK(adc_oneshot_read(adc2_handle, EXAMPLE_DAC_CHAN0_ADC_CHAN, &chan0_val));
|
|
||||||
ESP_ERROR_CHECK(adc_oneshot_read(adc2_handle, EXAMPLE_DAC_CHAN1_ADC_CHAN, &chan1_val));
|
|
||||||
printf("DAC channel 0 value: %4d\tDAC channel 1 value: %4d\n", chan0_val, chan1_val);
|
|
||||||
vTaskDelay(pdMS_TO_TICKS(100));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void app_main(void)
|
void app_main(void)
|
||||||
{
|
{
|
||||||
example_generate_wave();
|
|
||||||
#if CONFIG_EXAMPLE_DAC_CONTINUOUS_BY_DMA
|
#if CONFIG_EXAMPLE_DAC_CONTINUOUS_BY_DMA
|
||||||
/* Output 2 kHz waves using DMA */
|
/* Output 2 kHz waves using DMA */
|
||||||
example_dac_continuous_by_dma();
|
example_dac_continuous_by_dma();
|
||||||
@@ -102,20 +54,4 @@ void app_main(void)
|
|||||||
/* Output 50 Hz waves using timer interrupt */
|
/* Output 50 Hz waves using timer interrupt */
|
||||||
example_dac_continuous_by_timer();
|
example_dac_continuous_by_timer();
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
/* Set the ADC2 channels, these channels are connected to the DAC channels internally */
|
|
||||||
adc_oneshot_unit_handle_t adc2_handle;
|
|
||||||
adc_oneshot_unit_init_cfg_t adc_cfg = {
|
|
||||||
.unit_id = ADC_UNIT_2,
|
|
||||||
.ulp_mode = false,
|
|
||||||
};
|
|
||||||
ESP_ERROR_CHECK(adc_oneshot_new_unit(&adc_cfg, &adc2_handle));
|
|
||||||
adc_oneshot_chan_cfg_t chan_cfg = {
|
|
||||||
.atten = EXAMPLE_ADC_ATTEN,
|
|
||||||
.bitwidth = ADC_BITWIDTH_DEFAULT,
|
|
||||||
};
|
|
||||||
ESP_ERROR_CHECK(adc_oneshot_config_channel(adc2_handle, EXAMPLE_DAC_CHAN0_ADC_CHAN, &chan_cfg));
|
|
||||||
ESP_ERROR_CHECK(adc_oneshot_config_channel(adc2_handle, EXAMPLE_DAC_CHAN1_ADC_CHAN, &chan_cfg));
|
|
||||||
/* Create ADC monitor task to detect the voltage on DAC pin */
|
|
||||||
xTaskCreate(adc_monitor_task, "adc_monitor_task", 4096, adc2_handle, 5, NULL);
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,17 +1,9 @@
|
|||||||
/*
|
/*
|
||||||
* SPDX-FileCopyrightText: 2022-2023 Espressif Systems (Shanghai) CO LTD
|
* SPDX-FileCopyrightText: 2022-2026 Espressif Systems (Shanghai) CO LTD
|
||||||
*
|
*
|
||||||
* SPDX-License-Identifier: CC0-1.0
|
* SPDX-License-Identifier: CC0-1.0
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#include <stdio.h>
|
|
||||||
#include <stdlib.h>
|
|
||||||
#include <math.h>
|
|
||||||
#include <assert.h>
|
|
||||||
#include "freertos/FreeRTOS.h"
|
|
||||||
#include "freertos/task.h"
|
|
||||||
#include "freertos/queue.h"
|
|
||||||
#include "driver/gpio.h"
|
|
||||||
#include "driver/gptimer.h"
|
#include "driver/gptimer.h"
|
||||||
#include "driver/dac_oneshot.h"
|
#include "driver/dac_oneshot.h"
|
||||||
#include "esp_log.h"
|
#include "esp_log.h"
|
||||||
@@ -19,57 +11,32 @@
|
|||||||
|
|
||||||
#define EXAMPLE_TIMER_RESOLUTION 1000000 // 1MHz, 1 tick = 1us
|
#define EXAMPLE_TIMER_RESOLUTION 1000000 // 1MHz, 1 tick = 1us
|
||||||
#define EXAMPLE_WAVE_FREQ_HZ 50 // Default wave frequency 50 Hz, it can't be too high
|
#define EXAMPLE_WAVE_FREQ_HZ 50 // Default wave frequency 50 Hz, it can't be too high
|
||||||
#define EXAMPLE_CONVERT_FREQ_HZ (EXAMPLE_ARRAY_LEN * EXAMPLE_WAVE_FREQ_HZ) // The frequency that DAC convert every data in the wave array
|
#define EXAMPLE_UPDATE_RATE_HZ (EXAMPLE_ARRAY_LEN * EXAMPLE_WAVE_FREQ_HZ) // The frequency at which the DAC samples (codes) are updated
|
||||||
#define EXAMPLE_TIMER_ALARM_COUNT (EXAMPLE_TIMER_RESOLUTION / EXAMPLE_CONVERT_FREQ_HZ) // The count value that trigger the timer alarm callback
|
#define EXAMPLE_TIMER_ALARM_COUNT (EXAMPLE_TIMER_RESOLUTION / EXAMPLE_UPDATE_RATE_HZ) // The count value that trigger the timer alarm callback
|
||||||
|
|
||||||
static const char *TAG = "dac continuous(timer)";
|
|
||||||
static const char wav_name[DAC_WAVE_MAX][15] = {"sine", "triangle", "sawtooth", "square"};
|
|
||||||
static dac_oneshot_handle_t chan0_handle;
|
|
||||||
static dac_oneshot_handle_t chan1_handle;
|
|
||||||
|
|
||||||
extern uint8_t sin_wav[EXAMPLE_ARRAY_LEN]; // Used to store sine wave values
|
|
||||||
extern uint8_t tri_wav[EXAMPLE_ARRAY_LEN]; // Used to store triangle wave values
|
|
||||||
extern uint8_t saw_wav[EXAMPLE_ARRAY_LEN]; // Used to store sawtooth wave values
|
|
||||||
extern uint8_t squ_wav[EXAMPLE_ARRAY_LEN]; // Used to store square wave values
|
|
||||||
|
|
||||||
/* Timer interrupt service routine */
|
/* Timer interrupt service routine */
|
||||||
static bool IRAM_ATTR on_timer_alarm_cb(gptimer_handle_t timer, const gptimer_alarm_event_data_t *edata, void *user_data)
|
static bool IRAM_ATTR on_timer_alarm_cb(gptimer_handle_t timer, const gptimer_alarm_event_data_t *edata, void *user_data)
|
||||||
{
|
{
|
||||||
static uint32_t point_cnt = 0; // For counting the output points of one wave
|
static uint32_t point_cnt = 0; // For counting the output points of one wave
|
||||||
static uint32_t index = 0; // The current index of the wave buffer
|
static uint32_t index = 0; // The current index of the wave buffer
|
||||||
static dac_example_wave_type_t wav_sel = DAC_SINE_WAVE; // Start from sine wave
|
static dac_example_wave_type_t wave_sel = DAC_SINE_WAVE; // Start from sine wave
|
||||||
|
|
||||||
// Switch wave every CONFIG_EXAMPLE_WAVE_PERIOD_SEC second
|
dac_oneshot_handle_t dac_handle = user_data;
|
||||||
if (point_cnt < EXAMPLE_CONVERT_FREQ_HZ * CONFIG_EXAMPLE_WAVE_PERIOD_SEC) {
|
|
||||||
switch (wav_sel) {
|
if (point_cnt == 0) {
|
||||||
case DAC_SINE_WAVE:
|
ESP_EARLY_LOGI(TAG, "%s wave start", wave_name[wave_sel]);
|
||||||
ESP_ERROR_CHECK(dac_oneshot_output_voltage(chan0_handle, sin_wav[index]));
|
}
|
||||||
ESP_ERROR_CHECK(dac_oneshot_output_voltage(chan1_handle, sin_wav[index]));
|
|
||||||
break;
|
dac_example_sample_t code = wave_data[wave_sel][index];
|
||||||
case DAC_TRIANGLE_WAVE:
|
dac_oneshot_output_voltage(dac_handle, code);
|
||||||
ESP_ERROR_CHECK(dac_oneshot_output_voltage(chan0_handle, tri_wav[index]));
|
|
||||||
ESP_ERROR_CHECK(dac_oneshot_output_voltage(chan1_handle, tri_wav[index]));
|
point_cnt++;
|
||||||
break;
|
if (point_cnt < EXAMPLE_UPDATE_RATE_HZ * CONFIG_EXAMPLE_WAVE_PERIOD_SEC) {
|
||||||
case DAC_SAWTOOTH_WAVE:
|
index = (index + 1) % EXAMPLE_ARRAY_LEN;
|
||||||
ESP_ERROR_CHECK(dac_oneshot_output_voltage(chan0_handle, saw_wav[index]));
|
|
||||||
ESP_ERROR_CHECK(dac_oneshot_output_voltage(chan1_handle, saw_wav[index]));
|
|
||||||
break;
|
|
||||||
case DAC_SQUARE_WAVE:
|
|
||||||
ESP_ERROR_CHECK(dac_oneshot_output_voltage(chan0_handle, squ_wav[index]));
|
|
||||||
ESP_ERROR_CHECK(dac_oneshot_output_voltage(chan1_handle, squ_wav[index]));
|
|
||||||
break;
|
|
||||||
default:
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
point_cnt++;
|
|
||||||
index++;
|
|
||||||
index %= EXAMPLE_ARRAY_LEN;
|
|
||||||
} else {
|
} else {
|
||||||
wav_sel++;
|
|
||||||
wav_sel %= DAC_WAVE_MAX;
|
|
||||||
point_cnt = 0;
|
point_cnt = 0;
|
||||||
index = 0;
|
index = 0;
|
||||||
ESP_EARLY_LOGI(TAG, "%s wave start", wav_name[wav_sel]);
|
wave_sel = (wave_sel + 1) % DAC_WAVE_MAX;
|
||||||
}
|
}
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
@@ -83,16 +50,16 @@ void example_dac_continuous_by_timer(void)
|
|||||||
.resolution_hz = EXAMPLE_TIMER_RESOLUTION, // 1MHz, 1 tick = 1us
|
.resolution_hz = EXAMPLE_TIMER_RESOLUTION, // 1MHz, 1 tick = 1us
|
||||||
};
|
};
|
||||||
ESP_ERROR_CHECK(gptimer_new_timer(&timer_config, &gptimer));
|
ESP_ERROR_CHECK(gptimer_new_timer(&timer_config, &gptimer));
|
||||||
dac_oneshot_config_t dac0_cfg = {
|
|
||||||
|
dac_oneshot_handle_t dac_handle = NULL;
|
||||||
|
dac_oneshot_config_t dac_cfg = {
|
||||||
.chan_id = DAC_CHAN_0,
|
.chan_id = DAC_CHAN_0,
|
||||||
};
|
};
|
||||||
ESP_ERROR_CHECK(dac_oneshot_new_channel(&dac0_cfg, &chan0_handle));
|
ESP_ERROR_CHECK(dac_oneshot_new_channel(&dac_cfg, &dac_handle));
|
||||||
dac_oneshot_config_t dac1_cfg = {
|
|
||||||
.chan_id = DAC_CHAN_1,
|
|
||||||
};
|
|
||||||
ESP_ERROR_CHECK(dac_oneshot_new_channel(&dac1_cfg, &chan1_handle));
|
|
||||||
|
|
||||||
example_log_info(EXAMPLE_CONVERT_FREQ_HZ, EXAMPLE_WAVE_FREQ_HZ);
|
example_generate_wave(dac_oneshot_get_bitwidth(dac_handle));
|
||||||
|
|
||||||
|
example_log_info(EXAMPLE_UPDATE_RATE_HZ, EXAMPLE_WAVE_FREQ_HZ);
|
||||||
|
|
||||||
gptimer_alarm_config_t alarm_config = {
|
gptimer_alarm_config_t alarm_config = {
|
||||||
.reload_count = 0,
|
.reload_count = 0,
|
||||||
@@ -102,7 +69,7 @@ void example_dac_continuous_by_timer(void)
|
|||||||
gptimer_event_callbacks_t cbs = {
|
gptimer_event_callbacks_t cbs = {
|
||||||
.on_alarm = on_timer_alarm_cb,
|
.on_alarm = on_timer_alarm_cb,
|
||||||
};
|
};
|
||||||
ESP_ERROR_CHECK(gptimer_register_event_callbacks(gptimer, &cbs, NULL));
|
ESP_ERROR_CHECK(gptimer_register_event_callbacks(gptimer, &cbs, dac_handle));
|
||||||
ESP_ERROR_CHECK(gptimer_set_alarm_action(gptimer, &alarm_config));
|
ESP_ERROR_CHECK(gptimer_set_alarm_action(gptimer, &alarm_config));
|
||||||
ESP_ERROR_CHECK(gptimer_enable(gptimer));
|
ESP_ERROR_CHECK(gptimer_enable(gptimer));
|
||||||
ESP_ERROR_CHECK(gptimer_start(gptimer));
|
ESP_ERROR_CHECK(gptimer_start(gptimer));
|
||||||
|
|||||||
@@ -5,20 +5,12 @@ from pytest_embedded import Dut
|
|||||||
from pytest_embedded_idf.utils import idf_parametrize
|
from pytest_embedded_idf.utils import idf_parametrize
|
||||||
|
|
||||||
|
|
||||||
def test_dac_continuous_output(dut: Dut, mode: str, chan0_io: str, chan1_io: str) -> None:
|
def test_dac_continuous_output(dut: Dut, mode: str) -> None:
|
||||||
dut.expect('dac continuous: --------------------------------------------------', timeout=10)
|
dut.expect(f'signal_generator: DAC continuous output by {mode}', timeout=10)
|
||||||
dut.expect(f'dac continuous: DAC continuous output by {mode}', timeout=10)
|
dut.expect(r'signal_generator: sine wave start', timeout=20)
|
||||||
dut.expect(f'dac continuous: DAC channel 0 io: GPIO_NUM_{chan0_io}', timeout=10)
|
dut.expect(r'signal_generator: triangle wave start', timeout=20)
|
||||||
dut.expect(f'dac continuous: DAC channel 1 io: GPIO_NUM_{chan1_io}', timeout=10)
|
dut.expect(r'signal_generator: sawtooth wave start', timeout=20)
|
||||||
dut.expect('dac continuous: Waveform: SINE -> TRIANGLE -> SAWTOOTH -> SQUARE', timeout=10)
|
dut.expect(r'signal_generator: square wave start', timeout=20)
|
||||||
dut.expect('dac continuous: DAC conversion frequency \\(Hz\\): ([0-9]+)', timeout=10)
|
|
||||||
dut.expect('dac continuous: DAC wave frequency \\(Hz\\): ([0-9]+)', timeout=10)
|
|
||||||
dut.expect('dac continuous: --------------------------------------------------', timeout=10)
|
|
||||||
dut.expect(r'DAC channel 0 value:( +)(\d+)(.*)DAC channel 1 value:( +)(\d+)', timeout=10)
|
|
||||||
dut.expect(rf'dac continuous\({mode}\): sine wave start', timeout=20)
|
|
||||||
dut.expect(rf'dac continuous\({mode}\): triangle wave start', timeout=20)
|
|
||||||
dut.expect(rf'dac continuous\({mode}\): sawtooth wave start', timeout=20)
|
|
||||||
dut.expect(rf'dac continuous\({mode}\): square wave start', timeout=20)
|
|
||||||
|
|
||||||
|
|
||||||
@pytest.mark.generic
|
@pytest.mark.generic
|
||||||
@@ -31,15 +23,9 @@ def test_dac_continuous_output(dut: Dut, mode: str, chan0_io: str, chan1_io: str
|
|||||||
indirect=True,
|
indirect=True,
|
||||||
)
|
)
|
||||||
@idf_parametrize('target', ['esp32', 'esp32s2'], indirect=['target'])
|
@idf_parametrize('target', ['esp32', 'esp32s2'], indirect=['target'])
|
||||||
def test_dac_continuous_example_with_dma(dut: Dut) -> None:
|
def test_dac_continuous_example(dut: Dut) -> None:
|
||||||
sdkconfig = dut.app.sdkconfig
|
sdkconfig = dut.app.sdkconfig
|
||||||
if dut.target == 'esp32':
|
if sdkconfig['EXAMPLE_DAC_CONTINUOUS_BY_DMA']:
|
||||||
if sdkconfig['EXAMPLE_DAC_CONTINUOUS_BY_DMA']:
|
test_dac_continuous_output(dut, 'DMA')
|
||||||
test_dac_continuous_output(dut, 'DMA', '25', '26')
|
else:
|
||||||
else:
|
test_dac_continuous_output(dut, 'timer')
|
||||||
test_dac_continuous_output(dut, 'timer', '25', '26')
|
|
||||||
elif dut.target == 'esp32s2':
|
|
||||||
if sdkconfig['EXAMPLE_DAC_CONTINUOUS_BY_DMA']:
|
|
||||||
test_dac_continuous_output(dut, 'DMA', '17', '18')
|
|
||||||
else:
|
|
||||||
test_dac_continuous_output(dut, 'timer', '17', '18')
|
|
||||||
|
|||||||
@@ -1,7 +1,7 @@
|
|||||||
| Supported Targets | ESP32 | ESP32-S2 |
|
| Supported Targets | ESP32 | ESP32-S2 |
|
||||||
| ----------------- | ----- | -------- |
|
| ----------------- | ----- | -------- |
|
||||||
|
|
||||||
# DAC Constant Example
|
# DAC Cosine Wave Example
|
||||||
|
|
||||||
(See the README.md file in the upper level 'examples' directory for more information about examples.)
|
(See the README.md file in the upper level 'examples' directory for more information about examples.)
|
||||||
|
|
||||||
@@ -9,20 +9,19 @@
|
|||||||
|
|
||||||
This example shows the basic usage of outputting cosine wave by the DAC driver. The cosine wave is generated by the hardware cosine wave generator in the DAC module.
|
This example shows the basic usage of outputting cosine wave by the DAC driver. The cosine wave is generated by the hardware cosine wave generator in the DAC module.
|
||||||
|
|
||||||
This example will output cosine wave on both channels.
|
This example outputs cosine waves on both channels, with opposite phase and different amplitude.
|
||||||
|
|
||||||
## How to use the Example
|
## How to use the Example
|
||||||
|
|
||||||
### Hardware Required
|
### Hardware Required
|
||||||
|
|
||||||
* A development board with ESP32 or ESP32-S2 SoC
|
* A development board with ESP32 or ESP32-S2 SoC
|
||||||
- Note that some ESP32-S2 DevKits have LED on it which is connected to GPIO18 (same pin as DAC channel1), so the output voltage of DAC channel 1 can't go down due the this LED.
|
* DAC channel to GPIO mapping: see [GPIO Summary](https://docs.espressif.com/projects/esp-idf/en/latest/esp32/api-reference/peripherals/gpio.html#gpio-summary) (switch the chip target on the documentation page if needed)
|
||||||
|
* Note that some ESP32-S2 DevKits have an LED on the DAC1 pin, so that channel's output may not go fully low
|
||||||
* (Optional) An oscilloscope to monitor the output wave
|
* (Optional) An oscilloscope to monitor the output wave
|
||||||
|
|
||||||
### Build and Flash
|
### Build and Flash
|
||||||
|
|
||||||
Note that as we use the ADC to monitor the output data, we need to set false to `CONFIG_ADC_DISABLE_DAC_OUTPUT` in the menuconfig, otherwise the ADC will shutdown the DAC power to guarantee it won't be affect by DAC.
|
|
||||||
|
|
||||||
Build the project and flash it to the board, then run monitor tool to view serial output:
|
Build the project and flash it to the board, then run monitor tool to view serial output:
|
||||||
|
|
||||||
```
|
```
|
||||||
@@ -37,29 +36,8 @@ See the Getting Started Guide for full steps to configure and use ESP-IDF to bui
|
|||||||
|
|
||||||
## Example Output
|
## Example Output
|
||||||
|
|
||||||
The DAC channels can be read by ADC channels internally. The ADC read period is 100 ms, the following log is the raw ADC value read from the DAC channels. But since the ADC sample-rate might be lower than the DAC cosine period, the sampling value can only indicate that the voltage is changing.
|
|
||||||
|
|
||||||
```
|
```
|
||||||
DAC channel 0 value: 647 DAC channel 1 value: 1728
|
DAC cosine wave started
|
||||||
DAC channel 0 value: 2112 DAC channel 1 value: 2166
|
|
||||||
DAC channel 0 value: 778 DAC channel 1 value: 2483
|
|
||||||
DAC channel 0 value: 4095 DAC channel 1 value: 1922
|
|
||||||
DAC channel 0 value: 238 DAC channel 1 value: 1282
|
|
||||||
DAC channel 0 value: 3187 DAC channel 1 value: 2609
|
|
||||||
DAC channel 0 value: 627 DAC channel 1 value: 1068
|
|
||||||
DAC channel 0 value: 3168 DAC channel 1 value: 2624
|
|
||||||
DAC channel 0 value: 225 DAC channel 1 value: 1286
|
|
||||||
DAC channel 0 value: 4095 DAC channel 1 value: 2083
|
|
||||||
DAC channel 0 value: 89 DAC channel 1 value: 1934
|
|
||||||
DAC channel 0 value: 3603 DAC channel 1 value: 1434
|
|
||||||
DAC channel 0 value: 725 DAC channel 1 value: 2469
|
|
||||||
DAC channel 0 value: 2277 DAC channel 1 value: 960
|
|
||||||
DAC channel 0 value: 1306 DAC channel 1 value: 2670
|
|
||||||
DAC channel 0 value: 1670 DAC channel 1 value: 899
|
|
||||||
DAC channel 0 value: 3189 DAC channel 1 value: 2609
|
|
||||||
DAC channel 0 value: 86 DAC channel 1 value: 1459
|
|
||||||
DAC channel 0 value: 4095 DAC channel 1 value: 2258
|
|
||||||
...
|
|
||||||
```
|
```
|
||||||
|
|
||||||
If monitoring the DAC channels with an oscilloscope, there will be two cosine waves with opposite phase and different amplitude at 8000 Hz on the two DAC channels.
|
Connect an oscilloscope to the DAC GPIOs to observe two cosine waves with opposite phase and different amplitude at 8000 Hz.
|
||||||
|
|||||||
@@ -1,3 +1,3 @@
|
|||||||
idf_component_register(SRCS "dac_cosine_example_main.c"
|
idf_component_register(SRCS "dac_cosine_example_main.c"
|
||||||
INCLUDE_DIRS "."
|
INCLUDE_DIRS "."
|
||||||
PRIV_REQUIRES esp_driver_dac esp_adc)
|
PRIV_REQUIRES esp_driver_dac)
|
||||||
|
|||||||
@@ -1,41 +1,13 @@
|
|||||||
/*
|
/*
|
||||||
* SPDX-FileCopyrightText: 2022-2023 Espressif Systems (Shanghai) CO LTD
|
* SPDX-FileCopyrightText: 2022-2026 Espressif Systems (Shanghai) CO LTD
|
||||||
*
|
*
|
||||||
* SPDX-License-Identifier: CC0-1.0
|
* SPDX-License-Identifier: CC0-1.0
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#include "freertos/FreeRTOS.h"
|
#include <stdio.h>
|
||||||
#include "freertos/task.h"
|
|
||||||
#include "driver/dac_cosine.h"
|
#include "driver/dac_cosine.h"
|
||||||
#include "esp_adc/adc_oneshot.h"
|
|
||||||
#include "esp_check.h"
|
#include "esp_check.h"
|
||||||
|
|
||||||
#if CONFIG_IDF_TARGET_ESP32
|
|
||||||
#define EXAMPLE_DAC_CHAN0_ADC_CHAN ADC_CHANNEL_8 // GPIO25, same as DAC channel 0
|
|
||||||
#define EXAMPLE_DAC_CHAN1_ADC_CHAN ADC_CHANNEL_9 // GPIO26, same as DAC channel 1
|
|
||||||
#define EXAMPLE_ADC_WIDTH ADC_WIDTH_BIT_12
|
|
||||||
#elif CONFIG_IDF_TARGET_ESP32S2
|
|
||||||
#define EXAMPLE_DAC_CHAN0_ADC_CHAN ADC_CHANNEL_6 // GPIO17, same as DAC channel 0
|
|
||||||
#define EXAMPLE_DAC_CHAN1_ADC_CHAN ADC_CHANNEL_7 // GPIO18, same as DAC channel 1
|
|
||||||
#define EXAMPLE_ADC_WIDTH ADC_WIDTH_BIT_13
|
|
||||||
#endif
|
|
||||||
#define EXAMPLE_ADC_ATTEN ADC_ATTEN_DB_12
|
|
||||||
|
|
||||||
static void adc_monitor_task(void *args)
|
|
||||||
{
|
|
||||||
/* Set the ADC2 channels, these channels are connected to the DAC channels internally */
|
|
||||||
adc_oneshot_unit_handle_t adc2_handle = (adc_oneshot_unit_handle_t)args;
|
|
||||||
int chan0_val = 0;
|
|
||||||
int chan1_val = 0;
|
|
||||||
while (1) {
|
|
||||||
/* Read the DAC output voltage */
|
|
||||||
ESP_ERROR_CHECK(adc_oneshot_read(adc2_handle, EXAMPLE_DAC_CHAN0_ADC_CHAN, &chan0_val));
|
|
||||||
ESP_ERROR_CHECK(adc_oneshot_read(adc2_handle, EXAMPLE_DAC_CHAN1_ADC_CHAN, &chan1_val));
|
|
||||||
printf("DAC channel 0 value: %4d\tDAC channel 1 value: %4d\n", chan0_val, chan1_val);
|
|
||||||
vTaskDelay(pdMS_TO_TICKS(100));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void app_main(void)
|
void app_main(void)
|
||||||
{
|
{
|
||||||
dac_cosine_handle_t chan0_handle;
|
dac_cosine_handle_t chan0_handle;
|
||||||
@@ -62,18 +34,5 @@ void app_main(void)
|
|||||||
ESP_ERROR_CHECK(dac_cosine_start(chan0_handle));
|
ESP_ERROR_CHECK(dac_cosine_start(chan0_handle));
|
||||||
ESP_ERROR_CHECK(dac_cosine_start(chan1_handle));
|
ESP_ERROR_CHECK(dac_cosine_start(chan1_handle));
|
||||||
|
|
||||||
/* Set the ADC2 channels, these channels are connected to the DAC channels internally */
|
printf("DAC cosine wave started\n");
|
||||||
adc_oneshot_unit_handle_t adc2_handle;
|
|
||||||
adc_oneshot_unit_init_cfg_t adc_cfg = {
|
|
||||||
.unit_id = ADC_UNIT_2,
|
|
||||||
.ulp_mode = false,
|
|
||||||
};
|
|
||||||
ESP_ERROR_CHECK(adc_oneshot_new_unit(&adc_cfg, &adc2_handle));
|
|
||||||
adc_oneshot_chan_cfg_t chan_cfg = {
|
|
||||||
.atten = EXAMPLE_ADC_ATTEN,
|
|
||||||
.bitwidth = ADC_BITWIDTH_DEFAULT,
|
|
||||||
};
|
|
||||||
ESP_ERROR_CHECK(adc_oneshot_config_channel(adc2_handle, EXAMPLE_DAC_CHAN0_ADC_CHAN, &chan_cfg));
|
|
||||||
ESP_ERROR_CHECK(adc_oneshot_config_channel(adc2_handle, EXAMPLE_DAC_CHAN1_ADC_CHAN, &chan_cfg));
|
|
||||||
xTaskCreate(adc_monitor_task, "adc_monitor_task", 4096, adc2_handle, 5, NULL);
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,4 +1,4 @@
|
|||||||
# SPDX-FileCopyrightText: 2021-2025 Espressif Systems (Shanghai) CO LTD
|
# SPDX-FileCopyrightText: 2021-2026 Espressif Systems (Shanghai) CO LTD
|
||||||
# SPDX-License-Identifier: CC0-1.0
|
# SPDX-License-Identifier: CC0-1.0
|
||||||
import pytest
|
import pytest
|
||||||
from pytest_embedded import Dut
|
from pytest_embedded import Dut
|
||||||
@@ -6,28 +6,6 @@ from pytest_embedded_idf.utils import idf_parametrize
|
|||||||
|
|
||||||
|
|
||||||
@pytest.mark.generic
|
@pytest.mark.generic
|
||||||
@idf_parametrize('target', ['esp32'], indirect=['target'])
|
@idf_parametrize('target', ['esp32', 'esp32s2'], indirect=['target'])
|
||||||
def test_dac_cosine_wave_example_with_12bit_adc(dut: Dut) -> None:
|
def test_dac_cosine_wave_example(dut: Dut) -> None:
|
||||||
res = []
|
dut.expect_exact('DAC cosine wave started', timeout=10)
|
||||||
for _ in range(30):
|
|
||||||
res.append(dut.expect(r'DAC channel 0 value:( +)(\d+)(.*)DAC channel 1 value:( +)(\d+)', timeout=10))
|
|
||||||
|
|
||||||
chan0_val = []
|
|
||||||
for val in res:
|
|
||||||
chan0_val.append(int(val.group(2)))
|
|
||||||
|
|
||||||
assert max(chan0_val) - min(chan0_val) > 1000
|
|
||||||
|
|
||||||
|
|
||||||
@pytest.mark.generic
|
|
||||||
@idf_parametrize('target', ['esp32s2'], indirect=['target'])
|
|
||||||
def test_dac_cosine_wave_example_with_13bit_adc(dut: Dut) -> None:
|
|
||||||
res = []
|
|
||||||
for _ in range(30):
|
|
||||||
res.append(dut.expect(r'DAC channel 0 value:( +)(\d+)(.*)DAC channel 1 value:( +)(\d+)', timeout=10))
|
|
||||||
|
|
||||||
chan0_val = []
|
|
||||||
for val in res:
|
|
||||||
chan0_val.append(int(val.group(2)))
|
|
||||||
|
|
||||||
assert max(chan0_val) - min(chan0_val) > 3000
|
|
||||||
|
|||||||
@@ -9,20 +9,19 @@
|
|||||||
|
|
||||||
This example shows the oneshot usage of outputting a voltage directly by the DAC driver.
|
This example shows the oneshot usage of outputting a voltage directly by the DAC driver.
|
||||||
|
|
||||||
The output voltage will increase a step every 500 ms, and it will reset to 0 periodically.
|
Both DAC channels ramp the digital code by one eighth of the full-scale range every 500 ms, and wrap back to 0 periodically. Channel 1 starts 500 ms later than channel 0 so the two outputs are staggered.
|
||||||
|
|
||||||
## How to use the Example
|
## How to use the Example
|
||||||
|
|
||||||
### Hardware Required
|
### Hardware Required
|
||||||
|
|
||||||
* A development board with ESP32 or ESP32-S2 SoC
|
* A development board with ESP32 or ESP32-S2 SoC
|
||||||
- Note that some ESP32-S2 DevKits have LED on it which is connected to GPIO18 (same pin as DAC channel1), so the output voltage of DAC channel 1 can't go down due the this LED.
|
* DAC channel to GPIO mapping: see [GPIO Summary](https://docs.espressif.com/projects/esp-idf/en/latest/esp32/api-reference/peripherals/gpio.html#gpio-summary) (switch the chip target on the documentation page if needed)
|
||||||
* (Optional) An oscilloscope to monitor the output wave
|
* Note that some ESP32-S2 DevKits have an LED on the DAC channel 1 pin, so that channel's output may not go fully low
|
||||||
|
* (Optional) An oscilloscope to monitor the output voltage
|
||||||
|
|
||||||
### Build and Flash
|
### Build and Flash
|
||||||
|
|
||||||
Note that as we use the ADC to monitor the output data, we need to set false to `CONFIG_ADC_DISABLE_DAC_OUTPUT` in the menuconfig, otherwise the ADC will shutdown the DAC power to guarantee it won't be affect by DAC.
|
|
||||||
|
|
||||||
Build the project and flash it to the board, then run monitor tool to view serial output:
|
Build the project and flash it to the board, then run monitor tool to view serial output:
|
||||||
|
|
||||||
```
|
```
|
||||||
@@ -37,30 +36,16 @@ See the Getting Started Guide for full steps to configure and use ESP-IDF to bui
|
|||||||
|
|
||||||
## Example Output
|
## Example Output
|
||||||
|
|
||||||
The DAC channels can be read by ADC channels internally. The ADC read period is 100 ms, the following log is the raw ADC value read from the DAC channels, it shows the output voltage is increasing every 500 ms.
|
The example prints the digital code written by each channel. On ESP32 / ESP32-S2 the step is 32:
|
||||||
|
|
||||||
```
|
```
|
||||||
DAC channel 0 value: 37 DAC channel 1 value: 0
|
DAC oneshot example started
|
||||||
DAC channel 0 value: 37 DAC channel 1 value: 0
|
dac_chan0 = 0
|
||||||
DAC channel 0 value: 38 DAC channel 1 value: 0
|
dac_chan0 = 32
|
||||||
DAC channel 0 value: 38 DAC channel 1 value: 0
|
dac_chan1 = 0
|
||||||
DAC channel 0 value: 34 DAC channel 1 value: 0
|
dac_chan0 = 64
|
||||||
DAC channel 0 value: 179 DAC channel 1 value: 117
|
dac_chan1 = 32
|
||||||
DAC channel 0 value: 176 DAC channel 1 value: 117
|
|
||||||
DAC channel 0 value: 178 DAC channel 1 value: 122
|
|
||||||
DAC channel 0 value: 179 DAC channel 1 value: 118
|
|
||||||
DAC channel 0 value: 177 DAC channel 1 value: 115
|
|
||||||
DAC channel 0 value: 316 DAC channel 1 value: 261
|
|
||||||
DAC channel 0 value: 317 DAC channel 1 value: 263
|
|
||||||
DAC channel 0 value: 311 DAC channel 1 value: 261
|
|
||||||
DAC channel 0 value: 317 DAC channel 1 value: 260
|
|
||||||
DAC channel 0 value: 317 DAC channel 1 value: 262
|
|
||||||
DAC channel 0 value: 458 DAC channel 1 value: 406
|
|
||||||
DAC channel 0 value: 456 DAC channel 1 value: 406
|
|
||||||
DAC channel 0 value: 454 DAC channel 1 value: 403
|
|
||||||
DAC channel 0 value: 457 DAC channel 1 value: 406
|
|
||||||
DAC channel 0 value: 459 DAC channel 1 value: 407
|
|
||||||
...
|
...
|
||||||
```
|
```
|
||||||
|
|
||||||
If monitoring the DAC channels with an oscilloscope, there will be a direct voltage on the screen and it will be updated every 500 ms.
|
If monitoring the DAC channels with an oscilloscope, there will be two stepped voltages with a one-period (500 ms) time offset.
|
||||||
|
|||||||
@@ -1,3 +1,3 @@
|
|||||||
idf_component_register(SRCS "dac_oneshot_example_main.c"
|
idf_component_register(SRCS "dac_oneshot_example_main.c"
|
||||||
INCLUDE_DIRS "."
|
INCLUDE_DIRS "."
|
||||||
PRIV_REQUIRES esp_driver_dac esp_adc)
|
PRIV_REQUIRES esp_driver_dac)
|
||||||
|
|||||||
@@ -1,55 +1,32 @@
|
|||||||
/*
|
/*
|
||||||
* SPDX-FileCopyrightText: 2022 Espressif Systems (Shanghai) CO LTD
|
* SPDX-FileCopyrightText: 2022-2026 Espressif Systems (Shanghai) CO LTD
|
||||||
*
|
*
|
||||||
* SPDX-License-Identifier: CC0-1.0
|
* SPDX-License-Identifier: CC0-1.0
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
#include <stdio.h>
|
||||||
#include "freertos/FreeRTOS.h"
|
#include "freertos/FreeRTOS.h"
|
||||||
#include "freertos/task.h"
|
#include "freertos/task.h"
|
||||||
#include "driver/dac_oneshot.h"
|
#include "driver/dac_oneshot.h"
|
||||||
#include "esp_adc/adc_oneshot.h"
|
|
||||||
#include "esp_check.h"
|
#include "esp_check.h"
|
||||||
|
|
||||||
#if CONFIG_IDF_TARGET_ESP32
|
|
||||||
#define EXAMPLE_DAC_CHAN0_ADC_CHAN ADC_CHANNEL_8 // GPIO25, same as DAC channel 0
|
|
||||||
#define EXAMPLE_DAC_CHAN1_ADC_CHAN ADC_CHANNEL_9 // GPIO26, same as DAC channel 1
|
|
||||||
#define EXAMPLE_ADC_WIDTH ADC_WIDTH_BIT_12
|
|
||||||
#elif CONFIG_IDF_TARGET_ESP32S2
|
|
||||||
#define EXAMPLE_DAC_CHAN0_ADC_CHAN ADC_CHANNEL_6 // GPIO17, same as DAC channel 0
|
|
||||||
#define EXAMPLE_DAC_CHAN1_ADC_CHAN ADC_CHANNEL_7 // GPIO18, same as DAC channel 1
|
|
||||||
#define EXAMPLE_ADC_WIDTH ADC_WIDTH_BIT_13
|
|
||||||
#endif
|
|
||||||
#define EXAMPLE_ADC_ATTEN ADC_ATTEN_DB_12
|
|
||||||
|
|
||||||
static void adc_monitor_task(void *args)
|
|
||||||
{
|
|
||||||
adc_oneshot_unit_handle_t adc2_handle = (adc_oneshot_unit_handle_t)args;
|
|
||||||
int chan0_val = 0;
|
|
||||||
int chan1_val = 0;
|
|
||||||
while (1) {
|
|
||||||
/* Read the DAC output voltage */
|
|
||||||
ESP_ERROR_CHECK(adc_oneshot_read(adc2_handle, EXAMPLE_DAC_CHAN0_ADC_CHAN, &chan0_val));
|
|
||||||
ESP_ERROR_CHECK(adc_oneshot_read(adc2_handle, EXAMPLE_DAC_CHAN1_ADC_CHAN, &chan1_val));
|
|
||||||
printf("DAC channel 0 value: %4d\tDAC channel 1 value: %4d\n", chan0_val, chan1_val);
|
|
||||||
vTaskDelay(pdMS_TO_TICKS(100));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
static void dac_output_task(void *args)
|
static void dac_output_task(void *args)
|
||||||
{
|
{
|
||||||
dac_oneshot_handle_t handle = (dac_oneshot_handle_t)args;
|
dac_oneshot_handle_t handle = args;
|
||||||
uint32_t val = 0;
|
const uint16_t full_scale = 1U << dac_oneshot_get_bitwidth(handle);
|
||||||
|
uint16_t val = 0;
|
||||||
while (1) {
|
while (1) {
|
||||||
/* Set the voltage every 100 ms */
|
|
||||||
ESP_ERROR_CHECK(dac_oneshot_output_voltage(handle, val));
|
ESP_ERROR_CHECK(dac_oneshot_output_voltage(handle, val));
|
||||||
val += 10;
|
printf("%s = %u\n", pcTaskGetName(NULL), val);
|
||||||
val %= 250;
|
val = (val + full_scale / 8) % full_scale;
|
||||||
vTaskDelay(pdMS_TO_TICKS(500));
|
vTaskDelay(pdMS_TO_TICKS(500));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void app_main(void)
|
void app_main(void)
|
||||||
{
|
{
|
||||||
|
printf("DAC oneshot example started\n");
|
||||||
|
|
||||||
/* DAC oneshot init */
|
/* DAC oneshot init */
|
||||||
dac_oneshot_handle_t chan0_handle;
|
dac_oneshot_handle_t chan0_handle;
|
||||||
dac_oneshot_config_t chan0_cfg = {
|
dac_oneshot_config_t chan0_cfg = {
|
||||||
@@ -64,23 +41,7 @@ void app_main(void)
|
|||||||
ESP_ERROR_CHECK(dac_oneshot_new_channel(&chan1_cfg, &chan1_handle));
|
ESP_ERROR_CHECK(dac_oneshot_new_channel(&chan1_cfg, &chan1_handle));
|
||||||
|
|
||||||
/* DAC oneshot outputting threads */
|
/* DAC oneshot outputting threads */
|
||||||
xTaskCreate(dac_output_task, "dac_chan0_output_task", 4096, chan0_handle, 5, NULL);
|
xTaskCreate(dac_output_task, "dac_chan0", 4096, chan0_handle, 5, NULL);
|
||||||
vTaskDelay(pdMS_TO_TICKS(500)); // To differential the output of two channels
|
vTaskDelay(pdMS_TO_TICKS(500)); // To differential the output of two channels
|
||||||
xTaskCreate(dac_output_task, "dac_chan1_output_task", 4096, chan1_handle, 5, NULL);
|
xTaskCreate(dac_output_task, "dac_chan1", 4096, chan1_handle, 5, NULL);
|
||||||
|
|
||||||
/* ADC init, these channels are connected to the DAC channels internally */
|
|
||||||
adc_oneshot_unit_handle_t adc2_handle;
|
|
||||||
adc_oneshot_unit_init_cfg_t adc_cfg = {
|
|
||||||
.unit_id = ADC_UNIT_2,
|
|
||||||
.ulp_mode = false,
|
|
||||||
};
|
|
||||||
ESP_ERROR_CHECK(adc_oneshot_new_unit(&adc_cfg, &adc2_handle));
|
|
||||||
adc_oneshot_chan_cfg_t chan_cfg = {
|
|
||||||
.atten = EXAMPLE_ADC_ATTEN,
|
|
||||||
.bitwidth = ADC_BITWIDTH_DEFAULT,
|
|
||||||
};
|
|
||||||
ESP_ERROR_CHECK(adc_oneshot_config_channel(adc2_handle, EXAMPLE_DAC_CHAN0_ADC_CHAN, &chan_cfg));
|
|
||||||
ESP_ERROR_CHECK(adc_oneshot_config_channel(adc2_handle, EXAMPLE_DAC_CHAN1_ADC_CHAN, &chan_cfg));
|
|
||||||
/* ADC monitor thread */
|
|
||||||
xTaskCreate(adc_monitor_task, "adc_monitor_task", 4096, adc2_handle, 5, NULL);
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -8,16 +8,9 @@ from pytest_embedded_idf.utils import idf_parametrize
|
|||||||
@pytest.mark.generic
|
@pytest.mark.generic
|
||||||
@idf_parametrize('target', ['esp32', 'esp32s2'], indirect=['target'])
|
@idf_parametrize('target', ['esp32', 'esp32s2'], indirect=['target'])
|
||||||
def test_dac_oneshot_example(dut: Dut) -> None:
|
def test_dac_oneshot_example(dut: Dut) -> None:
|
||||||
res = []
|
dut.expect_exact('DAC oneshot example started', timeout=10)
|
||||||
for _ in range(10):
|
dut.expect_exact('dac_chan0 = 0', timeout=10)
|
||||||
res.append(dut.expect(r'DAC channel 0 value:( +)(\d+)(.*)DAC channel 1 value:( +)(\d+)', timeout=10))
|
dut.expect_exact('dac_chan1 = 0', timeout=10)
|
||||||
|
# next round
|
||||||
avg1_ch0 = sum(int(val.group(2)) for val in res[0:5]) / 5
|
dut.expect_exact('dac_chan0 = 0', timeout=10)
|
||||||
avg1_ch1 = sum(int(val.group(5)) for val in res[0:5]) / 5
|
dut.expect_exact('dac_chan1 = 0', timeout=10)
|
||||||
avg2_ch0 = sum(int(val.group(2)) for val in res[5:10]) / 5
|
|
||||||
avg2_ch1 = sum(int(val.group(5)) for val in res[5:10]) / 5
|
|
||||||
|
|
||||||
assert avg2_ch0 > avg1_ch0
|
|
||||||
# On ESP32-S2 CI runners, GPIO18 (DAC ch1) has an LED attached. The voltage is clamped.
|
|
||||||
if dut.target != 'esp32s2':
|
|
||||||
assert avg2_ch1 > avg1_ch1
|
|
||||||
|
|||||||
@@ -147,7 +147,6 @@ components_not_formatted_permanent:
|
|||||||
- "/components/soc/*/register/hw_ver*/soc/"
|
- "/components/soc/*/register/hw_ver*/soc/"
|
||||||
# Example resource files (generated)
|
# Example resource files (generated)
|
||||||
- "/examples/peripherals/lcd/i80_controller/main/images/"
|
- "/examples/peripherals/lcd/i80_controller/main/images/"
|
||||||
- "/examples/peripherals/dac/dac_continuous/dac_audio/main/audio_example_file.h"
|
|
||||||
# Coredump (generated)
|
# Coredump (generated)
|
||||||
- /components/espcoredump/include_core_dump/elf.h
|
- /components/espcoredump/include_core_dump/elf.h
|
||||||
# OpenOCD stub binaries (generated)
|
# OpenOCD stub binaries (generated)
|
||||||
|
|||||||
Reference in New Issue
Block a user