/*******************************************************************************
* Copyright (C) 2020-2023, tau Systems (R),All Rights Reserved.
*
* File:         demo_hal_i2ci.c
* Description： i2c demo code
* Version：      V0.1
* Date：         2023-07-27
* Author：       swx
 *******************************************************************************/

/*******************************************************************************
* 1.Included files
*******************************************************************************/
#include "hal_i2c_master.h"
#include "hal_i2c_slave.h"
#include "demo_hal_i2c.h"
#include "hal_gpio.h"
#include "tau_log.h"
#include "tau_delay.h"

#if _MODULE_DEMO_I2C_EN
/*******************************************************************************
* 2.Global constant and macro definitions using #define
*******************************************************************************/
#ifdef LOG_TAG
#undef LOG_TAG
#endif
#define LOG_TAG "demo_hal_i2c"
#define BUFFER_SIZE                 10    // 以10个数据为例

#define CHECK_TRANS_RESULT(src, dst, size)                 \
    for(uint32_t check_num = 0; check_num < size; check_num ++) \
    {\
        if(src[check_num] != dst[check_num])\
        {\
            TAU_LOGD("src[%d] = %x, dst[%d] = %x , error!!\n",check_num,src[check_num],check_num,dst[check_num]);\
            return false;\
        }\
    }\

/*******************************************************************************
* 3.Global function and Global variable declarations
*******************************************************************************/
static uint8_t i2cm_read_buffer[BUFFER_SIZE];
static uint8_t i2cs_read_buffer[BUFFER_SIZE];
static uint8_t i2cs_write_buffer[BUFFER_SIZE];


/*******************************************************************************
* 4.Global variable extern declarations
*******************************************************************************/

/*******************************************************************************
* 5.Global function prototypes
*******************************************************************************/
/**
* @brief  i2c master的IO初始化
* @param  none
* @retval none
*/
static void i2cm_io_init(void)
{
    io_pad_attr_t attrs[] =
    {
        {IO_PAD_TD_SPIM_CLK, PIN5_MODE_I2C1_SCL, IO_IOE_NONE, IO_LVL_HIGH},
        {IO_PAD_TD_SPIM_CSN, PIN6_MODE_I2C1_SDA, IO_IOE_NONE, IO_LVL_HIGH}
    };
    uint8_t size = sizeof(attrs) / sizeof(io_pad_attr_t);
    hal_gpio_config_pad(attrs, size);
}

/**
* @brief  i2c slave的IO初始化
* @param  none
* @retval none
*/
static void i2cs_io_init(void)
{
    io_pad_attr_t attrs[] =
    {
        {IO_PAD_AP_SPIS_CLK, PIN32_MODE_I2C02_SCL, IO_IOE_NONE, IO_LVL_HIGH},
        {IO_PAD_AP_SPIS_CSN, PIN31_MODE_I2C02_SDA, IO_IOE_NONE, IO_LVL_HIGH}
    };
    uint8_t size = sizeof(attrs) / sizeof(io_pad_attr_t);
    hal_gpio_config_pad(attrs, size);
}

/**
* @brief  i2c slave的中断回调服务函数
* @param  index: I2Cx index
* @param  int_status: 中断事件
* @param  recieve_num： 接收到的packet数
* @retval none
*/
static void i2cs_callback(i2c_index_e index, hal_i2cs_event_e int_status, size_t recieve_num)
{
    /* 收到READ_REQ中断 */
    if (int_status == I2CS_EVENT_READ)
    {
        /* 更新I2CS的txbuffer，将i2cs_write_buffer的数据发送给主机 */
        hal_i2cs_update_tx_buffer(index, i2cs_write_buffer, BUFFER_SIZE, false);
    }
    /* 收到stop中断 */
    else if (int_status == I2CS_EVENT_STOP)
    {
        if (recieve_num > 0)
        {
            /* 将读到的值写到i2cs_write_buffer中 */
            for (int i = 0; i < recieve_num; i++)
                i2cs_write_buffer[i] = i2cs_read_buffer[i];
        }
        /* 更新I2CS的rxbuffer */
        hal_i2cs_update_rx_buffer(index, i2cs_read_buffer, BUFFER_SIZE);
    }
}

/**
* @brief  i2c master初始化
* @param  index: I2Cx index
* @param  addr: 从机地址
* @param  addr_bits: 从机地址位数
* @param  speed: 主机速率设置
* @retval none
*/
void i2cm_init(i2c_index_e index, uint16_t addr, uint8_t addr_bits, uint32_t speed)
{
    /* I2CS的IO初始化 */
    i2cm_io_init();

    /* I2CM初始化 */
    hal_i2cm_init(index, addr, addr_bits, speed);
}

/**
* @brief  i2c slave初始化
* @param  index: I2Cx index
* @param  addr: 从机自身地址
* @param  addr_bits: 从机地址位数
* @retval none
*/
void i2cs_init(i2c_index_e       index, uint16_t addr, uint8_t addr_bits)
{
    /* I2CS的IO初始化 */
    i2cs_io_init();

    /* I2CS的初始化 */
    hal_i2cs_init(index, addr, addr_bits);

    /* I2CS注册回调函函数 */
    hal_i2cs_register_callback(index, i2cs_callback);

    /* I2CS设置初始读写buffer */
    hal_i2cs_update_rx_buffer(index, i2cs_read_buffer, BUFFER_SIZE);
    hal_i2cs_update_tx_buffer(index, i2cs_write_buffer, BUFFER_SIZE, false);

    /* I2CS启动 */
    hal_i2cs_start(index);
}

/**
* @brief  i2c master去初始化
* @param  index: I2Cx index
* @retval none
*/
void i2cm_deinit(i2c_index_e index)
{
    hal_i2cm_deinit(index);
}

/**
* @brief  i2c slave去初始化
* @param  index: I2Cx index
* @retval none
*/
void i2cs_deinit(i2c_index_e index)
{
    hal_i2cs_stop(index);
    hal_i2cs_deinit(index);
}

/**
* @brief  i2c case buffer初始化
* @param  none
* @retval none
*/
static void i2c_case_buffer_init(void)
{
    TAU_LOGD("i2c_case_buffer_init\n");
    /* init buffer */
    uint8_t i = 0 ;
    for (i = 0; i < BUFFER_SIZE; i ++)
    {
        i2cm_read_buffer[i] = 0;
        i2cs_read_buffer[i] = 0;
        i2cs_write_buffer[i] = 0;
    }
}

/**
* @brief  芯片I2CM与I2CS对接,验证I2CM用CPU方式传输数据的正确性
* @param
* @retval bool true/false
*/
static bool hal_i2c_cpu_transfer_case(void)
{
    uint8_t write_buffer[10] = {0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17, 0x18, 0x19};
    uint8_t addr_bit = 7;
    uint32_t speed =  400000;
    uint16_t addr = 0x50;

    /* I2CM初始化，I2C1+目标地址0x50+7位地址+400k传输速率 */
    i2cm_init(I2C_INDEX_1, addr, addr_bit, speed);

    /* I2CS初始化，I2C0+本机地址0x50+7位地址 */
    i2cs_init(I2C_INDEX_0, addr, addr_bit);

    /* buffer初始化 */
    i2c_case_buffer_init();

    /* I2CM写write_buffer数据到0x50地址的从机 */
    if (hal_i2cm_write(I2C_INDEX_1, write_buffer, BUFFER_SIZE) != true)
    {
        TAU_LOGD("I2CM CPU write data fail!\n");
        return false;
    }
    TAU_LOGD("tx: %x %x %x %x %x %x %x %x %x %x\n", write_buffer[0], write_buffer[1], write_buffer[2], \
             write_buffer[3], write_buffer[4], write_buffer[5], write_buffer[6], write_buffer[7], write_buffer[8], \
             write_buffer[9]);

    /* I2CM向地址为0x50的从机读取BUFFER_SIZE个数据，此case中，寄存器addr和size为0，可自行添加 */
    if (hal_i2cm_read(I2C_INDEX_1, 0, 0, i2cm_read_buffer, BUFFER_SIZE) != true)
    {
        TAU_LOGD("I2CM CPU read data fail!\n");
        return false;
    }
    TAU_LOGD("rx: %x %x %x %x %x %x %x %x %x %x\n", i2cm_read_buffer[0], i2cm_read_buffer[1], \
             i2cm_read_buffer[2], i2cm_read_buffer[3], i2cm_read_buffer[4], i2cm_read_buffer[5], \
             i2cm_read_buffer[6], i2cm_read_buffer[7], i2cm_read_buffer[8], i2cm_read_buffer[9]);

    /* 检查传输结果，I2CM发出去的数据是否与接收到的数据一致 */
    CHECK_TRANS_RESULT(write_buffer, i2cm_read_buffer, BUFFER_SIZE);

    /* I2CM && I2CS去初始化 */
    i2cs_deinit(I2C_INDEX_0);
    i2cm_deinit(I2C_INDEX_1);
    TAU_LOGD("hal_i2c_cpu_transfer_case done!\n");
    return true;
}


/**
* @brief  芯片I2CM与I2CS对接,验证I2CM用DMA方式传输数据的正确性
* @param
* @retval bool true/false
*/
static bool hal_i2c_dma_transfer_case(void)
{
    uint8_t write_buffer[10] = {0x20, 0x21, 0x22, 0x23, 0x24, 0x25, 0x26, 0x27, 0x28, 0x29};
    uint8_t addr_bit = 7;
    uint32_t speed =  400000;
    uint16_t addr = 0x50;

    /* I2CM初始化，I2C1+目标地址0x50+7位地址+400k传输速率 */
    i2cm_init(I2C_INDEX_1, addr, addr_bit, speed);

    /* I2CS初始化，I2C0+本机地址0x50+7位地址 */
    i2cs_init(I2C_INDEX_0, addr, addr_bit);

    /* buffer初始化 */
    i2c_case_buffer_init();

    /* I2CM写write_buffer数据到0x50地址的从机 */
    hal_i2cm_dma_write(I2C_INDEX_1, write_buffer, BUFFER_SIZE);

    /* 等待I2CM传输完成 */
    while (!hal_i2cm_get_transfer_complete(I2C_INDEX_1));
    TAU_LOGD("tx: %x %x %x %x %x %x %x %x %x %x\n", write_buffer[0], write_buffer[1], write_buffer[2], \
             write_buffer[3], write_buffer[4], write_buffer[5], write_buffer[6], write_buffer[7], write_buffer[8], \
             write_buffer[9]);

    /* I2CM向地址为0x50的从机读取BUFFER_SIZE个数据，此case中，寄存器addr和size为0，可自行添加 */
    hal_i2cm_dma_read(I2C_INDEX_1, 0, 0, i2cm_read_buffer, BUFFER_SIZE);

    /* 等待I2CM传输完成 */
    while (!hal_i2cm_get_transfer_complete(I2C_INDEX_1));
    TAU_LOGD("rx: %x %x %x %x %x %x %x %x %x %x\n", i2cm_read_buffer[0], i2cm_read_buffer[1], \
             i2cm_read_buffer[2], i2cm_read_buffer[3], i2cm_read_buffer[4], i2cm_read_buffer[5], \
             i2cm_read_buffer[6], i2cm_read_buffer[7], i2cm_read_buffer[8], i2cm_read_buffer[9]);

    /* 检查传输结果，I2CM发出去的数据是否与接收到的数据一致 */
    CHECK_TRANS_RESULT(write_buffer, i2cm_read_buffer, BUFFER_SIZE);

    /* I2CM && I2CS去初始化 */
    i2cs_deinit(I2C_INDEX_0);
    i2cm_deinit(I2C_INDEX_1);
    TAU_LOGD("hal_i2c_dma_transfer_case done!\n");
    return true;
}

/**
* @brief  芯片I2CM与I2CS对接,验证双slave通信的正确性
* @param
* @retval bool true/false
*/
static bool hal_i2c_double_slave_case(void)
{
    uint16_t i2cs1_addr = 0x50;
    uint8_t i2cs1_addrbit = 7;
    uint16_t i2cs2_addr = 0x120;
    uint8_t i2cs2_addrbit = 10;
    uint32_t speed = 400000;
    uint8_t write_buffer1[10] = {0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17, 0x18, 0x19};
    uint8_t write_buffer2[10] = {0x20, 0x21, 0x22, 0x23, 0x24, 0x25, 0x26, 0x27, 0x28, 0x29};

    /* I2CM初始化，I2C1+目标地址0x50+7位地址+400k传输速率 */
    i2cm_init(I2C_INDEX_1, i2cs1_addr, i2cs1_addrbit, speed);

    /* I2CS初始化，I2C0+本机地址0x50+7位地址 */
    i2cs_init(I2C_INDEX_0, i2cs1_addr, i2cs1_addrbit);

    /* I2CS初始化，I2C2+本机地址0x120+10位地址 */
    i2cs_init(I2C_INDEX_2, i2cs2_addr, i2cs2_addrbit);

    /* I2CM写write_buffer1数据到0x50地址的从机 */
    hal_i2cm_dma_write(I2C_INDEX_1, write_buffer1, BUFFER_SIZE);

    /* 等待I2CM传输完成 */
    while (!hal_i2cm_get_transfer_complete(I2C_INDEX_1));
    TAU_LOGD("tx: %x %x %x %x %x %x %x %x %x %x\n", write_buffer1[0], write_buffer1[1], write_buffer1[2], \
             write_buffer1[3], write_buffer1[4], write_buffer1[5], write_buffer1[6], write_buffer1[7], write_buffer1[8], \
             write_buffer1[9]);

    /* I2CM向地址为0x50的从机读取BUFFER_SIZE个数据，此case中，寄存器addr和size为0，可自行添加 */
    hal_i2cm_dma_read(I2C_INDEX_1, 0, 0, i2cm_read_buffer, BUFFER_SIZE);

    /* 等待I2CM传输完成 */
    while (!hal_i2cm_get_transfer_complete(I2C_INDEX_1));
    TAU_LOGD("rx: %x %x %x %x %x %x %x %x %x %x\n", i2cm_read_buffer[0], i2cm_read_buffer[1], \
             i2cm_read_buffer[2], i2cm_read_buffer[3], i2cm_read_buffer[4], i2cm_read_buffer[5], \
             i2cm_read_buffer[6], i2cm_read_buffer[7], i2cm_read_buffer[8], i2cm_read_buffer[9]);

    /* 检查传输结果，I2CM发出去的数据是否与接收到的数据一致 */
    CHECK_TRANS_RESULT(write_buffer1, i2cm_read_buffer, BUFFER_SIZE);

    /* 修改I2CM的目标从机地址为10位地址的0x120 */
    hal_i2cm_set_slave_addr(I2C_INDEX_1, i2cs2_addr, i2cs2_addrbit);

    /* I2CM写write_buffer2数据到0x120地址的从机 */
    hal_i2cm_dma_write(I2C_INDEX_1, write_buffer2, BUFFER_SIZE);

    /* 等待I2CM传输完成 */
    while (!hal_i2cm_get_transfer_complete(I2C_INDEX_1));
    TAU_LOGD("tx: %x %x %x %x %x %x %x %x %x %x\n", write_buffer2[0], write_buffer2[1], write_buffer2[2], \
             write_buffer2[3], write_buffer2[4], write_buffer2[5], write_buffer2[6], write_buffer2[7], write_buffer2[8], \
             write_buffer2[9]);

    /* I2CM向地址为0x120的从机读取BUFFER_SIZE个数据，此case中，寄存器addr和size为0，可自行添加 */
    hal_i2cm_dma_read(I2C_INDEX_1, 0, 0, i2cm_read_buffer, BUFFER_SIZE);

    /* 等待I2CM传输完成 */
    while (!hal_i2cm_get_transfer_complete(I2C_INDEX_1));
    TAU_LOGD("rx: %x %x %x %x %x %x %x %x %x %x\n", i2cm_read_buffer[0], i2cm_read_buffer[1], \
             i2cm_read_buffer[2], i2cm_read_buffer[3], i2cm_read_buffer[4], i2cm_read_buffer[5], \
             i2cm_read_buffer[6], i2cm_read_buffer[7], i2cm_read_buffer[8], i2cm_read_buffer[9]);

    /* 检查传输结果，I2CM发出去的数据是否与接收到的数据一致 */
    CHECK_TRANS_RESULT(write_buffer2, i2cm_read_buffer, BUFFER_SIZE);

    /* I2CM && I2CS去初始化 */
    i2cm_deinit(I2C_INDEX_1);
    i2cs_deinit(I2C_INDEX_0);
    i2cs_deinit(I2C_INDEX_2);
    TAU_LOGD("hal_i2c_double_slave_case done!\n");
    return true;
}

/**
* @brief  i2c demo case
* @param  none
* @retval none
*/
void demo_hal_i2c(void)
{
    /* I2C DMA传输case */
    if (!hal_i2c_dma_transfer_case())
    {
        i2cs_deinit(I2C_INDEX_0);
        i2cm_deinit(I2C_INDEX_1);
        TAU_LOGD("hal_i2c_dma_transfer_case fail!\n");
    }

    /* 双slave传输case */
    if (!hal_i2c_double_slave_case())
    {
        i2cm_deinit(I2C_INDEX_1);
        i2cs_deinit(I2C_INDEX_0);
        i2cs_deinit(I2C_INDEX_2);
        TAU_LOGD("hal_i2c_double_slave_case fail!\n");
    }

    /* I2C CPU传输case */
    if (!hal_i2c_cpu_transfer_case())
    {
        i2cs_deinit(I2C_INDEX_0);
        i2cm_deinit(I2C_INDEX_1);
        TAU_LOGD("hal_i2c_cpu_transfer_case fail!\n");
    }

    TAU_LOGD("i2c case done\n");
}
#endif

