#include "lks32mc09x_cmp.h"
#include "lks32mc09x_sys.h"
#include "lks32mc09x_user_manual.h"

// 模拟部分
/**
 * @brief 使能比较器
 * @param CMP_CHN_x: 比较器通道选择，CMP_CHN_0, CMP_CHN_1
 */
void CMP_Enable(uint8_t CMP_CHN_x)
{
    SYS_ModuleClockCmd(SYS_MODULE_CMP, ENABLE);
    if (CMP_CHN_x == CMP_CHN_0)
    {
        SYS0->PROTECT = 0x7a83;
        SYS0->AFE_REG5 |= SYS_AFE_REG5_CMP0PDN_BIT;
        SYS0->PROTECT = 0;
    }
    else
    {
        __NOP();
    }
    if (CMP_CHN_x == CMP_CHN_1)
    {
        SYS0->PROTECT = 0x7a83;
        SYS0->AFE_REG5 |= SYS_AFE_REG5_CMP1PDN_BIT;
        SYS0->PROTECT = 0;
    }
    else
    {
        __NOP();
    }
}
/**
 * @brief 失能比较器
 * @param CMP_CHN_x: 比较器通道选择，CMP_CHN_0, CMP_CHN_1
 */
void CMP_Disable(uint8_t CMP_CHN_x)
{
    if (CMP_CHN_x == CMP_CHN_0)
    {
        SYS0->PROTECT = 0x7a83;
        SYS0->AFE_REG5 &= ~BIT6;
        SYS0->PROTECT = 0;
    }
    else
    {
        __NOP();
    }
    if (CMP_CHN_x == CMP_CHN_1)
    {
        SYS0->PROTECT = 0x7a83;
        SYS0->AFE_REG5 &= ~BIT7;
        SYS0->PROTECT = 0;
    }
    else
    {
        __NOP();
    }
    // 当比较器0和比较器1同时关闭时，关闭总时钟
    if (REG_READ_BIT(SYS0->AFE_REG5, SYS_AFE_REG5_CMP0PDN_BIT | SYS_AFE_REG5_CMP1PDN_BIT) == 0)
    {
        SYS_ModuleClockCmd(SYS_MODULE_CMP, DISABLE);
    }
}
/**
 * @brief 设置比较器信号来源
 * @param CMP_CHN_x: 比较器通道选择，CMP_CHN_0, CMP_CHN_1
 * @param CMP_SELN_x_x: 信号负端选择，注意，由于比较器的各个通道不完全一样，所以这里需要指明使用的比较器
 * @param CMP_SELP_x_x: 信号正端选择，注意，由于比较器的各个通道不完全一样，所以这里需要指明使用的比较器
 */
void CMP_SetSignal(uint8_t CMP_CHN_x, uint8_t CMP_SELN_x_x, uint8_t CMP_SELP_x_x)
{
    if (CMP_CHN_x == CMP_CHN_0)
    {
        SYS0->PROTECT  = 0x7a83;
        SYS0->AFE_REG3 = (SYS0->AFE_REG3 & (~(0x0707))) |
                         (CMP_SELP_x_x << 8) |
                         (CMP_SELN_x_x);
        SYS0->PROTECT = 0;
    }
    else
    {
        __NOP();
    }
    if (CMP_CHN_x == CMP_CHN_1)
    {
        SYS0->PROTECT  = 0x7a83;
        SYS0->AFE_REG3 = (SYS0->AFE_REG3 & (~(0x7070))) |
                         (CMP_SELP_x_x << 12) |
                         (CMP_SELN_x_x << 4);
        SYS0->PROTECT = 0;
    }
    else
    {
        __NOP();
    }
}

/**
 * @brief 设置比较器回差(两个比较器共用同一个回差)
 * @param CMP_HYS_x: 回差选择，CMP_HYS_20mV, CMP_HYS_0mV
 */
void CMP_SetHysteresis(uint8_t CMP_HYS_x)
{
    SYS0->PROTECT  = 0x7a83;
    SYS0->AFE_REG3 = (SYS0->AFE_REG3 & (~(BIT7))) |
                     (CMP_HYS_x << 7);
    SYS0->PROTECT = 0;
}
// 数字部分
/**
 * @brief 设置比较器开窗信号
 * @param CMP_CHN_x: 比较器通道选择，CMP_CHN_0, CMP_CHN_1
 * @param CMP_WIN_x: 开窗信号选择，CMP_WIN_SIGNAL_NONE, CMP_WIN_SIGNAL_MCPWM0_0
 * @param CMP_WIN_LEVEL_x: 开窗电平选择，CMP_WIN_LEVEL_H, CMP_WIN_LEVEL_L
 */
void CMP_SetWindowSignal(uint8_t CMP_CHN_x, uint8_t CMP_WIN_x, uint8_t CMP_WIN_LEVEL_x)
{
    if (CMP_CHN_x == CMP_CHN_0)
    {
        CMP->BLCWIN = (CMP->BLCWIN & (~(0xf))) |
                      (CMP_WIN_x);
        CMP->CFG = (CMP->CFG & (~(BIT3))) |
                   (CMP_WIN_LEVEL_x << 3);
    }
    else
    {
        __NOP();
    }
    if (CMP_CHN_x == CMP_CHN_1)
    {
        CMP->BLCWIN = (CMP->BLCWIN & (~(0xf0))) |
                      (CMP_WIN_x << 4);
        CMP->CFG = (CMP->CFG & (~(BIT3))) |
                   (CMP_WIN_LEVEL_x << 7);
    }
    else
    {
        __NOP();
    }
}
/**
 * @brief 设置比较器的滤波宽度
 * @param CMP_CLK_DIV_x: 比较器时钟分频系数，CMP_CLK_DIV_0, CMP_CLK_DIV_1, CMP_CLK_DIV_2, CMP_CLK_DIV_3, CMP_CLK_DIV_4
 * @param CMP0_FIL_x: 比较器0滤波宽度，取值范围0-2047，0表示关闭信号的输入
 * @param CMP1_FIL_x: 比较器1滤波宽度，取值范围0-2047，0表示关闭信号的输入
 */
void CMP_SetFilterWidth(uint8_t CMP_CLK_DIV_x, uint16_t CMP0_FIL_x, uint16_t CMP1_FIL_x)
{
    uint16_t div2_0  = 0;
    uint16_t div16_0 = 0;
    uint16_t div2_1  = 0;
    uint16_t div16_1 = 0;
    uint16_t flten_0 = 0;
    uint16_t flten_1 = 0;
    if (CMP0_FIL_x > 2047)
    {
        CMP0_FIL_x = 2047;
    }
    if (CMP1_FIL_x > 2047)
    {
        CMP1_FIL_x = 2047;
    }
    for (; CMP0_FIL_x > 15;)
    {
        div2_0++;
        CMP0_FIL_x >>= 1;
    }
    div16_0 = CMP0_FIL_x;
    flten_0 = CMP0_FIL_x ? 1 : 0;

    for (; CMP1_FIL_x > 15;)
    {
        div2_1++;
        CMP1_FIL_x >>= 1;
    }
    div16_1 = CMP1_FIL_x;
    flten_1 = CMP1_FIL_x ? 1 : 0;

    CMP->TCLK = (CMP_CLK_DIV_x << 24) |
                (div16_1 << 12) |
                (flten_1 << 11) |
                (div2_1 << 8) |
                (div16_0 << 4) |
                (flten_0 << 3) |
                (div2_0);
}

/**
 * @brief 设置比较器中断信号
 * @param CMP_CHN_x: 比较器通道选择，CMP_CHN_0, CMP_CHN_1
 * @param CMP_SIGNAL_x: 中断信号选择，CMP_SIGNAL_NONE, CMP_SIGNAL_EDGE_P, CMP_SIGNAL_EDGE_N, CMP_SIGNAL_LEVEL_H, CMP_SIGNAL_LEVEL_L
 */
void CMP_SetIRQSignal(uint8_t CMP_CHN_x, uint8_t CMP_SIGNAL_x)
{
    if (CMP_CHN_x == CMP_CHN_0)
    {
        if (CMP_SIGNAL_x == CMP_SIGNAL_NONE)
        {
            CMP0->IE &= ~BIT0;
        }
        else
        {
            CMP0->IE |= BIT0;
        }
        CMP0->CFG = (CMP0->CFG & (~(0x7))) |
                    (CMP_SIGNAL_x);
    }
    else
    {
        __NOP();
    }
    if (CMP_CHN_x == CMP_CHN_1)
    {
        if (CMP_SIGNAL_x == CMP_SIGNAL_NONE)
        {
            CMP0->IE &= ~BIT1;
        }
        else
        {
            CMP0->IE |= BIT1;
        }
        CMP0->CFG = (CMP0->CFG & (~(0x70))) |
                    (CMP_SIGNAL_x << 4);
    }
    else
    {
        __NOP();
    }
}
/**
 * @brief 清除CMP中断标志
 * @param CMP_CHN_x: 比较器通道选择，CMP_CHN_0, CMP_CHN_1
 */
void CMP_ClearIRQFlag(uint8_t CMP_CHN_x)
{
    if (CMP_CHN_x == CMP_CHN_0)
    {
        CMP0->IF = BIT0;
    }
    else
    {
        __NOP();
    }
    if (CMP_CHN_x == CMP_CHN_1)
    {
        CMP0->IF = BIT1;
    }
    else
    {
        __NOP();
    }
}

/**
 * @brief 读取CMP中断标志
 * @param CMP_CHN_x: 比较器通道选择，CMP_CHN_0, CMP_CHN_1
 * @return: 中断标志状态 0或1
 */
uint8_t CMP_GetIRQFlag(uint8_t CMP_CHN_x)
{
    if (CMP_CHN_x == CMP_CHN_0)
    {
        return CMP0->IF & BIT0;
    }
    else if (CMP_CHN_x == CMP_CHN_1)
    {
        return (CMP0->IF & BIT1) >> 1;
    }
    else
    {
        return 0;
    }
}

/**
 * @brief 读取滤波后的比较器值
 * @return: 滤波后的比较器值 0或1
 */
uint8_t CMP_GetFilterValue(uint8_t CMP_CHN_x)
{
    if (CMP_CHN_x == CMP_CHN_0)
    {
        return (CMP0->DATA & BIT8) >> 8;
    }
    else if (CMP_CHN_x == CMP_CHN_1)
    {
        return (CMP0->DATA & BIT9) >> 9;
    }
    else
    {
        return 0;
    }
}

/**
 * @brief 读取未滤波的比较器值
 * @return: 未滤波的比较器值 0或1
 */
uint8_t CMP_GetValue(uint8_t CMP_CHN_x)
{
    if (CMP_CHN_x == CMP_CHN_0)
    {
        return CMP0->DATA & BIT0;
    }
    else if (CMP_CHN_x == CMP_CHN_1)
    {
        return (CMP0->DATA & BIT1) >> 1;
    }
    else
    {
        return 0;
    }
}
/**
 * @brief CMP结构体初始化
 * @param CMP_InitStruct 指向CMP初始化结构体的指针
 */
void CMP_StructInit(CMP_InitTypeDef *CMP_InitStruct)
{
    uint32_t i = 0;
    for (i = 0; i < sizeof(CMP_InitTypeDef); i++)
    {
        ((uint8_t *)CMP_InitStruct)[i] = 0;
    }
}
/**
 * @brief CMP初始化
 * @param CMP_InitStruct 指向CMP初始化结构体的指针
 */
void CMP_Init(CMP_InitTypeDef *CMP_InitStruct)
{
    if (CMP_InitStruct->CMP0_CFG.EN)
    {
        CMP_Enable(CMP_CHN_0);
    }
    else
    {
        CMP_Disable(CMP_CHN_0);
    }
    if (CMP_InitStruct->CMP1_CFG.EN)
    {
        CMP_Enable(CMP_CHN_1);
    }
    else
    {
        CMP_Disable(CMP_CHN_1);
    }
    CMP_SetHysteresis(CMP_InitStruct->HYS);
    {
        REG_WRITE_BIT(CMP0->TCLK, CMP_TCLK_COMM_DIV_MASK, CMP_TCLK_COMM_DIV(0));
        REG_SET(CMP0->TCLK, CMP_TCLK_CLK0_EN_BIT | CMP_TCLK_CLK1_EN_BIT);
        REG_WRITE_BIT(CMP0->TCLK, CMP_TCLK_FIL0_CLK_DIV16_MASK, CMP_TCLK_FIL0_CLK_DIV16(CMP_InitStruct->CMP0_CFG.FIL_CLK_DIV16));
        REG_WRITE_BIT(CMP0->TCLK, CMP_TCLK_FIL0_CLK_DIV2_MASK, CMP_TCLK_FIL0_CLK_DIV2(CMP_InitStruct->CMP0_CFG.FIL_CLK_DIV2));
        REG_WRITE_BIT(CMP0->TCLK, CMP_TCLK_FIL1_CLK_DIV16_MASK, CMP_TCLK_FIL1_CLK_DIV16(CMP_InitStruct->CMP1_CFG.FIL_CLK_DIV16));
        REG_WRITE_BIT(CMP0->TCLK, CMP_TCLK_FIL1_CLK_DIV2_MASK, CMP_TCLK_FIL1_CLK_DIV2(CMP_InitStruct->CMP1_CFG.FIL_CLK_DIV2));
    }

    CMP_SetSignal(CMP_CHN_0, CMP_InitStruct->CMP0_CFG.SELN, CMP_InitStruct->CMP0_CFG.SELP);
    CMP_SetSignal(CMP_CHN_1, CMP_InitStruct->CMP1_CFG.SELN, CMP_InitStruct->CMP1_CFG.SELP);

    {
        uint32_t val =
            (CMP_InitStruct->CMP0_CFG.CHN0P_PWM_EN << 0) |
            (CMP_InitStruct->CMP0_CFG.CHN1P_PWM_EN << 1) |
            (CMP_InitStruct->CMP0_CFG.CHN2P_PWM_EN << 2) |
            (CMP_InitStruct->CMP0_CFG.CHN3P_PWM_EN << 3);
        CMP_SetWindowSignal(CMP_CHN_0, val, CMP_InitStruct->CMP0_CFG.W_PWM_POL);
    }
    {
        uint32_t val =
            (CMP_InitStruct->CMP1_CFG.CHN0P_PWM_EN << 0) |
            (CMP_InitStruct->CMP1_CFG.CHN1P_PWM_EN << 1) |
            (CMP_InitStruct->CMP1_CFG.CHN2P_PWM_EN << 2) |
            (CMP_InitStruct->CMP1_CFG.CHN3P_PWM_EN << 3);
        CMP_SetWindowSignal(CMP_CHN_1, val, CMP_InitStruct->CMP1_CFG.W_PWM_POL);
    }

    {
        uint16_t irqSignal = 0;
        irqSignal |= (CMP_InitStruct->CMP0_CFG.POL) ? BIT0 : 0;      // 极性位
        irqSignal |= (CMP_InitStruct->CMP0_CFG.IE) ? BIT1 : 0;       // 中断使能位
        irqSignal |= (CMP_InitStruct->CMP0_CFG.IRQ_TRIG) ? BIT2 : 0; // 触发方式位

        CMP_SetIRQSignal(CMP_CHN_0, irqSignal);
    }
    {
        uint16_t irqSignal = 0;
        irqSignal |= (CMP_InitStruct->CMP1_CFG.POL) ? BIT0 : 0;      // 极性位
        irqSignal |= (CMP_InitStruct->CMP1_CFG.IE) ? BIT1 : 0;       // 中断使能位
        irqSignal |= (CMP_InitStruct->CMP1_CFG.IRQ_TRIG) ? BIT2 : 0; // 触发方式位

        CMP_SetIRQSignal(CMP_CHN_1, irqSignal);
    }

    if (CMP_InitStruct->CMP0_CFG.RE)
    {
        CMP0->IE |= BIT8;
    }
    if (CMP_InitStruct->CMP1_CFG.RE)
    {
        CMP0->IE |= BIT9;
    }
}
