mirror of
				https://github.com/espressif/esp-idf.git
				synced 2025-10-31 04:59:55 +00:00 
			
		
		
		
	
		
			
				
	
	
		
			262 lines
		
	
	
		
			15 KiB
		
	
	
	
		
			C
		
	
	
	
	
	
			
		
		
	
	
			262 lines
		
	
	
		
			15 KiB
		
	
	
	
		
			C
		
	
	
	
	
	
| /*
 | |
|  * 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_continuous_s      *dac_continuous_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_continuous_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_continuous_channel_mode_t    chan_mode;      /*!< The channel mode of continuous mode, only take effect when multiple channels enabled, depends converting the buffer alternately or simultaneously */
 | |
| } dac_continuous_config_t;
 | |
| 
 | |
| /**
 | |
|  * @brief Event structure used in DAC event queue
 | |
|  */
 | |
| 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_continuous_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_continuous_new_channels()`
 | |
|  * @param[in] event     DAC event data
 | |
|  * @param[in] user_data User registered context, passed from `dac_continuous_register_event_callback()`
 | |
|  *
 | |
|  * @return Whether a high priority task has been waken up by this callback function
 | |
|  */
 | |
| typedef bool (*dac_isr_callback_t)(dac_continuous_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]  cont_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_continuous_new_channels(const dac_continuous_config_t *cont_cfg, dac_continuous_handle_t *ret_handle);
 | |
| 
 | |
| /**
 | |
|  * @brief Delete the DAC continuous handle
 | |
|  *
 | |
|  * @param[in]  handle       The DAC continuous channel handle that obtained from 'dac_continuous_new_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_continuous_del_channels(dac_continuous_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_continuous_new_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_continuous_enable(dac_continuous_handle_t handle);
 | |
| 
 | |
| /**
 | |
|  * @brief Disable the DAC continuous mode
 | |
|  *
 | |
|  * @param[in]  handle       The DAC continuous channel handle that obtained from 'dac_continuous_new_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_continuous_disable(dac_continuous_handle_t handle);
 | |
| 
 | |
| /**
 | |
|  * @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_continuous_new_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_continuous_write(dac_continuous_handle_t handle, uint8_t *buf, size_t buf_size, size_t *bytes_loaded, int timeout_ms);
 | |
| 
 | |
| /**
 | |
|  * @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_continuous_new_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_continuous_write_cyclically(dac_continuous_handle_t handle, uint8_t *buf, size_t buf_size, size_t *bytes_loaded);
 | |
| 
 | |
| /**
 | |
|  * @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_continuous_new_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_continuous_register_event_callback(dac_continuous_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_continuous_register_event_callback' before enabling
 | |
|  *
 | |
|  * @param[in] handle        The DAC continuous channel handle that obtained from 'dac_continuous_new_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_continuous_start_async_writing(dac_continuous_handle_t handle);
 | |
| 
 | |
| /**
 | |
|  * @brief Stop the sync writing
 | |
|  *
 | |
|  * @param[in] handle        The DAC continuous channel handle that obtained from 'dac_continuous_new_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_continuous_stop_async_writing(dac_continuous_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_continuous_new_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_continuous_write_asynchronously(dac_continuous_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
 | 
