/* * Copyright (c) 2006-2021, RT-Thread Development Team * * SPDX-License-Identifier: Apache-2.0 * * Change Logs: * Date Author Notes * 2024-03-24 Oxlm first version */ #include #include #include "fsl_dac.h" #include "fsl_dac14.h" #ifdef RT_USING_DAC // #define DRV_DEBUG #define DBG_TAG "drv.dac" #ifdef DRV_DEBUG #define DBG_LVL DBG_LOG #else #define DBG_LVL DBG_INFO #endif /* DRV_DEBUG */ #include struct mcx_dac { struct rt_dac_device mcxn_dac_device; LPDAC_Type *dac_base; clock_attach_id_t clock_attach_id; clock_div_name_t clock_div_name; uint8_t clock_div; uint8_t referenceVoltageSource; /* kDAC_ReferenceVoltageSourceAlt1, VREFH reference pin */ uint8_t SOC_CNTRL_BIT; char *name; }; static struct mcx_dac mcx_dac_obj[] = { #ifdef BSP_USING_DAC0 { .dac_base = DAC0, .clock_attach_id = kFRO_HF_to_DAC0, .clock_div_name = kCLOCK_DivDac0Clk, .clock_div = 1u, .referenceVoltageSource = kDAC_ReferenceVoltageSourceAlt1, .SOC_CNTRL_BIT = 4, .name = "dac0", }, #endif #ifdef BSP_USING_DAC1 { .dac_base = DAC1, .clock_attach_id = kFRO_HF_to_DAC1, .clock_div_name = kCLOCK_DivDac1Clk, .clock_div = 1u, .referenceVoltageSource = kDAC_ReferenceVoltageSourceAlt1, .SOC_CNTRL_BIT = 5, .name = "dac1", }, #endif #ifdef BSP_USING_DAC2 { .dac_base = DAC2, .clock_attach_id = kFRO_HF_to_DAC2, .clock_div_name = kCLOCK_DivDac2Clk, .clock_div = 1u, .referenceVoltageSource = kDAC_ReferenceVoltageSourceAlt1, .SOC_CNTRL_BIT = 6, .name = "dac2", }, #endif }; rt_err_t mcxn_dac_disabled(struct rt_dac_device *device, rt_uint32_t channel) { RT_ASSERT(device != RT_NULL); struct mcx_dac *dac = (struct mcx_dac *)device->parent.user_data; if (dac->dac_base == DAC2) { DAC14_Deinit(dac->dac_base); } else { DAC_Deinit(dac->dac_base); } return RT_EOK; } rt_err_t mcxn_dac_enabled(struct rt_dac_device *device, rt_uint32_t channel) { RT_ASSERT(device != RT_NULL); struct mcx_dac *dac = (struct mcx_dac *)device->parent.user_data; dac_config_t dacConfigStruct; dac14_config_t dac14ConfigStruct; if (dac->dac_base == DAC2) { DAC14_GetDefaultConfig(&dac14ConfigStruct); dac14ConfigStruct.enableOpampBuffer = true; dac14ConfigStruct.enableDAC = true; DAC14_Init(dac->dac_base, &dac14ConfigStruct); } else { DAC_GetDefaultConfig(&dacConfigStruct); dacConfigStruct.referenceVoltageSource = dac->referenceVoltageSource; DAC_Init(dac->dac_base, &dacConfigStruct); DAC_Enable(dac->dac_base, RT_TRUE); } return RT_EOK; } rt_err_t mcxn_dac_write(struct rt_dac_device *device, rt_uint32_t channel, rt_uint32_t *value) { RT_ASSERT(device != RT_NULL); struct mcx_dac *dac = (struct mcx_dac *)device->parent.user_data; if (dac->dac_base == DAC2) { if (*value > 0x3FFFU) { *value = 0x3FFFU; } DAC14_SetData(dac->dac_base, *value); } else { if (*value > 0xFFFU) { *value = 0xFFFU; } DAC_SetData(dac->dac_base, *value); } return RT_EOK; } struct rt_dac_ops mcxn_dac_ops = { .disabled = mcxn_dac_disabled, .enabled = mcxn_dac_enabled, .convert = mcxn_dac_write, }; static int mcxn_dac_init(void) { int i; int dac_num = sizeof(mcx_dac_obj) / sizeof(struct mcx_dac); for (i = 0; i < dac_num; i++) { CLOCK_SetClkDiv(mcx_dac_obj[i].clock_div_name, mcx_dac_obj[i].clock_div); CLOCK_AttachClk(mcx_dac_obj[i].clock_attach_id); SPC0->ACTIVE_CFG1 |= 0x01; // Enable VREF SPC0->ACTIVE_CFG1 |= (0x01 << mcx_dac_obj[i].SOC_CNTRL_BIT); if (RT_EOK != rt_hw_dac_register(&mcx_dac_obj[i].mcxn_dac_device, mcx_dac_obj[i].name, &mcxn_dac_ops, (void *)(mcx_dac_obj + i))) { LOG_E("%s register failed", mcx_dac_obj[i].name); return -RT_ERROR; } } return RT_EOK; } INIT_DEVICE_EXPORT(mcxn_dac_init); #endif