1 /*
2  * Copyright (c) 2006-2021, RT-Thread Development Team
3  *
4  * SPDX-License-Identifier: Apache-2.0
5  *
6  * Change Logs:
7  * Date           Author       Notes
8  * 2020-06-27     AHTYDHD      the first version
9  */
10 
11 #include "drv_adc.h"
12 #include <stdint.h>
13 #include <stdbool.h>
14 #include "inc/hw_memmap.h"
15 #include "driverlib/adc.h"
16 #include "driverlib/sysctl.h"
17 
18 #ifdef  RT_USING_ADC
19 #include "adc_config.h"
20 #include "tm4c123_config.h"
21 #include <string.h>
22 
23 #define LOG_TAG             "drv.adc"
24 #include <drv_log.h>
25 
26 static struct tm4c123_adc_config adc_config[] =
27 {
28 #ifdef BSP_USING_ADC0
29     ADC0_CONFIG,
30 #endif
31 #ifdef BSP_USING_ADC1
32     ADC1_CONFIG,
33 #endif
34 };
35 
36 struct tm4c123_adc
37 {
38     struct tm4c123_adc_config *config;
39     struct rt_adc_device adc_device;
40 };
41 
42 static struct tm4c123_adc   adc_obj[sizeof(adc_config) / sizeof(adc_config[0])] = {0};
43 
tm4c123_adc_enabled(struct rt_adc_device * device,rt_uint32_t channel,rt_bool_t enabled)44 static rt_err_t tm4c123_adc_enabled(struct rt_adc_device *device, rt_uint32_t channel, rt_bool_t enabled)
45 {
46     RT_ASSERT(device != RT_NULL);
47     struct tm4c123_adc_config   *config = (struct tm4c123_adc_config *)device->parent.user_data;
48 
49     if (enabled)
50     {
51         ADCSequenceEnable(config->adcbase, config->sequence);
52         ADCIntClear(config->adcbase, config->sequence);
53     }
54     else
55     {
56         ADCSequenceDisable(config->adcbase, config->sequence);
57     }
58     return RT_EOK;
59 }
60 
tm4c123_get_adc_value(struct rt_adc_device * device,rt_uint32_t channel,rt_uint32_t * value)61 static rt_err_t tm4c123_get_adc_value(struct rt_adc_device *device, rt_uint32_t channel, rt_uint32_t *value)
62 {
63 
64     RT_ASSERT(device != RT_NULL);
65     RT_ASSERT(value != RT_NULL);
66 
67     uint32_t    pui32ADC0Value[4] = {0};
68     struct tm4c123_adc_config   *config = (struct tm4c123_adc_config *)device->parent.user_data;
69 
70     /* Trigger the ADC conversion. */
71     ADCProcessorTrigger(config->adcbase, config->sequence);
72 
73     while (!ADCIntStatus(config->adcbase, config->sequence, false))
74     {
75     }
76 
77     /* Clear the ADC interrupt flag. */
78     ADCIntClear(config->adcbase, config->sequence);
79 
80     /* Read ADC Value. */
81     ADCSequenceDataGet(config->adcbase, config->sequence, pui32ADC0Value);
82 
83     /* get ADC value */
84     *value = (rt_uint32_t)pui32ADC0Value[channel];
85 
86     return RT_EOK;
87 }
88 
89 static const struct rt_adc_ops tm4c123_adc_ops =
90 {
91     .enabled = tm4c123_adc_enabled,
92     .convert = tm4c123_get_adc_value,
93 };
94 
95 
tm4c123_hw_adc_init(struct tm4c123_adc * device)96 static rt_err_t tm4c123_hw_adc_init(struct tm4c123_adc *device)
97 {
98 
99     uint32_t  adcbase = device->config->adcbase;
100     uint32_t  sequencenum = device->config->sequence;
101 
102     ADCSequenceConfigure(adcbase, sequencenum,
103                          device->config->trigermode, 0);
104 
105     ADCSequenceStepConfigure(adcbase, sequencenum, 0, ADC_CTL_CH7);
106     ADCSequenceStepConfigure(adcbase, sequencenum, 1, ADC_CTL_CH6 | ADC_CTL_IE);
107     ADCSequenceStepConfigure(adcbase, sequencenum, 2, ADC_CTL_CH5);
108     /*Tell the ADC logic
109       that this is the last conversion on sequence 3 (ADC_CTL_END). */
110     ADCSequenceStepConfigure(adcbase, sequencenum, 3, ADC_CTL_CH4 | ADC_CTL_IE |
111                              ADC_CTL_END);
112     return RT_EOK;
113 }
114 
115 
tm4c123_adc_init(void)116 static int tm4c123_adc_init(void)
117 {
118     int i = 0;
119     rt_size_t obj_num = sizeof(adc_obj) / sizeof(struct tm4c123_adc);
120     rt_err_t result = RT_EOK;
121 
122     adc_hw_config();
123 
124     for (i = 0; i < obj_num; i++)
125     {
126         /* ADC init */
127         adc_obj[i].config = &adc_config[i];
128 
129 
130         if (tm4c123_hw_adc_init(&adc_obj[i]) != RT_EOK)
131         {
132             LOG_E("%s init failed", adc_obj[i].config->name);
133             result = -RT_ERROR;
134             return result;
135         }
136         else
137         {
138             LOG_D("%s init success", adc_obj[i].config->name);
139 
140             /* register adc device */
141             if (rt_hw_adc_register(&adc_obj[i].adc_device, adc_obj[i].config->name, &tm4c123_adc_ops, &adc_config[i]) == RT_EOK)
142             {
143                 LOG_D("%s register success", adc_obj[i].config->name);
144             }
145             else
146             {
147                 LOG_E("%s register failed", adc_obj[i].config->name);
148                 result = -RT_ERROR;
149             }
150         }
151     }
152 
153     return result;
154 }
155 INIT_APP_EXPORT(tm4c123_adc_init);
156 
157 #endif  /*RT_UING_ADC*/
158 
159 /************************** end of file ******************/
160