dac_continuous.h 15 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263
  1. /*
  2. * SPDX-FileCopyrightText: 2019-2022 Espressif Systems (Shanghai) CO LTD
  3. *
  4. * SPDX-License-Identifier: Apache-2.0
  5. */
  6. #pragma once
  7. #include "driver/dac_types.h"
  8. #include "esp_err.h"
  9. #ifdef __cplusplus
  10. extern "C" {
  11. #endif
  12. #if SOC_DAC_SUPPORTED
  13. /**
  14. * @brief DAC channel mask
  15. *
  16. */
  17. typedef enum {
  18. DAC_CHANNEL_MASK_CH0 = BIT(0), /*!< DAC channel 0 is GPIO25(ESP32) / GPIO17(ESP32S2) */
  19. DAC_CHANNEL_MASK_CH1 = BIT(1), /*!< DAC channel 1 is GPIO26(ESP32) / GPIO18(ESP32S2) */
  20. DAC_CHANNEL_MASK_ALL = BIT(0) | BIT(1), /*!< Both DAC channel 0 and channel 1 */
  21. } dac_channel_mask_t;
  22. typedef struct dac_continuous_s *dac_continuous_handle_t; /*!< DAC continuous channel handle */
  23. /**
  24. * @brief DAC continuous channels' configurations
  25. *
  26. */
  27. typedef struct {
  28. dac_channel_mask_t chan_mask; /*!< DAC channels' mask for selecting which channels are used */
  29. uint32_t desc_num; /*!< The number of DMA descriptor, at least 2 descriptors are required
  30. * The number of descriptors is directly proportional to the max data buffer size while converting in cyclic output
  31. * but only need to ensure it is greater than '1' in acyclic output
  32. * Typically, suggest to set the number bigger than 5, in case the DMA stopped while sending a short buffer
  33. */
  34. size_t buf_size; /*!< The DMA buffer size, should be within 32~4092 bytes. Each DMA buffer will be attached to a DMA descriptor,
  35. * i.e. the number of DMA buffer will be equal to the DMA descriptor number
  36. * The DMA buffer size is not allowed to be greater than 4092 bytes
  37. * The total DMA buffer size equal to `desc_num * buf_size`
  38. * Typically, suggest to set the size to the multiple of 4
  39. */
  40. uint32_t freq_hz; /*!< The frequency of DAC conversion in continuous mode, unit: Hz
  41. * The supported range is related to the target and the clock source.
  42. * For the clock `DAC_DIGI_CLK_SRC_DEFAULT`: the range is 19.6 KHz to several MHz on ESP32
  43. * and 77 Hz to several MHz on ESP32-S2.
  44. * For the clock `DAC_DIGI_CLK_SRC_APLL`: the range is 648 Hz to several MHz on ESP32
  45. * and 6 Hz to several MHz on ESP32-S2.
  46. * Typically not suggest to set the frequency higher than 2 MHz, otherwise the severe distortion will appear
  47. */
  48. int8_t offset; /*!< The offset of the DAC digital data. Range -128~127 */
  49. dac_continuous_digi_clk_src_t clk_src; /*!< The clock source of digital controller, which can affect the range of supported frequency
  50. * Currently `DAC_DIGI_CLK_SRC_DEFAULT` and `DAC_DIGI_CLK_SRC_APLL` are available
  51. */
  52. 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 */
  53. } dac_continuous_config_t;
  54. /**
  55. * @brief Event structure used in DAC event queue
  56. */
  57. typedef struct {
  58. void *buf; /*!< The pointer of DMA buffer that just finished sending */
  59. size_t buf_size; /*!< The writable buffer size of the DMA buffer, equal to 'dac_continuous_config_t::buf_size' */
  60. size_t write_bytes; /*!< The number of bytes that be written successfully */
  61. } dac_event_data_t;
  62. /**
  63. * @brief DAC event callback
  64. * @param[in] handle DAC channel handle, created from `dac_continuous_new_channels()`
  65. * @param[in] event DAC event data
  66. * @param[in] user_data User registered context, passed from `dac_continuous_register_event_callback()`
  67. *
  68. * @return Whether a high priority task has been waken up by this callback function
  69. */
  70. typedef bool (*dac_isr_callback_t)(dac_continuous_handle_t handle, const dac_event_data_t *event, void *user_data);
  71. /**
  72. * @brief Group of DAC callbacks
  73. * @note The callbacks are all running under ISR environment
  74. * @note When CONFIG_DAC_ISR_IRAM_SAFE is enabled, the callback itself and functions called by it should be placed in IRAM.
  75. * The variables used in the function should be in the SRAM as well.
  76. */
  77. typedef struct {
  78. dac_isr_callback_t on_convert_done; /**< Callback of data conversion done event
  79. * An event data buffer previously loaded to the driver has been output and converted.
  80. * The event data includes DMA buffer address and size that just finished converting.
  81. */
  82. dac_isr_callback_t on_stop; /**< Callback of finished sending all the data.
  83. * All loaded event data buffers are converted. Driver is pending for new data buffers to be loaded.
  84. * The event data will be NULL in this callback.
  85. */
  86. } dac_event_callbacks_t;
  87. /**
  88. * @brief Allocate new DAC channels in continuous mode
  89. * @note The DAC channels can't be registered to continuous mode separately
  90. *
  91. * @param[in] cont_cfg Continuous mode configuration
  92. * @param[out] ret_handle The returned continuous mode handle
  93. * @return
  94. * - ESP_ERR_INVALID_ARG The input parameter is invalid
  95. * - ESP_ERR_INVALID_STATE The DAC channel has been registered already
  96. * - ESP_ERR_NOT_FOUND Not found the available dma peripheral, might be occupied
  97. * - ESP_ERR_NO_MEM No memory for the DAC continuous mode resources
  98. * - ESP_OK Allocate the new DAC continuous mode success
  99. */
  100. esp_err_t dac_continuous_new_channels(const dac_continuous_config_t *cont_cfg, dac_continuous_handle_t *ret_handle);
  101. /**
  102. * @brief Delete the DAC continuous handle
  103. *
  104. * @param[in] handle The DAC continuous channel handle that obtained from 'dac_continuous_new_channels'
  105. * @return
  106. * - ESP_ERR_INVALID_ARG The input parameter is invalid
  107. * - ESP_ERR_INVALID_STATE The channels have already been deregistered or not disabled
  108. * - ESP_OK Delete the continuous channels success
  109. */
  110. esp_err_t dac_continuous_del_channels(dac_continuous_handle_t handle);
  111. /**
  112. * @brief Enabled the DAC continuous mode
  113. * @note Must enable the channels before
  114. *
  115. * @param[in] handle The DAC continuous channel handle that obtained from 'dac_continuous_new_channels'
  116. * @return
  117. * - ESP_ERR_INVALID_ARG The input parameter is invalid
  118. * - ESP_ERR_INVALID_STATE The channels have been enabled already
  119. * - ESP_OK Enable the continuous output success
  120. */
  121. esp_err_t dac_continuous_enable(dac_continuous_handle_t handle);
  122. /**
  123. * @brief Disable the DAC continuous mode
  124. *
  125. * @param[in] handle The DAC continuous channel handle that obtained from 'dac_continuous_new_channels'
  126. * @return
  127. * - ESP_ERR_INVALID_ARG The input parameter is invalid
  128. * - ESP_ERR_INVALID_STATE The channels have been enabled already
  129. * - ESP_OK Disable the continuous output success
  130. */
  131. esp_err_t dac_continuous_disable(dac_continuous_handle_t handle);
  132. /**
  133. * @brief Write DAC data continuously
  134. * @note The data in buffer will only be converted one time,
  135. * This function will be blocked until all data loaded or timeout
  136. * then the DAC output will keep outputting the voltage of the last data in the buffer
  137. * @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,
  138. * The driver will help to expand the inputted buffer automatically by default,
  139. * you can also align the data to 16 bits manually by clearing `CONFIG_DAC_DMA_AUTO_16BIT_ALIGN` in menuconfig.
  140. *
  141. * @param[in] handle The DAC continuous channel handle that obtained from 'dac_continuous_new_channels'
  142. * @param[in] buf The digital data buffer to convert
  143. * @param[in] buf_size The buffer size of digital data buffer
  144. * @param[out] bytes_loaded The bytes that has been loaded into DMA buffer, can be NULL if don't need it
  145. * @param[in] timeout_ms The timeout time in millisecond, set a minus value means will block forever
  146. * @return
  147. * - ESP_ERR_INVALID_ARG The input parameter is invalid
  148. * - ESP_ERR_INVALID_STATE The DAC continuous mode has not been enabled yet
  149. * - ESP_ERR_TIMEOUT Waiting for semaphore or message queue timeout
  150. * - ESP_OK Success to output the acyclic DAC data
  151. */
  152. 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);
  153. /**
  154. * @brief Write DAC continuous data cyclically
  155. * @note The data in buffer will be converted cyclically using DMA once this function is called,
  156. * This function will return once the data loaded into DMA buffers.
  157. * @note The buffer size of cyclically output is limited by the descriptor number and
  158. * dma buffer size while initializing the continuous mode.
  159. * Concretely, in order to load all the data into descriptors,
  160. * the cyclic buffer size is not supposed to be greater than `desc_num * buf_size`
  161. * @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,
  162. * The driver will help to expand the inputted buffer automatically by default,
  163. * you can also align the data to 16 bits manually by clearing `CONFIG_DAC_DMA_AUTO_16BIT_ALIGN` in menuconfig.
  164. *
  165. * @param[in] handle The DAC continuous channel handle that obtained from 'dac_continuous_new_channels'
  166. * @param[in] buf The digital data buffer to convert
  167. * @param[in] buf_size The buffer size of digital data buffer
  168. * @param[out] bytes_loaded The bytes that has been loaded into DMA buffer, can be NULL if don't need it
  169. * @return
  170. * - ESP_ERR_INVALID_ARG The input parameter is invalid
  171. * - ESP_ERR_INVALID_STATE The DAC continuous mode has not been enabled yet
  172. * - ESP_OK Success to output the acyclic DAC data
  173. */
  174. esp_err_t dac_continuous_write_cyclically(dac_continuous_handle_t handle, uint8_t *buf, size_t buf_size, size_t *bytes_loaded);
  175. /**
  176. * @brief Set event callbacks for DAC continuous mode
  177. *
  178. * @note User can deregister a previously registered callback by calling this function and setting the callback member in the `callbacks` structure to NULL.
  179. * @note When CONFIG_DAC_ISR_IRAM_SAFE is enabled, the callback itself and functions called by it should be placed in IRAM.
  180. * The variables used in this function, including the `user_data`, should be in the internal RAM as well.
  181. *
  182. * @param[in] handle The DAC continuous channel handle that obtained from 'dac_continuous_new_channels'
  183. * @param[in] callbacks Group of callback functions, input NULL to clear the former callbacks
  184. * @param[in] user_data User data, which will be passed to callback functions directly
  185. * @return
  186. * - ESP_OK Set event callbacks successfully
  187. * - ESP_ERR_INVALID_ARG Set event callbacks failed because of invalid argument
  188. */
  189. esp_err_t dac_continuous_register_event_callback(dac_continuous_handle_t handle, const dac_event_callbacks_t *callbacks, void *user_data);
  190. /**
  191. * @brief Start the async writing
  192. * @note When the asynchronous writing start, the DAC will keep outputting '0' until the data are loaded into the DMA buffer.
  193. * To loaded the data into DMA buffer, 'on_convert_done' callback is required,
  194. * which can be registered by 'dac_continuous_register_event_callback' before enabling
  195. *
  196. * @param[in] handle The DAC continuous channel handle that obtained from 'dac_continuous_new_channels'
  197. * @return
  198. * - ESP_OK Start asynchronous writing successfully
  199. * - ESP_ERR_INVALID_ARG The handle is NULL
  200. * - ESP_ERR_INVALID_STATE The channel is not enabled or the 'on_convert_done' callback is not registered
  201. */
  202. esp_err_t dac_continuous_start_async_writing(dac_continuous_handle_t handle);
  203. /**
  204. * @brief Stop the sync writing
  205. *
  206. * @param[in] handle The DAC continuous channel handle that obtained from 'dac_continuous_new_channels'
  207. * @return
  208. * - ESP_OK Stop asynchronous writing successfully
  209. * - ESP_ERR_INVALID_ARG The handle is NULL
  210. * - ESP_ERR_INVALID_STATE Asynchronous writing has not started
  211. */
  212. esp_err_t dac_continuous_stop_async_writing(dac_continuous_handle_t handle);
  213. /**
  214. * @brief Write DAC data asynchronously
  215. * @note This function can be called when the asynchronous writing started, and it can be called in the callback directly
  216. * but recommend to writing data in a task, referring to :example:`peripherals/dac/dac_continuous/dac_audio`
  217. *
  218. * @param[in] handle The DAC continuous channel handle that obtained from 'dac_continuous_new_channels'
  219. * @param[in] dma_buf The DMA buffer address, it can be acquired from 'dac_event_data_t' in the 'on_convert_done' callback
  220. * @param[in] dma_buf_len The DMA buffer length, it can be acquired from 'dac_event_data_t' in the 'on_convert_done' callback
  221. * @param[in] data The data that need to be written
  222. * @param[in] data_len The data length the need to be written
  223. * @param[out] bytes_loaded The bytes number that has been loaded/written into the DMA buffer
  224. * @return
  225. * - ESP_OK Write the data into DMA buffer successfully
  226. * - ESP_ERR_INVALID_ARG NULL pointer
  227. * - ESP_ERR_INVALID_STATE The channels haven't start the asynchronous writing
  228. * - ESP_ERR_NOT_FOUND The param 'dam_buf' not match any existed DMA buffer
  229. */
  230. esp_err_t dac_continuous_write_asynchronously(dac_continuous_handle_t handle,
  231. uint8_t *dma_buf,
  232. size_t dma_buf_len,
  233. const uint8_t *data,
  234. size_t data_len,
  235. size_t *bytes_loaded);
  236. #endif // SOC_DAC_SUPPORTED
  237. #ifdef __cplusplus
  238. }
  239. #endif