#include "lks32mc09x_gpio.h"
#include "lks32mc09x_sys.h"

/**
 * @brief gpio使能
 */
void GPIO_Enable(void)
{
    SYS_ModuleClockCmd(SYS_MODULE_GPIO, 1);
}
/**
 * @brief gpio失能
 */
void GPIO_Disable(void)
{
    SYS_ModuleClockCmd(SYS_MODULE_GPIO, 0);
}
/**
 * @brief gpio模块复位
 */
void GPIO_Reset(void)
{
    SYS_SoftResetModule(SYS_MODULE_GPIO);
}
/**
 * @brief 初始化GPIO结构体为默认值
 * @param GPIO_InitStruct 指向要初始化的GPIO_InitTypeDef结构体
 */
void GPIO_StructInit(GPIO_InitTypeDef *GPIO_InitStruct)
{
    uint32_t i;
    for (i = 0; i < sizeof(GPIO_InitTypeDef); i++)
    {
        ((uint8_t *)GPIO_InitStruct)[i] = 0;
    }
}

/**
 * @brief 初始化GPIO
 * @param GPIOx GPIO模块指针
 * @param GPIO_InitStruct 指向包含初始化参数的GPIO_InitTypeDef结构体
 */
void GPIO_Init(GPIO_TypeDef *GPIOx, GPIO_InitTypeDef *GPIO_InitStruct)
{
    // 使能GPIO时钟
    SYS_ModuleClockCmd(SYS_MODULE_GPIO, ENABLE);

    // 配置引脚模式
    if (GPIO_InitStruct->GPIO_Mode == GPIO_Mode_IN)
    {
        GPIOx->PIE |= GPIO_InitStruct->GPIO_Pin;  // 打开输入使能
        GPIOx->POE &= ~GPIO_InitStruct->GPIO_Pin; // 关闭输出使能
        GPIOx->PUE &= ~GPIO_InitStruct->GPIO_Pin; // 关闭上拉使能
    }
    else if (GPIO_InitStruct->GPIO_Mode == GPIO_Mode_OUT)
    {
        GPIOx->PIE &= ~GPIO_InitStruct->GPIO_Pin; // 关闭输入使能
        GPIOx->POE |= GPIO_InitStruct->GPIO_Pin;  // 使能输出
    }
    else if (GPIO_InitStruct->GPIO_Mode == GPIO_Mode_IO)
    {
        GPIOx->PIE |= GPIO_InitStruct->GPIO_Pin; // 使能输入
        GPIOx->POE |= GPIO_InitStruct->GPIO_Pin; // 使能输出
    }
    else // GPIO_Mode_ANA
    {
        GPIOx->PIE &= ~GPIO_InitStruct->GPIO_Pin; // 关闭输入使能
        GPIOx->POE &= ~GPIO_InitStruct->GPIO_Pin; // 关闭输出使能
        GPIOx->PUE &= ~GPIO_InitStruct->GPIO_Pin; // 关闭上拉使能
    }

    if (GPIO_InitStruct->GPIO_PuPd == GPIO_PuPd_UP)
    {
        GPIOx->PUE |= GPIO_InitStruct->GPIO_Pin; // 使能上拉
    }
    else
    {
        GPIOx->PUE &= ~GPIO_InitStruct->GPIO_Pin; // 关闭上拉
    }
    // 配置开漏使能
    if (GPIO_InitStruct->GPIO_PODEna)
    {
        GPIOx->PODE |= GPIO_InitStruct->GPIO_Pin;
    }
    else
    {
        GPIOx->PODE &= ~GPIO_InitStruct->GPIO_Pin;
    }

    // 配置滤波使能
    if (GPIO_InitStruct->GPIO_PFLT)
    {
        GPIOx->PFLT |= GPIO_InitStruct->GPIO_Pin;
    }
    else
    {
        GPIOx->PFLT &= ~GPIO_InitStruct->GPIO_Pin;
    }
}

/**
 * @brief 锁定GPIO寄存器
 * @param GPIOx GPIO模块指针
 */
void GPIO_LockRegister(GPIO_TypeDef *GPIOx)
{
    // 09x 无此功能
    if (GPIOx == GPIO0)
    {
        __NOP();
    }
}

/**
 * @brief 解锁GPIO寄存器
 * @param GPIOx GPIO模块指针
 */
void GPIO_UnlockRegister(GPIO_TypeDef *GPIOx)
{
    // 09x 无此功能
    if (GPIOx == GPIO0)
    {
        __NOP();
    }
}

/**
 * @brief 读取指定GPIO引脚的输入数据位
 * @param GPIOx GPIO模块指针
 * @param GPIO_Pin 要读取的引脚
 * @return 引脚的输入数据位状态
 */
uint8_t GPIO_ReadInputDataBit(GPIO_TypeDef *GPIOx, uint16_t GPIO_Pin)
{
    return (GPIOx->PDI & GPIO_Pin) ? 1 : 0;
}

/**
 * @brief 读取GPIO端口的输入数据
 * @param GPIOx GPIO模块指针
 * @return GPIO端口的输入数据
 */
uint32_t GPIO_ReadInputData(GPIO_TypeDef *GPIOx)
{
    return GPIOx->PDI;
}

/**
 * @brief 读取指定GPIO引脚的输出数据位
 * @param GPIOx GPIO模块指针
 * @param GPIO_Pin 要读取的引脚
 * @return 引脚的输出数据位状态
 */
uint8_t GPIO_ReadOutputDataBit(GPIO_TypeDef *GPIOx, uint16_t GPIO_Pin)
{
    return (GPIOx->PDO & GPIO_Pin) ? 1 : 0;
}

/**
 * @brief 读取GPIO端口的输出数据
 * @param GPIOx GPIO模块指针
 * @return GPIO端口的输出数据
 */
uint32_t GPIO_ReadOutputData(GPIO_TypeDef *GPIOx)
{
    return GPIOx->PDO;
}

/**
 * @brief 设置指定的GPIO引脚位
 * @param GPIOx GPIO模块指针
 * @param GPIO_Pin 要设置的引脚
 */
void GPIO_SetBits(GPIO_TypeDef *GPIOx, uint16_t GPIO_Pin)
{
    GPIOx->PDO |= GPIO_Pin;
}

/**
 * @brief 复位指定的GPIO引脚位
 * @param GPIOx GPIO模块指针
 * @param GPIO_Pin 要复位的引脚
 */
void GPIO_ResetBits(GPIO_TypeDef *GPIOx, uint16_t GPIO_Pin)
{
    GPIOx->PDO &= ~GPIO_Pin;
}

/**
 * @brief 写入数据到指定的GPIO端口
 * @param GPIOx GPIO模块指针
 * @param Val 要写入的数据
 */
void GPIO_Write(GPIO_TypeDef *GPIOx, uint32_t Val)
{
    GPIOx->PDO = Val;
}

/**
 * @brief 设置或复位指定的GPIO引脚位
 * @param GPIOx GPIO模块指针
 * @param GPIO_Pin 要操作的引脚
 * @param BitVal 要执行的操作：GPIO_Bit_SET 或 GPIO_Bit_RESET
 */
void GPIO_WriteBit(GPIO_TypeDef *GPIOx, uint16_t GPIO_Pin, GPIO_Bit_Action BitVal)
{
    if (BitVal == GPIO_Bit_SET)
    {
        GPIOx->PDO |= GPIO_Pin;
    }
    else
    {
        GPIOx->PDO &= ~GPIO_Pin;
    }
}

/**
 * @brief 配置GPIO引脚复用功能
 * @param GPIOx GPIO模块指针
 * @param GPIO_PinSource 引脚源
 * @param GPIO_AF 复用功能选择
 */
void GPIO_PinAFConfig(GPIO_TypeDef *GPIOx, uint32_t GPIO_PinSource, uint32_t GPIO_AF)
{
    uint8_t offset;
    uint8_t pins = GPIO_PinSource >> 2;
    offset       = ((GPIO_PinSource & 0x3) * 4);
    switch (pins)
    {
        case 0:
            GPIOx->F3210 = (GPIOx->F3210 & ~(0xf << offset)) | (GPIO_AF << offset);
            break;
        case 1:
            GPIOx->F7654 = (GPIOx->F7654 & ~(0xf << offset)) | (GPIO_AF << offset);
            break;
        case 2:
            GPIOx->FBA98 = (GPIOx->FBA98 & ~(0xf << offset)) | (GPIO_AF << offset);
            break;
        case 3:
            GPIOx->FFEDC = (GPIOx->FFEDC & ~(0xf << offset)) | (GPIO_AF << offset);
            break;
        default:
            break;
    }
}

/**
 * @brief 翻转指定的GPIO引脚位
 * @param GPIOx GPIO模块指针
 * @param GPIO_Pin 要翻转的引脚
 */
void GPIO_ToggleBits(GPIO_TypeDef *GPIOx, uint16_t GPIO_Pin)
{
    GPIOx->PDO = GPIOx->PDO ^ GPIO_Pin;
}

/**
 * @brief  GPIO配置函数
 * @param  GPIOx: GPIO端口
 * @param  GPIO_PinSource: GPIO引脚
 * @param  mode: GPIO模式
 * @param  GPIO_AF_x: GPIO复用功能选择
 */
void GPIO_Config(GPIO_TypeDef *GPIOx, uint32_t GPIO_PinSource, GPIO_Mode_TypeDef mode, uint32_t GPIO_AF_x)
{
    GPIO_PinAFConfig(GPIOx, GPIO_PinSource, GPIO_AF_x);
    GPIO_InitTypeDef GPIO_InitStructure;
    GPIO_StructInit(&GPIO_InitStructure);
    GPIO_InitStructure.GPIO_Pin  = 1 << GPIO_PinSource;
    GPIO_InitStructure.GPIO_Mode = mode;
    if (GPIO_AF_x == GPIO_AF_I2C)
    {
        GPIO_InitStructure.GPIO_PuPd = GPIO_PuPd_UP;
    }
    else
    {
        __NOP();
    }
    GPIO_Init(GPIOx, &GPIO_InitStructure);
}
