#include "lks32mc09x_dac.h"
#include "lks32mc09x_trim.h"

/**
 * @brief DAC初始化
 * @param DAC_Channel DAC通道选择
 * @param DAC_InitStruct DAC初始化结构体
 */
void DAC_Init(uint8_t DAC_Channel, DAC_InitTypeDef *DAC_InitStruct)
{
    DAC_Cmd(DAC_Channel, ENABLE);
    DAC_SetRange(DAC_Channel, DAC_InitStruct->DAC_RANGE);
    DAC_Step(DAC_Channel, DAC_InitStruct->DAC_STEP, DAC_InitStruct->DAC_STEP_TRG_x);
    DAC_Output(DAC_Channel, DAC_InitStruct->DACOUT_EN);
}
/**
 * @brief DAC初始化结构体初始化
 * @param DAC_InitStruct DAC初始化结构体
 */
void DAC_StructInit(DAC_InitTypeDef *DAC_InitStruct)
{
    uint32_t i;
    for (i = 0; i < sizeof(DAC_InitTypeDef); i++)
    {
        ((uint8_t *)DAC_InitStruct)[i] = 0;
    }
}
/**
 * @brief DAC输出数值设置（数字量）
 * @param DAC_Channel DAC通道选择
 * @param DACValue DAC输出数字量
 */
void DAC_OutputValue(uint8_t DAC_Channel, uint32_t DACValue)
{
    if (DACValue > 4095)
    {
        DACValue = 4095;
    }
    else
    {
        __NOP();
    }
    if (DAC_Channel == DAC_CHANNEL_0)
    {
        SYS0->AFE_DAC0 = DACValue;
    }
    else if (DAC_Channel == DAC_CHANNEL_1)
    {
        SYS0->AFE_DAC1 = DACValue >> 4; // DAC1本身是8位，DACValue是12位，这里右移4位，以方便使用
    }
    else
    {
        __NOP();
    }
}
/**
 * @brief 设置DAC量程
 * @param DAC_Channel DAC通道选择
 * @param DAC_RANGE_x DAC输出量程
 */
void DAC_SetRange(uint8_t DAC_Channel, uint32_t DAC_RANGE_x)
{
    SYS0->PROTECT = 0x7a83;
    if (DAC_Channel == DAC_CHANNEL_0)
    {
        if (DAC_RANGE_x == DAC_RANGE_0_1V2)
        {
            SYS0->AFE_REG1 |= BIT6;
            SYS0->AFE_DAC0_AMC = TRIM_Read(NVR_ADDR_DAC_0_AMC_1_20V);
            SYS0->AFE_DAC0_DC  = TRIM_Read(NVR_ADDR_DAC_0_DC_1_20V);
        }
        else
        {
            SYS0->AFE_REG1 &= ~BIT6;
            SYS0->AFE_DAC0_AMC = TRIM_Read(NVR_ADDR_DAC_0_AMC_4_8V);
            SYS0->AFE_DAC0_DC  = TRIM_Read(NVR_ADDR_DAC_0_DC_4_8V);
        }
    }
    else if (DAC_Channel == DAC_CHANNEL_1)
    {
        if (DAC_RANGE_x == DAC_RANGE_1_1V2)
        {
            SYS0->AFE_REG1 |= BIT7;
            SYS0->AFE_DAC1_AMC = TRIM_Read(NVR_ADDR_DAC_1_AMC_1_20V);
            SYS0->AFE_DAC1_DC  = TRIM_Read(NVR_ADDR_DAC_1_DC_1_20V);
        }
        else
        {
            SYS0->AFE_REG1 &= ~BIT7;
            SYS0->AFE_DAC1_AMC = TRIM_Read(NVR_ADDR_DAC_1_AMC_3_0V);
            SYS0->AFE_DAC1_DC  = TRIM_Read(NVR_ADDR_DAC_1_DC_3_0V);
        }
    }
    else
    {
        __NOP();
    }
    SYS0->PROTECT = 0;
}

/**
 * @brief DAC输出模拟量，自动配置量程&同时自动使能对应的模块
 * @param DAC_Channel DAC通道选择
 * @param DACVoltage DAC输出模拟量 单位mV
 */
void DAC_OutputVoltage(uint8_t DAC_Channel, uint16_t DACVoltage)
{
    uint32_t val;
    DAC_Enable(DAC_Channel);
    if (DAC_Channel == DAC_CHANNEL_0)
    {
        if (DACVoltage < 1000)
        {
            DAC_SetRange(DAC_Channel, DAC_RANGE_0_1V2);
            val = 0.001f * DACVoltage / 1.2f * 4095;
            DAC_OutputValue(DAC_Channel, val);
        }
        else
        {
            DAC_SetRange(DAC_Channel, DAC_RANGE_0_4V76);
            val = DACVoltage * 0.001f / 4.76f * 4096;
            DAC_OutputValue(DAC_Channel, val);
        }
    }
    else if (DAC_Channel == DAC_CHANNEL_1)
    {
        if (DACVoltage < 1000)
        {
            DAC_SetRange(DAC_Channel, DAC_RANGE_1_1V2);
            val = 0.001f * DACVoltage / 1.2f * 4095;
            DAC_OutputValue(DAC_Channel, val);
        }
        else
        {
            DAC_SetRange(DAC_Channel, DAC_RANGE_1_3V);
            val = 0.001f * DACVoltage / 3.0f * 4095;
            DAC_OutputValue(DAC_Channel, val);
        }
    }
    else
    {
        __NOP();
    }
}

/**
 * @brief DAC通道时钟使能
 * @param DAC_Channel DAC通道选择
 * @param state 使能状态，1模块使能 0 模块关闭
 */
void DAC_Cmd(uint8_t DAC_Channel, uint8_t state)
{
    SYS0->PROTECT = 0x7a83;
    if (DAC_Channel == DAC_CHANNEL_0)
    {
        if (state)
        {
            SYS0->AFE_REG5 |= BIT1;
        }
        else
        {
            SYS0->AFE_REG5 &= ~BIT1;
        }
    }
    else
    {
        __NOP();
    }
    if (DAC_Channel == DAC_CHANNEL_1)
    {
        if (state)
        {
            SYS0->AFE_REG5 |= BIT2;
        }
        else
        {
            SYS0->AFE_REG5 &= ~BIT2;
        }
    }
    else
    {
        __NOP();
    }
    SYS0->PROTECT = 0;
}

/**
 * @brief DAC使能
 * @param DAC_Channel DAC通道选择
 */
void DAC_Enable(uint8_t DAC_Channel)
{
    DAC_Cmd(DAC_Channel, ENABLE);
}
/**
 * @brief DAC失能
 * @param DAC_Channel DAC通道选择
 */
void DAC_Disable(uint8_t DAC_Channel)
{
    DAC_Cmd(DAC_Channel, DISABLE);
}
/**
 * @brief DAC复位
 * @param DAC_Channel DAC通道选择
 */
void DAC_Reset(uint8_t DAC_Channel)
{
    DAC_SetRange(DAC_Channel, DAC_RANGE_0_4V76);
    DAC_OutputValue(DAC_Channel, 0);
    DAC_Cmd(DAC_Channel, DISABLE);
}
/**
 * @brief DAC输出至IO口使能配置
 * @param DAC_Channel DAC通道选择
 * @param state 1Dac电压p0.0口 0停止输出到P0.0
 */
void DAC_Output(uint8_t DAC_Channel, uint8_t state)
{
    SYS0->PROTECT = 0x7a83;
    if (DAC_Channel == DAC_CHANNEL_0)
    {
        if (state)
        {
            SYS0->AFE_REG2 |= BIT6;
        }
        else
        {
            SYS0->AFE_REG2 &= ~BIT6;
        }
    }
    else if (DAC_Channel == DAC_CHANNEL_1)
    {
        if (state)
        {
            SYS0->AFE_REG2 |= BIT7;
        }
        else
        {
            SYS0->AFE_REG2 &= ~BIT7;
        }
    }
    else
    {
        __NOP();
    }
    SYS0->PROTECT = 0;
}
/**
 * @brief 获取当前DAC输出值
 * @param DAC_Channel DAC通道选择
 * @return DAC输出值
 */
uint32_t DAC_Value(uint8_t DAC_Channel)
{
    if (DAC_Channel == DAC_CHANNEL_0)
    {
        return (SYS0->AFE_DAC0 & 0xFFF);
    }
    else
    {
        return (SYS0->AFE_DAC1 & 0xFF) << 4; // DAC1本身是8位，这里左移4位，以确保DAC0和DAC1用法一致
    }
}
/**
 * @brief 获取当前DAC输出电压
 * @param DAC_Channel DAC通道选择
 * @return DAC输出电压 单位mV
 */
uint16_t DAC_Voltage(uint8_t DAC_Channel)
{
    uint32_t val = 0;
    if (DAC_Channel == DAC_CHANNEL_0)
    {
        if (DAC_Range(DAC_Channel)) // 1.2V量程
        {
            val = DAC_Value(DAC_Channel);
            val = val * 1.2f * 1000 / 4095;
        }
        else
        {
            val = DAC_Value(DAC_Channel);
            val = val * 4.85f * 1000 / 4095;
        }
    }
    else if (DAC_Channel == DAC_CHANNEL_1)
    {
        if (DAC_Range(DAC_Channel)) // 1.2V量程
        {
            val = DAC_Value(DAC_Channel);
            val = val * 1.2f * 1000 / 4095;
        }
        else
        {
            val = DAC_Value(DAC_Channel);
            val = val * 3.0f * 1000 / 4095;
        }
    }
    else
    {
        __NOP();
    }
    return val;
}
/**
 * @brief 获取当前DAC量程
 * @param DAC_Channel DAC通道选择
 * @return DAC量程 dac0 0:4.85V 1:1.2V dac1 0:3V 1:1.2V
 */
uint8_t DAC_Range(uint8_t DAC_Channel)
{
    if (DAC_Channel == DAC_CHANNEL_0)
    {
        if (SYS0->AFE_REG1 & BIT6)
        {
            return DAC_RANGE_0_4V76;
        }
        else
        {
            return DAC_RANGE_0_1V2;
        }
    }
    else if (DAC_Channel == DAC_CHANNEL_1)
    {
        if (SYS0->AFE_REG1 & BIT7)
        {
            return DAC_RANGE_1_3V;
        }
        else
        {
            return DAC_RANGE_1_1V2;
        }
    }
    else
    {
        __NOP();
    }
    return 0;
}
/**
 * @brief DAC0步进设置
 * @param DAC_Channel DAC通道选择
 * @param DAC_STEP_x DAC0步进值
 * @param DAC_STEP_TRG_x DAC0步进触发源
 */
void DAC_Step(uint8_t DAC_Channel, uint8_t DAC_STEP_x, uint8_t DAC_STEP_TRG_x)
{
    if (DAC_Channel == DAC_CHANNEL_0)
    {
        SYS0->PROTECT      = 0x7a83;
        SYS0->AFE_DAC_CTRL = (DAC_STEP_x << 4) | (DAC_STEP_TRG_x);
        SYS0->PROTECT      = 0;
    }
    else
    {
        // dac1不支持步进
    }
}
