#include "define.h"
#include "BoardCfg.h"
#include "I2C.h"

int mLastTransactionOK;
int mI2CWaitCounter;

int I2CInit()
{
    //SPI and I2C BRG work the same way.  So let's reuse some code!
    // int BaudRateGenerator = SPICalculateBRG(80000000,100000);  //PBclk is 80MHz, I2C clk = 100KHz
    int BaudRateGenerator = 398;
    
    I2C3CON = 0;
    
    I2C3CONbits.DISSLW = 1; //disable slew rate control since we are only at 100KHz
    I2C3BRG = BaudRateGenerator;
    
    I2C3CONbits.ON = 1;
    
    mLastTransactionOK = 0;
    mI2CWaitCounter = 0;
}


int I2CWrite(unsigned char* OutBuf, unsigned char length)
{
    int RET = RET_OK;
    int i;
    
    //Emit start event
    I2C3CONbits.SEN = 1;
    while(I2C3CONbits.SEN == 1)
    {
        
    }
    
    if(I2C3STATbits.BCL == 1)
    {
        mLastTransactionOK = false;
        return RET_ERROR;
    }
    
    for(i = 0; i < length; i++)
    {
        I2C3TRN = OutBuf[i];
        mI2CWaitCounter = 0;
        while(I2C3STATbits.TRSTAT == 1)
        {
            if(I2C3STATbits.BCL == 1 || mI2CWaitCounter++ > I2C_TRANSACTION_TIMEOUT_COUNT)
            {
                mLastTransactionOK = false;
                RET = RET_ERROR;
                break;
            }
        }
        
        //        if(I2C3STATbits.ACKSTAT == 1)
        //        {
        //            RET = RET_ERROR;
        //        }
    }
    
    //Emit stop event
    I2C3CONbits.PEN = 1;
    mI2CWaitCounter = 0;
    while(I2C3CONbits.PEN == 1)
    {
        if(I2C3STATbits.BCL == 1 || mI2CWaitCounter++ > I2C_TRANSACTION_TIMEOUT_COUNT)
        {
            mLastTransactionOK = false;
            RET = RET_ERROR;
            break;
        }
    }
    
    mLastTransactionOK = true;
    return RET;
}

int I2CTransmitByte(unsigned char Byte)
{
    
    
    return RET_ERROR;
}

int I2CRead(unsigned char SlaveAddress,unsigned char* InputBuf,unsigned char length)
{
    int RET = RET_OK;
    int i;
    //Emit start event
    
    I2C3CONbits.SEN = 1;
    mI2CWaitCounter = 0;
    while(I2C3CONbits.SEN == 1)
    
    if(I2C3STATbits.BCL == 1)
    {
        mLastTransactionOK = false;
        return RET_ERROR;
    }
    
    //Transmit slave address and write bit
    I2C3TRN = SlaveAddress;
    mI2CWaitCounter = 0;
    while(I2C3STATbits.TRSTAT == 1)
    {
        
        if(I2C3STATbits.BCL == 1 || mI2CWaitCounter++ > I2C_TRANSACTION_TIMEOUT_COUNT)
        {
            mLastTransactionOK = false;
            return RET_ERROR;
        }
    }
    
    for(i = 0; i < length; i++)
    {
        //
        I2C3CONbits.RCEN = 1;
        mI2CWaitCounter = 0;
        while(I2C3CONbits.RCEN == 1)
        {
            
            if(I2C3STATbits.BCL == 1 || mI2CWaitCounter++ > I2C_TRANSACTION_TIMEOUT_COUNT)
            {
                mLastTransactionOK = false;
                return RET_ERROR;
            }
        }
        
        InputBuf[i] = I2C3RCV;
        
        //Acknowledge reception
        I2C3CONbits.ACKDT = 1;
        I2C3CONbits.ACKEN = 1;
        mI2CWaitCounter = 0;
        while(I2C3CONbits.ACKEN == 1)
        {
            
            if(I2C3STATbits.BCL == 1 || mI2CWaitCounter++ > I2C_TRANSACTION_TIMEOUT_COUNT)
            {
                mLastTransactionOK = false;
                return RET_ERROR;
            }
        }
        
    }
    
    //Emit stop event
    I2C3CONbits.PEN = 1;
    mI2CWaitCounter = 0;
    while(I2C3CONbits.PEN == 1)
    {
        
        if(I2C3STATbits.BCL == 1 || mI2CWaitCounter++ > I2C_TRANSACTION_TIMEOUT_COUNT)
        {
            mLastTransactionOK = false;
            return RET_ERROR;
        }
    }
    
    
    mLastTransactionOK = true;
    return RET;
}

bool I2CWasLastTransactionOK()
{
    return mLastTransactionOK;
}