• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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