/*
 * i2c_init.c
 *
 *  Created on: 5 сент. 2023 г.
 *      Author: seklyuts
 */
#include "f28x_project.h"
#include "i2c_init.h"
//
// Function to configure I2CA as Master Transmitter.
//

//
// I2C GPIO pins
//
#define GPIO_PIN_SDAA        0U  // GPIO number for I2C SDAA
#define GPIO_PIN_SCLA        1U  // GPIO number for I2C SCLA

#define TIME_OVER           100 //*0.1 mS, 1000 ~ 100 mS, 100 ~ 10mS

volatile uint16_t TimerTimeouts = 0, ErrI2c = 0, ErrI2c1 = 0, ErrI2c2 = 0, ErrI2c3 = 0, ErrI2c4 = 0, ErrI2c5 = 0, Addr1[255];
volatile uint16_t RXdata, addrCount=0;

void TimerBaseTimeoutInc(void)
{
    if(TimerTimeouts < TIME_OVER*16) TimerTimeouts++;
}


void I2CMasterGpioInit(void)
{
        //
        //Configure I2C pins
        //
        GPIO_SetupPinMux(GPIO_PIN_SDAA, GPIO_MUX_CPU1, 6);
        GPIO_SetupPinOptions(GPIO_PIN_SDAA, GPIO_OUTPUT, GPIO_PULLUP);
        GPIO_SetupPinMux(GPIO_PIN_SCLA, GPIO_MUX_CPU1, 6);
        GPIO_SetupPinOptions(GPIO_PIN_SCLA, GPIO_OUTPUT, GPIO_PULLUP);
}

void I2CMasterInit(uint16_t I2C_OwnAddress, uint16_t I2CSlave_Address)
{
    EALLOW;
    //
    // Must put I2C into reset before configuring it
    //
    I2caRegs.I2CMDR.all &= ~(0x20U);

    //
    // I2C configuration. Use a 400kHz I2CCLK with a 50% duty cycle.
    //
    //I2C_initMaster(base, DEVICE_SYSCLK_FREQ, 400000, I2C_DUTYCYCLE_50); = 1000000 / (I2CPSC+1) / (I2CCLKL + I2CCLKH)
    I2caRegs.I2CPSC.all = 49;        // Prescaler - need 7-12 Mhz on module clk
    I2caRegs.I2CCLKL = 12;          // NOTE: must be non zero
    I2caRegs.I2CCLKH = 12;           // NOTE: must be non zero


    //
    // Configure Master as a Transmitter
    //
    I2caRegs.I2CMDR.bit.MST = 0x1;
    I2caRegs.I2CMDR.bit.TRX = 0x1;

    //
    // Set data count
    //
//    I2caRegs.I2CCNT = I2C_NUMBYTES;

    //
    // Set the bit count to 8 bits per data byte
    //
    I2caRegs.I2CMDR.bit.BC = 0x0U;


    I2caRegs.I2CFFRX.bit.RXFFRST = 1;
    I2caRegs.I2CFFTX.bit.I2CFFEN = 1;
    I2caRegs.I2CFFTX.bit.TXFFRST = 1;
    //
    // Configure slave and own address
    //
    I2caRegs.I2COAR.all = I2C_OwnAddress;      // Own address
    I2caRegs.I2CSAR.all = I2CSlave_Address;      // Slave address

    //
    // Set emulation mode to FREE
    //
    I2caRegs.I2CMDR.bit.FREE = 0x1;

    //
    //Clear all status
    //
    I2caRegs.I2CSTR.all = 0xFFFF;

    //
    // I2C Interrupts
    //
    I2caRegs.I2CIER.all = 0x08;

    //
    // Take I2C out of reset
    //
    I2caRegs.I2CMDR.all |= 0x0020;
    EDIS;

}


void I2CWriteRes(void)
{
    I2caRegs.I2CSAR.all = 0xFF;
    I2caRegs.I2CMDR.bit.MST = 0x1;
    I2caRegs.I2CMDR.bit.TRX = 0x0;
    I2caRegs.I2CCNT = 0;
    I2caRegs.I2CMDR.bit.STT = 0x1;
    I2caRegs.I2CSTR.bit.BYTESENT = 0x1;
    I2caRegs.I2CMDR.bit.STP = 0x1;
    TimerTimeouts = 0;
    while((I2caRegs.I2CMDR.bit.STP != 0x0)&&(TimerTimeouts < TIME_OVER));
    if(TimerTimeouts >= TIME_OVER) ErrI2c1++;
    I2caRegs.I2CSTR.bit.BYTESENT = 0x1;
    I2caRegs.I2CMDR.bit.STP = 0x1;
    I2caRegs.I2CSTR.bit.BYTESENT = 0x1;
}
uint16_t j = 0;
//
// Function to send data over I2C.
//
uint16_t I2CWrite(uint16_t slaveAddr, uint16_t MemAdr, uint16_t byteCount, bool sendStopCondition, uint16_t * I2C_TXdata)
{
    uint16_t index = 0;

    I2caRegs.I2CFFRX.bit.RXFFRST = 0;
    I2caRegs.I2CFFTX.bit.I2CFFEN = 0;
    I2caRegs.I2CFFTX.bit.TXFFRST = 0;
    I2caRegs.I2CFFRX.bit.RXFFRST = 1;
    I2caRegs.I2CFFTX.bit.I2CFFEN = 1;
    I2caRegs.I2CFFTX.bit.TXFFRST = 1;

    TimerTimeouts = 0;
    while((I2caRegs.I2CSTR.bit.BB == 1)&&(TimerTimeouts < TIME_OVER));
    if(TimerTimeouts >= TIME_OVER)
    {
        ErrI2c++;
        return 1;
    }

    I2caRegs.I2CSAR.all = slaveAddr;      // Slave address
    I2caRegs.I2CMDR.bit.MST = 0x1;
    I2caRegs.I2CMDR.bit.TRX = 0x1;
    I2caRegs.I2CFFTX.bit.TXFFINTCLR = 1;
    I2caRegs.I2CCNT = byteCount+1;
    I2caRegs.I2CMDR.bit.NACKMOD = 0x0;
    I2caRegs.I2CDXR.all = MemAdr ;

    for(index=0; index < byteCount; index++)
    {
        I2caRegs.I2CDXR.all= I2C_TXdata[index];

    }

    I2caRegs.I2CMDR.bit.STT = 0x1;

    TimerTimeouts = 0;
    while((I2caRegs.I2CFFTX.bit.TXFFST > 0)&&(TimerTimeouts < TIME_OVER*(byteCount+1)));
    if(TimerTimeouts >= TIME_OVER)
    {
        ErrI2c++;
        return 1;
    }
    I2caRegs.I2CFFTX.bit.TXFFINTCLR = 1;

    TimerTimeouts = 0;
    while((I2caRegs.I2CSTR.bit.NACK == 0x1)&&(TimerTimeouts < TIME_OVER));
    if(TimerTimeouts >= TIME_OVER)
    {
        ErrI2c1++;
        return 1;
    }

    if(sendStopCondition)
    {
        I2caRegs.I2CMDR.bit.STP = 0x1;
        TimerTimeouts = 0;
        while((I2caRegs.I2CMDR.bit.STP != 0x0)&&(TimerTimeouts < TIME_OVER));
        if(TimerTimeouts >= TIME_OVER)
        {
            ErrI2c2++;
            return 1;
        }
    }
    I2caRegs.I2CSTR.bit.BYTESENT = 0x1;
    TimerTimeouts = 0;
    while(TimerTimeouts < TIME_OVER);
    return 0;
}

//
// Function to read data over I2C. Returns the number of bytes read
//
uint16_t ttest=0;

uint16_t I2CRead(uint16_t slaveAddr, uint16_t byteCount, bool sendStopCondition, uint16_t * I2C_RXdata)
{
    I2caRegs.I2CMDR.bit.NACKMOD = 0x0;
    I2caRegs.I2CSAR.all = slaveAddr;
    I2caRegs.I2CMDR.bit.MST = 0x1;
    I2caRegs.I2CMDR.bit.TRX = 0x0;
    uint16_t count = 0;
    I2caRegs.I2CFFRX.bit.RXFFINTCLR = 0;
    I2caRegs.I2CCNT = byteCount;
    I2caRegs.I2CMDR.bit.STT = 0x1;

    TimerTimeouts = 0;
    while( (I2caRegs.I2CFFRX.bit.RXFFST < byteCount) && (TimerTimeouts < TIME_OVER*byteCount));
    if(TimerTimeouts >= TIME_OVER)
    {
        ErrI2c3++;
        return 1;
    }

    I2caRegs.I2CMDR.bit.STP = 0x1;

    for(count=0; count < byteCount; count++)
    {
        RXdata = I2C_RXdata[count] = I2caRegs.I2CDRR.all;
    }

    I2caRegs.I2CMDR.bit.NACKMOD = 0x1;

    TimerTimeouts = 0;
    while((I2caRegs.I2CMDR.bit.STP != 0x0)&&(TimerTimeouts < TIME_OVER));
    if(TimerTimeouts >= TIME_OVER)
    {
        ErrI2c5++;
        return 1;
    }
    I2caRegs.I2CSTR.bit.BYTESENT = 0x1;
    I2caRegs.I2CFFRX.bit.RXFFINTCLR = 0;
    return 0;
}

uint16_t I2CVerify(uint16_t slaveAddr, uint16_t byteCount, bool sendStopCondition, uint16_t * I2C_Vfdata)
{
    uint16_t VerErr = 0;

    I2caRegs.I2CMDR.bit.NACKMOD = 0x0;
    I2caRegs.I2CSAR.all = slaveAddr;
    I2caRegs.I2CMDR.bit.MST = 0x1;
    I2caRegs.I2CMDR.bit.TRX = 0x0;
    uint16_t count = 0;
    I2caRegs.I2CFFRX.bit.RXFFINTCLR = 0;
    I2caRegs.I2CCNT = byteCount;
    I2caRegs.I2CMDR.bit.STT = 0x1;

    TimerTimeouts = 0;
    while( (I2caRegs.I2CFFRX.bit.RXFFST < byteCount) && (TimerTimeouts < TIME_OVER*byteCount));
    if(TimerTimeouts >= TIME_OVER)
    {
        ErrI2c3++;
        return 1;
    }

    I2caRegs.I2CMDR.bit.STP = 0x1;

    for(count=0; count < byteCount; count++)
    {
        RXdata = I2caRegs.I2CDRR.all;
        if(I2C_Vfdata[count] != RXdata) VerErr = 1;
    }

    I2caRegs.I2CMDR.bit.NACKMOD = 0x1;

    TimerTimeouts = 0;
    while((I2caRegs.I2CMDR.bit.STP != 0x0)&&(TimerTimeouts < TIME_OVER));
    if(TimerTimeouts >= TIME_OVER)
    {
        ErrI2c5++;
        return 1;
    }
    I2caRegs.I2CSTR.bit.BYTESENT = 0x1;
    I2caRegs.I2CFFRX.bit.RXFFINTCLR = 0;
    if(VerErr) return 2;
    else return 0;
}
