mirror of
https://github.com/espressif/esp-idf.git
synced 2025-11-02 16:11:41 +01:00
dac: optimize the dma stratege
This commit is contained in:
263
components/driver/include/driver/dac_conti.h
Normal file
263
components/driver/include/driver/dac_conti.h
Normal file
@@ -0,0 +1,263 @@
|
||||
/*
|
||||
* SPDX-FileCopyrightText: 2019-2022 Espressif Systems (Shanghai) CO LTD
|
||||
*
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "driver/dac_types.h"
|
||||
#include "esp_err.h"
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
#if SOC_DAC_SUPPORTED
|
||||
|
||||
/**
|
||||
* @brief DAC channel mask
|
||||
*
|
||||
*/
|
||||
typedef enum {
|
||||
DAC_CHANNEL_MASK_CH0 = BIT(0), /*!< DAC channel 0 is GPIO25(ESP32) / GPIO17(ESP32S2) */
|
||||
DAC_CHANNEL_MASK_CH1 = BIT(1), /*!< DAC channel 1 is GPIO26(ESP32) / GPIO18(ESP32S2) */
|
||||
DAC_CHANNEL_MASK_ALL = BIT(0) | BIT(1), /*!< Both DAC channel 0 and channel 1 */
|
||||
} dac_channel_mask_t;
|
||||
|
||||
typedef struct dac_conti_s *dac_conti_handle_t; /*!< DAC continuous channel handle */
|
||||
|
||||
/**
|
||||
* @brief DAC continuous channels' configurations
|
||||
*
|
||||
*/
|
||||
typedef struct {
|
||||
dac_channel_mask_t chan_mask; /*!< DAC channels' mask for selecting which channels are used */
|
||||
uint32_t desc_num; /*!< The number of DMA descriptor, at least 2 descriptors are required
|
||||
* The number of descriptors is directly proportional to the max data buffer size while converting in cyclic output
|
||||
* but only need to ensure it is greater than '1' in acyclic output
|
||||
* Typically, suggest to set the number bigger than 5, in case the DMA stopped while sending a short buffer
|
||||
*/
|
||||
size_t buf_size; /*!< The DMA buffer size, should be within 32~4092 bytes. Each DMA buffer will be attached to a DMA descriptor,
|
||||
* i.e. the number of DMA buffer will be equal to the DMA descriptor number
|
||||
* The DMA buffer size is not allowed to be greater than 4092 bytes
|
||||
* The total DMA buffer size equal to `desc_num * buf_size`
|
||||
* Typically, suggest to set the size to the multiple of 4
|
||||
*/
|
||||
uint32_t freq_hz; /*!< The frequency of DAC conversion in continuous mode, unit: Hz
|
||||
* The supported range is related to the target and the clock source.
|
||||
* For the clock `DAC_DIGI_CLK_SRC_DEFAULT`: the range is 19.6 KHz to several MHz on ESP32
|
||||
* and 77 Hz to several MHz on ESP32-S2.
|
||||
* For the clock `DAC_DIGI_CLK_SRC_APLL`: the range is 648 Hz to several MHz on ESP32
|
||||
* and 6 Hz to several MHz on ESP32-S2.
|
||||
* Typically not suggest to set the frequency higher than 2 MHz, otherwise the severe distortion will appear
|
||||
*/
|
||||
int8_t offset; /*!< The offset of the DAC digital data. Range -128~127 */
|
||||
dac_conti_digi_clk_src_t clk_src; /*!< The clock source of digital controller, which can affect the range of supported frequency
|
||||
* Currently `DAC_DIGI_CLK_SRC_DEFAULT` and `DAC_DIGI_CLK_SRC_APLL` are available
|
||||
*/
|
||||
dac_conti_channel_mode_t chan_mode; /*!< The channel mode of continuous mode, only take effect when multiple channels enabled, depends converting the buffer alternately or simultaneously */
|
||||
} dac_conti_config_t;
|
||||
|
||||
|
||||
/**
|
||||
* @brief Event structure used in DAC event queue
|
||||
*/
|
||||
typedef struct {
|
||||
void *buf; /*!< The pointer of DMA buffer that just finished sending */
|
||||
size_t buf_size; /*!< The writable buffer size of the DMA buffer, equal to 'dac_conti_config_t::buf_size' */
|
||||
size_t write_bytes; /*!< The number of bytes that be written successfully */
|
||||
} dac_event_data_t;
|
||||
|
||||
/**
|
||||
* @brief DAC event callback
|
||||
* @param[in] handle DAC channel handle, created from `dac_new_conti_channels()`
|
||||
* @param[in] event DAC event data
|
||||
* @param[in] user_data User registered context, passed from `dac_conti_register_event_callback()`
|
||||
*
|
||||
* @return Whether a high priority task has been waken up by this callback function
|
||||
*/
|
||||
typedef bool (*dac_isr_callback_t)(dac_conti_handle_t handle, const dac_event_data_t *event, void *user_data);
|
||||
|
||||
/**
|
||||
* @brief Group of DAC callbacks
|
||||
* @note The callbacks are all running under ISR environment
|
||||
* @note When CONFIG_DAC_ISR_IRAM_SAFE is enabled, the callback itself and functions called by it should be placed in IRAM.
|
||||
* The variables used in the function should be in the SRAM as well.
|
||||
*/
|
||||
typedef struct {
|
||||
dac_isr_callback_t on_convert_done; /**< Callback of data conversion done event
|
||||
* An event data buffer previously loaded to the driver has been output and converted.
|
||||
* The event data includes DMA buffer address and size that just finished converting.
|
||||
*/
|
||||
dac_isr_callback_t on_stop; /**< Callback of finished sending all the data.
|
||||
* All loaded event data buffers are converted. Driver is pending for new data buffers to be loaded.
|
||||
* The event data will be NULL in this callback.
|
||||
*/
|
||||
} dac_event_callbacks_t;
|
||||
|
||||
|
||||
/**
|
||||
* @brief Allocate new DAC channels in continuous mode
|
||||
* @note The DAC channels can't be registered to continuous mode separately
|
||||
*
|
||||
* @param[in] conti_cfg Continuous mode configuration
|
||||
* @param[out] ret_handle The returned continuous mode handle
|
||||
* @return
|
||||
* - ESP_ERR_INVALID_ARG The input parameter is invalid
|
||||
* - ESP_ERR_INVALID_STATE The DAC channel has been registered already
|
||||
* - ESP_ERR_NOT_FOUND Not found the available dma peripheral, might be occupied
|
||||
* - ESP_ERR_NO_MEM No memory for the DAC continuous mode resources
|
||||
* - ESP_OK Allocate the new DAC continuous mode success
|
||||
*/
|
||||
esp_err_t dac_new_conti_channels(const dac_conti_config_t *conti_cfg, dac_conti_handle_t *ret_handle);
|
||||
|
||||
/**
|
||||
* @brief Delete the DAC continuous handle
|
||||
*
|
||||
* @param[in] handle The DAC continuous channel handle that obtained from 'dac_new_conti_channels'
|
||||
* @return
|
||||
* - ESP_ERR_INVALID_ARG The input parameter is invalid
|
||||
* - ESP_ERR_INVALID_STATE The channels have already been deregistered or not disabled
|
||||
* - ESP_OK Delete the continuous channels success
|
||||
*/
|
||||
esp_err_t dac_del_conti_channels(dac_conti_handle_t handle);
|
||||
|
||||
/**
|
||||
* @brief Enabled the DAC continuous mode
|
||||
* @note Must enable the channels before
|
||||
*
|
||||
* @param[in] handle The DAC continuous channel handle that obtained from 'dac_new_conti_channels'
|
||||
* @return
|
||||
* - ESP_ERR_INVALID_ARG The input parameter is invalid
|
||||
* - ESP_ERR_INVALID_STATE The channels have been enabled already
|
||||
* - ESP_OK Enable the continuous output success
|
||||
*/
|
||||
esp_err_t dac_conti_enable(dac_conti_handle_t handle);
|
||||
|
||||
/**
|
||||
* @brief Disable the DAC continuous mode
|
||||
*
|
||||
* @param[in] handle The DAC continuous channel handle that obtained from 'dac_new_conti_channels'
|
||||
* @return
|
||||
* - ESP_ERR_INVALID_ARG The input parameter is invalid
|
||||
* - ESP_ERR_INVALID_STATE The channels have been enabled already
|
||||
* - ESP_OK Disable the continuous output success
|
||||
*/
|
||||
esp_err_t dac_conti_disable(dac_conti_handle_t handle);
|
||||
|
||||
/**
|
||||
* @brief Write DAC continuous data cyclically
|
||||
* @note The data in buffer will be converted cyclically using DMA once this function is called,
|
||||
* This function will return once the data loaded into DMA buffers.
|
||||
* @note The buffer size of cyclically output is limited by the descriptor number and
|
||||
* dma buffer size while initializing the continuous mode.
|
||||
* Concretely, in order to load all the data into descriptors,
|
||||
* the cyclic buffer size is not supposed to be greater than `desc_num * buf_size`
|
||||
* @note Specially, on ESP32, the data bit width of DAC continuous data is fixed to 16 bits while only the high 8 bits are available,
|
||||
* The driver will help to expand the inputted buffer automatically by default,
|
||||
* you can also align the data to 16 bits manually by clearing `CONFIG_DAC_DMA_AUTO_16BIT_ALIGN` in menuconfig.
|
||||
*
|
||||
* @param[in] handle The DAC continuous channel handle that obtained from 'dac_new_conti_channels'
|
||||
* @param[in] buf The digital data buffer to convert
|
||||
* @param[in] buf_size The buffer size of digital data buffer
|
||||
* @param[out] bytes_loaded The bytes that has been loaded into DMA buffer, can be NULL if don't need it
|
||||
* @return
|
||||
* - ESP_ERR_INVALID_ARG The input parameter is invalid
|
||||
* - ESP_ERR_INVALID_STATE The DAC continuous mode has not been enabled yet
|
||||
* - ESP_OK Success to output the acyclic DAC data
|
||||
*/
|
||||
esp_err_t dac_conti_write_cyclically(dac_conti_handle_t handle, uint8_t *buf, size_t buf_size, size_t *bytes_loaded);
|
||||
|
||||
/**
|
||||
* @brief Write DAC data continuously
|
||||
* @note The data in buffer will only be converted one time,
|
||||
* This function will be blocked until all data loaded or timeout
|
||||
* then the DAC output will keep outputting the voltage of the last data in the buffer
|
||||
* @note Specially, on ESP32, the data bit width of DAC continuous data is fixed to 16 bits while only the high 8 bits are available,
|
||||
* The driver will help to expand the inputted buffer automatically by default,
|
||||
* you can also align the data to 16 bits manually by clearing `CONFIG_DAC_DMA_AUTO_16BIT_ALIGN` in menuconfig.
|
||||
*
|
||||
* @param[in] handle The DAC continuous channel handle that obtained from 'dac_new_conti_channels'
|
||||
* @param[in] buf The digital data buffer to convert
|
||||
* @param[in] buf_size The buffer size of digital data buffer
|
||||
* @param[out] bytes_loaded The bytes that has been loaded into DMA buffer, can be NULL if don't need it
|
||||
* @param[in] timeout_ms The timeout time in millisecond, set a minus value means will block forever
|
||||
* @return
|
||||
* - ESP_ERR_INVALID_ARG The input parameter is invalid
|
||||
* - ESP_ERR_INVALID_STATE The DAC continuous mode has not been enabled yet
|
||||
* - ESP_ERR_TIMEOUT Waiting for semaphore or message queue timeout
|
||||
* - ESP_OK Success to output the acyclic DAC data
|
||||
*/
|
||||
esp_err_t dac_conti_write(dac_conti_handle_t handle, uint8_t *buf, size_t buf_size, size_t *bytes_loaded, int timeout_ms);
|
||||
|
||||
/**
|
||||
* @brief Set event callbacks for DAC continuous mode
|
||||
*
|
||||
* @note User can deregister a previously registered callback by calling this function and setting the callback member in the `callbacks` structure to NULL.
|
||||
* @note When CONFIG_DAC_ISR_IRAM_SAFE is enabled, the callback itself and functions called by it should be placed in IRAM.
|
||||
* The variables used in this function, including the `user_data`, should be in the internal RAM as well.
|
||||
*
|
||||
* @param[in] handle The DAC continuous channel handle that obtained from 'dac_new_conti_channels'
|
||||
* @param[in] callbacks Group of callback functions, input NULL to clear the former callbacks
|
||||
* @param[in] user_data User data, which will be passed to callback functions directly
|
||||
* @return
|
||||
* - ESP_OK Set event callbacks successfully
|
||||
* - ESP_ERR_INVALID_ARG Set event callbacks failed because of invalid argument
|
||||
*/
|
||||
esp_err_t dac_conti_register_event_callback(dac_conti_handle_t handle, const dac_event_callbacks_t *callbacks, void *user_data);
|
||||
|
||||
/**
|
||||
* @brief Start the async writing
|
||||
* @note When the asynchronous writing start, the DAC will keep outputting '0' until the data are loaded into the DMA buffer.
|
||||
* To loaded the data into DMA buffer, 'on_convert_done' callback is required,
|
||||
* which can be registered by 'dac_conti_register_event_callback' before enabling
|
||||
*
|
||||
* @param[in] handle The DAC continuous channel handle that obtained from 'dac_new_conti_channels'
|
||||
* @return
|
||||
* - ESP_OK Start asynchronous writing successfully
|
||||
* - ESP_ERR_INVALID_ARG The handle is NULL
|
||||
* - ESP_ERR_INVALID_STATE The channel is not enabled or the 'on_convert_done' callback is not registered
|
||||
*/
|
||||
esp_err_t dac_conti_start_async_writing(dac_conti_handle_t handle);
|
||||
|
||||
/**
|
||||
* @brief Stop the sync writing
|
||||
*
|
||||
* @param[in] handle The DAC continuous channel handle that obtained from 'dac_new_conti_channels'
|
||||
* @return
|
||||
* - ESP_OK Stop asynchronous writing successfully
|
||||
* - ESP_ERR_INVALID_ARG The handle is NULL
|
||||
* - ESP_ERR_INVALID_STATE Asynchronous writing has not started
|
||||
*/
|
||||
esp_err_t dac_conti_stop_async_writing(dac_conti_handle_t handle);
|
||||
|
||||
/**
|
||||
* @brief Write DAC data asynchronously
|
||||
* @note This function can be called when the asynchronous writing started, and it can be called in the callback directly
|
||||
* but recommend to writing data in a task, referring to :example:`peripherals/dac/dac_continuous/dac_audio`
|
||||
*
|
||||
* @param[in] handle The DAC continuous channel handle that obtained from 'dac_new_conti_channels'
|
||||
* @param[in] dma_buf The DMA buffer address, it can be acquired from 'dac_event_data_t' in the 'on_convert_done' callback
|
||||
* @param[in] dma_buf_len The DMA buffer length, it can be acquired from 'dac_event_data_t' in the 'on_convert_done' callback
|
||||
* @param[in] data The data that need to be written
|
||||
* @param[in] data_len The data length the need to be written
|
||||
* @param[out] bytes_loaded The bytes number that has been loaded/written into the DMA buffer
|
||||
* @return
|
||||
* - ESP_OK Write the data into DMA buffer successfully
|
||||
* - ESP_ERR_INVALID_ARG NULL pointer
|
||||
* - ESP_ERR_INVALID_STATE The channels haven't start the asynchronous writing
|
||||
* - ESP_ERR_NOT_FOUND The param 'dam_buf' not match any existed DMA buffer
|
||||
*/
|
||||
esp_err_t dac_conti_write_asynchronously(dac_conti_handle_t handle,
|
||||
uint8_t *dma_buf,
|
||||
size_t dma_buf_len,
|
||||
const uint8_t *data,
|
||||
size_t data_len,
|
||||
size_t *bytes_loaded);
|
||||
|
||||
#endif // SOC_DAC_SUPPORTED
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
97
components/driver/include/driver/dac_cosine.h
Normal file
97
components/driver/include/driver/dac_cosine.h
Normal file
@@ -0,0 +1,97 @@
|
||||
/*
|
||||
* SPDX-FileCopyrightText: 2019-2022 Espressif Systems (Shanghai) CO LTD
|
||||
*
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "driver/dac_types.h"
|
||||
#include "esp_err.h"
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
#if SOC_DAC_SUPPORTED
|
||||
|
||||
typedef struct dac_cosine_s *dac_cosine_handle_t; /*!< DAC cosine wave channel handle */
|
||||
|
||||
/**
|
||||
* @brief DAC cosine channel configurations
|
||||
*
|
||||
*/
|
||||
typedef struct {
|
||||
dac_channel_t chan_id; /*!< The cosine wave channel id */
|
||||
uint32_t freq_hz; /*!< The frequency of cosine wave, unit: Hz.
|
||||
* The cosine wave generator is driven by RTC_FAST clock which is divide from RC_FAST,
|
||||
* With the default RTC clock, the minimum frequency of cosine wave is about 130 Hz,
|
||||
* Although it can support up to several MHz frequency theoretically,
|
||||
* the waveform will distort at high frequency due to the hardware limitation.
|
||||
* Typically not suggest to set the frequency higher than 200 KHz
|
||||
*/
|
||||
dac_cosine_clk_src_t clk_src; /*!< The clock source of the cosine wave generator, currently only support `DAC_COSINE_CLK_SRC_DEFAULT` */
|
||||
dac_cosine_atten_t atten; /*!< The attenuation of cosine wave amplitude */
|
||||
dac_cosine_phase_t phase; /*!< The phase of cosine wave, can only support DAC_COSINE_PHASE_0 or DAC_COSINE_PHASE_180, default as 0 while setting an unsupported phase */
|
||||
int8_t offset; /*!< The DC offset of cosine wave */
|
||||
struct {
|
||||
bool force_set_freq: 1; /*!< Force to set the cosine wave frequency */
|
||||
} flags; /*!< Flags of cosine mode */
|
||||
} dac_cosine_config_t;
|
||||
|
||||
/**
|
||||
* @brief Allocate a new DAC cosine wave channel
|
||||
* @note Since there is only one cosine wave generator,
|
||||
* only the first channel can set the frequency of the cosine wave.
|
||||
* Normally, the latter one is not allowed to set a different frequency,
|
||||
* but the it can be forced to set by setting the bit `force_set_freq` in the configuration,
|
||||
* notice that another channel will be affected as well when the frequency is updated.
|
||||
*
|
||||
* @param[in] cos_cfg The configuration of cosine wave channel
|
||||
* @param[out] ret_handle The returned cosine wave channel handle
|
||||
* @return
|
||||
* - ESP_ERR_INVALID_ARG The input parameter is invalid
|
||||
* - ESP_ERR_INVALID_STATE The DAC channel has been registered already
|
||||
* - ESP_ERR_NO_MEM No memory for the DAC cosine wave channel resources
|
||||
* - ESP_OK Allocate the new DAC cosine wave channel success
|
||||
*/
|
||||
esp_err_t dac_new_cosine_channel(const dac_cosine_config_t *cos_cfg, dac_cosine_handle_t *ret_handle);
|
||||
|
||||
/**
|
||||
* @brief Delete the DAC cosine wave channel
|
||||
*
|
||||
* @param[in] handle The DAC cosine wave channel handle
|
||||
* @return
|
||||
* - ESP_ERR_INVALID_ARG The input parameter is invalid
|
||||
* - ESP_ERR_INVALID_STATE The channel has already been deregistered
|
||||
* - ESP_OK Delete the cosine wave channel success
|
||||
*/
|
||||
esp_err_t dac_del_cosine_channel(dac_cosine_handle_t handle);
|
||||
|
||||
/**
|
||||
* @brief Start outputting the cosine wave on the channel
|
||||
*
|
||||
* @param[in] handle The DAC cosine wave channel handle
|
||||
* @return
|
||||
* - ESP_ERR_INVALID_ARG The input parameter is invalid
|
||||
* - ESP_ERR_INVALID_STATE The channel has been started already
|
||||
* - ESP_OK Start the cosine wave success
|
||||
*/
|
||||
esp_err_t dac_cosine_start(dac_cosine_handle_t handle);
|
||||
|
||||
/**
|
||||
* @brief Stop outputting the cosine wave on the channel
|
||||
*
|
||||
* @param[in] handle The DAC cosine wave channel handle
|
||||
* @return
|
||||
* - ESP_ERR_INVALID_ARG The input parameter is invalid
|
||||
* - ESP_ERR_INVALID_STATE The channel has been stopped already
|
||||
* - ESP_OK Stop the cosine wave success
|
||||
*/
|
||||
esp_err_t dac_cosine_stop(dac_cosine_handle_t handle);
|
||||
|
||||
#endif // SOC_DAC_SUPPORTED
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
@@ -1,298 +0,0 @@
|
||||
/*
|
||||
* SPDX-FileCopyrightText: 2019-2022 Espressif Systems (Shanghai) CO LTD
|
||||
*
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "driver/dac_types.h"
|
||||
#include "driver/gpio.h"
|
||||
#include "esp_err.h"
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
#if SOC_DAC_SUPPORTED
|
||||
|
||||
/**
|
||||
* @brief DAC channel configuration
|
||||
*
|
||||
*/
|
||||
typedef struct {
|
||||
dac_channel_mask_t chan_sel; /*!< Using DAC channel mask to select the channels */
|
||||
} dac_channels_config_t;
|
||||
|
||||
/**
|
||||
* @brief DAC continuous mode configration
|
||||
*
|
||||
*/
|
||||
typedef struct {
|
||||
uint32_t freq_hz; /*!< The frequency of DAC conversion in continuous mode, unit: Hz
|
||||
* The supported range is related to the target and the clock source.
|
||||
* For the clock `DAC_DIGI_CLK_SRC_DEFAULT`: the range is 19.6 KHz to several MHz on ESP32
|
||||
* and 77 Hz to several MHz on ESP32-S2.
|
||||
* For the clock `DAC_DIGI_CLK_SRC_APLL`: the range is 648 Hz to several MHz on ESP32
|
||||
* and 6 Hz to several MHz on ESP32-S2.
|
||||
* Typically not suggest to set the frequency higher than 2 MHz, otherwise the severe distortion will appear
|
||||
*/
|
||||
dac_conti_clk_src_t clk_src; /*!< The clock source of digital controller, which can affect the range of supported frequency
|
||||
* Currently `DAC_DIGI_CLK_SRC_DEFAULT` and `DAC_DIGI_CLK_SRC_APLL` are available
|
||||
*/
|
||||
uint32_t desc_num; /*!< The number of DMA descriptor, at least 2 descriptors are required
|
||||
* The number of descriptors is directly proportional to the max data buffer size while converting in cyclic output
|
||||
* but only need to ensure it is greater than '1' in acyclic output
|
||||
* Typically, suggest to set the number bigger than 5, in case the DMA stopped while sending a short buffer
|
||||
*/
|
||||
uint32_t buf_size; /*!< The DMA buffer size, should be within 4092 bytes. Each DMA buffer will be attached to a DMA descriptor,
|
||||
* i.e. the number of DMA buffer will be equal to the DMA descriptor number
|
||||
* The DMA buffer size is not allowed to be greater than 4092 bytes
|
||||
* The total DMA buffer size equal to `desc_num * buf_size`
|
||||
* Typically, suggest to set the size to the multiple of 4
|
||||
*/
|
||||
dac_conti_channel_mode_t chan_mode; /*!< The channel mode of continuous mode, only take effect when multiple channels enabled, depends converting the buffer alternately or simultaneously */
|
||||
} dac_conti_config_t;
|
||||
|
||||
/**
|
||||
* @brief DAC cosine wave gnerator configuration
|
||||
*
|
||||
*/
|
||||
typedef struct {
|
||||
uint32_t freq_hz; /*!< The frequency of cosine wave, unit: Hz.
|
||||
* The cosine wave generator is driven by RTC clock which is about SOC_CLK_RC_FAST_FREQ_APPROX Hz by default,
|
||||
* With the default RTC clock, the minimun frequency of cosine wave is about 130 Hz,
|
||||
* Although it can support up to serveral MHz frequency theoretically,
|
||||
* the waveform will distort at high frequency due to the hardware limitation.
|
||||
* Typically not suggest to set the frequency higher than 200 KHz
|
||||
*/
|
||||
dac_cosine_clk_src_t clk_src; /*!< The clock source of the cosine wave generator, currently only support `DAC_COSINE_CLK_SRC_DEFAULT` which comes from RTC FAST clock */
|
||||
dac_cosine_scale_t scale; /*!< The scale of cosine wave amplitude */
|
||||
dac_cosine_phase_t phase; /*!< The phase of cosine wave */
|
||||
int8_t offset; /*!< The DC offset of cosine wave */
|
||||
} dac_cosine_config_t;
|
||||
|
||||
typedef struct dac_channels_s *dac_channels_handle_t; /*!< DAC channels' handle of DAC peripheral, one or multiple DAC channels can be controlled by this handle */
|
||||
|
||||
/*--------------------------------------------------------------------------
|
||||
DAC common APIs
|
||||
---------------------------------------------------------------------------*/
|
||||
/**
|
||||
* @brief Allocate a new DAC channels' handle
|
||||
* @note The driver supports to manage one single channel by enabling only one channel in the channel mask,
|
||||
* or multiple channels together as a whole by enabling multiple channels in the channel mask.
|
||||
* Moreover, the channels can also be managed separately if they are allocated separately.
|
||||
*
|
||||
* @param[in] dac_cfg DAC basic configuration
|
||||
* @param[out] handle DAC channels handle
|
||||
* @return
|
||||
* - ESP_ERR_INVALID_ARG The input parameter is invalid
|
||||
* - ESP_ERR_NO_MEM No memory for a new DAC handle
|
||||
* - ESP_ERR_INVALID_STATE The specified DAC channel is occupied already
|
||||
* - ESP_OK Success to allocate DAC channels
|
||||
*/
|
||||
esp_err_t dac_new_channels(const dac_channels_config_t *dac_cfg, dac_channels_handle_t *handle);
|
||||
|
||||
/**
|
||||
* @brief Delete and free the DAC channels
|
||||
*
|
||||
* @param[in] handle DAC channels handle
|
||||
* @return
|
||||
* - ESP_ERR_INVALID_ARG The input parameter is invalid
|
||||
* - ESP_ERR_INVALID_STATE The channels are not disabled
|
||||
* - ESP_OK Success to delete the channels
|
||||
*/
|
||||
esp_err_t dac_del_channels(dac_channels_handle_t handle);
|
||||
|
||||
/**
|
||||
* @brief Enabled the DAC channels in the channels
|
||||
* @note GPIOs of DAC channles will be enabled in this step
|
||||
*
|
||||
* @param[in] handle DAC channels handle
|
||||
* @return
|
||||
* - ESP_ERR_INVALID_ARG The input parameter is invalid
|
||||
* - ESP_ERR_INVALID_STATE The channels has enabled already or the channels are running
|
||||
* - ESP_OK Success to enable the channels
|
||||
*/
|
||||
esp_err_t dac_channels_enable(dac_channels_handle_t handle);
|
||||
|
||||
/**
|
||||
* @brief Disable the DAC channels in the channels
|
||||
*
|
||||
* @param[in] handle DAC channels handle
|
||||
* @return
|
||||
* - ESP_ERR_INVALID_ARG The input parameter is invalid
|
||||
* - ESP_ERR_INVALID_STATE The channels has disabled already or the channels are running
|
||||
* - ESP_OK Success to enable the channels
|
||||
*/
|
||||
esp_err_t dac_channels_disable(dac_channels_handle_t handle);
|
||||
|
||||
/*--------------------------------------------------------------------------
|
||||
DAC direct voltage outputting APIs
|
||||
---------------------------------------------------------------------------*/
|
||||
/**
|
||||
* @brief DAC channels output a voltage directly
|
||||
* @note This function is available when DAC chennels is enbled
|
||||
* @note Please enable 'DAC ISR IRAM-Safe' in memuconfig when it is called in an IRAM safe ISR
|
||||
*
|
||||
* @param[in] handle DAC channels handle
|
||||
* @param[in] value The digital value of the voltage
|
||||
* @return
|
||||
* - ESP_ERR_INVALID_ARG The input parameter is invalid
|
||||
* - ESP_ERR_INVALID_STATE The channels are not enabled
|
||||
* - ESP_OK Success to enable the channels
|
||||
*/
|
||||
esp_err_t dac_channels_set_voltage(dac_channels_handle_t handle, uint8_t value);
|
||||
|
||||
/*--------------------------------------------------------------------------
|
||||
DAC continuous outputting APIs
|
||||
---------------------------------------------------------------------------*/
|
||||
/**
|
||||
* @brief Initialize the DAC channels to continuous mode
|
||||
* @note DAC can convert digital data continuously in continuous mode
|
||||
*
|
||||
* @param[in] handle DAC channels handle
|
||||
* @param[in] conti_cfg DAC continuous mode configuration
|
||||
* @return
|
||||
* - ESP_ERR_INVALID_ARG The input parameter is invalid
|
||||
* - ESP_ERR_INVALID_STATE The DAC channels has been initialized already
|
||||
* - ESP_ERR_NO_MEM No memory for DAC continuous mode
|
||||
* - ESP_OK Success to initializing the DAC channels to continuous mode
|
||||
*/
|
||||
esp_err_t dac_channels_init_continuous_mode(dac_channels_handle_t handle, const dac_conti_config_t *conti_cfg);
|
||||
|
||||
/**
|
||||
* @brief Deinitialize the continuous mode of the DAC channels
|
||||
* @note It can only be deinitialized when the continuous output is disabled
|
||||
*
|
||||
* @param[in] handle DAC channels handle
|
||||
* @return
|
||||
* - ESP_ERR_INVALID_ARG The input parameter is invalid
|
||||
* - ESP_ERR_INVALID_STATE The DAC continuous mode is not disabled yet
|
||||
* - ESP_OK Success to deinitialize the DAC continuous mode
|
||||
*/
|
||||
esp_err_t dac_channels_deinit_continuous_mode(dac_channels_handle_t handle);
|
||||
|
||||
/**
|
||||
* @brief Enable the DAC continuous output
|
||||
*
|
||||
* @param[in] handle DAC channels handle
|
||||
* @return
|
||||
* - ESP_ERR_INVALID_ARG The input parameter is invalid
|
||||
* - ESP_ERR_INVALID_STATE The DAC continuous mode has been enabled already
|
||||
* - ESP_OK Success to start the continuous output
|
||||
*/
|
||||
esp_err_t dac_channels_enable_continuous_mode(dac_channels_handle_t handle);
|
||||
|
||||
/**
|
||||
* @brief Disable the DAC continuous output
|
||||
*
|
||||
* @param[in] handle DAC channels handle
|
||||
* @return
|
||||
* - ESP_ERR_INVALID_ARG The input parameter is invalid
|
||||
* - ESP_ERR_INVALID_STATE The DAC continuous mode is disabled already
|
||||
* - ESP_OK Success to stop the continuous output
|
||||
*/
|
||||
esp_err_t dac_channels_disable_continuous_mode(dac_channels_handle_t handle);
|
||||
|
||||
/**
|
||||
* @brief Write DAC continuous data continuously
|
||||
* @note The data in buffer will only be converted one time,
|
||||
* This function will be blocked until all data loaded or timeout
|
||||
* then the DAC output will keep outputting the voltage of the last data in the buffer
|
||||
* @note On ESP32, the data bit width of DAC continuous data is fixed to 16 bits while only the high 8 bits are available,
|
||||
* you can align the DAC data to 16 bits manually or set `CONFIG_DAC_DMA_AUTO_16BIT_ALIGN` to get the correct wave.
|
||||
* But the data bit width is already 8 bits on ESP32-S2, each byte stands for an vailable voltage,
|
||||
* no need to do any alignment.
|
||||
*
|
||||
* @param[in] handle DAC channels handle
|
||||
* @param[in] buf The digital data buffer to convert
|
||||
* @param[in] buf_size The buffer size of digital data buffer
|
||||
* @param[out] bytes_loaded The bytes that has been loaded into DMA buffer, can be NULL if don't need it
|
||||
* @param[in] timeout_ms The timeout time in mili-second
|
||||
* @return
|
||||
* - ESP_ERR_INVALID_ARG The input parameter is invalid
|
||||
* - ESP_ERR_INVALID_STATE The DAC continuous mode has not been enabled yet
|
||||
* - ESP_ERR_TIMEOUT Waiting for semaphore or message queue timeout
|
||||
* - ESP_OK Success to output the acyclic DAC data
|
||||
*/
|
||||
esp_err_t dac_channels_write_continuously(dac_channels_handle_t handle, uint8_t *buf, size_t buf_size, size_t *bytes_loaded, uint32_t timeout_ms);
|
||||
|
||||
/**
|
||||
* @brief Write DAC continuous data cyclically
|
||||
* @note The data in buffer will be converted cyclically once this function is called,
|
||||
* This function won't be blocked, it will return once the data loaded into DMA buffers
|
||||
* @note The buffer size of cyclically output is limited by the descriptor number while initializing the continuous mode,
|
||||
* Concretely, in order to load all the data into descriptors,
|
||||
* the cyclic buffer size is not supposed to be greater than `desc_num * 4092`
|
||||
* @note On ESP32, the data bit width of DAC continuous data is fixed to 16 bits while only the high 8 bits are available,
|
||||
* you can align the DAC data to 16 bits manually or set `CONFIG_DAC_DMA_AUTO_16BIT_ALIGN` to get the correct wave.
|
||||
* But the data bit width is already 8 bits on ESP32-S2, each byte stands for an vailable voltage,
|
||||
* no need to do any alignment.
|
||||
*
|
||||
* @param[in] handle DAC channels handle
|
||||
* @param[in] buf The digital data buffer to convert
|
||||
* @param[in] buf_size The buffer size of digital data buffer
|
||||
* @param[out] bytes_loaded The bytes that has been loaded into DMA buffer, can be NULL if don't need it
|
||||
* @param[in] timeout_ms The timeout time in mili-second
|
||||
* @return
|
||||
* - ESP_ERR_INVALID_ARG The input parameter is invalid
|
||||
* - ESP_ERR_INVALID_STATE The DAC continuous mode has not been enabled yet
|
||||
* - ESP_ERR_TIMEOUT Waiting for semaphore or message queue timeout
|
||||
* - ESP_OK Success to output the acyclic DAC data
|
||||
*/
|
||||
esp_err_t dac_channels_write_cyclically(dac_channels_handle_t handle, uint8_t *buf, size_t buf_size, size_t *bytes_loaded, uint32_t timeout_ms);
|
||||
|
||||
/*--------------------------------------------------------------------------
|
||||
DAC cosine wave outputting APIs
|
||||
---------------------------------------------------------------------------*/
|
||||
/**
|
||||
* @brief Initialize the DAC channels to cosine wave mode
|
||||
*
|
||||
* @param[in] handle DAC channels handle
|
||||
* @param[in] cw_cfg DAC cosine wave generater configuration
|
||||
* @return
|
||||
* - ESP_ERR_INVALID_ARG The input parameter is invalid
|
||||
* - ESP_ERR_INVALID_STATE The DAC channels has been initialized already
|
||||
* - ESP_OK Success to initialize the DAC channels into cosine wave mode
|
||||
*/
|
||||
esp_err_t dac_channels_init_cosine_mode(dac_channels_handle_t handle, const dac_cosine_config_t *cw_cfg);
|
||||
|
||||
/**
|
||||
* @brief Deinitialize the DAC channels to cosine wave mode
|
||||
*
|
||||
* @param[in] handle DAC channels handle
|
||||
* @return
|
||||
* - ESP_ERR_INVALID_ARG The input parameter is invalid
|
||||
* - ESP_ERR_INVALID_STATE The DAC cosine wave generator is not stopped yet
|
||||
* - ESP_OK Success to deinitialize the DAC cosine mode
|
||||
*/
|
||||
esp_err_t dac_channels_deinit_cosine_mode(dac_channels_handle_t handle);
|
||||
|
||||
/**
|
||||
* @brief Start the DAC cosine wave generator output
|
||||
*
|
||||
* @param[in] handle DAC channels handle
|
||||
* @return
|
||||
* - ESP_ERR_INVALID_ARG The input parameter is invalid
|
||||
* - ESP_ERR_INVALID_STATE The DAC channels has not been enabled yet or started already
|
||||
* - ESP_OK Success to start cosine wave generator
|
||||
*/
|
||||
esp_err_t dac_channels_start_cosine_output(dac_channels_handle_t handle);
|
||||
|
||||
/**
|
||||
* @brief Stop the DAC cosine wave generator output
|
||||
*
|
||||
* @param[in] handle DAC channels handle
|
||||
* @return
|
||||
* - ESP_ERR_INVALID_ARG The input parameter is invalid
|
||||
* - ESP_ERR_INVALID_STATE The DAC channels has not been enabled yet or stoppped already
|
||||
* - ESP_OK Success to stop cosine wave generator
|
||||
*/
|
||||
esp_err_t dac_channels_stop_cosine_output(dac_channels_handle_t handle);
|
||||
|
||||
#endif // SOC_DAC_SUPPORTED
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
70
components/driver/include/driver/dac_oneshot.h
Normal file
70
components/driver/include/driver/dac_oneshot.h
Normal file
@@ -0,0 +1,70 @@
|
||||
/*
|
||||
* SPDX-FileCopyrightText: 2019-2022 Espressif Systems (Shanghai) CO LTD
|
||||
*
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "driver/dac_types.h"
|
||||
#include "esp_err.h"
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
#if SOC_DAC_SUPPORTED
|
||||
|
||||
typedef struct dac_oneshot_s *dac_oneshot_handle_t; /*!< DAC oneshot channel handle */
|
||||
|
||||
/**
|
||||
* @brief DAC oneshot channel configuration
|
||||
*
|
||||
*/
|
||||
typedef struct {
|
||||
dac_channel_t chan_id; /*!< DAC channel id */
|
||||
} dac_oneshot_config_t;
|
||||
|
||||
/**
|
||||
* @brief Allocate a new DAC oneshot channel
|
||||
* @note The channel will be enabled as well when the channel allocated
|
||||
*
|
||||
* @param[in] oneshot_cfg The configuration for the oneshot channel
|
||||
* @param[out] ret_handle The returned oneshot channel handle
|
||||
* @return
|
||||
* - ESP_ERR_INVALID_ARG The input parameter is invalid
|
||||
* - ESP_ERR_INVALID_STATE The DAC channel has been registered already
|
||||
* - ESP_ERR_NO_MEM No memory for the DAC oneshot channel resources
|
||||
* - ESP_OK Allocate the new DAC oneshot channel success
|
||||
*/
|
||||
esp_err_t dac_new_oneshot_channel(const dac_oneshot_config_t *oneshot_cfg, dac_oneshot_handle_t *ret_handle);
|
||||
|
||||
/**
|
||||
* @brief Delete the DAC oneshot channel
|
||||
* @note The channel will be disabled as well when the channel deleted
|
||||
*
|
||||
* @param[in] handle The DAC oneshot channel handle
|
||||
* @return
|
||||
* - ESP_ERR_INVALID_ARG The input parameter is invalid
|
||||
* - ESP_ERR_INVALID_STATE The channel has already been de-registered
|
||||
* - ESP_OK Delete the oneshot channel success
|
||||
*/
|
||||
esp_err_t dac_del_oneshot_channel(dac_oneshot_handle_t handle);
|
||||
|
||||
/**
|
||||
* @brief Output the voltage
|
||||
* @note Generally it'll take 7~11 us on ESP32 and 10~21 us on ESP32-S2
|
||||
*
|
||||
* @param[in] handle The DAC oneshot channel handle
|
||||
* @param[in] digi_value The digital value that need to be converted
|
||||
* @return
|
||||
* - ESP_ERR_INVALID_ARG The input parameter is invalid
|
||||
* - ESP_OK Convert the digital value success
|
||||
*/
|
||||
esp_err_t dac_oneshot_output_voltage(dac_oneshot_handle_t handle, uint8_t digi_value);
|
||||
|
||||
#endif // SOC_DAC_SUPPORTED
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
@@ -12,6 +12,7 @@
|
||||
#include "soc/soc_caps.h"
|
||||
#include "soc/clk_tree_defs.h"
|
||||
#include "hal/adc_types.h"
|
||||
#include "hal/dac_types.h"
|
||||
#include "esp_bit_defs.h"
|
||||
#include "sdkconfig.h"
|
||||
|
||||
@@ -20,17 +21,6 @@ extern "C" {
|
||||
#endif
|
||||
|
||||
#if SOC_DAC_SUPPORTED
|
||||
|
||||
/**
|
||||
* @brief DAC channel mask
|
||||
*
|
||||
*/
|
||||
typedef enum {
|
||||
DAC_CHANNEL_MASK_CH0 = BIT(0), /*!< DAC channel 0 is GPIO25(ESP32) / GPIO17(ESP32S2) */
|
||||
DAC_CHANNEL_MASK_CH1 = BIT(1), /*!< DAC channel 1 is GPIO26(ESP32) / GPIO18(ESP32S2) */
|
||||
DAC_CHANNEL_MASK_BOTH = BIT(0) | BIT(1), /*!< Both DAC channel 0 and channel 1 */
|
||||
} dac_channel_mask_t;
|
||||
|
||||
/**
|
||||
* @brief DAC channel work mode in dma mode
|
||||
* @note Only take effect when multiple channels enabled.
|
||||
@@ -51,7 +41,7 @@ typedef enum {
|
||||
* @brief DAC DMA (digitial controller) clock source
|
||||
*
|
||||
*/
|
||||
typedef soc_periph_dac_digi_clk_src_t dac_conti_clk_src_t;
|
||||
typedef soc_periph_dac_digi_clk_src_t dac_conti_digi_clk_src_t;
|
||||
|
||||
/**
|
||||
* @brief DAC cosine wave generator clock source
|
||||
@@ -59,26 +49,6 @@ typedef soc_periph_dac_digi_clk_src_t dac_conti_clk_src_t;
|
||||
*/
|
||||
typedef soc_periph_dac_cosine_clk_src_t dac_cosine_clk_src_t;
|
||||
|
||||
/**
|
||||
* @brief The attenuation of the amplitude of the cosine wave generator. The max amplitude is VDD3P3_RTC.
|
||||
*/
|
||||
typedef enum {
|
||||
DAC_COSINE_NO_ATTEN = 0x0, /*!< No attenuation to the DAC cosine wave amplitude. Default. */
|
||||
DAC_COSINE_ATTEN_2 = 0x1, /*!< 1/2 amplitude of the DAC cosine wave */
|
||||
DAC_COSINE_ATTEN_4 = 0x2, /*!< 1/4 amplitude of the DAC cosine wave */
|
||||
DAC_COSINE_ATTEN_8 = 0x3, /*!< 1/8 amplitude of the DAC cosine wave */
|
||||
} dac_cosine_scale_t;
|
||||
|
||||
/**
|
||||
* @brief Set the phase of the cosine wave generator output.
|
||||
* @note Only 0 or 180 are supported,
|
||||
* it will be set to 0 as default if configured to an unsupported phase.
|
||||
*/
|
||||
typedef enum {
|
||||
DAC_COSINE_PHASE_0 = 0, /*!< Phase shift +0° */
|
||||
DAC_COSINE_PHASE_180 = 180, /*!< Phase shift +180° */
|
||||
} dac_cosine_phase_t;
|
||||
|
||||
#endif // SOC_DAC_SUPPORTED
|
||||
|
||||
#ifdef __cplusplus
|
||||
|
||||
Reference in New Issue
Block a user