#include <stdint.h>
#include <stdbool.h>  
#include <stddef.h>
#include "I2CBUS.h"


extern uint8_t I2CWriteRead(I2CBUS_t * pI2CObj);


#ifdef USE_I2C1
I2CBUS_t I2C_myObj1;
/*  no need because all variables can be accessed in strucy I2C_myObj1
extern volatile uint8_t ReadDataByte1_1[];  //second 1 is peripheral no, first 1 is Seq No
extern volatile uint8_t ReadDataByte2_1[];
extern uint16_t ReadQTY_1[];  //unit: byte
extern volatile uint8_t WriteDataByte1_1[]; //second 1 is peripheral no, first 1 is Seq No
extern volatile uint8_t WriteDataByte2_1[];
extern uint16_t WriteQTY_1[]; //unit: byte
 * */  
#endif




#ifdef USE_I2C2
I2CBUS_t I2C_myObj2;
extern volatile uint8_t ReadDataByte1_2[];  //second 1 is peripheral no, first 1 is Seq No
extern volatile uint8_t ReadDataByte2_2[];
extern uint16_t ReadQTY_2[];  //unit: byte
extern volatile uint8_t WriteDataByte1_2[]; //second 1 is peripheral no, first 1 is Seq No
extern volatile uint8_t WriteDataByte2_2[];
extern uint16_t WriteQTY_2[]; //unit: byte
#endif

#ifdef USE_I2C3
I2CBUS_t I2C_myObj3;
extern volatile uint8_t ReadDataByte1_3[];  //second 1 is peripheral no, first 1 is Seq No
extern volatile uint8_t ReadDataByte2_3[];
extern uint16_t ReadQTY_3[];  //unit: byte
extern volatile uint8_t WriteDataByte1_3[]; //second 1 is peripheral no, first 1 is Seq No
extern volatile uint8_t WriteDataByte2_3[];
extern uint16_t WriteQTY_3[]; //unit: byte
#endif

#ifdef USE_I2C4
I2CBUS_t I2C_myObj4;
extern volatile uint8_t ReadDataByte1_4[];  //second 1 is peripheral no, first 1 is Seq No
extern volatile uint8_t ReadDataByte2_4[];
extern uint16_t ReadQTY_4[];  //unit: byte
extern volatile uint8_t WriteDataByte1_4[]; //second 1 is peripheral no, first 1 is Seq No
extern volatile uint8_t WriteDataByte2_4[];
extern uint16_t WriteQTY_4[]; //unit: byte
#endif

/**
 * Pre-condition for calling:
 *     Must call CAN_set_Mask firdt for PIC
 * @param pCANxObj
 * @param CAN_Peripheral_No
 * @param enSync
 * @param SyncUseStdID
 * @param SyncCANID
 * @param FrameNoIs0_based
 * @param pLogicRuleA
 * @param pLogicRuleB
 * @param pLogicRuleC
 * @param MaxSeqQTY4ChannelA
 * @param MaxSeqQTY4ChannelB
 * @param MaxSeqQTY4ChannelC
 * @param RxStdFrameQTY4short
 * @param RxExtFrameQTY4short
 * @param RxStdFrameQTY4long
 * @param RxExtFrameQTY4long
 */
void I2CBUS_init(I2CBUS_t * pI2CMyOBJ, uint8_t I2C_Peripheral_No, uint16_t * I2Caddr, uint8_t MAxSeq_Qty, uint16_t * QTY4Read,uint16_t * QTY4Write,
        uint16_t Max_ByteQTY4read, uint16_t Max_ByteQTY4write, volatile uint8_t * Virtual4pReadData[], volatile uint8_t * Virtual4pWriteData[] ) {
    pI2CMyOBJ->I2C_Peripheral_No= I2C_Peripheral_No;    
    pI2CMyOBJ->I2CAddr=I2Caddr;
    pI2CMyOBJ->Max_Seq_QTY=MAxSeq_Qty;
    pI2CMyOBJ->QTY4Read=QTY4Read;
    pI2CMyOBJ->QTY4Write=QTY4Write;
    pI2CMyOBJ->Max_ByteQTY4read=Max_ByteQTY4read;
    pI2CMyOBJ->Max_ByteQTY4write=Max_ByteQTY4write;
    pI2CMyOBJ->LogicRule= 0;
    pI2CMyOBJ->PresentSeqNo=0;    
    pI2CMyOBJ->state=0;
    pI2CMyOBJ->SuccessWR=0;  
    pI2CMyOBJ->pReadData=Virtual4pReadData;
    pI2CMyOBJ->pWriteData=Virtual4pWriteData;
   
}

void I2CBus_Poll(I2CBUS_t * pCANxObj) {
    
    int8_t TxResult;   
   
    if (pCANxObj->LogicRule & (1u << pCANxObj->PresentSeqNo))
    {
        //Need to read/write
        TxResult=I2CWriteRead(pCANxObj);
        if (0 == TxResult) {
            //Success for read/write
            pCANxObj->SuccessWR |= (1U<<pCANxObj->PresentSeqNo);
            pCANxObj->LogicRule &= ~(1U<<pCANxObj->PresentSeqNo); 
            pCANxObj->PresentSeqNo++;
            if (pCANxObj->PresentSeqNo>=pCANxObj->Max_Seq_QTY) pCANxObj->PresentSeqNo=0;
        }
        else if (TxResult < 0) {
            //Read/Write fail
            pCANxObj->SuccessWR &= ~(1U<<pCANxObj->PresentSeqNo); 
            pCANxObj->LogicRule &= ~(1U<<pCANxObj->PresentSeqNo); 
            pCANxObj->PresentSeqNo++;
            if (pCANxObj->PresentSeqNo>=pCANxObj->Max_Seq_QTY) pCANxObj->PresentSeqNo=0;
        }
        else {
            //Run again next time (continue), so do nothing
        }    
    }
    else
    {   
        //no need to read/write
        pCANxObj->PresentSeqNo++;
        if (0x8000==pCANxObj->LogicRule)
        {
            pCANxObj->PresentSeqNo=0;
        }
        else {
            if (pCANxObj->PresentSeqNo==pCANxObj->Max_Seq_QTY) pCANxObj->PresentSeqNo=0;
        } 
        
    }
    
    
}




