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