/**************************************************************************//** * @copyright (C) 2020 Nuvoton Technology Corp. All rights reserved. * * SPDX-License-Identifier: Apache-2.0 * * Change Logs: * Date Author Notes * 2020-9-16 Philo First version * ******************************************************************************/ #include #include #include "NuMicro.h" #ifdef BSP_USING_ADC /* Private define ---------------------------------------------------------------*/ /* Private Typedef --------------------------------------------------------------*/ struct nu_adc { struct rt_adc_device dev; char *name; ADC_T *adc_base; int adc_reg_tab; int adc_max_ch_num; }; typedef struct nu_adc *nu_adc_t; /* Private functions ------------------------------------------------------------*/ static rt_err_t nu_adc_enabled(struct rt_adc_device *device, rt_uint32_t channel, rt_bool_t enabled); static rt_err_t nu_get_adc_value(struct rt_adc_device *device, rt_uint32_t channel, rt_uint32_t *value); /* Public functions ------------------------------------------------------------*/ int rt_hw_adc_init(void); /* Private variables ------------------------------------------------------------*/ static struct nu_adc nu_adc_arr [] = { #if defined(BSP_USING_ADC0) { .name = "adc0", .adc_base = ADC, .adc_max_ch_num = 15, }, #endif {0} }; static const struct rt_adc_ops nu_adc_ops = { nu_adc_enabled, nu_get_adc_value, }; typedef struct rt_adc_ops *rt_adc_ops_t; /* nu_adc_enabled - Enable ADC clock and wait for ready */ static rt_err_t nu_adc_enabled(struct rt_adc_device *device, rt_uint32_t channel, rt_bool_t enabled) { ADC_T *adc_base = ((nu_adc_t)device)->adc_base; int *padc_reg_tab = &((nu_adc_t)device)->adc_reg_tab; RT_ASSERT(device != RT_NULL); if (channel >= ((nu_adc_t)device)->adc_max_ch_num) return -(RT_EINVAL); if (enabled) { ADC_POWER_ON(adc_base); if (*padc_reg_tab == 0) { ADC_Open(adc_base, ADC_ADCR_DIFFEN_SINGLE_END, ADC_ADCR_ADMD_SINGLE, (0x1 << channel)); } *padc_reg_tab |= (0x1 << channel); } else { *padc_reg_tab &= ~(0x1 << channel); if (*padc_reg_tab == 0) { ADC_Close(adc_base); } ADC_POWER_DOWN(adc_base); } return RT_EOK; } static rt_err_t nu_get_adc_value(struct rt_adc_device *device, rt_uint32_t channel, rt_uint32_t *value) { RT_ASSERT(device != RT_NULL); RT_ASSERT(value != RT_NULL); ADC_T *adc_base = ((nu_adc_t)device)->adc_base; int *padc_reg_tab = &((nu_adc_t)device)->adc_reg_tab; if (channel >= ((nu_adc_t)device)->adc_max_ch_num) { *value = 0xFFFFFFFF; return -(RT_EINVAL); } if ((*padc_reg_tab & (1 << channel)) == 0) { *value = 0xFFFFFFFF; return -(RT_EBUSY); } ADC_SET_INPUT_CHANNEL(adc_base, (0x1<