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