1 // Copyright 2019-2020 Espressif Systems (Shanghai) PTE LTD
2 //
3 // Licensed under the Apache License, Version 2.0 (the "License");
4 // you may not use this file except in compliance with the License.
5 // You may obtain a copy of the License at
6 //
7 // http://www.apache.org/licenses/LICENSE-2.0
8 //
9 // Unless required by applicable law or agreed to in writing, software
10 // distributed under the License is distributed on an "AS IS" BASIS,
11 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 // See the License for the specific language governing permissions and
13 // limitations under the License.
14
15
16 #include <string.h>
17 #include "esp_log.h"
18 #include "esp_err.h"
19 #include "esp_pm.h"
20 #include "freertos/FreeRTOS.h"
21 #include "freertos/semphr.h"
22 #include "freertos/timers.h"
23 #include "driver/rtc_io.h"
24 #include "driver/dac.h"
25 #include "soc/dac_periph.h"
26 #include "hal/dac_hal.h"
27
28 static const char *DAC_TAG = "DAC";
29
30 #define DAC_CHECK(a, str, ret_val) ({ \
31 if (!(a)) { \
32 ESP_LOGE(DAC_TAG,"%s:%d (%s):%s", __FILE__, __LINE__, __FUNCTION__, str); \
33 return (ret_val); \
34 } \
35 })
36
37 extern portMUX_TYPE rtc_spinlock; //TODO: Will be placed in the appropriate position after the rtc module is finished.
38 #define DAC_ENTER_CRITICAL() portENTER_CRITICAL(&rtc_spinlock)
39 #define DAC_EXIT_CRITICAL() portEXIT_CRITICAL(&rtc_spinlock)
40
41 #ifdef CONFIG_PM_ENABLE
42 static esp_pm_lock_handle_t s_dac_digi_lock = NULL;
43 #endif //CONFIG_PM_ENABLE
44
45 /*---------------------------------------------------------------
46 Digital controller setting
47 ---------------------------------------------------------------*/
48
dac_digi_init(void)49 esp_err_t dac_digi_init(void)
50 {
51 DAC_ENTER_CRITICAL();
52 dac_hal_digi_init();
53 DAC_EXIT_CRITICAL();
54
55 return ESP_OK;
56 }
57
dac_digi_deinit(void)58 esp_err_t dac_digi_deinit(void)
59 {
60 #ifdef CONFIG_PM_ENABLE
61 if (s_dac_digi_lock) {
62 esp_pm_lock_delete(s_dac_digi_lock);
63 s_dac_digi_lock = NULL;
64 }
65 #endif
66 DAC_ENTER_CRITICAL();
67 dac_hal_digi_deinit();
68 DAC_EXIT_CRITICAL();
69
70 return ESP_OK;
71 }
72
dac_digi_controller_config(const dac_digi_config_t * cfg)73 esp_err_t dac_digi_controller_config(const dac_digi_config_t *cfg)
74 {
75 DAC_CHECK(cfg->mode < DAC_CONV_MAX, "DAC mode error", ESP_ERR_INVALID_ARG);
76 DAC_CHECK(cfg->interval > 0 && cfg->interval < 4096, "DAC interval error", ESP_ERR_INVALID_ARG);
77 DAC_CHECK(cfg->dig_clk.div_num < 256, "DAC clk div_num error", ESP_ERR_INVALID_ARG);
78 DAC_CHECK(cfg->dig_clk.div_b > 0 && cfg->dig_clk.div_b < 64, "DAC clk div_b error", ESP_ERR_INVALID_ARG);
79 DAC_CHECK(cfg->dig_clk.div_a < 64, "DAC clk div_a error", ESP_ERR_INVALID_ARG);
80 #ifdef CONFIG_PM_ENABLE
81 esp_err_t err;
82 if (s_dac_digi_lock == NULL) {
83 if (cfg->dig_clk.use_apll) {
84 err = esp_pm_lock_create(ESP_PM_NO_LIGHT_SLEEP, 0, "dac_dma", &s_dac_digi_lock);
85 } else {
86 err = esp_pm_lock_create(ESP_PM_APB_FREQ_MAX, 0, "dac_dma", &s_dac_digi_lock);
87 }
88 if (err != ESP_OK) {
89 s_dac_digi_lock = NULL;
90 ESP_LOGE(DAC_TAG, "DAC-DMA pm lock error");
91 return err;
92 }
93 }
94 #endif //CONFIG_PM_ENABLE
95
96 DAC_ENTER_CRITICAL();
97 dac_hal_digi_controller_config(cfg);
98 DAC_EXIT_CRITICAL();
99
100 return ESP_OK;
101 }
102
dac_digi_start(void)103 esp_err_t dac_digi_start(void)
104 {
105 #ifdef CONFIG_PM_ENABLE
106 DAC_CHECK((s_dac_digi_lock), "Should start after call `dac_digi_controller_config`", ESP_FAIL);
107 esp_pm_lock_acquire(s_dac_digi_lock);
108 #endif
109 DAC_ENTER_CRITICAL();
110 dac_hal_digi_start();
111 DAC_EXIT_CRITICAL();
112
113 return ESP_OK;
114 }
115
dac_digi_stop(void)116 esp_err_t dac_digi_stop(void)
117 {
118 #ifdef CONFIG_PM_ENABLE
119 if (s_dac_digi_lock) {
120 esp_pm_lock_release(s_dac_digi_lock);
121 }
122 #endif
123 DAC_ENTER_CRITICAL();
124 dac_hal_digi_stop();
125 DAC_EXIT_CRITICAL();
126
127 return ESP_OK;
128 }
129
dac_digi_fifo_reset(void)130 esp_err_t dac_digi_fifo_reset(void)
131 {
132 DAC_ENTER_CRITICAL();
133 dac_hal_digi_fifo_reset();
134 DAC_EXIT_CRITICAL();
135
136 return ESP_OK;
137 }
138
dac_digi_reset(void)139 esp_err_t dac_digi_reset(void)
140 {
141 DAC_ENTER_CRITICAL();
142 dac_hal_digi_reset();
143 DAC_EXIT_CRITICAL();
144
145 return ESP_OK;
146 }
147