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