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



extern uint8_t SPIWriteRead(SPIBUS_t * pSPIObj);

#ifdef USE_SPI1
SPIBUS_t SPI_myObj1;
#ifndef SPI1_USE16BIT_WIDTH
extern volatile uint8_t ReadDataByte1_1[];  //second 1 is peripheral number
extern volatile uint8_t ReadDataByte2_1[]; 
extern volatile uint8_t ReadDataByte3_1[]; 
extern volatile uint8_t ReadDataByte4_1[]; 
extern volatile uint8_t ReadDataByte5_1[];  //how many? depends on how many sequences
extern uint16_t ReadQTY_1[];  //unit: byte or word, Now it is byte because bus width=8

extern volatile uint8_t WriteDataByte1_1[]; //second 1 is peripheral number
extern volatile uint8_t WriteDataByte2_1[]; 
extern volatile uint8_t WriteDataByte3_1[]; 
extern volatile uint8_t WriteDataByte4_1[]; 
extern volatile uint8_t WriteDataByte5_1[];  //how many? depends on how many sequences
extern uint16_t WriteQTY_1[]; //unit: byte or word, Now it is byte because bus width=8
 
#else
extern volatile uint16_t ReadDataWord1_1[];  //second 1 is peripheral number
extern volatile uint16_t ReadDataWord2_1[];
extern volatile uint16_t ReadDataWord3_1[];
extern volatile uint16_t ReadDataWord4_1[];
extern volatile uint16_t ReadDataWord5_1[];   //how many? depends on how many sequences
extern uint16_t ReadQTY_1[];  //unit: byte or word, Now it is word because bus width=16

extern volatile uint16_t WriteDataWord1_1[]; 
extern volatile uint16_t WriteDataWord2_1[]; 
extern volatile uint16_t WriteDataWord3_1[]; 
extern volatile uint16_t WriteDataWord4_1[]; 
extern volatile uint16_t WriteDataWord5_1[]; 
extern uint16_t WriteQTY_1[]; //unit: byte or word, Now it is word because bus width=16

#endif
#endif




#ifdef USE_SPI2
SPIBUS_t SPI_myObj2;
#ifndef SPI2_USE16BIT_WIDTH
extern volatile uint8_t ReadDataByte1_2[];  //second 1 is peripheral number
extern volatile uint8_t ReadDataByte2_2[]; 
extern volatile uint8_t ReadDataByte3_2[]; 
extern volatile uint8_t ReadDataByte4_2[]; 
extern volatile uint8_t ReadDataByte5_2[];  //how many? depends on how many sequences
extern uint16_t ReadQTY_2[];  //unit: byte or word, Now it is byte because bus width=8

extern volatile uint8_t WriteDataByte1_2[]; //second 1 is peripheral number
extern volatile uint8_t WriteDataByte2_2[]; 
extern volatile uint8_t WriteDataByte3_2[]; 
extern volatile uint8_t WriteDataByte4_2[]; 
extern volatile uint8_t WriteDataByte5_2[];  //how many? depends on how many sequences
extern uint16_t WriteQTY_2[]; //unit: byte or word, Now it is byte because bus width=8
 
#else
extern volatile uint16_t ReadDataWord1_2[];  //second 2 is peripheral number
extern volatile uint16_t ReadDataWord2_2[];
extern volatile uint16_t ReadDataWord3_2[];
extern volatile uint16_t ReadDataWord4_2[];
extern volatile uint16_t ReadDataWord5_2[];   //how many? depends on how many sequences
extern uint16_t ReadQTY_2[];  //unit: byte or word, Now it is word because bus width=16

extern volatile uint16_t WriteDataWord1_2[]; 
extern volatile uint16_t WriteDataWord2_2[]; 
extern volatile uint16_t WriteDataWord3_2[]; 
extern volatile uint16_t WriteDataWord4_2[]; 
extern volatile uint16_t WriteDataWord5_2[]; 
extern uint16_t WriteQTY_2[]; //unit: byte or word, Now it is word because bus width=16
 
#endif
#endif


#ifdef USE_SPI3
SPIBUS_t SPI_myObj3;
#ifndef SPI3_USE16BIT_WIDTH
extern volatile uint8_t ReadDataByte1_3[];  //second 1 is peripheral number
extern volatile uint8_t ReadDataByte2_3[]; 
extern volatile uint8_t ReadDataByte3_3[]; 
extern volatile uint8_t ReadDataByte4_3[]; 
extern volatile uint8_t ReadDataByte5_3[];  //how many? depends on how many sequences
extern uint16_t ReadQTY_3[];  //unit: byte or word, Now it is byte because bus width=8

extern volatile uint8_t WriteDataByte1_3[]; //second 1 is peripheral number
extern volatile uint8_t WriteDataByte2_3[]; 
extern volatile uint8_t WriteDataByte3_3[]; 
extern volatile uint8_t WriteDataByte4_3[]; 
extern volatile uint8_t WriteDataByte5_3[];  //how many? depends on how many sequences
extern uint16_t WriteQTY_3[]; //unit: byte or word, Now it is byte because bus width=8

#else
extern volatile uint16_t ReadDataWord1_3[];  //second 2 is peripheral number
extern volatile uint16_t ReadDataWord2_3[];
extern volatile uint16_t ReadDataWord3_3[];
extern volatile uint16_t ReadDataWord4_3[];
extern volatile uint16_t ReadDataWord5_3[];   //how many? depends on how many sequences
extern uint16_t ReadQTY_3[];  //unit: byte or word, Now it is word because bus width=16
//no beed because we have macro
//extern uint16_t sizeof_ReadDataWord_3; 
extern volatile uint16_t WriteDataWord1_3[]; 
extern volatile uint16_t WriteDataWord2_3[]; 
extern volatile uint16_t WriteDataWord3_3[]; 
extern volatile uint16_t WriteDataWord4_3[]; 
extern volatile uint16_t WriteDataWord5_3[]; 
extern uint16_t WriteQTY_3[]; //unit: byte or word, Now it is word because bus width=16

#endif
#endif

#ifdef USE_SPI4
SPIBUS_t SPI_myObj4;
#ifndef SPI4_USE16BIT_WIDTH
extern volatile uint8_t ReadDataByte1_4[];  //second 1 is peripheral number
extern volatile uint8_t ReadDataByte2_4[]; 
extern volatile uint8_t ReadDataByte3_4[]; 
extern volatile uint8_t ReadDataByte4_4[]; 
extern volatile uint8_t ReadDataByte5_4[];  //how many? depends on how many sequences
extern uint16_t ReadQTY_4[];  //unit: byte or word, Now it is byte because bus width=8

extern volatile uint8_t WriteDataByte1_4[]; //second 1 is peripheral number
extern volatile uint8_t WriteDataByte2_4[]; 
extern volatile uint8_t WriteDataByte3_4[]; 
extern volatile uint8_t WriteDataByte4_4[]; 
extern volatile uint8_t WriteDataByte5_4[];  //how many? depends on how many sequences
extern uint16_t WriteQTY_4[]; //unit: byte or word, Now it is byte because bus width=8

#else
extern volatile uint16_t ReadDataWord1_4[];  //second 2 is peripheral number
extern volatile uint16_t ReadDataWord2_4[];
extern volatile uint16_t ReadDataWord3_4[];
extern volatile uint16_t ReadDataWord4_4[];
extern volatile uint16_t ReadDataWord5_4[];   //how many? depends on how many sequences
extern uint16_t ReadQTY_4[];  //unit: byte or word, Now it is word because bus width=16
//no beed because we have macro
//extern uint16_t sizeof_ReadDataWord_4; 
extern volatile uint16_t WriteDataWord1_4[]; 
extern volatile uint16_t WriteDataWord2_4[]; 
extern volatile uint16_t WriteDataWord3_4[]; 
extern volatile uint16_t WriteDataWord4_4[]; 
extern volatile uint16_t WriteDataWord5_4[]; 
extern uint16_t WriteQTY_4[]; //unit: byte or word, Now it is word because bus width=16

#endif
#endif

/**
 * 
 * @param pSPIMyOBJ
 * @param SPI_Peripheral_No
 * @param pReadData
 * @param pWriteData
 * @param MAxSeq_Qty
 * @param Max_ByteQTY4read
 * @param Max_ByteQTY4write
 */
void SPIBUS_init(SPIBUS_t * pSPIMyOBJ, uint8_t SPI_Peripheral_No, bool Use16bitsBus, uint8_t MAxSeq_Qty, uint16_t * QTY4Read, uint16_t * QTY4Write, 
        uint16_t Max_ByteQTY4ReadWrite, volatile uint8_t * Room4pReadData[], volatile uint8_t * Room4pWriteData[],void (* set_CS_Fn[])(bool)) {

    pSPIMyOBJ->SPI_Peripheral_No= SPI_Peripheral_No;
    pSPIMyOBJ->Use16bitsBus = Use16bitsBus;    
    pSPIMyOBJ->Max_Seq_QTY=MAxSeq_Qty;
    pSPIMyOBJ->pReadData=Room4pReadData;
    pSPIMyOBJ->pWriteData=Room4pWriteData;
    pSPIMyOBJ->QTY4Read=QTY4Read;
    pSPIMyOBJ->QTY4Write=QTY4Write;
    pSPIMyOBJ->Max_ByteQTY4read_Or_write=Max_ByteQTY4ReadWrite;    
    pSPIMyOBJ->LogicRule= 0;
    pSPIMyOBJ->PresentSeqNo=0;  
    //pSPIMyOBJ->DummyDataAllOne=0x7fff;  //Don't do it in case "setup block" init executing after every "read/write block" start
    pSPIMyOBJ->state=0;
    pSPIMyOBJ->set_CS=set_CS_Fn;
}

void SPIBUS_Poll(SPIBUS_t * pSPIObj) {
    
    int8_t TxResult;    
   
    if (pSPIObj->LogicRule & (1u << pSPIObj->PresentSeqNo))
    {
        //Need to read/write
        TxResult=SPIWriteRead(pSPIObj);
        if (0 == TxResult) {
            //Done for read/write            
            pSPIObj->LogicRule &= ~(1U<<pSPIObj->PresentSeqNo); 
            pSPIObj->PresentSeqNo++;
            if (pSPIObj->PresentSeqNo>=pSPIObj->Max_Seq_QTY) pSPIObj->PresentSeqNo=0;
        }
        else if (TxResult < 0) {
            pSPIObj->LogicRule &= ~(1U<<pSPIObj->PresentSeqNo); 
            pSPIObj->PresentSeqNo++;
            if (pSPIObj->PresentSeqNo>=pSPIObj->Max_Seq_QTY) pSPIObj->PresentSeqNo=0;
        }
        else {
            //Run again next time (continue), so do nothing
        }    
    }
    else
    {   
        //no need to read/write
        pSPIObj->PresentSeqNo++;
        if (0x8000==pSPIObj->LogicRule)
        {
            pSPIObj->PresentSeqNo=0;
        }
        else {
            if (pSPIObj->PresentSeqNo==pSPIObj->Max_Seq_QTY) pSPIObj->PresentSeqNo=0;
        } 
        
    }
    
    
}




