#include "lks32mc09x_i2c.h"
#include "lks32mc09x_sys.h"

/**
 * @brief I2C初始化
 * @param I2Cx: I2C外设指针
 * @param I2C_InitStruct: I2C初始化结构体指针
 */
void I2C_Init(I2C_TypeDef *I2Cx, I2C_InitTypeDef *I2C_InitStruct)
{
    SYS_ModuleClockCmd(SYS_MODULE_I2C0, ENABLE);
    SYS_SoftResetModule(SYS_MODULE_I2C0);
    I2C_SetBaudRate(I2Cx, I2C_InitStruct->BaudRate);
    I2Cx->ADDR = (I2C_InitStruct->ADRCMP << 7);
    I2Cx->CFG  = (I2C_InitStruct->IE << 7) | (I2C_InitStruct->TC_IE << 6) |
                (I2C_InitStruct->BUS_ERR_IE << 5) | (I2C_InitStruct->STOP_IE << 4) |
                (I2C_InitStruct->MST_MODE << 1) | (I2C_InitStruct->SLV_MODE);
    I2Cx->SCR  = 0;
    I2Cx->DATA = 0;
    I2Cx->MSCR = 0;
    I2Cx->BCR  = (I2C_InitStruct->BURST_NACK << 7) | (I2C_InitStruct->BURST_ADDR_CMP << 6) |
                (I2C_InitStruct->BUSRT_EN << 5);
}

/**
 * @brief I2C配置结构体初始化
 * @param I2C_InitStruct: I2C初始化结构体指针
 */
void I2C_StructInit(I2C_InitTypeDef *I2C_InitStruct)
{
    for (int i = 0; i < sizeof(I2C_InitTypeDef) / sizeof(uint32_t); i++)
    {
        ((uint32_t *)I2C_InitStruct)[i] = 0;
    }
}

/**
 * @brief 清除I2C中断标志
 * @param I2Cx: I2C外设指针
 * @param I2C_IF_x: 要清除的中断标志
 */
void I2C_ClearIRQFlag(I2C_TypeDef *I2Cx, uint16_t I2C_IF_x)
{
    switch (I2C_IF_x)
    {
        case I2C_IF_TC: // 传输完成中断
            I2Cx->SCR &= ~BIT0;
            break;
        case I2C_IF_BUS_ERR: // 总线错误中断
            I2Cx->SCR &= ~BIT7;
            break;
        case I2C_IF_STOP: // STOP事件中断
            I2Cx->SCR &= ~BIT5;
            break;
        case I2C_IF_NACK: // NACK事件中断
            I2Cx->SCR &= ~BIT1;
            break;
        case I2C_IF_ADDR_CMP: // 硬件地址比较中断

            break;
        default:
            break;
    }
}

/**
 * @brief 获取I2C中断标志状态
 * @param I2Cx: I2C外设指针
 * @param I2C_IF_x: 要获取的中断标志
 * @return 中断标志状态
 */
uint8_t I2C_GetIRQFlag(I2C_TypeDef *I2Cx, uint16_t I2C_IF_x)
{
    return I2C_GetFlag(I2Cx, I2C_IF_x);
}

/**
 * @brief 获取I2C状态标志
 * @param I2Cx: I2C外设指针
 * @param I2C_IF_x: 要获取的状态标志
 * @return 状态标志状态
 */
uint8_t I2C_GetFlag(I2C_TypeDef *I2Cx, uint16_t I2C_IF_x)
{
    switch (I2C_IF_x)
    {
        case I2C_IF_TC: // 传输完成中断
            if (I2Cx->SCR & BIT0)
            {
                return 1;
            }
            else
            {
                return 0;
            }
        case I2C_IF_BUS_ERR: // 总线错误中断
            if (I2Cx->SCR & BIT7)
            {
                return 1;
            }
            else
            {
                return 0;
            }
        case I2C_IF_STOP: // STOP事件中断
            if (I2Cx->SCR & BIT5)
            {
                return 1;
            }
            else
            {
                return 0;
            }
        case I2C_IF_NACK: // NACK事件中断
            if (I2Cx->SCR & BIT1)
            {
                return 1;
            }
            else
            {
                return 0;
            }
        case I2C_IF_ADDR_CMP: // 硬件地址匹配中断
            if (I2Cx->SCR & BIT3)
            {
                if ((u32)(I2Cx->DATA >> 1) == (I2Cx->ADDR & 0x7f))
                {
                    return 1;
                }
                else
                {
                    return 0;
                }
            }
            else
            {
                return 0;
            }
        default:
            return 0;
    }
}

/**
 * @brief 使能I2C外设
 * @param I2Cx: I2C外设指针
 */
void I2C_Enable(I2C_TypeDef *I2Cx)
{
    SYS_ModuleClockCmd(SYS_MODULE_I2C0, ENABLE);
}

/**
 * @brief 禁用I2C外设
 * @param I2Cx: I2C外设指针
 */
void I2C_Disable(I2C_TypeDef *I2Cx)
{
    SYS_ModuleClockCmd(SYS_MODULE_I2C0, DISABLE);
}

/**
 * @brief 设置I2C波特率
 * @param BaudRate: 波特率值
 */
void I2C_SetBaudRate(I2C_TypeDef *I2Cx, uint32_t BaudRate)
{
    // 根据系统时钟和波特率计算分频值
    u32 div;
    div = ((u32)SYS_ReadMcuClk() + ((BaudRate * 17) >> 1)) / (BaudRate * 17) - 1;
    SYS_I2CClkDiv(div);
}

/**
 * @brief 读取I2C总线状态
 * @param I2Cx: I2C外设指针
 * @param state: 要读取的状态位
 * @return 状态位值
 */
uint8_t I2c_ReadBusState(I2C_TypeDef *I2Cx, uint16_t state)
{
    if (I2Cx->SCR & state)
    {
        return ENABLE;
    }
    else
    {
        return DISABLE;
    }
}

/**
 * @brief 清除I2C总线状态
 * @param I2Cx: I2C外设指针
 * @param state: 要清除的状态位
 */
void I2c_ClearBusState(I2C_TypeDef *I2Cx, uint16_t state)
{
    I2Cx->SCR &= ~state;
}

/**
 * @brief 发送数据到I2C总线
 * @param I2Cx: I2C外设指针
 * @param n: 要发送的数据
 */
void I2C_SendData(I2C_TypeDef *I2Cx, uint8_t n)
{
    I2Cx->DATA = n;
}

/**
 * @brief 从I2C总线读取数据
 * @param I2Cx: I2C外设指针
 * @return 读取到的数据
 */
uint8_t I2C_ReadData(I2C_TypeDef *I2Cx)
{
    return I2Cx->DATA;
}
// 仅用于Table收发的变量
struct iictmpval
{
    volatile uint8_t *txdata;
    volatile uint8_t txdatap;
    volatile uint8_t *rxdata;
    volatile uint8_t rxdatap;
    volatile uint8_t state;   // 0 无动作 1接收 2发送
    volatile uint8_t nackflg; // 0 通信正常 1 发生nack事件
};
static volatile struct iictmpval I2C_TableVariable[1] = {0}; // 只有一个tab

/**
 * @brief 向从机发送数据 （需要在中断里执行I2C_TableIrq）
 * @param I2Cx I2C外设指针
 * @param taddr 从机地址
 * @param data 数据指针
 * @param len 数据长度
 * @return 状态，0成功 1失败（i2c总线非空闲，或上一次数据尚未发送完毕）
 */
int I2C_TableSend(I2C_TypeDef *I2Cx, u8 taddr, u8 *data, u8 len)
{
    I2C_TableVariable[0].nackflg = 0;
    while (I2C_TableVariable[0].state != 0);
    I2C->SCR                     = 0;
    I2C_TableVariable[0].txdata  = data;
    I2C_TableVariable[0].txdatap = len;
    I2C_TableVariable[0].state   = 2;
    I2C->DATA                    = taddr;
    I2C->MSCR                    = 1; // 触发I2C发送数据
    return 0;
}

/**
 * @brief 向从机读取数据 （需要在中断里执行I2C_TableIrq）
 * @param I2Cx I2C外设指针
 * @param taddr 从机地址
 * @param data 数据指针
 * @param len 数据长度
 * @return 状态，0成功 1失败（i2c总线非空闲，或上一次数据尚未发送完毕）
 */
int I2C_TableRead(I2C_TypeDef *I2Cx, u8 taddr, u8 *data, u8 len)
{
    I2C_TableVariable[0].nackflg = 0;
    while (I2C_TableVariable[0].state != 0);
    I2C->SCR                     = 0;
    I2C_TableVariable[0].rxdata  = data;
    I2C_TableVariable[0].rxdatap = len;
    I2C_TableVariable[0].state   = 1;
    I2C->DATA                    = taddr | 1;
    I2C->MSCR                    = 1; // 触发I2C发送数据
    return 0;
}
/**
 * @brief 获取I2C_Table发送后的ack电平
 * @return 收到的ACK电平
 */
int I2C_TableAck(I2C_TypeDef *I2Cx)
{
    return I2C_TableVariable[0].nackflg;
}
/**
 * @brief 获取I2C_Table发送状态
 * @return 状态，0空闲 1正在发送或接收数据
 */
int I2C_TableState(I2C_TypeDef *I2Cx)
{
    return I2C_TableVariable[0].state;
}
/**
 * @brief I2C_SendTable和I2C_ReadTable对应的中断处理函数
 */
void I2C_TableIrq(I2C_TypeDef *I2Cx)
{

    if (I2Cx->SCR & BIT1)
    {
        I2C_TableVariable[0].nackflg = 1;
    }
    else
    {
        __NOP();
    }
    if (I2Cx->SCR & BIT5)
    {
        I2C_TableVariable[0].state = 0;
        I2Cx->SCR                  = 0;
    }
    else if (I2C_TableVariable[0].state == 1)
    {
        if (I2Cx->SCR & BIT3)
        {
            I2Cx->SCR = 0;
        }
        else
        {
            I2Cx->DATA                   = 0xff;
            *I2C_TableVariable[0].rxdata = I2Cx->DATA;
            I2C_TableVariable[0].rxdatap--;
            if (I2C_TableVariable[0].rxdatap != 0)
            {
                I2C_TableVariable[0].rxdata++;
                I2Cx->SCR = BIT4;
            }
            else
            {
                I2Cx->SCR = 0;
            }
        }
    }
    else if (I2C_TableVariable[0].state == 2)
    {
        if (I2C_TableVariable[0].txdatap != 0)
        {
            I2Cx->DATA = *I2C_TableVariable[0].txdata;
            I2C_TableVariable[0].txdata++;
            I2C_TableVariable[0].txdatap--;
            I2Cx->SCR = BIT2;
        }
        else
        {
            I2Cx->SCR = 0;
        }
    }
    else
    {
        I2Cx->SCR = 0;
    }
}
