/**
 * @brief I2C-读写EEPROM
 * @details
 * 先后向eeprom里写入两次数据，
 * 写入完成后从 eeprom 里都回来
 * 判断写入的数据和读回来的是否一致
 */
#include "lks32mc09x_gpio.h"
#include "lks32mc09x_i2c.h"
void WriteData(uint8_t eepromaddr, u16 taddr, u8 *data, uint32_t len);
void ReadData(uint8_t eepromaddr, u16 taddr, u8 *data, uint32_t len);
void SoftDelaymS(uint32_t n);
volatile uint32_t testflg = 0; // 测试状态，0空闲 1进行中 2写入数据&读回数据一致 3写入数据&读回数据不一致
volatile uint32_t errline = 0; // 测试状态，0空闲 1进行中 2写入数据&读回数据一致 3写入数据&读回数据不一致
uint8_t read_data[32];
uint8_t read_data1[32];
uint8_t write_data[32] = {0};
#define EEPROMADDR 0xa0
/**
 * @brief 主函数，用于测试HSI时钟输出及GPIO翻转
 */
int main(void)
{
    GPIO_Config(GPIO0, GPIO_PinSource_3, GPIO_Mode_IO, GPIO_AF_I2C);
    GPIO_Config(GPIO0, GPIO_PinSource_4, GPIO_Mode_IO, GPIO_AF_I2C);
    {
        I2C_InitTypeDef I2C_InitStruct;
        I2C_StructInit(&I2C_InitStruct);

        I2C_InitStruct.ADRCMP = DISABLE;         //  I2C 硬件地址比较使能开关，只有在 DMA 模式下开启才有效。
        I2C_InitStruct.MST_MODE = ENABLE;        //  I2C 主模式使能
        I2C_InitStruct.SLV_MODE = DISABLE;       //  I2C 从模式使能
        I2C_InitStruct.BaudRate = 10000;         //  I2C 波特率
        I2C_InitStruct.IE = ENABLE;              //  I2C 中断使能
        I2C_InitStruct.TC_IE = ENABLE;           //  I2C 数据传输完成中断使能
        I2C_InitStruct.BUS_ERR_IE = ENABLE;      //  I2C 总线错误事件中断使能
        I2C_InitStruct.STOP_IE = ENABLE;         //  I2C STOP 事件中断使能
        I2C_InitStruct.BURST_NACK = ENABLE;      //  I2C 传输，NACK 事件中断使能
        I2C_InitStruct.BURST_ADDR_CMP = DISABLE; //  I2C 传输，硬件地址匹配中断使能
        I2C_Init(I2C0, &I2C_InitStruct);
    }
    NVIC_EnableIRQ(I2C0_IRQn);      /* 使能I2C中断*/
    NVIC_SetPriority(I2C0_IRQn, 1); /* I2C中断优先级配置*/
    __enable_irq();                 /* 开启总中断 */

    for (;;)
    {
        if (testflg == 1) // 开始写入数据
        {
            for (int len = 1; len <= 32; len++) // 数据长度从1到32，以确保不同数据长度下i2c通信都正常
            {
                for (int i = 0; i < len; i++)
                {
                    write_data[i] = i + len; // 确保每次写入的数据都不一样
                }
                WriteData(EEPROMADDR, 0, write_data, len);
                SoftDelaymS(10);
                ReadData(EEPROMADDR, 0, read_data, len);
                for (int i = 0; i < len; i++)
                {
                    if (read_data[i] != write_data[i])
                    {
                        if (errline == 0)
                        {
                            errline = i;
                        }
                        testflg = 3;
                    }
                }
            }
            if (testflg != 3)
            {
                testflg = 2; // 测试完成，并且没有出现错误
            }
        }
    }
}

void WriteData(uint8_t eepromaddr, u16 taddr, u8 *data, uint32_t len)
{
    int i;
    static uint8_t txdata[34];
    if (len > 32) // 一次最多写32个
    {
        len = 32;
    }
    txdata[0] = taddr >> 8;
    txdata[1] = taddr;
    for (i = 0; i < len; i++)
    {
        txdata[i + 2] = data[i];
    }
    for (i = 0; i < 10; i++) // 如果收到nack 则最多尝试发送10次
    {
        I2C_TableSend(I2C0, eepromaddr, txdata, len + 2);
        while (I2C_TableState(I2C0))
            ; // 等待发送完成
        if (I2C_TableAck(I2C0) == 0)
        {
            return;
        }
    }
    return;
}
void ReadData(uint8_t eepromaddr, u16 taddr, u8 *data, uint32_t len)
{
    uint8_t txdata[2];
    int i;
    uint16_t val;
    for (i = 0; i < 10; i++) // 如果收到nack 则最多尝试发送10次
    {
        txdata[0] = taddr >> 8;
        txdata[1] = taddr;
        I2C_TableSend(I2C0, eepromaddr, txdata, 2); // 写地址
        I2C_TableRead(I2C0, eepromaddr, data, len); // 读数据
        while (I2C_TableState(I2C0))
            ; // 等待发送完成
        if (I2C_TableAck(I2C0) == 0)
        {
            return;
        }
    }
    return;
}
void I2C0_IRQHandler(void)
{
    I2C_TableIrq(I2C0);
}

