#include "i2c_eeprom.h"
#include "soft_iic.h"

u8 eeprom_write_buf[256];
u8 eeprom_read_buf[256];

//Read EEPROM one byte
u8 at24c02_read_one_byte(u8 addr)
{
    u8 tmp = 0;

    #if SOFT_I2C_ENABLE
        i2c_start();
        i2c_send_byte(EEPROM_WRITE_ADDR);
        i2c_wait_ack();
        i2c_send_byte(addr);
        i2c_wait_ack();

        i2c_start();
        i2c_send_byte(EEPROM_READ_ADDR);
        i2c_wait_ack();
        tmp = i2c_read_byte(0);
        i2c_stop();
    #else
        tmp = iic_receive_data(EEPROM_WRITE_ADDR, addr, 1, EEPROM_READ_ADDR);
    #endif // SOFT_I2C_ENABLE

    return tmp;
}

//Write EEPROM one byte
void at24c02_write_one_byte(u8 addr,u8 data)
{
    #if SOFT_I2C_ENABLE
        i2c_start();
        i2c_send_byte(EEPROM_WRITE_ADDR);
        i2c_wait_ack();
        i2c_send_byte(addr);
        i2c_wait_ack();
        i2c_send_byte(data);
        i2c_wait_ack();
        i2c_stop();
        delay_ms(10);
    #else
        iic_send_data(EEPROM_WRITE_ADDR, addr, data, 1);
    #endif // SOFT_I2C_ENABLE
}

// Write EEPROM one data unit, maximum 4 bytes
u32 at24c02_read_len_byte(u16 addr,u8 len)
{
    u32 tmp = 0;

    #if SOFT_I2C_ENABLE
        u8 i;

        for (i = 0; i < len; i++) {
            tmp <<= 8;
            at24c02_read_one_byte(addr + len - i - 1);
        }
    #else
        tmp = iic_receive_data(EEPROM_WRITE_ADDR, addr, len, EEPROM_READ_ADDR);
    #endif // SOFT_I2C_ENABLE

    return tmp;
}

// Read EEPROM one data unit, maximum 4 bytes
void at24c02_write_len_byte(u16 addr,u32 data,u8 len)
{
    #if SOFT_I2C_ENABLE
        u8 i;

        for (i = 0; i < len; i++) {
            at24c02_write_one_byte(addr + i, (data >> (8 * i)) & 0xff);
        }
    #else
        iic_send_data(EEPROM_WRITE_ADDR, addr, data, len);
    #endif // SOFT_I2C_ENABLE
}

// Write EEPROM continuously
void at24c02_write(u16 addr,u8 *p,u16 num)
{
    while (num--) {
        at24c02_write_one_byte(addr, *p);
        addr++;
        p++;
    }
}

// Read EEPROM continuously
void at24c02_read(u16 addr,u8 *p,u16 num)
{
    while (num) {
        *p++ = at24c02_read_one_byte(addr);
        addr++;
        num--;
    }
}

//连续一次性写入多个
void at24c01_write_countine(u16 addr,u8 *p,u16 num) //P src
{
    u16 i;
    u8 iic_data;
/*************************************************/
    IIC->con1 = 0;
    IIC->con1 |= IIC_CON1_ADR0_EN;  //给5位写1 地址0使能
    IIC->con1 |= IIC_CON1_CTL0_EN;  //给4位写1 地址0控制使能
    IIC->con1 |= IIC_CON1_START0_EN;//给3位写1 发送开始使能-起始信号
    IIC->con1 |= 0x01 & IIC_CON1_DATA_CNT;//限制数据长度
    IIC->cmda = EEPROM_WRITE_ADDR | (addr << 8);//寄存器地址15-8 设备地址0-7
    IIC->con1 |= IIC_CON1_WDAT_EN;  //发送数据使能
/**********************************************/
    IIC->data = p[0];
    IIC->con0 |= IIC_CON0_KS; //总使能
    while ((IIC->con0 & IIC_CON0_DONE) == RESET);   //完成

    for(i=1;i<num;i++)
    {
        IIC->con1 = 0;
        IIC->con1 |= 0x01;//限制数据长度
        IIC->con1 |= IIC_CON1_WDAT_EN;  //使能数据的发送
        if(i==num-1)
            IIC->con1 |= IIC_CON1_STOP_EN;

        iic_data = p[i];
        IIC->data = iic_data;
        IIC->con0 |= IIC_CON0_KS; //总使能
        while ((IIC->con0 & IIC_CON0_DONE) == RESET); //wait ACK
    }
    IIC->con0 |= IIC_CON0_CLR_DONE; //STOP
    delay_ms(5);    //芯片手册写必须等5ms，如果不必等可删除
}

//连续一次读多个
void at24c01_read_countine(u16 addr,u8 *dst,u16 num)
{
/*************************************************/
     //1...
    IIC->con1 = 0;
    IIC->con1 |= IIC_CON1_ADR0_EN;  //给5位写1 ADR0使能
    IIC->con1 |= IIC_CON1_CTL0_EN;  //给4位写1 地址0控制使能
    IIC->con1 |= IIC_CON1_START0_EN;//给3位写1 发送开始使能-起始信号
    IIC->con1 |= 0x01 & IIC_CON1_DATA_CNT;//限制数据长度
    IIC->cmda = EEPROM_WRITE_ADDR | (addr << 8);//寄存器地址15-8 设备地址0-7 //赋值给CTL0 ADR0

    IIC->con1 |= IIC_CON1_RDAT_EN;  //给9位写1 接收数据使能
    IIC->con1 |= IIC_CON1_CTL1_EN;  //给8位写1 控制ctl1发送使能
    IIC->con1 |= IIC_CON1_START1_EN;//给7位写1 发送start使能
    IIC->cmda |= (EEPROM_READ_ADDR << 24); //赋值给CTL1
    IIC->con1 |= IIC_CON1_TXNAK_EN; //nak

    IIC->con0 |= IIC_CON0_KS; //总使能
    while ((IIC->con0 & IIC_CON0_DONE) == RESET);   //完成
    dst[0] = (IIC->data);
    //2...
    IIC->con1 = 0;
    IIC->con1 |= IIC_CON1_RDAT_EN;  //给9位写1 使能数据的接收
    IIC->cmda |= (EEPROM_READ_ADDR << 24); //赋值给CTL1
    IIC->con1 |= IIC_CON1_CTL1_EN;  //给8位写1 控制1发送使能

    IIC->con0 |= IIC_CON0_KS; //总使能-启动
    IIC->con1 |= IIC_CON1_START1_EN;//给8位写1
    while ((IIC->con0 & IIC_CON0_DONE) == RESET);   //等待完成
    dst[1] = (IIC->data);
    //3..
    for(u16 i=2;i<num;i++)
    {
        IIC->con1 = 0;
        IIC->con1 |= 0x01;
        IIC->con1 |= IIC_CON1_RDAT_EN;  //给9位写1 使能数据的接收
        if(i>=num-1)
        {
            IIC->con1 |= IIC_CON1_TXNAK_EN; //IIC->con1 |= IIC_CON1_STOP_EN;
            IIC->con1 |= IIC_CON1_STOP_EN;
        }
        IIC->con0 |= IIC_CON0_KS; //总使能-启动
        while ((IIC->con0 & IIC_CON0_DONE) == RESET); //wait ACK
        dst[i]=(u8)(IIC->data);
    }
    IIC->con0 |= IIC_CON0_CLR_DONE; //STOP
}

// Hardware IIC initialization
void hardware_i2c_init(void)
{
    gpio_init_typedef gpio_init_structure;
    iic_init_typedef iic_init_struct;

    clock_gate2_cmd(CLOCK_GATE2_IIC, ENABLE);

    gpio_init_structure.gpio_pin = GPIO_PIN_1 | GPIO_PIN_2;
    gpio_init_structure.gpio_dir = GPIO_DIR_INPUT;
    gpio_init_structure.gpio_fen = GPIO_FEN_PER;
    gpio_init_structure.gpio_mode = GPIO_MODE_DIGITAL;
    gpio_init_structure.gpio_pupd = GPIO_PUPD_UP;
    gpio_init(GPIOB_REG, &gpio_init_structure);

    gpio_func_mapping(IICMAP_G3);

    iic_init_struct.clk_source = IIC_CLK_XOSC24M_DIV8;
    iic_init_struct.scl_pose_div = 63;
    iic_init_struct.sda_hold_cnt = 2;
    iic_init(&iic_init_struct);

    iic_cmd(ENABLE);
}


//Check whether EEPROM is online
//Success: 1
//Failed: 0
u8 at24c02_check(void)
{
    u8 tmp;

    tmp = at24c02_read_one_byte(CHECK_ADDR);
    if (tmp == CHECK_FLAG) {
        return 1;
    } else {
        at24c02_write_one_byte(CHECK_ADDR, CHECK_FLAG);
        delay_ms(10);
        tmp = at24c02_read_one_byte(CHECK_ADDR);
        if (tmp == CHECK_FLAG) {
            return 1;
        }
    }
    return 0;
}

//Initialize IIC
void IIC_AT24C01_init(void)
{
    #if SOFT_I2C_ENABLE
        set_sys_clk(SYS_80M);
        i2c_init();
        printf("\n---> run with software iic <---\n");
    #else
        hardware_i2c_init();
        printf("\n---> run with hardware iic <---\n");
    #endif // SOFT_I2C_ENABLE
}

//Test function
void IIC_AT24C01_example(void)
{
#if HARDWARE_COUNTINE
    for(u8 i=0;i<255;i++)
    {
        eeprom_write_buf[i]= i;
        printf("%d",eeprom_write_buf[i]);
    }
    delay_ms(100);
    for(u8 j=0;j<256/8;j++) //芯片要求，连续写一次只能写8个数据
    {
        at24c01_write_countine(0x00+j*8, &eeprom_write_buf[j*8],8);//连续写
    }
    printf("write OK \n");

    at24c01_read_countine(0x00, eeprom_read_buf,255);   //连续读
    printf("read OK \n");
    for(u8 i=0;i<255;i++)
    {
        printf("[%02x] %02x\n ",i,eeprom_read_buf[i]);
    }
#else
    memset(eeprom_write_buf,0x00,255);
    for(u8 i=0;i<255;i++)
    {
        eeprom_write_buf[i]= i;
        printf("%d ",eeprom_write_buf[i]);
    }
    printf("\n");
    at24c02_write(0, eeprom_write_buf, 255);

    printf("---> eeprom init success.\n");
    printf("EEPROM READ:\n");
    at24c02_read(0, eeprom_read_buf, 255);
    for(u8 i=0;i<255;i++)
    {
        printf("%d ",eeprom_read_buf[i]);
    }
    printf("\n");

#endif
}
