1 /*
2  * Copyright (c) 2006-2024, RT-Thread Development Team
3  *
4  * SPDX-License-Identifier: Apache-2.0
5  *
6  * Change Logs:
7  * Date           Author       Notes
8  * 2024-05-17     QT-one       first version
9  */
10 
11 #include <rtdbg.h>
12 #include "drv_adc.h"
13 
14 
15 #ifdef RT_USING_ADC
16 #if !defined(BSP_USING_ADC0) && !defined(BSP_USING_ADC1)
17     #error "Please define at least one BSP_USING_ADCx"
18     /* this driver can be disabled at menuconfig RT-Thread Components Device Drivers */
19 #endif
20 
21 struct ht32_adc
22 {
23     struct rt_adc_device ht32_adc_device;
24     HT_ADC_TypeDef *adc_x;
25     char *name;
26 };
27 
28 /* ADC Peripheral List */
29 static struct ht32_adc ht32_adc_obj[] =
30 {
31 #ifdef BSP_USING_ADC0
32     {
33         .adc_x        = HT_ADC0,
34         .name         = BSP_USING_ADC0_NAME,
35     },
36 #endif
37 
38 #ifdef BSP_USING_ADC1
39     {
40         .adc_x        = HT_ADC1,
41         .name         = BSP_USING_ADC1_NAME,
42     },
43 #endif
44 };
45 
ht32_adc_enabled(struct rt_adc_device * device,rt_int8_t channel,rt_bool_t enabled)46 static rt_err_t ht32_adc_enabled(struct rt_adc_device *device, rt_int8_t channel, rt_bool_t enabled)
47 {
48     HT_ADC_TypeDef *adc_x;
49     RT_ASSERT(device != RT_NULL);
50     adc_x = (HT_ADC_TypeDef*)device->parent.user_data;
51 
52     if(enabled)
53     {
54         ht32_adc_gpio_init(adc_x,channel);
55         /* Configure the CK_ADCn prescaler */
56 #ifdef BSP_USING_ADC0
57         if(HT_ADC0 == adc_x)
58         {
59             CKCU_SetADCnPrescaler(CKCU_ADCPRE_ADC0,CKCU_ADCPRE_DIV64);
60         }
61 #endif
62 #ifdef BSP_USING_ADC1
63         if(HT_ADC1 == adc_x)
64         {
65             CKCU_SetADCnPrescaler(CKCU_ADCPRE_ADC1,CKCU_ADCPRE_DIV64);
66         }
67 #endif
68         /* Configure conversion mode and sequence length (number of conversion channels) */
69         ADC_RegularGroupConfig(adc_x,ONE_SHOT_MODE,1,0);
70 
71 #ifdef SOC_SERIES_HT32F5
72         /* Configuring the Sampling Time */
73         ADC_SamplingTimeConfig(adc_x,0);
74         /* Configuring Channel Priority */
75         ADC_RegularChannelConfig(adc_x,channel,0);
76 #endif
77 #ifdef SOC_SERIES_HT32F1
78         /* Configuring Channel Priority */
79         ADC_RegularChannelConfig(adc_x,channel,0,0);
80 #endif
81         /* Configuring the Trigger Source */
82         ADC_RegularTrigConfig(adc_x,ADC_TRIG_SOFTWARE);
83         /* Enable ADC */
84         ADC_Cmd(adc_x,ENABLE);
85     }
86     else
87     {
88         /* Disable ADC */
89         ADC_Cmd(adc_x,DISABLE);
90     }
91     return RT_EOK;
92 }
93 
ht32_adc_convert(struct rt_adc_device * device,rt_int8_t channel,rt_uint32_t * value)94 static rt_err_t ht32_adc_convert(struct rt_adc_device *device, rt_int8_t channel, rt_uint32_t *value)
95 {
96     HT_ADC_TypeDef *adc_x;
97     rt_uint32_t timeout = 0;
98     FlagStatus adc_writ_flag = RESET;
99     RT_ASSERT(device != RT_NULL);
100     adc_x = (HT_ADC_TypeDef*)device->parent.user_data;
101 
102     /* Toggle the acquisition channel */
103 #ifdef SOC_SERIES_HT32F5
104     ADC_RegularChannelConfig(adc_x,channel,0);
105 #endif
106 #ifdef SOC_SERIES_HT32F1
107     ADC_RegularChannelConfig(adc_x,channel,0,0);
108 #endif
109 
110     /* enable Software triggered */
111     ADC_SoftwareStartConvCmd(adc_x,ENABLE);
112     while((!adc_writ_flag) && (timeout < 0xFFFF))
113     {
114         /* Wait for the conversion to complete */
115         adc_writ_flag = ADC_GetFlagStatus(adc_x,ADC_FLAG_SINGLE_EOC);
116         timeout++;
117     }
118     if(timeout >= 0xFFFF)
119     {
120         LOG_D("channel%d converts timeout, please confirm adc_x enabled or not", channel);
121         /* disable Software triggered */
122         ADC_SoftwareStartConvCmd(adc_x,DISABLE);
123         return -RT_ERROR;
124     }
125     /* clear ADC_FLAG_SINGLE_EOC flag */
126     ADC_ClearIntPendingBit(adc_x,ADC_FLAG_SINGLE_EOC);
127     /* get adc value */
128     *value = ADC_GetConversionData(adc_x,ADC_REGULAR_DATA0);
129     /* disable Software triggered */
130     ADC_SoftwareStartConvCmd(adc_x,DISABLE);
131     return RT_EOK;
132 }
133 
ht32_adc_get_resolution(struct rt_adc_device * device)134 static rt_uint8_t ht32_adc_get_resolution(struct rt_adc_device *device)
135 {
136     return 0;
137 }
138 
ht32_adc_get_vref(struct rt_adc_device * device)139 static rt_int16_t ht32_adc_get_vref(struct rt_adc_device *device)
140 {
141     return 0;
142 }
143 
144 /* ADC Device Operation Function Interface */
145 static const struct rt_adc_ops ht32_adc_ops =
146 {
147     .enabled = ht32_adc_enabled,
148     .convert = ht32_adc_convert,
149     .get_resolution = ht32_adc_get_resolution,
150     .get_vref = ht32_adc_get_vref,
151 };
152 
rt_hw_adc_init(void)153 static int rt_hw_adc_init(void)
154 {
155     int result = RT_EOK;
156     int i = 0;
157     for (i = 0; i < sizeof(ht32_adc_obj) / sizeof(ht32_adc_obj[0]); i++)
158     {
159         /* register ADC device */
160         if (rt_hw_adc_register(&ht32_adc_obj[i].ht32_adc_device, ht32_adc_obj[i].name, &ht32_adc_ops, ht32_adc_obj[i].adc_x) == RT_EOK)
161         {
162             LOG_D("%s register success", ht32_adc_obj[i].name);
163         }
164         else
165         {
166             LOG_E("%s register failed", ht32_adc_obj[i].name);
167             result = -RT_ERROR;
168         }
169     }
170     return result;
171 }
172 INIT_BOARD_EXPORT(rt_hw_adc_init);
173 
174 #endif /* RT_USING_ADC */
175