#include "lks32mc09x_mcpwm.h"
#include "lks32mc09x_sys.h"
#include "lks32mc09x_user_manual.h"
static uint32_t mcpwm_default_io;
// 仅内部使用
static void MCPWM_TmpUpdateFailIo(MCPWM_TypeDef *MCPWMx);
/**
 * @brief 模块使能
 * @param MCPWMx MCPWM模块
 */
void MCPWM_Enable(MCPWM_TypeDef *MCPWMx)
{
    SYS_ModuleClockCmd(SYS_MODULE_MCPWM0, ENABLE);
    MCPWMx->PRT = 0xdead;
    MCPWMx->TCLK |= BIT2;
    MCPWMx->PRT = 0;
}
/**
 * @brief 模块失能
 * @param MCPWMx MCPWM模块
 */
void MCPWM_Disable(MCPWM_TypeDef *MCPWMx)
{
    MCPWMx->PRT = 0xdead;
    MCPWMx->TCLK &= ~BIT2;
    MCPWMx->PRT = 0;
    SYS_ModuleClockCmd(SYS_MODULE_MCPWM0, DISABLE);
}
/**
 * @brief 模块复位
 * @param MCPWMx MCPWM模块
 */
void MCPWM_Reset(MCPWM_TypeDef *MCPWMx)
{
    if (MCPWMx == MCPWM0)
    {
        SYS_SoftResetModule(SYS_MODULE_MCPWM0);
    }
}
/**
 * @brief 初始化MCPWM模块
 * @param MCPWMx MCPWM模块指针
 * @param MCPWM_InitStruct 指向包含初始化参数的MCPWM_InitTypeDef结构体
 */
void MCPWM_Init(MCPWM_TypeDef *MCPWMx, MCPWM_InitTypeDef *MCPWM_InitStruct)
{
    // 复位MCPWM模块
    MCPWM_Reset(MCPWMx);
    if (MCPWM_InitStruct->EN)
    {
        // 使能MCPWM模块
        MCPWM_Enable(MCPWMx);
        // 初始化MCPWM模块
        MCPWMx->PRT = 0xdead; // mcpwm模块解锁
        if (MCPWM_InitStruct->COUNT & MCPWM_COUNT_START)
        {
            MCPWMx->TCLK = BIT6 | (MCPWM_InitStruct->CLK_DIV << 12) | BIT2;
        }
        else
        {
            if (MCPWM_InitStruct->COUNT != 0)
            {
                MCPWMx->TCLK = ((MCPWMx->TCLK & (~BIT6)) | BIT8) | (MCPWM_InitStruct->CLK_DIV << 12) | BIT2; // 关闭计数器，并打开外部触发
                MCPWMx->EVT0 = MCPWM_InitStruct->COUNT;                                                      // 设置外部触发信号
            }
            else
            {
                MCPWMx->TCLK = (MCPWM_InitStruct->CLK_DIV << 12) | BIT2;
            }
        }
        MCPWMx->TH00    = 0;
        MCPWMx->TH01    = 0;
        MCPWMx->TH10    = 0;
        MCPWMx->TH11    = 0;
        MCPWMx->TH20    = 0;
        MCPWMx->TH21    = 0;
        MCPWMx->TH30    = 0;
        MCPWMx->TH31    = 0;
        MCPWMx->CNT0    = -MCPWM_InitStruct->TH;
        MCPWMx->TH0     = MCPWM_InitStruct->TH;
        MCPWMx->TMR0    = MCPWM_InitStruct->TMR0;
        MCPWMx->TMR1    = MCPWM_InitStruct->TMR1;
        MCPWMx->TMR2    = MCPWM_InitStruct->TMR2;
        MCPWMx->TMR3    = MCPWM_InitStruct->TMR3;
        MCPWMx->DTH00   = MCPWM_InitStruct->DTHP;
        MCPWMx->DTH01   = MCPWM_InitStruct->DTHN;
        MCPWMx->FLT     = MCPWM_InitStruct->FLT_DIV;
        MCPWMx->IO01    = MCPWM_InitStruct->IO0 | (MCPWM_InitStruct->IO1 << 8);
        MCPWMx->IO23    = MCPWM_InitStruct->IO2 | (MCPWM_InitStruct->IO3 << 8);
        MCPWMx->CH_FAIL = MCPWM_InitStruct->FAIL0 | MCPWM_InitStruct->FAIL1;
        MCPWMx->AUEN    = MCPWM_InitStruct->AUEN;
        MCPWMx->IE0     = MCPWM_InitStruct->IE;
        MCPWMx->EIE     = MCPWM_InitStruct->EIE;
        MCPWMx->RE      = MCPWM_InitStruct->RE;
        MCPWMx->SDCFG   = MCPWM_InitStruct->TR;
        // 更新所有存在影子寄存器的寄存器
        MCPWMx->UPDATE = 0xffffffff;
        {
            // IO01 IO23更新完成后再设置默认电平，会根据FAIL_IO的设置，自动处理极性和通道交换
            mcpwm_default_io = MCPWM_InitStruct->FAIL_IO;
            MCPWM_TmpUpdateFailIo(MCPWMx);
        }
        MCPWMx->IF0 = 0xffff;
        MCPWMx->EIF = 0xffff;
        MCPWMx->PRT = 0x0000; // mcpwm模块上锁
    }
    else
    {
        // 失能MCPWM模块
        MCPWM_Disable(MCPWMx);
    }
}

/**
 * @brief 将MCPWM_InitTypeDef结构体初始化为默认值
 * @param MCPWM_InitStruct 指向要初始化的MCPWM_InitTypeDef结构体
 */
void MCPWM_StructInit(MCPWM_InitTypeDef *MCPWM_InitStruct)
{
    uint32_t i;
    for (i = 0; i < sizeof(MCPWM_InitTypeDef); i++)
    {
        ((uint8_t *)MCPWM_InitStruct)[i] = 0;
    }
}
/**
 * @brief 设置MCPWM输出状态
 * @param MCPWMx MCPWM模块
 * @param state 输出状态 1打开输出 0关闭输出
 */
void MCPWM_SetOutputState(MCPWM_TypeDef *MCPWMx, uint8_t state)
{
    MCPWMx->PRT = 0xdead; // mcpwm模块解锁
    if (state)
    {
        MCPWMx->EIF = MCPWMx->EIF;
        MCPWMx->CH_FAIL |= BIT6;
    }
    else
    {
        MCPWMx->CH_FAIL &= ~BIT6;
    }
    MCPWMx->PRT = 0x0000; // mcpwm模块上锁
}
/**
 * @brief 设置MCPWM输出值
 * @param MCPWMx MCPWM模块
 * @param chn 通道号 0-3
 * @param p 上管打开时间
 * @param n 下管打开时间
 */
void MCPWM_SetOutputVal(MCPWM_TypeDef *MCPWMx, uint8_t chn, int16_t p, int16_t n)
{
    switch (chn)
    {
        case 0:
            MCPWMx->TH00 = p;
            MCPWMx->TH01 = n;
            break;
        case 1:
            MCPWMx->TH10 = p;
            MCPWMx->TH11 = n;
            break;
        case 2:
            MCPWMx->TH20 = p;
            MCPWMx->TH21 = n;
            break;
        case 3:
            MCPWMx->TH30 = p;
            MCPWMx->TH31 = n;
            break;
        default:
            break;
    }
}
/**
 * @brief 设置MCPWM触发ADC事件时间
 * @param MCPWMx MCPWM模块
 * @param tmr0 事件0时间
 * @param tmr1 事件1时间
 * @param tmr2 事件2时间
 * @param tmr3 事件3时间
 */
void MCPWM_SetTMR(MCPWM_TypeDef *MCPWMx, int16_t tmr0, int16_t tmr1, int16_t tmr2, int16_t tmr3)
{
    MCPWMx->TMR0 = tmr0;
    MCPWMx->TMR1 = tmr1;
    MCPWMx->TMR2 = tmr2;
    MCPWMx->TMR3 = tmr3;
}
/**
 * @brief 设置IO配置
 * @param MCPWMx MCPWM模块
 * @param io0 IO0配置
 * @param io1 IO1配置
 * @param io2 IO2配置
 * @param io3 IO3配置
 * @note 由于mcpwm的io0和io1是一个寄存器，io2和io3是一个寄存器，所以需要同时配置
 */
void MCPWM_SetIOConfig(MCPWM_TypeDef *MCPWMx, uint16_t io0, uint16_t io1, uint16_t io2, uint16_t io3)
{
    MCPWMx->PRT  = 0xdead; // mcpwm模块解锁
    MCPWMx->IO01 = io0 | (io1 << 8);
    MCPWMx->IO23 = io2 | (io3 << 8);
    MCPWMx->PRT  = 0x0000; // mcpwm模块上锁
}
/**
 * @brief 开始计数
 * @param MCPWMx MCPWM模块
 * @param count 计数器初始值
 */
void MCPWM_StartCount(MCPWM_TypeDef *MCPWMx)
{
    MCPWMx->PRT = 0xdead; // mcpwm模块解锁
                          //    MCPWMx->UPDATE = BIT11;
    MCPWMx->TCLK |= BIT6;
    MCPWMx->PRT = 0x0000; // mcpwm模块上锁
}
/**
 * @brief 停止计数
 * @param MCPWMx MCPWM模块
 */
void MCPWM_StopCount(MCPWM_TypeDef *MCPWMx)
{
    MCPWMx->PRT = 0xdead; // mcpwm模块解锁
    MCPWMx->TCLK &= ~BIT6;
    MCPWMx->PRT = 0x0000; // mcpwm模块上锁
}
/**
 * @brief 获取MCPWM中断标志
 * @param MCPWMx MCPWM模块
 * @param MCPWM_IF_x 中断标志位
 * @return 1中断发生 0中断未发生
 */
uint16_t MCPWM_GetIRQFlag(MCPWM_TypeDef *MCPWMx, uint32_t MCPWM_IF_x)
{
    return (MCPWMx->IF0 & MCPWMx->IE0 & MCPWM_IF_x) ? 1 : 0;
}
/**
 * @brief 获取MCPWM事件
 * @param MCPWMx MCPWM模块
 * @param MCPWM_IF_x 中断标志位
 * @return 1事件发生 0事件未发生
 * @note 事件和中断的区别在于事件只是一个标志位，用于在中断函数外部判断事件是否发生
 */
uint16_t MCPWM_GetIfFlag(MCPWM_TypeDef *MCPWMx, uint32_t MCPWM_IF_x)
{
    return (MCPWMx->IF0 & MCPWM_IF_x) ? 1 : 0;
}
/**
 * @brief 获取MCPWM错误中断标志
 * @param MCPWMx MCPWM模块
 * @param MCPWM_EIF_x 错误中断标志位
 * @return 1事件发生 0事件未发生
 */
uint16_t MCPWM_GetEifFlag(MCPWM_TypeDef *MCPWMx, uint32_t MCPWM_IF_x)
{
    return (MCPWMx->EIF & MCPWMx->EIE & MCPWM_IF_x) ? 1 : 0;
}
/**
 * @brief 获取CMPWM错误中断标志
 * @param MCPWMx MCPWM模块
 * @param MCPWM_EIF_x 错误中断标志位
 * @return 1中断发生 0中断未发生
 */
uint16_t MCPWM_GetErrorIRQFlag(MCPWM_TypeDef *MCPWMx, uint32_t MCPWM_EIF_x)
{
    return (MCPWMx->EIF & MCPWM_EIF_x) ? 1 : 0;
}
/**
 * @brief 清除MCPWM中断标志
 * @param MCPWMx MCPWM模块
 * @param MCPWM_IF_x 中断标志位
 */
void MCPWM_ClearIRQFlag(MCPWM_TypeDef *MCPWMx, uint32_t MCPWM_IF_x)
{
    MCPWMx->IF0 = MCPWM_IF_x;
}
/**
 * @brief 清除MCPWM错误中断标志
 * @param MCPWMx MCPWM模块
 * @param MCPWM_EIF_x 错误中断标志位
 */
void MCPWM_ClearErrorIRQFlag(MCPWM_TypeDef *MCPWMx, uint32_t MCPWM_EIF_x)
{
    MCPWMx->EIF = MCPWM_EIF_x;
}

/**
 * @brief 获取当前计数器门限值
 * @param MCPWMx MCPWM模块
 * @return 当前计数器门限值
 */
int16_t MCPWM_GetCountTh(MCPWM_TypeDef *MCPWMx)
{
    return MCPWMx->TH0;
}
/**
 * @brief 获取当前计数器值
 * @param MCPWMx MCPWM模块
 * @return 当前计数器值
 */
int16_t MCPWM_GetCountVal(MCPWM_TypeDef *MCPWMx)
{
    return MCPWMx->CNT0;
}
/**
 * @brief 更新failIO状态(仅库函数内部使用)
 */
static void MCPWM_TmpUpdateFailIo(MCPWM_TypeDef *MCPWMx)
{
    uint32_t chdef = mcpwm_default_io;
    if (MCPWMx->IO01 & MCPWM0_IO01_CH0_NP_BIT)
    {
        chdef ^= BIT0;
    }
    if (MCPWMx->IO01 & MCPWM0_IO01_CH0_PP_BIT)
    {
        chdef ^= BIT1;
    }
    if (MCPWMx->IO01 & MCPWM0_IO01_CH1_NP_BIT)
    {
        chdef ^= BIT2;
    }
    if (MCPWMx->IO01 & MCPWM0_IO01_CH1_PP_BIT)
    {
        chdef ^= BIT3;
    }
    if (MCPWMx->IO23 & MCPWM0_IO23_CH2_NP_BIT)
    {
        chdef ^= BIT4;
    }
    if (MCPWMx->IO23 & MCPWM0_IO23_CH2_PP_BIT)
    {
        chdef ^= BIT5;
    }
    if (MCPWMx->IO23 & MCPWM0_IO23_CH3_NP_BIT)
    {
        chdef ^= BIT6;
    }
    if (MCPWMx->IO23 & MCPWM0_IO23_CH3_PP_BIT)
    {
        chdef ^= BIT7;
    }
    if (MCPWMx->IO01 & MCPWM0_IO01_CH0_PN_SW_BIT)
    {
        // 交换chdef的bit0和bit1
        chdef = (chdef & (~(BIT0 | BIT1))) | ((chdef & BIT0) << 1) | ((chdef & BIT1) >> 1);
    }
    if (MCPWMx->IO01 & MCPWM0_IO01_CH1_PN_SW_BIT)
    {
        // 交换chdef的bit2和bit3
        chdef = (chdef & (~(BIT2 | BIT3))) | ((chdef & BIT2) << 1) | ((chdef & BIT3) >> 1);
    }
    if (MCPWMx->IO23 & MCPWM0_IO23_CH2_PN_SW_BIT)
    {
        // 交换chdef的bit4和bit5
        chdef = (chdef & (~(BIT4 | BIT5))) | ((chdef & BIT4) << 1) | ((chdef & BIT5) >> 1);
    }
    if (MCPWMx->IO23 & MCPWM0_IO23_CH3_PN_SW_BIT)
    {
        // 交换chdef的bit6和bit7
        chdef = (chdef & (~(BIT6 | BIT7))) | ((chdef & BIT6) << 1) | ((chdef & BIT7) >> 1);
    }

    MCPWMx->PRT    = 0xdead;
    MCPWMx->CH_DEF = chdef;
}
