1 /*
2  * SPDX-FileCopyrightText: 2019-2022 Espressif Systems (Shanghai) CO LTD
3  *
4  * SPDX-License-Identifier: Apache-2.0
5  */
6 
7 
8 #include <string.h>
9 #include "sdkconfig.h"
10 #include "freertos/FreeRTOS.h"
11 #include "driver/dac_types_legacy.h"
12 #include "hal/adc_ll.h"
13 #include "hal/dac_ll.h"
14 #include "esp_check.h"
15 #include "esp_pm.h"
16 
17 static __attribute__((unused)) const char *TAG = "DAC";
18 
19 extern portMUX_TYPE rtc_spinlock; //TODO: Will be placed in the appropriate position after the rtc module is finished.
20 #define DAC_ENTER_CRITICAL()  portENTER_CRITICAL(&rtc_spinlock)
21 #define DAC_EXIT_CRITICAL()  portEXIT_CRITICAL(&rtc_spinlock)
22 
23 #ifdef CONFIG_PM_ENABLE
24 static esp_pm_lock_handle_t s_dac_digi_lock = NULL;
25 #endif  //CONFIG_PM_ENABLE
26 
27 /*---------------------------------------------------------------
28                     Digital controller setting
29 ---------------------------------------------------------------*/
30 
dac_digi_init(void)31 esp_err_t dac_digi_init(void)
32 {
33     DAC_ENTER_CRITICAL();
34     dac_ll_digi_clk_inv(true);
35     DAC_EXIT_CRITICAL();
36 
37     return ESP_OK;
38 }
39 
dac_digi_deinit(void)40 esp_err_t dac_digi_deinit(void)
41 {
42 #ifdef CONFIG_PM_ENABLE
43     if (s_dac_digi_lock) {
44         esp_pm_lock_delete(s_dac_digi_lock);
45         s_dac_digi_lock = NULL;
46     }
47 #endif
48     DAC_ENTER_CRITICAL();
49     dac_ll_digi_trigger_output(false);
50     dac_ll_digi_enable_dma(false);
51     dac_ll_digi_fifo_reset();
52     dac_ll_digi_reset();
53     DAC_EXIT_CRITICAL();
54 
55     return ESP_OK;
56 }
57 
dac_digi_controller_config(const dac_digi_config_t * cfg)58 esp_err_t dac_digi_controller_config(const dac_digi_config_t *cfg)
59 {
60     ESP_RETURN_ON_FALSE(cfg->mode <= DAC_CONV_ALTER, ESP_ERR_INVALID_ARG, TAG, "DAC mode error");
61     ESP_RETURN_ON_FALSE(cfg->interval > 0 && cfg->interval < 4096, ESP_ERR_INVALID_ARG, TAG, "DAC interval error");
62     ESP_RETURN_ON_FALSE(cfg->dig_clk.div_num < 256, ESP_ERR_INVALID_ARG, TAG, "DAC clk div_num error");
63     ESP_RETURN_ON_FALSE(cfg->dig_clk.div_b > 0 && cfg->dig_clk.div_b < 64, ESP_ERR_INVALID_ARG, TAG, "DAC clk div_b error");
64     ESP_RETURN_ON_FALSE(cfg->dig_clk.div_a < 64, ESP_ERR_INVALID_ARG, TAG, "DAC clk div_a error");
65 #ifdef CONFIG_PM_ENABLE
66     esp_err_t err;
67     if (s_dac_digi_lock == NULL) {
68         if (cfg->dig_clk.use_apll) {
69             err = esp_pm_lock_create(ESP_PM_NO_LIGHT_SLEEP, 0, "dac_dma", &s_dac_digi_lock);
70         } else {
71             err = esp_pm_lock_create(ESP_PM_APB_FREQ_MAX, 0, "dac_dma", &s_dac_digi_lock);
72         }
73         if (err != ESP_OK) {
74             s_dac_digi_lock = NULL;
75             ESP_LOGE(TAG, "DAC-DMA pm lock error");
76             return err;
77         }
78     }
79 #endif //CONFIG_PM_ENABLE
80 
81     DAC_ENTER_CRITICAL();
82     dac_ll_digi_set_convert_mode(cfg->mode == DAC_CONV_ALTER);
83     dac_ll_digi_set_trigger_interval(cfg->interval);
84     adc_ll_digi_controller_clk_div(cfg->dig_clk.div_num, cfg->dig_clk.div_b, cfg->dig_clk.div_a);
85     adc_ll_digi_clk_sel(cfg->dig_clk.use_apll ? ADC_DIGI_CLK_SRC_APLL : ADC_DIGI_CLK_SRC_DEFAULT);
86     DAC_EXIT_CRITICAL();
87 
88     return ESP_OK;
89 }
90 
dac_digi_start(void)91 esp_err_t dac_digi_start(void)
92 {
93 #ifdef CONFIG_PM_ENABLE
94     ESP_RETURN_ON_FALSE(s_dac_digi_lock, ESP_FAIL, TAG, "Should start after call `dac_digi_controller_config`");
95     esp_pm_lock_acquire(s_dac_digi_lock);
96 #endif
97     DAC_ENTER_CRITICAL();
98     dac_ll_digi_enable_dma(true);
99     dac_ll_digi_trigger_output(true);
100     DAC_EXIT_CRITICAL();
101 
102     return ESP_OK;
103 }
104 
dac_digi_stop(void)105 esp_err_t dac_digi_stop(void)
106 {
107 #ifdef CONFIG_PM_ENABLE
108     if (s_dac_digi_lock) {
109         esp_pm_lock_release(s_dac_digi_lock);
110     }
111 #endif
112     DAC_ENTER_CRITICAL();
113     dac_ll_digi_trigger_output(false);
114     dac_ll_digi_enable_dma(false);
115     DAC_EXIT_CRITICAL();
116 
117     return ESP_OK;
118 }
119 
dac_digi_fifo_reset(void)120 esp_err_t dac_digi_fifo_reset(void)
121 {
122     DAC_ENTER_CRITICAL();
123     dac_ll_digi_fifo_reset();
124     DAC_EXIT_CRITICAL();
125 
126     return ESP_OK;
127 }
128 
dac_digi_reset(void)129 esp_err_t dac_digi_reset(void)
130 {
131     DAC_ENTER_CRITICAL();
132     dac_ll_digi_reset();
133     DAC_EXIT_CRITICAL();
134 
135     return ESP_OK;
136 }
137