#include "lks32mc09x_eeprom.h"
#include "lks32mc09x_sys.h"
#ifndef EEPROM_CFG
#define EEPROM_CFG REG32(0x40048000)
#endif
#ifndef EEPROM_RDATA
#define EEPROM_RDATA REG32(0x40048004)
#endif
/**
 * @brief 初始化
 * @param EEPROM_InitStruct EEPROM初始化结构体指针
 */
void EEPROM_Init(EEPROM_InitTypeDef *EEPROM_InitStruct)
{
    EEPROM_Enable();
    EEPROM_InitStruct->addr >>= 1;
    EEPROM_CFG = (EEPROM_InitStruct->addr << 2) |
                 (EEPROM_InitStruct->EEPROM_BAUD_x << 0) |
                 (EEPROM_InitStruct->RDY_RLS << 16) |
                 (EEPROM_InitStruct->IO_SWITCH << 10) |
                 (EEPROM_InitStruct->ADDR_LEN_x << 9);
}
/**
 * @brief 初始化EEPROM_InitStruct结构体为默认值
 */
void EEPROM_StructInit(EEPROM_InitTypeDef *EEPROM_InitStruct)
{
    uint32_t i;
    for (i = 0; i < sizeof(EEPROM_InitTypeDef); i++)
    {
        ((uint8_t *)EEPROM_InitStruct)[i] = 0;
    }
}
/**
 * @brief 初始化为默认配置，IO不交换，波特率100k，地址数据长度16位，读写时响应中断
 */
void EEPROM_InitDefault(void)
{
    EEPROM_Enable();
    EEPROM_CFG = BIT16 | BIT9 | (0xa0 << 1) | 0;
}
/**
 * @brief EEPROM使能
 */
void EEPROM_Enable(void)
{
    SYS_ModuleClockCmd(SYS_MODULE_EEPROM, ENABLE);
}
/**
 * @brief EEPROM失能
 */
void EEPROM_Disable(void)
{
    SYS_ModuleClockCmd(SYS_MODULE_EEPROM, DISABLE);
}
/**
 * @brief EEPROM复位
 */
void EEPROM_Reset(void)
{
    SYS_SoftResetModule(SYS_MODULE_EEPROM);
}

/**
 * @brief 读取eeprom内数据
 * @param eeprom_addr eeprom数据地址
 * @return 数据
 */
uint8_t EEPROM_Read(uint16_t eeprom_addr)
{
    uint8_t val;
    if (eeprom_addr > 32767)
    {
        eeprom_addr = 32767;
    }
    else
    {
        __NOP();
    }
    while (EEPROM_CFG & BIT17); // 等待之前的操作结束（如果有的话）
    do
    {
        val = REG8(eeprom_addr | 0x40040000);
        while (EEPROM_CFG & BIT17);
    } while (EEPROM_CFG & BIT11);
    val = EEPROM_RDATA;
    return val;
}
/**
 * @brief 向eeprom写入数据
 * @param eeprom_addr eeprom数据地址
 * @param data 要写入的数据
 */
void EEPROM_Write(uint16_t eeprom_addr, uint8_t data)
{
    if (eeprom_addr > 32767)
    {
        eeprom_addr = 32767;
    }
    else
    {
        __NOP();
    }
    if (EEPROM_CFG & BIT16)
    {
        do
        {
            REG8(eeprom_addr + 0x40040000) = data;
            while (EEPROM_CFG & BIT17);
        } while (EEPROM_CFG & BIT11); // 收到NACK则自动重发
    }
    else
    {
        REG8(eeprom_addr + 0x40040000) = data; // 先触发一次写操作
        do
        {
            REG8(eeprom_addr + 0x40040000) = data; // 这里的写操作时，mcu会暂停运行，等待上一个写操作完成
        } while (EEPROM_CFG & BIT11); // 这里判断的是上一次的写操作是否收到nack
    }
}
/**
 * @brief 向eeprom写入数据(多字节)，09上eeprom本身不支持多字节模式，这里用n个单次读写实现，执行时间为len*5mS（典型值）
 * @param eepromaddr eeprom模块设备地址，例如0xa0
 * @param taddr eeprom数据的起始地址
 * @param data 要写入的数据地址
 * @param len 要写入的长度
 */
void EEPROM_WriteData(uint8_t eepromaddr, u16 taddr, u8 *data, uint32_t len)
{
    uint16_t i;
    eepromaddr &= 0xfe;
    EEPROM_CFG = (EEPROM_CFG & (~0x1fc)) | (eepromaddr << 1);
    for (i = 0; i < len; i++)
    {
        EEPROM_Write(taddr + i, data[i]);
    }
}
/**
 * @brief 读取eeprom内数据，09上eeprom本身不支持多字节模式，这里用n个单次读写实现
 * @param eepromaddr eeprom模块设备地址，例如0xa0
 * @param taddr eeprom数据的起始地址
 * @param data 存放数据的地址
 * @param len 数据长度
 */
void EEPROM_ReadData(uint8_t eepromaddr, u16 taddr, u8 *data, uint32_t len)
{
    uint16_t i;
    eepromaddr &= 0xfe;
    EEPROM_CFG = (EEPROM_CFG & (~0x1fc)) | (eepromaddr << 1);
    for (i = 0; i < len; i++)
    {
        data[i] = EEPROM_Read(taddr + i);
    }
}
