1 /*
2 * SPDX-FileCopyrightText: 2019-2022 Espressif Systems (Shanghai) CO LTD
3 *
4 * SPDX-License-Identifier: Apache-2.0
5 */
6
7 /*******************************************************************************
8 * NOTICE
9 * The ll is not public api, don't use in application code.
10 * See readme.md in hal/include/hal/readme.md
11 ******************************************************************************/
12
13 #pragma once
14
15 #include <stdlib.h>
16 #include "hal/misc.h"
17 #include "soc/dac_periph.h"
18 #include "hal/dac_types.h"
19 #include "soc/apb_saradc_struct.h"
20 #include "soc/sens_struct.h"
21 #include "soc/rtc_io_struct.h"
22 #include "soc/apb_saradc_reg.h"
23
24 #ifdef __cplusplus
25 extern "C" {
26 #endif
27
28 #define DAC_LL_CW_PHASE_0 0x02
29 #define DAC_LL_CW_PHASE_180 0x03
30
31 /*---------------------------------------------------------------
32 DAC common setting
33 ---------------------------------------------------------------*/
34 /**
35 * Power on dac module and start output voltage.
36 *
37 * @note Before powering up, make sure the DAC PAD is set to RTC PAD and floating status.
38 * @param channel DAC channel num.
39 */
dac_ll_power_on(dac_channel_t channel)40 static inline void dac_ll_power_on(dac_channel_t channel)
41 {
42 SENS.sar_dac_ctrl1.dac_clkgate_en = 1;
43 RTCIO.pad_dac[channel].dac_xpd_force = 1;
44 RTCIO.pad_dac[channel].xpd_dac = 1;
45 }
46
47 /**
48 * Power done dac module and stop output voltage.
49 *
50 * @param channel DAC channel num.
51 */
dac_ll_power_down(dac_channel_t channel)52 static inline void dac_ll_power_down(dac_channel_t channel)
53 {
54 RTCIO.pad_dac[channel].dac_xpd_force = 0;
55 RTCIO.pad_dac[channel].xpd_dac = 0;
56 if (RTCIO.pad_dac[0].xpd_dac == 0 && RTCIO.pad_dac[1].xpd_dac == 0) {
57 SENS.sar_dac_ctrl1.dac_clkgate_en = 0;
58 }
59 }
60
61 /*---------------------------------------------------------------
62 RTC controller setting
63 ---------------------------------------------------------------*/
64 /**
65 * Output voltage with value (8 bit).
66 *
67 * @param channel DAC channel num.
68 * @param value Output value. Value range: 0 ~ 255.
69 * The corresponding range of voltage is 0v ~ VDD3P3_RTC.
70 */
71 __attribute__((always_inline))
dac_ll_update_output_value(dac_channel_t channel,uint8_t value)72 static inline void dac_ll_update_output_value(dac_channel_t channel, uint8_t value)
73 {
74 if (channel == DAC_CHAN_0) {
75 SENS.sar_dac_ctrl2.dac_cw_en1 = 0;
76 HAL_FORCE_MODIFY_U32_REG_FIELD(RTCIO.pad_dac[channel], dac, value);
77 } else if (channel == DAC_CHAN_1) {
78 SENS.sar_dac_ctrl2.dac_cw_en2 = 0;
79 HAL_FORCE_MODIFY_U32_REG_FIELD(RTCIO.pad_dac[channel], dac, value);
80 }
81 }
82
83 /**
84 * Reset dac by software.
85 */
dac_ll_rtc_reset(void)86 static inline void dac_ll_rtc_reset(void)
87 {
88 SENS.sar_dac_ctrl1.dac_reset = 1;
89 SENS.sar_dac_ctrl1.dac_reset = 0;
90 }
91
92 /**
93 * Enable/disable the synchronization operation function of ADC1 and DAC.
94 *
95 * @note If enabled(default), ADC RTC controller sampling will cause the DAC channel output voltage.
96 *
97 * @param enable Enable or disable adc and dac synchronization function.
98 */
dac_ll_rtc_sync_by_adc(bool enable)99 static inline void dac_ll_rtc_sync_by_adc(bool enable)
100 {
101 SENS.sar_amp_ctrl3.sar1_dac_xpd_fsm = enable;
102 }
103
104 /************************************/
105 /* DAC cosine wave generator API's */
106 /************************************/
107 /**
108 * Enable cosine wave generator output.
109 */
dac_ll_cw_generator_enable(void)110 static inline void dac_ll_cw_generator_enable(void)
111 {
112 SENS.sar_dac_ctrl1.sw_tone_en = 1;
113 }
114
115 /**
116 * Disable cosine wave generator output.
117 */
dac_ll_cw_generator_disable(void)118 static inline void dac_ll_cw_generator_disable(void)
119 {
120 SENS.sar_dac_ctrl1.sw_tone_en = 0;
121 }
122
123 /**
124 * Enable the cosine wave generator of DAC channel.
125 *
126 * @param channel DAC channel num.
127 * @param enable
128 */
dac_ll_cw_enable_channel(dac_channel_t channel,bool enable)129 static inline void dac_ll_cw_enable_channel(dac_channel_t channel, bool enable)
130 {
131 if (channel == DAC_CHAN_0) {
132 SENS.sar_dac_ctrl2.dac_cw_en1 = enable;
133 } else if (channel == DAC_CHAN_1) {
134 SENS.sar_dac_ctrl2.dac_cw_en2 = enable;
135 }
136 }
137
138 /**
139 * Set frequency of cosine wave generator output.
140 *
141 * @note We know that CLK8M is about 8M, but don't know the actual value. so this freq have limited error.
142 * @param freq_hz CW generator frequency. Range: >= 130Hz, no exact ceiling limitation, but will distort when reach several MHz
143 * @param rtc8m_freq the calibrated RTC 8M clock frequency
144 */
dac_ll_cw_set_freq(uint32_t freq,uint32_t rtc8m_freq)145 static inline void dac_ll_cw_set_freq(uint32_t freq, uint32_t rtc8m_freq)
146 {
147 uint32_t sw_freq = (uint32_t)(((uint64_t)freq << 16) / rtc8m_freq);
148 HAL_FORCE_MODIFY_U32_REG_FIELD(SENS.sar_dac_ctrl1, sw_fstep, (sw_freq > 0xFFFF) ? 0xFFFF : sw_freq);
149 }
150
151 /**
152 * Set the amplitude of the cosine wave generator output.
153 *
154 * @param channel DAC channel num.
155 * @param atten The attenuation of the amplitude. The max amplitude is VDD3P3_RTC.
156 * 0: attenuation = 1, amplitude = VDD3P3_RTC / attenuation,
157 * 1: attenuation = 2, amplitude = VDD3P3_RTC / attenuation,
158 * 2: attenuation = 4, amplitude = VDD3P3_RTC / attenuation,
159 * 3: attenuation = 8, amplitude = VDD3P3_RTC / attenuation
160 */
dac_ll_cw_set_atten(dac_channel_t channel,dac_cosine_atten_t atten)161 static inline void dac_ll_cw_set_atten(dac_channel_t channel, dac_cosine_atten_t atten)
162 {
163 if (channel == DAC_CHAN_0) {
164 SENS.sar_dac_ctrl2.dac_scale1 = atten;
165 } else if (channel == DAC_CHAN_1) {
166 SENS.sar_dac_ctrl2.dac_scale2 = atten;
167 }
168 }
169
170 /**
171 * Set the phase of the cosine wave generator output.
172 *
173 * @param channel DAC channel num.
174 * @param phase Phase value. 0: 0x02 180: 0x03.
175 */
dac_ll_cw_set_phase(dac_channel_t channel,dac_cosine_phase_t phase)176 static inline void dac_ll_cw_set_phase(dac_channel_t channel, dac_cosine_phase_t phase)
177 {
178 if (channel == DAC_CHAN_0) {
179 SENS.sar_dac_ctrl2.dac_inv1 = phase;
180 } else if (channel == DAC_CHAN_1) {
181 SENS.sar_dac_ctrl2.dac_inv2 = phase;
182 }
183 }
184
185 /**
186 * Set the voltage value of the DC component of the cosine wave generator output.
187 *
188 * @note The DC offset setting should be after phase setting.
189 * @note Unreasonable settings can cause the signal to be oversaturated.
190 * @param channel DAC channel num.
191 * @param offset DC value. Range: -128 ~ 127.
192 */
dac_ll_cw_set_dc_offset(dac_channel_t channel,int8_t offset)193 static inline void dac_ll_cw_set_dc_offset(dac_channel_t channel, int8_t offset)
194 {
195 if (channel == DAC_CHAN_0) {
196 if (SENS.sar_dac_ctrl2.dac_inv1 == DAC_LL_CW_PHASE_180) {
197 offset = -offset;
198 }
199 HAL_FORCE_MODIFY_U32_REG_FIELD(SENS.sar_dac_ctrl2, dac_dc1, offset);
200 } else if (channel == DAC_CHAN_1) {
201 if (SENS.sar_dac_ctrl2.dac_inv2 == DAC_LL_CW_PHASE_180) {
202 offset = -offset;
203 }
204 HAL_FORCE_MODIFY_U32_REG_FIELD(SENS.sar_dac_ctrl2, dac_dc2, offset);
205 }
206 }
207
208 /*---------------------------------------------------------------
209 Digital controller setting
210 ---------------------------------------------------------------*/
211
212 /************************************/
213 /* DAC DMA API's */
214 /************************************/
215
216 /**
217 * Enable/disable invert the DAC digital controller clock signal.
218 *
219 * @param enable true or false.
220 */
dac_ll_digi_clk_inv(bool enable)221 static inline void dac_ll_digi_clk_inv(bool enable)
222 {
223 SENS.sar_dac_ctrl1.dac_clk_inv = enable;
224 }
225
226 /**
227 * Enable/disable DAC-DMA mode for dac digital controller.
228 */
dac_ll_digi_enable_dma(bool enable)229 static inline void dac_ll_digi_enable_dma(bool enable)
230 {
231 SENS.sar_dac_ctrl1.dac_dig_force = enable;
232 APB_SARADC.apb_dac_ctrl.apb_dac_trans = enable;
233 }
234
235 /**
236 * Sets the number of interval clock cycles for the digital controller to trigger the DAC output.
237 * Expression: `dac_output_freq` = `controller_clk` / interval.
238 *
239 * @note The clocks of the DAC digital controller use the ADC digital controller clock divider.
240 *
241 * @param cycle The number of clock cycles for the trigger output interval. The unit is the divided clock.
242 */
dac_ll_digi_set_trigger_interval(uint32_t cycle)243 static inline void dac_ll_digi_set_trigger_interval(uint32_t cycle)
244 {
245 APB_SARADC.apb_dac_ctrl.dac_timer_target = cycle;
246 }
247
248 /**
249 * Enable/disable DAC digital controller to trigger the DAC output.
250 *
251 * @param enable true or false.
252 */
dac_ll_digi_trigger_output(bool enable)253 static inline void dac_ll_digi_trigger_output(bool enable)
254 {
255 APB_SARADC.apb_dac_ctrl.dac_timer_en = enable;
256 }
257
258 /**
259 * Set DAC conversion mode for digital controller.
260 *
261 * @param mode Conversion mode select. See ``dac_digi_convert_mode_t``.
262 */
dac_ll_digi_set_convert_mode(bool is_alternate)263 static inline void dac_ll_digi_set_convert_mode(bool is_alternate)
264 {
265 APB_SARADC.apb_dac_ctrl.apb_dac_alter_mode = is_alternate;
266 }
267
268 /**
269 * Reset FIFO of DAC digital controller.
270 */
dac_ll_digi_fifo_reset(void)271 static inline void dac_ll_digi_fifo_reset(void)
272 {
273 APB_SARADC.apb_dac_ctrl.dac_reset_fifo = 1;
274 APB_SARADC.apb_dac_ctrl.dac_reset_fifo = 0;
275 }
276
277 /**
278 * Reset DAC digital controller.
279 */
dac_ll_digi_reset(void)280 static inline void dac_ll_digi_reset(void)
281 {
282 APB_SARADC.apb_dac_ctrl.apb_dac_rst = 1;
283 APB_SARADC.apb_dac_ctrl.apb_dac_rst = 0;
284 }
285
286 #ifdef __cplusplus
287 }
288 #endif
289