1 /*
2 * Copyright (C) 2022-2024, Xiaohua Semiconductor Co., Ltd.
3 *
4 * SPDX-License-Identifier: Apache-2.0
5 *
6 * Change Logs:
7 * Date Author Notes
8 * 2023-05-12 CDT first version
9 */
10 #include <board.h>
11
12 #if defined(BSP_USING_DAC1) || defined(BSP_USING_DAC2) || defined(BSP_USING_DAC3) || defined(BSP_USING_DAC4)
13
14 #include <drivers/dac.h>
15 #include <drv_dac.h>
16 #include <drv_config.h>
17 #include "rtdevice.h"
18 #include "hc32_ll.h"
19 #include <drv_log.h>
20 #include "board_config.h"
21
22 /* DAC features */
23 #define DAC_CHANNEL_ID_MAX (DAC_CH2 + 1U)
24 #define DAC_RESOLUTION (12)
25 #define DAC_LEFT_ALIGNED_DATA_MASK (0xFFF0U)
26 #define DAC_RIGHT_ALIGNED_DATA_MASK (0xFFFU)
27
28 typedef struct
29 {
30 struct rt_dac_device rt_dac;
31 CM_DAC_TypeDef *instance;
32 struct dac_dev_init_params init;
33 } dac_device;
34
35 static dac_device _g_dac_dev_array[] =
36 {
37 #ifdef BSP_USING_DAC1
38 {
39 {0},
40 #if defined (HC32F4A0) || defined (HC32F472) || defined (HC32F4A8)
41 CM_DAC1,
42 #elif defined (HC32F448)
43 CM_DAC,
44 #endif
45 DAC1_INIT_PARAMS,
46 },
47 #endif
48 #ifdef BSP_USING_DAC2
49 {
50 {0},
51 CM_DAC2,
52 DAC2_INIT_PARAMS,
53 },
54 #endif
55 #ifdef BSP_USING_DAC3
56 {
57 {0},
58 CM_DAC3,
59 DAC3_INIT_PARAMS,
60 },
61 #endif
62 #ifdef BSP_USING_DAC4
63 {
64 {0},
65 CM_DAC4,
66 DAC4_INIT_PARAMS,
67 },
68 #endif
69 };
70
_dac_get_channel(rt_uint32_t channel)71 static rt_uint16_t _dac_get_channel(rt_uint32_t channel)
72 {
73 rt_uint16_t ll_channel = 0;
74
75 switch (channel)
76 {
77 case 1:
78 ll_channel = DAC_CH1;
79 break;
80 case 2:
81 ll_channel = DAC_CH2;
82 break;
83 default:
84 RT_ASSERT(0);
85 break;
86 }
87
88 return ll_channel;
89 }
90
_dac_enabled(struct rt_dac_device * device,rt_uint32_t channel)91 static rt_err_t _dac_enabled(struct rt_dac_device *device, rt_uint32_t channel)
92 {
93 RT_ASSERT(device != RT_NULL);
94 RT_ASSERT(channel <= DAC_CHANNEL_ID_MAX);
95
96 CM_DAC_TypeDef *p_ll_instance = device->parent.user_data;
97 uint16_t ll_channel = _dac_get_channel(channel);
98 int32_t result = DAC_Start(p_ll_instance, ll_channel);
99
100 return (result == LL_OK) ? RT_EOK : -RT_ERROR;
101 }
102
_dac_disabled(struct rt_dac_device * device,rt_uint32_t channel)103 static rt_err_t _dac_disabled(struct rt_dac_device *device, rt_uint32_t channel)
104 {
105 RT_ASSERT(device != RT_NULL);
106 RT_ASSERT(channel <= DAC_CHANNEL_ID_MAX);
107
108 CM_DAC_TypeDef *p_ll_instance = device->parent.user_data;
109 uint16_t ll_channel = _dac_get_channel(channel);
110 int32_t result = DAC_Stop(p_ll_instance, ll_channel);
111
112 return (result == LL_OK) ? RT_EOK : -RT_ERROR;
113 }
114
_dac_get_resolution(struct rt_dac_device * device)115 static rt_uint8_t _dac_get_resolution(struct rt_dac_device *device)
116 {
117 return DAC_RESOLUTION;
118 }
119
_dac_set_value(struct rt_dac_device * device,rt_uint32_t channel,rt_uint32_t * value)120 static rt_err_t _dac_set_value(struct rt_dac_device *device, rt_uint32_t channel, rt_uint32_t *value)
121 {
122 RT_ASSERT(device != RT_NULL);
123 RT_ASSERT(channel <= DAC_CHANNEL_ID_MAX);
124 CM_DAC_TypeDef *p_ll_instance = device->parent.user_data;
125
126 if (READ_REG16_BIT(p_ll_instance->DACR, DAC_DACR_DPSEL) == DAC_DATA_ALIGN_LEFT)
127 {
128 RT_ASSERT(0U == (*value & ~DAC_LEFT_ALIGNED_DATA_MASK));
129 }
130 else
131 {
132 RT_ASSERT(0U == (*value & ~DAC_RIGHT_ALIGNED_DATA_MASK));
133 }
134 uint16_t ll_channel = _dac_get_channel(channel);
135 DAC_SetChData(p_ll_instance, ll_channel, *value);
136
137 return RT_EOK;
138 }
139
140 static const struct rt_dac_ops g_dac_ops =
141 {
142 .disabled = _dac_disabled,
143 .enabled = _dac_enabled,
144 .convert = _dac_set_value,
145 .get_resolution = _dac_get_resolution,
146 };
147
_dac_clock_enable(void)148 static void _dac_clock_enable(void)
149 {
150 #if defined(BSP_USING_DAC1)
151 #if defined (HC32F4A0) || defined (HC32F472) || defined (HC32F4A8)
152 FCG_Fcg3PeriphClockCmd(FCG3_PERIPH_DAC1, ENABLE);
153 #elif defined (HC32F448)
154 FCG_Fcg3PeriphClockCmd(FCG3_PERIPH_DAC, ENABLE);
155 #endif
156 #endif
157 #if defined(BSP_USING_DAC2)
158 FCG_Fcg3PeriphClockCmd(FCG3_PERIPH_DAC2, ENABLE);
159 #endif
160 #if defined(BSP_USING_DAC3)
161 FCG_Fcg3PeriphClockCmd(FCG3_PERIPH_DAC3, ENABLE);
162 #endif
163 #if defined(BSP_USING_DAC4)
164 FCG_Fcg3PeriphClockCmd(FCG3_PERIPH_DAC4, ENABLE);
165 #endif
166 }
167
168 extern rt_err_t rt_hw_board_dac_init(CM_DAC_TypeDef *DACx);
rt_hw_dac_init(void)169 int rt_hw_dac_init(void)
170 {
171 int result = RT_EOK;
172 rt_err_t ret;
173 int i = 0;
174 stc_dac_init_t stcDacInit = {0};
175 int32_t ll_ret = 0;
176
177 _dac_clock_enable();
178 uint32_t dev_cnt = sizeof(_g_dac_dev_array) / sizeof(_g_dac_dev_array[0]);
179 for (; i < dev_cnt; i++)
180 {
181 DAC_DeInit(_g_dac_dev_array[i].instance);
182 stcDacInit.enOutput = _g_dac_dev_array[i].init.ch1_output_enable;
183 #if defined (HC32F4A0) || defined (HC32F448) || defined (HC32F4A8)
184 stcDacInit.u16Src = _g_dac_dev_array[i].init.ch1_data_src;
185 #endif
186 ll_ret = DAC_Init((void *)_g_dac_dev_array[i].instance, DAC_CH1, &stcDacInit);
187 #if defined (HC32F4A0) || defined (HC32F448) || defined (HC32F4A8)
188 stcDacInit.u16Src = _g_dac_dev_array[i].init.ch2_data_src;
189 #endif
190 stcDacInit.enOutput = _g_dac_dev_array[i].init.ch2_output_enable;
191 ll_ret = DAC_Init((void *)_g_dac_dev_array[i].instance, DAC_CH2, &stcDacInit);
192 DAC_DataRegAlignConfig(_g_dac_dev_array[i].instance, _g_dac_dev_array[i].init.data_align);
193
194 if (ll_ret != LL_OK)
195 {
196 ret = -RT_ERROR;
197 break;
198 }
199
200 DAC_ADCPrioConfig(_g_dac_dev_array[i].instance, _g_dac_dev_array[i].init.dac_adp_sel, ENABLE);
201 DAC_ADCPrioCmd(_g_dac_dev_array[i].instance, _g_dac_dev_array[i].init.dac_adp_enable);
202
203 #if defined (HC32F472)
204 DAC_SetAmpGain(_g_dac_dev_array[i].instance, DAC_CH1, _g_dac_dev_array[i].init.ch1_amp_gain);
205 DAC_SetAmpGain(_g_dac_dev_array[i].instance, DAC_CH2, _g_dac_dev_array[i].init.ch2_amp_gain);
206 #endif
207 DAC_AMPCmd(_g_dac_dev_array[i].instance, DAC_CH1, _g_dac_dev_array[i].init.ch1_amp_enable);
208 DAC_AMPCmd(_g_dac_dev_array[i].instance, DAC_CH2, _g_dac_dev_array[i].init.ch2_amp_enable);
209
210 rt_hw_board_dac_init(_g_dac_dev_array[i].instance);
211 ret = rt_hw_dac_register(&_g_dac_dev_array[i].rt_dac, \
212 (const char *)_g_dac_dev_array[i].init.name, \
213 &g_dac_ops, (void *)_g_dac_dev_array[i].instance);
214 if (ret == RT_EOK)
215 {
216 LOG_D("%s init success", (const char *)_g_dac_dev_array[i].init.name);
217 }
218 else
219 {
220 LOG_E("%s register failed", (const char *)_g_dac_dev_array[i].init.name);
221 result = -RT_ERROR;
222 }
223 }
224
225 return result;
226 }
227 INIT_DEVICE_EXPORT(rt_hw_dac_init);
228
229 #endif /* BSP_USING_DAC */
230