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  * 2021-09-27     fzxhub       the first version
9  */
10 
11 #include <rtthread.h>
12 #include <rtdevice.h>
13 #include "board.h"
14 #include "drv_adc.h"
15 
16 #ifdef RT_USING_ADC
17 
18 #ifdef BSP_USING_ADC
19 
20 struct lpc_adc
21 {
22     LPC_ADC_TypeDef *ADC;
23 };
24 /*
25 * channel:0-7
26 */
lpc_adc_enabled(struct rt_adc_device * device,rt_uint32_t channel,rt_bool_t enabled)27 static rt_err_t lpc_adc_enabled(struct rt_adc_device *device, rt_uint32_t channel, rt_bool_t enabled)
28 {
29     struct lpc_adc *adc;
30 
31     RT_ASSERT(device != RT_NULL);
32     adc = (struct lpc_adc *)device->parent.user_data;
33 
34     //enabled ADC
35     if(enabled == RT_FALSE) adc->ADC->CR &= ~(1<<21);
36     else adc->ADC->CR |= (1<<21);
37 
38     //Select the channel
39     adc->ADC->CR |= (1<<channel);
40 
41     return RT_EOK;
42 }
43 
lpc_adc_convert(struct rt_adc_device * device,rt_uint32_t channel,rt_uint32_t * value)44 static rt_err_t lpc_adc_convert(struct rt_adc_device *device, rt_uint32_t channel, rt_uint32_t *value)
45 {
46     rt_uint32_t data;
47 
48     struct lpc_adc *adc;
49 
50     RT_ASSERT(device != RT_NULL);
51     adc = (struct lpc_adc *)device->parent.user_data;
52 
53     adc->ADC->CR = (LPC_ADC->CR & 0x00FFFF00) | (1<<channel) | (1 << 24);
54     while ((adc->ADC->GDR & 0x80000000) == 0);
55     adc->ADC->CR = adc->ADC->CR | (1 << 24);
56     while ((adc->ADC->GDR & 0x80000000) == 0);
57 
58     data = adc->ADC->GDR;
59     data = (data >> 4) & 0xFFF;
60 
61     *value = data;
62 
63     return RT_EOK;
64 }
65 
66 static const struct rt_adc_ops lpc_adc_ops =
67 {
68     lpc_adc_enabled,
69     lpc_adc_convert,
70 };
71 
72 struct lpc_adc lpc_adc0 =
73 {
74     LPC_ADC,
75 };
76 
77 struct rt_adc_device adc0;
78 
rt_hw_adc_init(void)79 int rt_hw_adc_init(void)
80 {
81     rt_err_t ret = RT_EOK;
82     struct lpc_adc *adc;
83 
84     adc = &lpc_adc0;
85 
86     adc0.ops = &lpc_adc_ops;
87     adc0.parent.user_data = adc;
88 
89     //ADC port
90     LPC_IOCON->P0_23 = 0x01;     //ADC0[0]
91     LPC_IOCON->P0_24 = 0x01;     //ADC0[1]
92     LPC_IOCON->P0_25 = 0x01;     //ADC0[2]
93     LPC_IOCON->P0_26 = 0x01;     //ADC0[3]
94     LPC_IOCON->P1_30 = 0x03;     //ADC0[4]
95     LPC_IOCON->P1_31 = 0x03;     //ADC0[5]
96     LPC_IOCON->P0_12 = 0x03;     //ADC0[6]
97     LPC_IOCON->P0_13 = 0x03;     //ADC0[7]
98 
99 
100     //clock
101     LPC_SC->PCONP |= (1U << 12);
102     //config
103     LPC_ADC->CR = 0;
104     LPC_ADC->CR = (1 << 0)|      // SEL
105                   ((PeripheralClock / 1000000 - 1) << 8) |    // CLKDIV = Fpclk / 1000000 - 1
106                   (0 << 16)|     // BURST
107                   (0 << 17)|     // CLKS
108                   (1 << 21)|     // PDN
109                   (0 << 22)|     // TEST1
110                   (1 << 24)|     // START
111                   (0 << 27);     // EDGE
112     //waiting
113     while ((LPC_ADC->GDR & 0x80000000) == 0);
114 
115     ret = rt_hw_adc_register(&adc0,"adc0",&lpc_adc_ops,adc);
116 
117     return ret;
118 }
119 
120 INIT_BOARD_EXPORT(rt_hw_adc_init);
121 #endif /* BSP_USING_ADC */
122 
123 #endif /* RT_USING_ADC */
124