1 /*
2 * Copyright (c) 2006-2023, RT-Thread Development Team
3 *
4 * SPDX-License-Identifier: Apache-2.0
5 *
6 * Change Logs:
7 * Date Author Notes
8 * 2022-03-04 stevetong459 first version
9 * 2022-07-15 Aligagago add APM32F4 series MCU support
10 * 2022-12-26 luobeihai add APM32F0 series MCU support
11 * 2023-03-27 luobeihai add APM32E1 series MCU support
12 */
13
14 #include <board.h>
15
16 #if defined(BSP_USING_DAC1)
17
18 #define DBG_TAG "drv.dac"
19 #define DBG_LVL DBG_LOG
20 #include <rtdbg.h>
21
22 struct apm32_dac
23 {
24 const char *name;
25 DAC_T *dac;
26 DAC_Config_T dac_conf;
27 struct rt_dac_device dac_dev;
28 };
29
30 static struct apm32_dac dac_config[] =
31 {
32
33 #if defined (BSP_USING_DAC1)
34 {
35 #if defined (SOC_SERIES_APM32F0)
36 "dac1",
37 DAC,
38 {
39 DAC_TRIGGER_SOFTWARE,
40 DAC_OUTPUTBUFF_DISABLE,
41 DAC_WAVE_GENERATION_NONE,
42 DAC_TRIANGLEAMPLITUDE_4095,
43 },
44 #elif defined (SOC_SERIES_APM32F1) || defined (SOC_SERIES_APM32E1) || defined (SOC_SERIES_APM32F4)
45 "dac1",
46 DAC,
47 {
48 DAC_TRIGGER_SOFT,
49 DAC_OUTPUT_BUFFER_DISABLE,
50 DAC_WAVE_GENERATION_NONE,
51 DAC_TRIANGLE_AMPLITUDE_4095,
52 },
53 #endif
54 }
55 #endif
56 };
57
58 /**
59 * @brief This function will enable dac.
60 *
61 * @param device is a pointer to dac device.
62 *
63 * @param channel is the dac channel.
64 *
65 * @return RT_EOK indicates successful enable dac, other value indicates failed.
66 */
apm32_dac_enabled(struct rt_dac_device * device,rt_uint32_t channel)67 static rt_err_t apm32_dac_enabled(struct rt_dac_device *device, rt_uint32_t channel)
68 {
69 GPIO_Config_T GPIO_ConfigStruct;
70 struct apm32_dac *cfg = (struct apm32_dac *)device->parent.user_data;
71 #if defined (SOC_SERIES_APM32F1) || defined (SOC_SERIES_APM32E1)
72 RCM_EnableAPB2PeriphClock(RCM_APB2_PERIPH_GPIOA);
73 GPIO_ConfigStruct.mode = GPIO_MODE_ANALOG;
74 #elif defined (SOC_SERIES_APM32F4)
75 RCM_EnableAHB1PeriphClock(RCM_AHB1_PERIPH_GPIOA);
76 GPIO_ConfigStruct.mode = GPIO_MODE_AN;
77 #elif defined (SOC_SERIES_APM32F0)
78 RCM_EnableAHBPeriphClock(RCM_AHB_PERIPH_GPIOA);
79 GPIO_ConfigStruct.mode = GPIO_MODE_AN;
80 #endif
81 if (channel == 1)
82 {
83 GPIO_ConfigStruct.pin = GPIO_PIN_4;
84 GPIO_Config(GPIOA, &GPIO_ConfigStruct);
85
86 DAC_Config(DAC_CHANNEL_1, &cfg->dac_conf);
87 DAC_Enable(DAC_CHANNEL_1);
88 }
89 else if (channel == 2)
90 {
91 GPIO_ConfigStruct.pin = GPIO_PIN_5;
92 GPIO_Config(GPIOA, &GPIO_ConfigStruct);
93
94 DAC_Config(DAC_CHANNEL_2, &cfg->dac_conf);
95 DAC_Enable(DAC_CHANNEL_2);
96 }
97 else
98 {
99 LOG_E("dac channel must be 1 or 2.");
100 return -RT_ERROR;
101 }
102
103 return RT_EOK;
104 }
105
106 /**
107 * @brief This function will disable dac.
108 *
109 * @param device is a pointer to dac device.
110 *
111 * @param channel is the dac channel.
112 *
113 * @return RT_EOK indicates successful disable dac, other value indicates failed.
114 */
apm32_dac_disabled(struct rt_dac_device * device,rt_uint32_t channel)115 static rt_err_t apm32_dac_disabled(struct rt_dac_device *device, rt_uint32_t channel)
116 {
117 if (channel == 1)
118 {
119 DAC_Disable(DAC_CHANNEL_1);
120 }
121 else if (channel == 2)
122 {
123 DAC_Disable(DAC_CHANNEL_2);
124 }
125 else
126 {
127 LOG_E("dac channel must be 1 or 2.");
128 return -RT_ERROR;
129 }
130
131 return RT_EOK;
132 }
133
134 /**
135 * @brief This function will set the vaule of dac.
136 *
137 * @param device is a pointer to dac device.
138 *
139 * @param channel is the dac channel.
140 *
141 * @param value is a pointer to dac value to be convert.
142 *
143 * @return RT_EOK indicates successful set dac value, other value indicates failed.
144 */
apm32_dac_set_value(struct rt_dac_device * device,rt_uint32_t channel,rt_uint32_t * value)145 static rt_err_t apm32_dac_set_value(struct rt_dac_device *device, rt_uint32_t channel, rt_uint32_t *value)
146 {
147 #if defined (SOC_SERIES_APM32F0)
148 if (channel == 1)
149 {
150 DAC_ConfigChannel1Data(DAC_ALIGN_12B_R, *value);
151 DAC_EnableSoftwareTrigger(DAC_CHANNEL_1);
152 }
153 else if (channel == 2)
154 {
155 DAC_ConfigChannel2Data(DAC_ALIGN_12B_R, *value);
156 DAC_EnableSoftwareTrigger(DAC_CHANNEL_2);
157 }
158 else
159 {
160 LOG_E("dac channel must be 1 or 2.");
161 return -RT_ERROR;
162 }
163 #elif defined (SOC_SERIES_APM32F1) || defined (SOC_SERIES_APM32E1) || defined (SOC_SERIES_APM32F4)
164 if (channel == 1)
165 {
166 DAC_ConfigChannel1Data(DAC_ALIGN_12BIT_R, *value);
167 DAC_EnableSoftwareTrigger(DAC_CHANNEL_1);
168 }
169 else if (channel == 2)
170 {
171 DAC_ConfigChannel2Data(DAC_ALIGN_12BIT_R, *value);
172 DAC_EnableSoftwareTrigger(DAC_CHANNEL_2);
173 }
174 else
175 {
176 LOG_E("dac channel must be 1 or 2.");
177 return -RT_ERROR;
178 }
179 #endif
180 return RT_EOK;
181 }
182
183 static const struct rt_dac_ops apm32_dac_ops =
184 {
185 .disabled = apm32_dac_disabled,
186 .enabled = apm32_dac_enabled,
187 .convert = apm32_dac_set_value,
188 };
189
190 /**
191 * @brief DAC initialization function.
192 *
193 * @return RT_EOK indicates successful initialization, other value indicates failed;
194 */
rt_hw_dac_init(void)195 static int rt_hw_dac_init(void)
196 {
197 rt_err_t result = RT_EOK;
198 rt_size_t obj_num = sizeof(dac_config) / sizeof(struct apm32_dac);
199 rt_uint32_t i = 0;
200
201 RCM_EnableAPB1PeriphClock(RCM_APB1_PERIPH_DAC);
202
203 for (i = 0; i < obj_num; i++)
204 {
205 /* register dac device */
206 if (rt_hw_dac_register(&dac_config[i].dac_dev, dac_config[i].name, &apm32_dac_ops, dac_config) == RT_EOK)
207 {
208 LOG_D("%s init success", dac_config[i].name);
209 }
210 else
211 {
212 LOG_E("%s init failed", dac_config[i].name);
213 result = -RT_ERROR;
214 }
215 }
216
217 return result;
218 }
219 INIT_DEVICE_EXPORT(rt_hw_dac_init);
220
221 #endif /* BSP_USING_DACX */
222