1 /*
2 * Copyright (c) 2021 HPMicro
3 *
4 * SPDX-License-Identifier: BSD-3-Clause
5 *
6 */
7
8 #include "hpm_dac_drv.h"
9
dac_get_default_config(dac_config_t * config)10 void dac_get_default_config(dac_config_t *config)
11 {
12 config->sync_mode = false;
13 config->dac_mode = dac_mode_direct;
14 config->ana_div = dac_ana_div_2;
15 }
16
dac_init(DAC_Type * ptr,dac_config_t * config)17 hpm_stat_t dac_init(DAC_Type *ptr, dac_config_t *config)
18 {
19 if (config->dac_mode > dac_mode_trig) {
20 return status_invalid_argument;
21 }
22
23 if (config->ana_div > dac_ana_div_8) {
24 return status_invalid_argument;
25 }
26
27 /* reset DAC output data */
28 ptr->CFG0_BAK &= ~DAC_CFG0_SW_DAC_DATA_MASK;
29
30 /* set sync mode */
31 ptr->CFG0_BAK &= ~DAC_CFG0_SYNC_MODE_MASK;
32 ptr->CFG0_BAK |= DAC_CFG0_SYNC_MODE_SET(config->sync_mode);
33
34 /* set DAC mode */
35 ptr->CFG0_BAK &= ~DAC_CFG0_DAC_MODE_MASK;
36 ptr->CFG0_BAK |= DAC_CFG0_DAC_MODE_SET(config->dac_mode);
37
38 /* refresh the CFG0 */
39 ptr->CFG0 = ptr->CFG0_BAK;
40
41 /* set DAC clock config */
42 ptr->CFG1 &= ~DAC_CFG1_ANA_DIV_CFG_MASK;
43 ptr->CFG1 |= DAC_CFG1_ANA_DIV_CFG_SET(config->ana_div);
44
45 if (config->dac_mode == dac_mode_direct || config->dac_mode == dac_mode_trig) {
46 /* set ANA_CLK_EN */
47 ptr->CFG1 |= DAC_CFG1_ANA_CLK_EN_MASK;
48 }
49
50 return status_success;
51 }
52
dac_set_step_config(DAC_Type * ptr,uint8_t step_cfg_idx,dac_step_config_t * config)53 hpm_stat_t dac_set_step_config(DAC_Type *ptr, uint8_t step_cfg_idx, dac_step_config_t *config)
54 {
55 uint16_t temp;
56
57 /* check the validity */
58 if (step_cfg_idx > DAC_STEP_CFG_STEP3) {
59 return status_invalid_argument;
60 }
61
62 if (config->up_down == dac_step_up) {
63 if (config->start_point > config->end_point) {
64 return status_invalid_argument;
65 }
66 } else {
67 if (config->start_point < config->end_point) {
68 return status_invalid_argument;
69 }
70 }
71
72 /* check if the output data can reach the end point */
73 if (config->step_num != 0) {
74 if (config->start_point <= config->end_point) {
75 temp = config->end_point - config->start_point;
76 } else {
77 temp = config->start_point - config->end_point;
78 }
79
80 if (temp % config->step_num != 0) {
81 return status_invalid_argument;
82 }
83 }
84
85 /* set the round mode */
86 ptr->STEP_CFG[step_cfg_idx] &= ~DAC_STEP_CFG_ROUND_MODE_MASK;
87 ptr->STEP_CFG[step_cfg_idx] |= DAC_STEP_CFG_ROUND_MODE_SET(config->round_mode);
88
89 /* set the step direction */
90 ptr->STEP_CFG[step_cfg_idx] &= ~DAC_STEP_CFG_UP_DOWN_MASK;
91 ptr->STEP_CFG[step_cfg_idx] |= DAC_STEP_CFG_UP_DOWN_SET(config->up_down);
92
93 /* set the start point */
94 ptr->STEP_CFG[step_cfg_idx] &= ~DAC_STEP_CFG_START_POINT_MASK;
95 ptr->STEP_CFG[step_cfg_idx] |= DAC_STEP_CFG_START_POINT_SET(config->start_point);
96
97 /* set the end point */
98 ptr->STEP_CFG[step_cfg_idx] &= ~DAC_STEP_CFG_END_POINT_MASK;
99 ptr->STEP_CFG[step_cfg_idx] |= DAC_STEP_CFG_END_POINT_SET(config->end_point);
100
101 /* set the step value */
102 ptr->STEP_CFG[step_cfg_idx] &= ~DAC_STEP_CFG_STEP_NUM_MASK;
103 ptr->STEP_CFG[step_cfg_idx] |= DAC_STEP_CFG_STEP_NUM_SET(config->step_num);
104
105 return status_success;
106 }
107
dac_set_buffer_config(DAC_Type * ptr,dac_buffer_config_t * config)108 hpm_stat_t dac_set_buffer_config(DAC_Type *ptr, dac_buffer_config_t *config)
109 {
110 if (config->buf0.len == 0) {
111 return status_invalid_argument;
112 }
113
114 /* disable the internal DMA */
115 ptr->CFG0_BAK &= ~DAC_CFG0_DMA_AHB_EN_MASK;
116
117 /* refresh the CFG0 */
118 ptr->CFG0 = ptr->CFG0_BAK;
119
120 /* set buffer data mode */
121 ptr->CFG0_BAK &= ~DAC_CFG0_BUF_DATA_MODE_MASK;
122 ptr->CFG0_BAK |= DAC_CFG0_BUF_DATA_MODE_SET(config->buf_data_mode);
123
124 /* set burst type */
125 ptr->CFG0_BAK &= ~DAC_CFG0_HBURST_CFG_MASK;
126 ptr->CFG0_BAK |= DAC_CFG0_HBURST_CFG_SET(config->burst);
127
128 /* reset DMA and FIFO */
129 ptr->CFG2 |= DAC_CFG2_DMA_RST1_MASK | DAC_CFG2_DMA_RST0_MASK | DAC_CFG2_FIFO_CLR_MASK;
130
131 /* set buffer 0 start address for DMA */
132 ptr->BUF_ADDR[DAC_BUF_ADDR_BUF0] &= ~DAC_BUF_ADDR_BUF_START_ADDR_MASK;
133 ptr->BUF_ADDR[DAC_BUF_ADDR_BUF0] |= config->buf0.start_addr & DAC_BUF_ADDR_BUF_START_ADDR_MASK;
134
135 /* set buffer 0 stop */
136 ptr->BUF_ADDR[DAC_BUF_ADDR_BUF0] &= ~DAC_BUF_ADDR_BUF_STOP_MASK;
137 ptr->BUF_ADDR[DAC_BUF_ADDR_BUF0] |= DAC_BUF_ADDR_BUF_STOP_SET(config->buf0.stop);
138
139 /* set buffer 0 length */
140 ptr->BUF_LENGTH &= ~DAC_BUF_LENGTH_BUF0_LEN_MASK;
141 ptr->BUF_LENGTH |= DAC_BUF_LENGTH_BUF0_LEN_SET(config->buf0.len - 1);
142
143 /* set buffer 1 start address for DMA */
144 ptr->BUF_ADDR[DAC_BUF_ADDR_BUF1] &= ~DAC_BUF_ADDR_BUF_START_ADDR_MASK;
145 ptr->BUF_ADDR[DAC_BUF_ADDR_BUF1] |= config->buf1.start_addr & DAC_BUF_ADDR_BUF_START_ADDR_MASK;
146
147 /* set buffer 1 stop */
148 ptr->BUF_ADDR[DAC_BUF_ADDR_BUF1] &= ~DAC_BUF_ADDR_BUF_STOP_MASK;
149 ptr->BUF_ADDR[DAC_BUF_ADDR_BUF1] |= DAC_BUF_ADDR_BUF_STOP_SET(config->buf1.stop);
150
151 /* set buffer 1 length */
152 ptr->BUF_LENGTH &= ~DAC_BUF_LENGTH_BUF1_LEN_MASK;
153 ptr->BUF_LENGTH |= DAC_BUF_LENGTH_BUF1_LEN_SET(config->buf1.len - 1);
154
155 /* enable the internal DMA */
156 ptr->CFG0_BAK |= DAC_CFG0_DMA_AHB_EN_MASK;
157
158 /* refresh the CFG0 */
159 ptr->CFG0 = ptr->CFG0_BAK;
160
161 return status_success;
162 }
163
dac_set_direct_config(DAC_Type * ptr,uint16_t data)164 hpm_stat_t dac_set_direct_config(DAC_Type *ptr, uint16_t data)
165 {
166 if (data > DAC_SOC_MAX_DATA) {
167 return status_invalid_argument;
168 }
169
170 /* set dac data to analog output */
171 ptr->CFG0_BAK &= ~DAC_CFG0_SW_DAC_DATA_MASK;
172 ptr->CFG0_BAK |= DAC_CFG0_SW_DAC_DATA_SET(data);
173
174 /* refresh the CFG0 */
175 ptr->CFG0 = ptr->CFG0_BAK;
176
177 return status_success;
178 }
179
dac_set_output_frequency(DAC_Type * ptr,uint32_t dac_input_freq,uint32_t dac_output_freq)180 hpm_stat_t dac_set_output_frequency(DAC_Type *ptr, uint32_t dac_input_freq, uint32_t dac_output_freq)
181 {
182 if (dac_output_freq > DAC_SOC_MAX_OUTPUT_FREQ) {
183 return status_invalid_argument;
184 }
185
186 /* set output frequency config */
187 ptr->CFG1 &= ~DAC_CFG1_DIV_CFG_MASK;
188 ptr->CFG1 |= DAC_CFG1_DIV_CFG_SET(dac_input_freq % dac_output_freq ? (dac_input_freq / dac_output_freq + 1) : (dac_input_freq / dac_output_freq));
189
190 return status_success;
191 }
192
dac_set_step_sw_trigger(DAC_Type * ptr,uint8_t step_sw_trig_idx)193 hpm_stat_t dac_set_step_sw_trigger(DAC_Type *ptr, uint8_t step_sw_trig_idx)
194 {
195 if (step_sw_trig_idx > DAC_STEP_CFG_STEP3) {
196 return status_invalid_argument;
197 }
198
199 /* disable hw trigger */
200 ptr->CFG0_BAK &= ~DAC_CFG0_HW_TRIG_EN_MASK;
201
202 /* refresh the CFG0 */
203 ptr->CFG0 = ptr->CFG0_BAK;
204
205 /* enable sw trigger */
206 ptr->CFG2 |= 1 << step_sw_trig_idx;
207
208 return status_success;
209 }
210
dac_set_buffer_sw_trigger(DAC_Type * ptr)211 void dac_set_buffer_sw_trigger(DAC_Type *ptr)
212 {
213 /* disable hw trigger */
214 ptr->CFG0_BAK &= ~DAC_CFG0_HW_TRIG_EN_MASK;
215
216 /* refresh the CFG0 */
217 ptr->CFG0 = ptr->CFG0_BAK;
218
219 /* enable sw trigger */
220 ptr->CFG2 |= DAC_CFG2_BUF_SW_TRIG_MASK;
221 }
222
dac_set_buffer_DMA_reset(DAC_Type * ptr)223 void dac_set_buffer_DMA_reset(DAC_Type *ptr)
224 {
225 ptr->CFG2 |= DAC_CFG2_DMA_RST1_MASK | DAC_CFG2_DMA_RST0_MASK | DAC_CFG2_FIFO_CLR_MASK;
226 }
227
dac_set_hw_trigger_enable(DAC_Type * ptr,bool enable)228 void dac_set_hw_trigger_enable(DAC_Type *ptr, bool enable)
229 {
230 ptr->CFG0_BAK &= ~DAC_CFG0_HW_TRIG_EN_MASK;
231 ptr->CFG0_BAK |= DAC_CFG0_HW_TRIG_EN_SET(enable);
232
233 /* refresh the CFG0 */
234 ptr->CFG0 = ptr->CFG0_BAK;
235 }
236
dac_enable_conversion(DAC_Type * ptr,bool enable)237 void dac_enable_conversion(DAC_Type *ptr, bool enable)
238 {
239 ptr->ANA_CFG0 &= ~DAC_ANA_CFG0_DAC12BIT_EN_MASK;
240 ptr->ANA_CFG0 |= DAC_ANA_CFG0_DAC12BIT_EN_SET(enable);
241 }
242
dac_external_DMA_request_enable(DAC_Type * ptr,uint8_t buf_idx,bool enable)243 hpm_stat_t dac_external_DMA_request_enable(DAC_Type *ptr, uint8_t buf_idx, bool enable)
244 {
245 if (buf_idx > DAC_BUF_ADDR_BUF1) {
246 return status_invalid_argument;
247 }
248
249 ptr->DMA_EN &= ~(1 << buf_idx);
250 ptr->DMA_EN |= enable << buf_idx;
251
252 return status_success;
253 }
254
dac_enable_interrupts(DAC_Type * ptr,uint32_t mask)255 void dac_enable_interrupts(DAC_Type *ptr, uint32_t mask)
256 {
257 ptr->IRQ_EN |= mask;
258 }
259
dac_get_status_flags(DAC_Type * ptr)260 uint32_t dac_get_status_flags(DAC_Type *ptr)
261 {
262 return ptr->IRQ_STS;
263 }
264
dac_set_status_flags(DAC_Type * ptr,uint32_t mask)265 void dac_set_status_flags(DAC_Type *ptr, uint32_t mask)
266 {
267 ptr->IRQ_STS = mask;
268 }
269
dac_get_current_buffer_index(DAC_Type * ptr)270 uint8_t dac_get_current_buffer_index(DAC_Type *ptr)
271 {
272 return DAC_STATUS0_CUR_BUF_INDEX_GET(ptr->STATUS0);
273 }
274
dac_get_current_buffer_offset(DAC_Type * ptr)275 uint16_t dac_get_current_buffer_offset(DAC_Type *ptr)
276 {
277 return DAC_STATUS0_CUR_BUF_OFFSET_GET(ptr->STATUS0);
278 }
279