#include <xdc/std.h>
#include <xdc/cfg/global.h>
#include <xdc/runtime/System.h>
#include <xdc/runtime/Error.h>

/* BIOS Header files */
#include <ti/sysbios/BIOS.h>
#include <ti/sysbios/knl/Task.h>


#include <stdio.h>
#include <string.h>

/* TI-RTOS Header files */
#include <ti/board/src/bbbAM335x/include/board_cfg.h>
#include <ti/drv/i2c/I2C.h>
#include <ti/drv/i2c/soc/I2C_soc.h>
#include <ti/board/src/evmKeystone/include/board_utils.h>
#include <ti/drv/i2c/test/eeprom_read/src/I2C_log.h>
#include <ti/drv/i2c/test/eeprom_read/src/I2C_board.h>
//#include <board_cfg.h>
#define I2C_TRANSACTION_TIMEOUT 1000
char eeprom_data[I2C_EEPROM_RX_LENGTH];
bool CompareData(char *expData, char *rxData, unsigned int length);


/*
 *  ======== Board_initI2C ========
 */
void Board_initI2C(void)
{
    Board_initCfg boardCfg;

    I2C_HwAttrs i2c_cfg;

    /* Get the default I2C init configurations */
    I2C_socGetInitCfg(I2C_EEPROM_INSTANCE, &i2c_cfg);

    /* Modify the default I2C configurations if necessary */

    /* Set the default I2C init configurations */
    I2C_socSetInitCfg(I2C_EEPROM_INSTANCE, &i2c_cfg);

    boardCfg = BOARD_INIT_PINMUX_CONFIG |
        BOARD_INIT_MODULE_CLOCK |
        BOARD_INIT_UART_STDIO;
 Board_init(boardCfg);
}

void i2c_test(UArg arg0, UArg arg1)

{
    I2C_Params i2cParams;
    I2C_Handle handle = NULL;
    I2C_Transaction i2cTransaction;
    char txBuf[I2C_EEPROM_TEST_LENGTH + I2C_EEPROM_ADDR_SIZE] = {0x00, };
    char rxBuf[I2C_EEPROM_TEST_LENGTH];
    bool status_400kbps;
    int16_t status;



    Board_initI2C();


    /* Set the I2C EEPROM write/read address */
    txBuf[0] = (I2C_EEPROM_TEST_ADDR >> 8) & 0xff; /* EEPROM memory high address byte */
    txBuf[1] = I2C_EEPROM_TEST_ADDR & 0xff;        /* EEPROM memory low address byte */

    I2C_init();

    I2C_Params_init(&i2cParams);

    /* BitRate : 400 Kbps */
    i2cParams.bitRate = I2C_400kHz;

    handle = I2C_open(I2C_EEPROM_INSTANCE, &i2cParams);

 memcpy(&txBuf[I2C_EEPROM_ADDR_SIZE],eeprom_data, I2C_EEPROM_TEST_LENGTH);
    I2C_transactionInit(&i2cTransaction);
    i2cTransaction.slaveAddress = I2C_EEPROM_ADDR;
    i2cTransaction.writeBuf = (uint8_t *)&txBuf[0];
    i2cTransaction.writeCount = I2C_EEPROM_TEST_LENGTH + I2C_EEPROM_ADDR_SIZE;
    i2cTransaction.readBuf = NULL;
    i2cTransaction.readCount = 0;
    i2cTransaction.timeout   = I2C_TRANSACTION_TIMEOUT;
    status = I2C_transfer(handle, &i2cTransaction);

    if(I2C_STS_SUCCESS != status)
    {
        I2C_log("\n I2C Test: 400Kbps: Write Data Transfer failed. \n");

    }

    BOARD_delay(100);
    memset(rxBuf, 0, I2C_EEPROM_TEST_LENGTH);
    I2C_transactionInit(&i2cTransaction);
    i2cTransaction.slaveAddress = I2C_EEPROM_ADDR;
    i2cTransaction.writeBuf = (uint8_t *)&txBuf[0];
    i2cTransaction.writeCount = I2C_EEPROM_ADDR_SIZE;
    i2cTransaction.readBuf = (uint8_t *)&rxBuf[0];
    i2cTransaction.readCount = I2C_EEPROM_TEST_LENGTH;
    i2cTransaction.timeout   = I2C_TRANSACTION_TIMEOUT;
    status = I2C_transfer(handle, &i2cTransaction);

    if(I2C_STS_SUCCESS != status)
    {
        I2C_log("\n I2C Test: 400Kbps: Read Data Transfer failed. \n");
    }

    I2C_close(handle);
 status_400kbps = CompareData(&eeprom_data[0], &rxBuf[0], I2C_EEPROM_TEST_LENGTH);
    if(TRUE == status_400kbps)
    {
        I2C_log("\n I2C Test: 400Kbps: PASS \n");
    }
    else
    {
        I2C_log("\n I2C Test: 400Kbps: Data Mismatch \n");
    }


}
/*
 *  ======== main ========
 */
int main(void)
{
    Board_initI2C();

    Task_Handle task;
    Error_Block eb;

    Error_init(&eb);

    task = Task_create(i2c_test, NULL, &eb);
    if (task == NULL) {
        System_printf("Task_create() failed!\n");
        BIOS_exit(0);
    }


    /* Start BIOS */
    BIOS_start();
    return (0);
}

bool CompareData(char *expData, char *rxData, unsigned int length)
{
    uint32_t idx = 0;
    uint32_t match = 1;
    bool retVal = false;

    for(idx = 0; ((idx < length) && (match != 0)); idx++)
    {
        if(*expData != *rxData) match = 0;
        expData++;
        rxData++;
    }

    if(match == 1) retVal = true;

    return retVal;

}

