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  * 2022-07-04     Rbb666       first version
9  */
10 #include "drv_config.h"
11 
12 #if defined(BSP_USING_ADC1) || defined(BSP_USING_ADC2)
13 
14 /*#define DRV_DEBUG*/
15 #define LOG_TAG             "drv.adc"
16 #include <drv_log.h>
17 
18 static struct ifx_adc ifx_adc_obj[] =
19 {
20     #ifdef BSP_USING_ADC1
21     ADC1_CONFIG,
22     #endif
23 };
24 
ifx_adc_enabled(struct rt_adc_device * device,rt_uint32_t channel,rt_bool_t enabled)25 static rt_err_t ifx_adc_enabled(struct rt_adc_device *device, rt_uint32_t channel, rt_bool_t enabled)
26 {
27     cyhal_adc_channel_t *adc_ch;
28     cy_rslt_t result;
29 
30     RT_ASSERT(device != RT_NULL);
31     adc_ch = device->parent.user_data;
32 
33     const cyhal_adc_channel_config_t channel_config =
34     {
35         .enable_averaging = false,      /* Disable averaging for channel*/
36         .min_acquisition_ns = 1000,     /* Minimum acquisition time set to 1us*/
37         .enabled = enabled              /* Sample this channel when ADC performs a scan*/
38     };
39 
40     if (enabled)
41     {
42         result = cyhal_adc_init(&adc_obj, adc_gpio[channel], NULL);
43 
44         if (result != RT_EOK)
45         {
46             LOG_E("ADC initialization failed. Error: %u\n", result);
47             return -RT_ENOSYS;
48         }
49 
50         result  = cyhal_adc_channel_init_diff(adc_ch, &adc_obj, adc_gpio[channel],
51                                               CYHAL_ADC_VNEG, &channel_config);
52 
53         if (result != RT_EOK)
54         {
55             LOG_E("ADC single ended channel initialization failed. Error: %u\n", result);
56             return -RT_ENOSYS;
57         }
58 
59         /* Update ADC configuration */
60         result = cyhal_adc_configure(&adc_obj, &adc_config);
61 
62         if (result != RT_EOK)
63         {
64             rt_kprintf("ADC configuration update failed. Error: %u\n", result);
65             return -RT_ENOSYS;
66         }
67     }
68     else
69     {
70         cyhal_adc_channel_free(adc_ch);
71         cyhal_adc_free(&adc_obj);
72     }
73 
74     return RT_EOK;
75 }
76 
ifx_get_adc_value(struct rt_adc_device * device,rt_uint32_t channel,rt_uint32_t * value)77 static rt_err_t ifx_get_adc_value(struct rt_adc_device *device, rt_uint32_t channel, rt_uint32_t *value)
78 {
79     cyhal_adc_channel_t *adc_ch;
80 
81     RT_ASSERT(device != RT_NULL);
82     adc_ch = device->parent.user_data;
83 
84     channel = adc_ch->channel_idx;
85 
86     *value = cyhal_adc_read(adc_ch);
87 
88     return RT_EOK;
89 }
90 
91 static const struct rt_adc_ops at_adc_ops =
92 {
93     .enabled = ifx_adc_enabled,
94     .convert = ifx_get_adc_value,
95 };
96 
rt_hw_adc_init(void)97 static int rt_hw_adc_init(void)
98 {
99     int result = RT_EOK;
100     int i = 0;
101 
102     for (i = 0; i < sizeof(ifx_adc_obj) / sizeof(ifx_adc_obj[0]); i++)
103     {
104         /* register ADC device */
105         if (rt_hw_adc_register(&ifx_adc_obj[i].ifx_adc_device, ifx_adc_obj[i].name, &at_adc_ops, ifx_adc_obj[i].adc_ch) == RT_EOK)
106         {
107             LOG_D("%s register success", ifx_adc_obj[i].name);
108         }
109         else
110         {
111             LOG_E("%s register failed", ifx_adc_obj[i].name);
112             result = -RT_ERROR;
113         }
114     }
115 
116     return result;
117 }
118 INIT_BOARD_EXPORT(rt_hw_adc_init);
119 
120 #endif /* BSP_USING_ADC */
121