/* * Copyright (C) 2022-2024, Xiaohua Semiconductor Co., Ltd. * * SPDX-License-Identifier: Apache-2.0 * * Change Logs: * Date Author Notes * 2023-05-12 CDT first version */ #include #if defined(BSP_USING_DAC1) || defined(BSP_USING_DAC2) || defined(BSP_USING_DAC3) || defined(BSP_USING_DAC4) #include #include #include #include "rtdevice.h" #include "hc32_ll.h" #include #include "board_config.h" /* DAC features */ #define DAC_CHANNEL_ID_MAX (DAC_CH2 + 1U) #define DAC_RESOLUTION (12) #define DAC_LEFT_ALIGNED_DATA_MASK (0xFFF0U) #define DAC_RIGHT_ALIGNED_DATA_MASK (0xFFFU) typedef struct { struct rt_dac_device rt_dac; CM_DAC_TypeDef *instance; struct dac_dev_init_params init; } dac_device; static dac_device _g_dac_dev_array[] = { #ifdef BSP_USING_DAC1 { {0}, #if defined (HC32F4A0) || defined (HC32F472) || defined (HC32F4A8) || defined (HC32F334) CM_DAC1, #elif defined (HC32F448) CM_DAC, #endif DAC1_INIT_PARAMS, }, #endif #ifdef BSP_USING_DAC2 { {0}, CM_DAC2, DAC2_INIT_PARAMS, }, #endif #ifdef BSP_USING_DAC3 { {0}, CM_DAC3, DAC3_INIT_PARAMS, }, #endif #ifdef BSP_USING_DAC4 { {0}, CM_DAC4, DAC4_INIT_PARAMS, }, #endif }; static rt_uint16_t _dac_get_channel(rt_uint32_t channel) { rt_uint16_t ll_channel = 0; switch (channel) { case 1: ll_channel = DAC_CH1; break; case 2: ll_channel = DAC_CH2; break; default: RT_ASSERT(0); break; } return ll_channel; } static rt_err_t _dac_enabled(struct rt_dac_device *device, rt_uint32_t channel) { RT_ASSERT(device != RT_NULL); RT_ASSERT(channel <= DAC_CHANNEL_ID_MAX); CM_DAC_TypeDef *p_ll_instance = device->parent.user_data; uint16_t ll_channel = _dac_get_channel(channel); int32_t result = DAC_Start(p_ll_instance, ll_channel); return (result == LL_OK) ? RT_EOK : -RT_ERROR; } static rt_err_t _dac_disabled(struct rt_dac_device *device, rt_uint32_t channel) { RT_ASSERT(device != RT_NULL); RT_ASSERT(channel <= DAC_CHANNEL_ID_MAX); CM_DAC_TypeDef *p_ll_instance = device->parent.user_data; uint16_t ll_channel = _dac_get_channel(channel); int32_t result = DAC_Stop(p_ll_instance, ll_channel); return (result == LL_OK) ? RT_EOK : -RT_ERROR; } static rt_uint8_t _dac_get_resolution(struct rt_dac_device *device) { return DAC_RESOLUTION; } static rt_err_t _dac_set_value(struct rt_dac_device *device, rt_uint32_t channel, rt_uint32_t *value) { RT_ASSERT(device != RT_NULL); RT_ASSERT(channel <= DAC_CHANNEL_ID_MAX); CM_DAC_TypeDef *p_ll_instance = device->parent.user_data; if (READ_REG16_BIT(p_ll_instance->DACR, DAC_DACR_DPSEL) == DAC_DATA_ALIGN_LEFT) { RT_ASSERT(0U == (*value & ~DAC_LEFT_ALIGNED_DATA_MASK)); } else { RT_ASSERT(0U == (*value & ~DAC_RIGHT_ALIGNED_DATA_MASK)); } uint16_t ll_channel = _dac_get_channel(channel); DAC_SetChData(p_ll_instance, ll_channel, *value); return RT_EOK; } static const struct rt_dac_ops g_dac_ops = { .disabled = _dac_disabled, .enabled = _dac_enabled, .convert = _dac_set_value, .get_resolution = _dac_get_resolution, }; static void _dac_clock_enable(void) { #if defined(BSP_USING_DAC1) #if defined (HC32F4A0) || defined (HC32F472) || defined (HC32F4A8) || defined (HC32F334) FCG_Fcg3PeriphClockCmd(FCG3_PERIPH_DAC1, ENABLE); #elif defined (HC32F448) FCG_Fcg3PeriphClockCmd(FCG3_PERIPH_DAC, ENABLE); #endif #endif #if defined(BSP_USING_DAC2) FCG_Fcg3PeriphClockCmd(FCG3_PERIPH_DAC2, ENABLE); #endif #if defined(BSP_USING_DAC3) FCG_Fcg3PeriphClockCmd(FCG3_PERIPH_DAC3, ENABLE); #endif #if defined(BSP_USING_DAC4) FCG_Fcg3PeriphClockCmd(FCG3_PERIPH_DAC4, ENABLE); #endif } extern rt_err_t rt_hw_board_dac_init(CM_DAC_TypeDef *DACx); int rt_hw_dac_init(void) { int result = RT_EOK; rt_err_t ret; int i = 0; stc_dac_init_t stcDacInit = {0}; int32_t ll_ret = 0; _dac_clock_enable(); uint32_t dev_cnt = sizeof(_g_dac_dev_array) / sizeof(_g_dac_dev_array[0]); for (; i < dev_cnt; i++) { DAC_DeInit(_g_dac_dev_array[i].instance); stcDacInit.enOutput = (en_functional_state_t)_g_dac_dev_array[i].init.ch1_output_enable; #if defined (HC32F4A0) || defined (HC32F448) || defined (HC32F4A8) stcDacInit.u16Src = _g_dac_dev_array[i].init.ch1_data_src; #endif ll_ret = DAC_Init((void *)_g_dac_dev_array[i].instance, DAC_CH1, &stcDacInit); #if defined (HC32F4A0) || defined (HC32F448) || defined (HC32F4A8) || defined (HC32F460) #if defined (HC32F4A0) || defined (HC32F448) || defined (HC32F4A8) stcDacInit.u16Src = _g_dac_dev_array[i].init.ch2_data_src; #endif stcDacInit.enOutput = _g_dac_dev_array[i].init.ch2_output_enable; ll_ret = DAC_Init((void *)_g_dac_dev_array[i].instance, DAC_CH2, &stcDacInit); #elif defined (HC32F334) if (CM_DAC1 == (void *)_g_dac_dev_array[i].instance) { stcDacInit.enOutput = (en_functional_state_t)_g_dac_dev_array[i].init.ch2_output_enable; ll_ret = DAC_Init((void *)_g_dac_dev_array[i].instance, DAC_CH2, &stcDacInit); } #endif DAC_DataRegAlignConfig(_g_dac_dev_array[i].instance, _g_dac_dev_array[i].init.data_align); if (ll_ret != LL_OK) { ret = -RT_ERROR; break; } DAC_ADCPrioConfig(_g_dac_dev_array[i].instance, _g_dac_dev_array[i].init.dac_adp_sel, ENABLE); DAC_ADCPrioCmd(_g_dac_dev_array[i].instance, (en_functional_state_t)_g_dac_dev_array[i].init.dac_adp_enable); #if defined (HC32F472) DAC_SetAmpGain(_g_dac_dev_array[i].instance, DAC_CH1, _g_dac_dev_array[i].init.ch1_amp_gain); DAC_SetAmpGain(_g_dac_dev_array[i].instance, DAC_CH2, _g_dac_dev_array[i].init.ch2_amp_gain); #endif DAC_AMPCmd(_g_dac_dev_array[i].instance, DAC_CH1, (en_functional_state_t)_g_dac_dev_array[i].init.ch1_amp_enable); #if defined (HC32F4A0) || defined (HC32F448) || defined (HC32F4A8) || defined (HC32F460) DAC_AMPCmd(_g_dac_dev_array[i].instance, DAC_CH2, _g_dac_dev_array[i].init.ch2_amp_enable); #elif defined (HC32F334) if (CM_DAC1 == (void *)_g_dac_dev_array[i].instance) { DAC_AMPCmd(_g_dac_dev_array[i].instance, DAC_CH2, (en_functional_state_t)_g_dac_dev_array[i].init.ch2_amp_enable); } #endif rt_hw_board_dac_init(_g_dac_dev_array[i].instance); ret = rt_hw_dac_register(&_g_dac_dev_array[i].rt_dac, \ (const char *)_g_dac_dev_array[i].init.name, \ &g_dac_ops, (void *)_g_dac_dev_array[i].instance); if (ret == RT_EOK) { LOG_D("%s init success", (const char *)_g_dac_dev_array[i].init.name); } else { LOG_E("%s register failed", (const char *)_g_dac_dev_array[i].init.name); result = -RT_ERROR; } } return result; } INIT_DEVICE_EXPORT(rt_hw_dac_init); #endif /* BSP_USING_DAC */