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

extern volatile uint16_t tick;
uint32_t hspi[4];   //spi base  
uint8_t SPIWriteRead(SPIBUS_t * pSPIObj);
#ifdef SPI1_USE_FIFO
    #define VFIFO4SPI1 true
#else
    #define VFIFO4SPI1 false
#endif
#ifdef SPI2_USE_FIFO
    #define VFIFO4SPI2 true
#else
    #define VFIFO4SPI2 false
#endif
#ifdef SPI3_USE_FIFO
    #define VFIFO4SPI3 true
#else
    #define VFIFO4SPI3 false
#endif
#ifdef SPI4_USE_FIFO
    #define VFIFO4SPI4 true
#else
    #define VFIFO4SPI4 false
#endif
bool SPIUseFIFO_EN[4]={VFIFO4SPI1, VFIFO4SPI2, VFIFO4SPI3, VFIFO4SPI4};

#if (VFIFO4SPI1==true) || (VFIFO4SPI2==true) || (VFIFO4SPI3==true) || (VFIFO4SPI4==true)
    #define DSP_SPI_SupportFIFO 1
#endif

#ifdef USE_SPI1
static uint16_t dataSentCount_1;
static uint16_t dataReceivedCount_1;
static uint16_t MaxSize_1; //uint may byte, may word
static uint8_t ReTry_1=0;
static uint16_t Delay_1 = 0;

volatile SPI_Transaction spiTxRx1;  //New add for F28X Mock STM32Cube API
#endif

#ifdef USE_SPI2
static uint16_t dataSentCount_2;
static uint16_t dataReceivedCount_2;
static uint16_t MaxSize_2; //uint may byte, may word
static uint8_t ReTry_2=0;
static uint16_t Delay_2 = 0;

volatile SPI_Transaction spiTxRx2;  //New add for F28X Mock STM32Cube API
#endif


#ifdef USE_SPI3
static uint16_t dataSentCount_3;
static uint16_t dataReceivedCount_3;
static uint16_t MaxSize_3; //uint may byte, may word
static uint8_t ReTry_3=0;
static uint16_t Delay_3 = 0;

volatile SPI_Transaction spiTxRx3;  //New add for F28X Mock STM32Cube API
#endif

#ifdef USE_SPI4
static uint16_t dataSentCount_4;
static uint16_t dataReceivedCount_4;
static uint16_t MaxSize_4; //uint may byte, may word
static uint8_t ReTry_4=0;
static uint16_t Delay_4 = 0;

volatile SPI_Transaction spiTxRx4;  //New add for F28X Mock STM32Cube API
#endif

SPI_Poll_t POLL_InMain ={0,0,0,0};  //let main loop call forever if it is 1. Actualy we used ISR SPI, so no need it, just keep all zero
#ifdef USE_SPI1 
uint8_t LowerLayer_spi_ReturnResult1 = 1; //means continue
#endif
#ifdef USE_SPI2 
uint8_t LowerLayer_spi_ReturnResult2 = 1; //means continue
#endif
#ifdef USE_SPI3 
uint8_t LowerLayer_spi_ReturnResult3 = 1; //means continue
#endif
#ifdef USE_SPI4 
uint8_t LowerLayer_spi_ReturnResult4 = 1; //means continue
#endif


/**
 * 
 * @param pSPIObj
 * @return 0: success, plus: continue, negative : fail
 */
uint8_t SPIWriteRead(SPIBUS_t * pSPIObj) {
    uint16_t i;
    switch (pSPIObj->state) {
        case 0:
            //prepare all spi ans transmit Data including dummy data, 
            //Actually Transmit and receiver Array is equal size.
            //So Actually we defined equal size array in pSPIObj
            if (1 == pSPIObj->SPI_Peripheral_No) {
#ifdef USE_SPI1      
                dataSentCount_1 = 0;
                dataReceivedCount_1 = 0;
                MaxSize_1 = (pSPIObj->QTY4Read[pSPIObj->PresentSeqNo] > pSPIObj->QTY4Write[pSPIObj->PresentSeqNo]) ? pSPIObj->QTY4Read[pSPIObj->PresentSeqNo] : pSPIObj->QTY4Write[pSPIObj->PresentSeqNo];
                if (pSPIObj->Use16bitsBus) {
                    //16 bits
                    if (pSPIObj->QTY4Write[pSPIObj->PresentSeqNo] < MaxSize_1) {
                        if (pSPIObj->DummyDataAllOne & (1U << pSPIObj->PresentSeqNo)) {
                            //All 1 for dummy data
                            for (i = pSPIObj->QTY4Write[pSPIObj->PresentSeqNo]; i < MaxSize_1; i++) {
                                ((uint16_t * *) pSPIObj->pWriteData)[pSPIObj->PresentSeqNo][i] = 0xFFFFU;
                            }
                        } else {
                            //All 0 for dummy data
                            for (i = pSPIObj->QTY4Write[pSPIObj->PresentSeqNo]; i < MaxSize_1; i++) {
                                ((uint16_t * *) pSPIObj->pWriteData)[pSPIObj->PresentSeqNo][i] = 0x0;
                            }
                        }
                        //Transmit---16 bits bus
                        pSPIObj->set_CS[pSPIObj->PresentSeqNo](true);
                        #ifndef USE_SPI1_DMA
                        if (SPI_TransmitReceive_IT(&SPI_myObj1, /* uint16_t *pTxData */ (uint16_t *)&(pSPIObj->pWriteData)[pSPIObj->PresentSeqNo][0], /* uint16_t *pRxData */(uint16_t *)&(pSPIObj->pReadData)[pSPIObj->PresentSeqNo][0],
                                                                                         /* uint16_t Size */MaxSize_1))
                        #else
                        if (SPI_TransmitReceive_DMA(&SPI_myObj1, /* uint16_t *pTxData */ (uint16_t *)&(pSPIObj->pWriteData)[pSPIObj->PresentSeqNo][0], /* uint16_t *pRxData */(uint16_t *)&(pSPIObj->pReadData)[pSPIObj->PresentSeqNo][0],
                                                                                         /* uint16_t Size */MaxSize_1))
                        #endif
                        {
                        	pSPIObj->state++;
                        	Delay_1=0;
                        }
                        
                        

                    }
                } else {
                    //8 bits
                    if (pSPIObj->QTY4Write[pSPIObj->PresentSeqNo] < MaxSize_1) {
                        if (pSPIObj->DummyDataAllOne & (1U << pSPIObj->PresentSeqNo)) {
                            //All 1 for dummy data
                            for (i = pSPIObj->QTY4Write[pSPIObj->PresentSeqNo]; i < MaxSize_1; i++) {
                                pSPIObj->pWriteData[pSPIObj->PresentSeqNo][i] = 0xFF;
                            }
                        } else {
                            //All 0 for dummy data
                            for (i = pSPIObj->QTY4Write[pSPIObj->PresentSeqNo]; i < MaxSize_1; i++) {
                                pSPIObj->pWriteData[pSPIObj->PresentSeqNo][i] = 0x0;
                            }
                        }
                    }
                    //transmit ---8 bits bus
                    (pSPIObj->set_CS[pSPIObj->PresentSeqNo])(true);
                    #ifndef USE_SPI1_DMA
                    if (SPI_TransmitReceive_IT(&SPI_myObj1, /* uint16_t *pTxData */ ( uint16_t *)&(pSPIObj->pWriteData)[pSPIObj->PresentSeqNo][0], /* uint16_t *pRxData */(uint16_t *)&(pSPIObj->pReadData)[pSPIObj->PresentSeqNo][0],
                    		/* uint16_t Size */MaxSize_1))
                    #else
                    if (SPI_TransmitReceive_DMA(&SPI_myObj1, /* uint16_t *pTxData */ ( uint16_t *)&(pSPIObj->pWriteData)[pSPIObj->PresentSeqNo][0], /* uint16_t *pRxData */(uint16_t *)&(pSPIObj->pReadData)[pSPIObj->PresentSeqNo][0],
                    		/* uint16_t Size */MaxSize_1))                    
                    #endif        
                    {
                    	pSPIObj->state++;
                    	Delay_1=0;
                    }
                }
                if(spiTxRx1.busy == false) {
                    //done all transmit/receive                    
                    //pSPIObj->set_CS[pSPIObj->PresentSeqNo](false);  already did in callback                                        
                    return 0; //success
                }                
                return 1;  //continue
#else
                return -1;
#endif
            } else if (2 == pSPIObj->SPI_Peripheral_No) {
#ifdef USE_SPI2   
                dataSentCount_2 = 0;
                dataReceivedCount_2 = 0;
                MaxSize_2 = (pSPIObj->QTY4Read[pSPIObj->PresentSeqNo] > pSPIObj->QTY4Write[pSPIObj->PresentSeqNo]) ? pSPIObj->QTY4Read[pSPIObj->PresentSeqNo] : pSPIObj->QTY4Write[pSPIObj->PresentSeqNo];
                if (pSPIObj->Use16bitsBus) {
                    //16 bits
                    if (pSPIObj->QTY4Write[pSPIObj->PresentSeqNo] < MaxSize_2) {
                        if (pSPIObj->DummyDataAllOne & (1U << pSPIObj->PresentSeqNo)) {
                            //All 1 for dummy data
                            for (i = pSPIObj->QTY4Write[pSPIObj->PresentSeqNo]; i < MaxSize_2; i++) {
                                ((uint16_t * *) pSPIObj->pWriteData)[pSPIObj->PresentSeqNo][i] = 0xFFFFU;
                            }
                        } else {
                            //All 0 for dummy data
                            for (i = pSPIObj->QTY4Write[pSPIObj->PresentSeqNo]; i < MaxSize_2; i++) {
                                ((uint16_t * *) pSPIObj->pWriteData)[pSPIObj->PresentSeqNo][i] = 0x0;
                            }
                        }
                        //Transmit---16 bits bus
                        pSPIObj->set_CS[pSPIObj->PresentSeqNo](true);
                        #ifndef USE_SPI2_DMA
                        if (SPI_TransmitReceive_IT(&SPI_myObj2, /* uint16_t *pTxData */ (uint16_t *)&(pSPIObj->pWriteData)[pSPIObj->PresentSeqNo][0], /* uint16_t *pRxData */(uint16_t *)&(pSPIObj->pReadData)[pSPIObj->PresentSeqNo][0],
                                                                 /* uint16_t Size */MaxSize_2))
                        #else
                        if (SPI_TransmitReceive_DMA(&SPI_myObj2, /* uint16_t *pTxData */ (uint16_t *)&(pSPIObj->pWriteData)[pSPIObj->PresentSeqNo][0], /* uint16_t *pRxData */(uint16_t *)&(pSPIObj->pReadData)[pSPIObj->PresentSeqNo][0],
                                                                 /* uint16_t Size */MaxSize_2))
                        #endif
                        {
                        	pSPIObj->state++;
                        	Delay_2=0;
                        }
                    }
                } else {
                    //8 bits
                    if (pSPIObj->QTY4Write[pSPIObj->PresentSeqNo] < MaxSize_2) {
                        if (pSPIObj->DummyDataAllOne & (1U << pSPIObj->PresentSeqNo)) {
                            //All 1 for dummy data
                            for (i = pSPIObj->QTY4Write[pSPIObj->PresentSeqNo]; i < MaxSize_2; i++) {
                                pSPIObj->pWriteData[pSPIObj->PresentSeqNo][i] = 0xFF;
                            }
                        } else {
                            //All 0 for dummy data
                            for (i = pSPIObj->QTY4Write[pSPIObj->PresentSeqNo]; i < MaxSize_2; i++) {
                                pSPIObj->pWriteData[pSPIObj->PresentSeqNo][i] = 0x0;
                            }
                        }
                    }
                    //transmit ---8 bits bus
                    pSPIObj->set_CS[pSPIObj->PresentSeqNo](true);
                    #ifndef USE_SPI2_DMA
                    if (SPI_TransmitReceive_IT(&SPI_myObj2, /* uint16_t *pTxData */ (uint16_t *)&(pSPIObj->pWriteData)[pSPIObj->PresentSeqNo][0], /* uint16_t *pRxData */(uint16_t *)&(pSPIObj->pReadData)[pSPIObj->PresentSeqNo][0],
                    		/* uint16_t Size */MaxSize_2))
                    #else
                    if (SPI_TransmitReceive_DMA(&SPI_myObj2, /* uint16_t *pTxData */ (uint16_t *)&(pSPIObj->pWriteData)[pSPIObj->PresentSeqNo][0], /* uint16_t *pRxData */(uint16_t *)&(pSPIObj->pReadData)[pSPIObj->PresentSeqNo][0],
                    		/* uint16_t Size */MaxSize_2))
                    #endif
                    {
                    	pSPIObj->state++;
                    	Delay_2=0;
                    }
                    
                }
                if(spiTxRx2.busy == false) {
                    //done all transmit/receive
                    //pSPIObj->set_CS[pSPIObj->PresentSeqNo](false);  already did in callback                                        
                    return 0; //success
                }                
                return 1;  //continue
#else
                return -1;
#endif
            } else if (3 == pSPIObj->SPI_Peripheral_No) {
#ifdef USE_SPI3   
                dataSentCount_3 = 0;
                dataReceivedCount_3 = 0;
                MaxSize_3 = (pSPIObj->QTY4Read[pSPIObj->PresentSeqNo] > pSPIObj->QTY4Write[pSPIObj->PresentSeqNo]) ? pSPIObj->QTY4Read[pSPIObj->PresentSeqNo] : pSPIObj->QTY4Write[pSPIObj->PresentSeqNo];
                if (pSPIObj->Use16bitsBus) {
                    //16 bits
                    if (pSPIObj->QTY4Write[pSPIObj->PresentSeqNo] < MaxSize_3) {
                        if (pSPIObj->DummyDataAllOne & (1U << pSPIObj->PresentSeqNo)) {
                            //All 1 for dummy data
                            for (i = pSPIObj->QTY4Write[pSPIObj->PresentSeqNo]; i < MaxSize_3; i++) {
                                ((uint16_t * *) pSPIObj->pWriteData)[pSPIObj->PresentSeqNo][i] = 0xFFFFU;
                            }
                        } else {
                            //All 0 for dummy data
                            for (i = pSPIObj->QTY4Write[pSPIObj->PresentSeqNo]; i < MaxSize_3; i++) {
                                ((uint16_t * *) pSPIObj->pWriteData)[pSPIObj->PresentSeqNo][i] = 0x0;
                            }
                        }
                        //Transmit---16 bits bus
                        pSPIObj->set_CS[pSPIObj->PresentSeqNo](true);
                        #ifndef USE_SPI3_DMA
                        if (SPI_TransmitReceive_IT(&SPI_myObj3, /* uint16_t *pTxData */ (uint16_t *)&(pSPIObj->pWriteData)[pSPIObj->PresentSeqNo][0], /* uint16_t *pRxData */(uint16_t *)&(pSPIObj->pReadData)[pSPIObj->PresentSeqNo][0],
                        		/* uint16_t Size */MaxSize_3))
                        #else
                        if (SPI_TransmitReceive_DMA(&SPI_myObj3, /* uint16_t *pTxData */ (uint16_t *)&(pSPIObj->pWriteData)[pSPIObj->PresentSeqNo][0], /* uint16_t *pRxData */(uint16_t *)&(pSPIObj->pReadData)[pSPIObj->PresentSeqNo][0],
                        		/* uint16_t Size */MaxSize_3))
                        #endif
                        {
                        	pSPIObj->state++;
                        	Delay_3=0;
                        }

                    }
                } else {
                    //8 bits
                    if (pSPIObj->QTY4Write[pSPIObj->PresentSeqNo] < MaxSize_3) {
                        if (pSPIObj->DummyDataAllOne & (1U << pSPIObj->PresentSeqNo)) {
                            //All 1 for dummy data
                            for (i = pSPIObj->QTY4Write[pSPIObj->PresentSeqNo]; i < MaxSize_3; i++) {
                                pSPIObj->pWriteData[pSPIObj->PresentSeqNo][i] = 0xFF;
                            }
                        } else {
                            //All 0 for dummy data
                            for (i = pSPIObj->QTY4Write[pSPIObj->PresentSeqNo]; i < MaxSize_3; i++) {
                                pSPIObj->pWriteData[pSPIObj->PresentSeqNo][i] = 0x0;
                            }
                        }
                    }
                    //transmit ---8 bits bus
                    pSPIObj->set_CS[pSPIObj->PresentSeqNo](true);
                    #ifndef USE_SPI3_DMA
                    if (SPI_TransmitReceive_IT(&SPI_myObj3, /* uint16_t *pTxData */ (uint16_t *)&(pSPIObj->pWriteData)[pSPIObj->PresentSeqNo][0], /* uint16_t *pRxData */(uint16_t *)&(pSPIObj->pReadData)[pSPIObj->PresentSeqNo][0],
                    		/* uint16_t Size */MaxSize_3))
                    #else
                    if (SPI_TransmitReceive_DMA(&SPI_myObj3, /* uint16_t *pTxData */ (uint16_t *)&(pSPIObj->pWriteData)[pSPIObj->PresentSeqNo][0], /* uint16_t *pRxData */(uint16_t *)&(pSPIObj->pReadData)[pSPIObj->PresentSeqNo][0],
                    		/* uint16_t Size */MaxSize_3))
                    #endif
                    {
                    	pSPIObj->state++;
                    	Delay_3=0;
                    }
                }
                if(spiTxRx3.busy == false) {
                    //done all transmit/receive
                    //pSPIObj->set_CS[pSPIObj->PresentSeqNo](false);  already did in callback                                        
                    return 0; //success
                }                
                return 1;  //continue
#else
                return -1;
#endif
            } else if (4 == pSPIObj->SPI_Peripheral_No) {
#ifdef USE_SPI4 
                dataSentCount_4 = 0;
                dataReceivedCount_4 = 0;
                MaxSize_4 = (pSPIObj->QTY4Read[pSPIObj->PresentSeqNo] > pSPIObj->QTY4Write[pSPIObj->PresentSeqNo]) ? pSPIObj->QTY4Read[pSPIObj->PresentSeqNo] : pSPIObj->QTY4Write[pSPIObj->PresentSeqNo];
                if (pSPIObj->Use16bitsBus) {
                    //16 bits
                    if (pSPIObj->QTY4Write[pSPIObj->PresentSeqNo] < MaxSize_4) {
                        if (pSPIObj->DummyDataAllOne & (1U << pSPIObj->PresentSeqNo)) {
                            //All 1 for dummy data
                            for (i = pSPIObj->QTY4Write[pSPIObj->PresentSeqNo]; i < MaxSize_4; i++) {
                                ((uint16_t * *) pSPIObj->pWriteData)[pSPIObj->PresentSeqNo][i] = 0xFFFFU;
                            }
                        } else {
                            //All 0 for dummy data
                            for (i = pSPIObj->QTY4Write[pSPIObj->PresentSeqNo]; i < MaxSize_4; i++) {
                                ((uint16_t * *) pSPIObj->pWriteData)[pSPIObj->PresentSeqNo][i] = 0x0;
                            }
                        }
                        //Transmit---16 bits bus
                        pSPIObj->set_CS[pSPIObj->PresentSeqNo](true);
                        #ifndef USE_SPI4_DMA
                        if (SPI_TransmitReceive_IT(&SPI_myObj4, /* uint16_t *pTxData */ (uint16_t *)&(pSPIObj->pWriteData)[pSPIObj->PresentSeqNo][0], /* uint16_t *pRxData */(uint16_t *)&(pSPIObj->pReadData)[pSPIObj->PresentSeqNo][0],
                        		/* uint16_t Size */MaxSize_4))
                        #else
                        if (SPI_TransmitReceive_DMA(&SPI_myObj4, /* uint16_t *pTxData */ (uint16_t *)&(pSPIObj->pWriteData)[pSPIObj->PresentSeqNo][0], /* uint16_t *pRxData */(uint16_t *)&(pSPIObj->pReadData)[pSPIObj->PresentSeqNo][0],
                        		/* uint16_t Size */MaxSize_4))
                        #endif
                        {
                        	pSPIObj->state++;
                        	Delay_4=0;
                        }


                    }
                } else {
                    //8 bits
                    if (pSPIObj->QTY4Write[pSPIObj->PresentSeqNo] < MaxSize_4) {
                        if (pSPIObj->DummyDataAllOne & (1U << pSPIObj->PresentSeqNo)) {
                            //All 1 for dummy data
                            for (i = pSPIObj->QTY4Write[pSPIObj->PresentSeqNo]; i < MaxSize_4; i++) {
                                pSPIObj->pWriteData[pSPIObj->PresentSeqNo][i] = 0xFF;
                            }
                        } else {
                            //All 0 for dummy data
                            for (i = pSPIObj->QTY4Write[pSPIObj->PresentSeqNo]; i < MaxSize_4; i++) {
                                pSPIObj->pWriteData[pSPIObj->PresentSeqNo][i] = 0x0;
                            }
                        }
                    }
                    //transmit ---8 bits bus
                    pSPIObj->set_CS[pSPIObj->PresentSeqNo](true);
                    #ifndef USE_SPI4_DMA
                    if (SPI_TransmitReceive_IT(&SPI_myObj4, /* uint16_t *pTxData */ (uint16_t *)&(pSPIObj->pWriteData)[pSPIObj->PresentSeqNo][0], /* uint16_t *pRxData */(uint16_t *)&(pSPIObj->pReadData)[pSPIObj->PresentSeqNo][0],
                    		/* uint16_t Size */MaxSize_4))
                    #else
                    if (SPI_TransmitReceive_DMA(&SPI_myObj4, /* uint16_t *pTxData */ (uint16_t *)&(pSPIObj->pWriteData)[pSPIObj->PresentSeqNo][0], /* uint16_t *pRxData */(uint16_t *)&(pSPIObj->pReadData)[pSPIObj->PresentSeqNo][0],
                    		/* uint16_t Size */MaxSize_4))
                    #endif
                    {
                    	pSPIObj->state++;
                    	Delay_4=0;
                    }
                }
                if(spiTxRx4.busy == false) {
                    //done all transmit/receive                   
                    //pSPIObj->set_CS[pSPIObj->PresentSeqNo](false);  already did in callback                                        
                    return 0; //success
                }                
                return 1;  //continue
#else                
                return -1;
#endif
            }
            break;
        case 1:
            //Transmit/receiving continuously, wait for done
            if (1 == pSPIObj->SPI_Peripheral_No) {
#ifdef USE_SPI1                
                if(spiTxRx1.busy == false) {
                    //done all transmit/receive
                    //pSPIObj->set_CS[pSPIObj->PresentSeqNo](false);  already did in callback    
                    pSPIObj->state=0;
                    ReTry_1=0;
                    return 0; //success
                }
                else  {
                	Delay_1++;
                	if (Delay_1>200)  {  //200ms as timeout
                		Delay_1=0;
                		ReTry_1++;
                		if (ReTry_1>2) {
                			ReTry_1=0;
                		    pSPIObj->state=0;
                		    return -1; //Fail
                		}
                		else {
                			pSPIObj->state=0;
                		}
                	}
                }
                return 1;  //continue
#else
                pSPIObj->state = 0;
                return -1; //Fail
#endif
            } else if (2 == pSPIObj->SPI_Peripheral_No) {
#ifdef USE_SPI2
                if(spiTxRx2.busy == false) {
                    //done all transmit/receive
                    //pSPIObj->set_CS[pSPIObj->PresentSeqNo](false);  already did in callback    
                    pSPIObj->state=0;
                    ReTry_2=0;
                    return 0; //success
                }
                else  {
                	Delay_2++;
                	if (Delay_2>200)  {   //200ms as timeout
                		Delay_2=0;
                		ReTry_2++;
                		if (ReTry_2>2) {
                			ReTry_2=0;
                		    pSPIObj->state=0;
                		    return -1; //Fail
                		}
                		else {
                			pSPIObj->state=0;
                		}
                	}
                }
                return 1;  //continue
#else
                pSPIObj->state = 0;
                return -1; //Fail
#endif                
            } else if (3 == pSPIObj->SPI_Peripheral_No) {
#ifdef USE_SPI3
                if(spiTxRx3.busy == false) {
                    //done all transmit/receive
                    //pSPIObj->set_CS[pSPIObj->PresentSeqNo](false);  already did in callback    
                    pSPIObj->state=0;
                    ReTry_3=0;
                    return 0; //success
                }
                else  {
                	Delay_3++;
                	if (Delay_3>200)  {   //200ms as timeout
                		Delay_3=0;
                		ReTry_3++;
                		if (ReTry_3>2) {
                			ReTry_3=0;
                		    pSPIObj->state=0;
                		    return -1; //Fail
                		}
                		else {
                			pSPIObj->state=0;
                		}
                	}
                }                
                return 1;  //continue
#else
                pSPIObj->state = 0;
                return -1; //Fail
#endif                
            } else if (4 == pSPIObj->SPI_Peripheral_No) {
#ifdef USE_SPI4
                if(spiTxRx4.busy == false) {
                    //done all transmit/receive
                    //pSPIObj->set_CS[pSPIObj->PresentSeqNo](false);  already did in callback    
                    pSPIObj->state=0;
                    ReTry_4=0;
                    return 0; //success
                }
                else  {
                	Delay_4++;
                	if (Delay_4>200)  {   //200ms as timeout
                		Delay_4=0;
                		ReTry_4++;
                		if (ReTry_4>2) {
                			ReTry_4=0;
                		    pSPIObj->state=0;
                		    return -1; //Fail
                		}
                		else {
                			pSPIObj->state=0;
                		}
                	}
                }                
                return 1;  //continue
#else
                pSPIObj->state = 0;
                return -1; //Fail
#endif               
            }

    }
    return 1;    

}

/**
 * SPI Write-only/ Read-only/ Write and read   Function
 * This is only for Non-ISR SPI bus main-loop call forever.  But for PIC32, we used ISR call back.  So no use, we just return 0
 * @param pSPIObj --- SPI Bus object
 * 
 * @return 
 * 0: Success
 * 1: Continue
 * negative: fail
 */
uint8_t SPIWriteRead_lowLayer(SPIBUS_t * pSPIObj) {

    return 0;  
}

/**
 * @brief 
 * 
 * @param base 
 * @param txBuf 
 * @param rxBuf 
 * @param length 
 * @return true 
 * @return false 
 */
bool SPI_TransmitReceive_IT(SPIBUS_t * pSPIObj, uint16_t * txBuf, uint16_t * rxBuf, uint16_t length)
{        
    if (1 == pSPIObj->SPI_Peripheral_No) {
         #if defined(USE_SPI1) && !defined(USE_SPI1_DMA)
         if (spiTxRx1.busy ) return false;
         spiTxRx1.txBuf=txBuf;
         spiTxRx1.rxBuf=rxBuf;
         spiTxRx1.length=length;
         spiTxRx1.txIndex = 0;
         spiTxRx1.rxIndex = 0;
         spiTxRx1.busy = true;          
         #else
         return false;
         #endif
    }
    else if (2 == pSPIObj->SPI_Peripheral_No) {
          #if defined(USE_SPI2) && !defined(USE_SPI2_DMA)
         if (spiTxRx2.busy ) return false;
         spiTxRx2.txBuf=txBuf;
         spiTxRx2.rxBuf=rxBuf;
         spiTxRx2.length=length;
         spiTxRx2.txIndex = 0;
         spiTxRx2.rxIndex = 0;
         spiTxRx2.busy = true;          
         #else
         return false;
         #endif
    }
    else if (3 == pSPIObj->SPI_Peripheral_No) {
         #if defined(USE_SPI3) && !defined(USE_SPI3_DMA)
         if (spiTxRx3.busy ) return false;
         spiTxRx3.txBuf=txBuf;
         spiTxRx3.rxBuf=rxBuf;
         spiTxRx3.length=length;
         spiTxRx3.txIndex = 0;
         spiTxRx3.rxIndex = 0;
         spiTxRx3.busy = true;  
         
         #else
         return false;
         #endif
    }
    else if (4 == pSPIObj->SPI_Peripheral_No) {
         #if defined(USE_SPI4) && !defined(USE_SPI4_DMA) 
         if (spiTxRx4.busy ) return false;
         spiTxRx4.txBuf=txBuf;
         spiTxRx4.rxBuf=rxBuf;
         spiTxRx4.length=length;
         spiTxRx4.txIndex = 0;
         spiTxRx4.rxIndex = 0;
         spiTxRx4.busy = true;  
         
         #else
         return false;
         #endif
    }
    #ifdef DSP_SPI_SupportFIFO
    if (SPIUseFIFO_EN[pSPIObj->SPI_Peripheral_No-1])  {
        //FIFO Mode
        SPI_setTxFifoTransmitDelay(hspi[pSPIObj->SPI_Peripheral_No-1], 0);  //delay =0 for Interrupt-driven SPI, example 1 to 2, please increase or decrease adjust speed , unit is clock cycle    
        SPI_disableInterrupt(hspi[pSPIObj->SPI_Peripheral_No-1], SPI_INT_TXFF);
        SPI_disableInterrupt(hspi[pSPIObj->SPI_Peripheral_No-1], SPI_INT_RXFF); 
        SPI_clearInterruptStatus(hspi[pSPIObj->SPI_Peripheral_No-1], SPI_INT_RXFF);
        SPI_clearInterruptStatus(hspi[pSPIObj->SPI_Peripheral_No-1], SPI_INT_TXFF);
        if (length<16)  {
            SPI_setFIFOInterruptLevel(hspi[pSPIObj->SPI_Peripheral_No-1], SPI_FIFO_TXEMPTY, length);   
        }
        else  {
            SPI_setFIFOInterruptLevel(hspi[pSPIObj->SPI_Peripheral_No-1], SPI_FIFO_TXEMPTY, 16);  
        }
        SPI_enableInterrupt(hspi[pSPIObj->SPI_Peripheral_No-1], SPI_INT_TXFF);
        SPI_enableInterrupt(hspi[pSPIObj->SPI_Peripheral_No-1], SPI_INT_RXFF);
    }
    else {
        //Non-FIFO Mode
        if (1 == pSPIObj->SPI_Peripheral_No)  {
            #if defined(USE_SPI1)            
                spiTxRx1.txIndex++;           
                #ifdef SPI1_USE16BIT_WIDTH
                SPI_writeDataBlockingNonFIFO(hspi[pSPIObj->SPI_Peripheral_No-1], txBuf[0]);
                #else
                SPI_writeDataBlockingNonFIFO(hspi[pSPIObj->SPI_Peripheral_No-1], (txBuf[0]<<8));
                #endif         
            #endif
        }
        #if defined(USE_SPI2)
        else if (2 == pSPIObj->SPI_Peripheral_No)  {            
            spiTxRx2.txIndex++;
            #ifdef SPI2_USE16BIT_WIDTH
            SPI_writeDataBlockingNonFIFO(hspi[pSPIObj->SPI_Peripheral_No-1], txBuf[0]); 
            #else
            SPI_writeDataBlockingNonFIFO(hspi[pSPIObj->SPI_Peripheral_No-1], (txBuf[0]<<8));
            #endif             
        }
        #endif
        #if defined(USE_SPI3)
        else if (3 == pSPIObj->SPI_Peripheral_No)  {            
            spiTxRx3.txIndex++;
            #ifdef SPI3_USE16BIT_WIDTH
            SPI_writeDataBlockingNonFIFO(hspi[pSPIObj->SPI_Peripheral_No-1], txBuf[0]); 
            #else
            SPI_writeDataBlockingNonFIFO(hspi[pSPIObj->SPI_Peripheral_No-1], (txBuf[0]<<8));
            #endif            
        }
        #endif
        #if defined(USE_SPI4)
        else if (4 == pSPIObj->SPI_Peripheral_No)  {           
            spiTxRx4.txIndex++;
            #ifdef SPI4_USE16BIT_WIDTH
            SPI_writeDataBlockingNonFIFO(hspi[pSPIObj->SPI_Peripheral_No-1], txBuf[0]); 
            #else
            SPI_writeDataBlockingNonFIFO(hspi[pSPIObj->SPI_Peripheral_No-1], (txBuf[0]<<8));
            #endif             
        } 
        #endif    

    }
    #else
        //Non-FIFO Mode       
        if (1 == pSPIObj->SPI_Peripheral_No)  {
            #if defined(USE_SPI1)            
                spiTxRx1.txIndex++;           
                #ifdef SPI1_USE16BIT_WIDTH
                SPI_writeDataBlockingNonFIFO(hspi[pSPIObj->SPI_Peripheral_No-1], txBuf[0]);
                #else
                SPI_writeDataBlockingNonFIFO(hspi[pSPIObj->SPI_Peripheral_No-1], (txBuf[0]<<8));
                #endif         
            #endif
        }
        #if defined(USE_SPI2)
        else if (2 == pSPIObj->SPI_Peripheral_No)  {            
            spiTxRx2.txIndex++;
            #ifdef SPI2_USE16BIT_WIDTH
            SPI_writeDataBlockingNonFIFO(hspi[pSPIObj->SPI_Peripheral_No-1], txBuf[0]); 
            #else
            SPI_writeDataBlockingNonFIFO(hspi[pSPIObj->SPI_Peripheral_No-1], (txBuf[0]<<8));
            #endif             
        }
        #endif
        #if defined(USE_SPI3)
        else if (3 == pSPIObj->SPI_Peripheral_No)  {            
            spiTxRx3.txIndex++;
            #ifdef SPI3_USE16BIT_WIDTH
            SPI_writeDataBlockingNonFIFO(hspi[pSPIObj->SPI_Peripheral_No-1], txBuf[0]); 
            #else
            SPI_writeDataBlockingNonFIFO(hspi[pSPIObj->SPI_Peripheral_No-1], (txBuf[0]<<8));
            #endif            
        }
        #endif
        #if defined(USE_SPI4)
        else if (4 == pSPIObj->SPI_Peripheral_No)  {           
            spiTxRx4.txIndex++;
            #ifdef SPI4_USE16BIT_WIDTH
            SPI_writeDataBlockingNonFIFO(hspi[pSPIObj->SPI_Peripheral_No-1], txBuf[0]); 
            #else
            SPI_writeDataBlockingNonFIFO(hspi[pSPIObj->SPI_Peripheral_No-1], (txBuf[0]<<8));
            #endif             
        } 
        #endif    
    #endif
    
    
    return true;
}
#if defined( USE_SPI1_DMA) || defined( USE_SPI2_DMA) || defined( USE_SPI3_DMA) || defined( USE_SPI4_DMA)


// Function used to select correct dma channel based base address provided
//
uint32_t selectDMA_PIE_Interrupt(uint32_t dmachbase)
{

    uint32_t DMA_Channel = 0;

    switch(dmachbase)
    {
        case DMA_CH1_BASE:
            DMA_startChannel(DMA_CH1_BASE);
            DMA_Channel = INT_DMA_CH1;
            Interrupt_enable(DMA_Channel);
            break;

        case DMA_CH2_BASE:
            DMA_startChannel(DMA_CH2_BASE);
            DMA_Channel = INT_DMA_CH2;
            Interrupt_enable(DMA_Channel);
            break;
        case DMA_CH3_BASE:
            DMA_startChannel(DMA_CH3_BASE);
            DMA_Channel = INT_DMA_CH3;
            Interrupt_enable(DMA_Channel);
            break;

        case DMA_CH4_BASE:
            DMA_startChannel(DMA_CH4_BASE);
            DMA_Channel = INT_DMA_CH4;
            Interrupt_enable(DMA_Channel);
            break;

        case DMA_CH5_BASE:
            DMA_startChannel(DMA_CH5_BASE);
            DMA_Channel = INT_DMA_CH5;
            Interrupt_enable(DMA_Channel);
            break;

        case DMA_CH6_BASE:
            DMA_startChannel(DMA_CH6_BASE);
            DMA_Channel = INT_DMA_CH6;
            Interrupt_enable(DMA_Channel);
            break;
    }

    return(DMA_Channel);
}
#endif
/**
 * @brief 
 * 
 * @param pSPIObj 
 * @param txBuf 
 * @param rxBuf 
 * @param length 
 * @return true 
 * @return false 
 */

bool SPI_TransmitReceive_DMA(SPIBUS_t * pSPIObj, uint16_t * txBuf, uint16_t * rxBuf, uint16_t length)
{       
     DMA_Trigger Rx_trigger; 
     if (1 == pSPIObj->SPI_Peripheral_No) {
         #if defined(USE_SPI1) && defined (USE_SPI1_DMA ) 
         if (spiTxRx1.busy ) return false;
         spiTxRx1.txBuf=txBuf;
         spiTxRx1.rxBuf=rxBuf;
         spiTxRx1.length=length;
         spiTxRx1.txIndex = 0;   //Track how many transmit
         spiTxRx1.rxIndex = 0;  //no usein DMA
         spiTxRx1.busy = true; 
         #ifndef SPI1_USE16BIT_WIDTH
             //8 bits bus
             uint16_t i;
             for (i=0;i<length;i++) {
                *(spiTxRx1.txBuf+i)=(*(spiTxRx1.txBuf+i))<<8;
             }
         #endif

         uint16_t burst_size; 
         uint16_t transfer_size;
         SPI_disableInterrupt(hspi[pSPIObj->SPI_Peripheral_No-1], SPI_INT_TXFF);
         SPI_disableInterrupt(hspi[pSPIObj->SPI_Peripheral_No-1], SPI_INT_RXFF); 
         SPI_clearInterruptStatus(hspi[pSPIObj->SPI_Peripheral_No-1], SPI_INT_RXFF);
         SPI_clearInterruptStatus(hspi[pSPIObj->SPI_Peripheral_No-1], SPI_INT_TXFF);
         //Reset the TX / RX FIFO buffers to default state
         SPI_disableFIFO(hspi[pSPIObj->SPI_Peripheral_No-1]); //Disable FIFO register
         SPI_enableFIFO(hspi[pSPIObj->SPI_Peripheral_No-1]);  //Enable FIFO register
         SPI_setTxFifoTransmitDelay(hspi[pSPIObj->SPI_Peripheral_No-1], 4);  //delay =1 to 4 for DMA with FIFO enabled, please increase or decrease adjust speed , unit is clock cycle
         if (length<16)  {
            SPI_setFIFOInterruptLevel(hspi[pSPIObj->SPI_Peripheral_No-1], SPI_FIFO_TXEMPTY, length);   
            burst_size=length;
         }
         else  {
            SPI_setFIFOInterruptLevel(hspi[pSPIObj->SPI_Peripheral_No-1], SPI_FIFO_TXEMPTY, 16);  
            burst_size=16;
         }
        transfer_size=length /16;
        if (0==transfer_size) transfer_size=1;
        SPI_enableInterrupt(hspi[pSPIObj->SPI_Peripheral_No-1], SPI_INT_RXFF);
          // Initialize DMA
        DMA_initController();
         //uint32_t dmaTX_IntNum = selectDMA_PIE_Interrupt(SPI1_DMA_TX_base);
         //Interrupt_register(dmaTX_IntNum, &SPI1_DMA_TX_ISR);
         uint16_t *psrcAddr  = spiTxRx1.txBuf;
         uint16_t *pdestAddr = (uint16_t *)(hspi[pSPIObj->SPI_Peripheral_No-1] + SPI_O_TXBUF);
         DMA_configAddresses(SPI1_DMA_TX_base, pdestAddr, psrcAddr);
        DMA_configBurst(SPI1_DMA_TX_base, burst_size, 1, 0);  //src burst step=1, dest burst step=0
        DMA_configTransfer(SPI1_DMA_TX_base, transfer_size, 1, 0); //src trsnsfer step = burst_size, dest transfer step=0  -> but in example , src trsnsfer step= 1
        DMA_configMode(SPI1_DMA_TX_base, DMA_TRIGGER_SOFTWARE, DMA_CFG_ONESHOT_DISABLE | DMA_CFG_CONTINUOUS_ENABLE |
                                                    DMA_CFG_SIZE_16BIT);


        DMA_setEmulationMode(DMA_EMULATION_FREE_RUN);

        // DMA  trigger enabel, so wait for trigger source coming
        DMA_enableTrigger(SPI1_DMA_TX_base);
        
        /********************************************************************************/
        // DMA RX Channel configuration
        /********************************************************************************/   
        uint32_t dmaRX_IntNum = selectDMA_PIE_Interrupt(SPI1_DMA_RX_base);
        Interrupt_register(dmaRX_IntNum, &SPI1_DMA_RX_ISR);

        psrcAddr  = (uint16_t *)(hspi[pSPIObj->SPI_Peripheral_No-1] + SPI_O_RXBUF);
        pdestAddr =  spiTxRx1.rxBuf;

        //Enable RXFIFO interrupt to ensure DMA RX channel is triggered
        SPI_enableInterrupt(hspi[pSPIObj->SPI_Peripheral_No-1], SPI_INT_RXFF);

        DMA_configAddresses(SPI1_DMA_RX_base, pdestAddr, psrcAddr);
        //DMA_configBurst(SPI1_DMA_RX_base, burst_size, 0, 1);  //src burst step=0, dest burst step=1
        DMA_configBurst(SPI1_DMA_RX_base, burst_size, 0, 1);  //src burst step=0, dest burst step=1
       // DMA_configTransfer(SPI1_DMA_RX_base, transfer_size, 0, 1); //src trsnsfer step = 0, dest transfer step= burst_size  -> but in example , dest trsnsfer step=1
       DMA_configTransfer(SPI1_DMA_RX_base, 1, 0, 1); //src trsnsfer step = 0, dest transfer step= burst_size  -> but in example , dest trsnsfer step=1
        //DMA_Trigger Rx_trigger;
        if (hspi[pSPIObj->SPI_Peripheral_No-1]==SPIA_BASE) {
            Rx_trigger=DMA_TRIGGER_SPIARX;
        }
        #ifdef SPIB_BASE
        else if (hspi[pSPIObj->SPI_Peripheral_No-1]==SPIB_BASE) {
            Rx_trigger=DMA_TRIGGER_SPIBRX;
        }
        #ifdef SPIC_BASE
        else if (hspi[pSPIObj->SPI_Peripheral_No-1]==SPIC_BASE) {
            Rx_trigger=DMA_TRIGGER_SPICRX;
        }   
        #ifdef SPID_BASE
        else if (hspi[pSPIObj->SPI_Peripheral_No-1]==SPID_BASE) {
            Rx_trigger=DMA_TRIGGER_SPIDRX;
        }        
        #endif     
        #endif
        #endif
        DMA_configMode(SPI1_DMA_RX_base, Rx_trigger, DMA_CFG_ONESHOT_DISABLE |
                    DMA_CFG_CONTINUOUS_ENABLE | DMA_CFG_SIZE_16BIT);

        //
        // Configure DMA RX interrupts
        //
        DMA_setInterruptMode(SPI1_DMA_RX_base, DMA_INT_AT_END);
        DMA_enableInterrupt(SPI1_DMA_RX_base);
        DMA_enableTrigger(SPI1_DMA_RX_base);  // DMA  trigger enabel, so wait for trigger source coming

        SPI_disableInterrupt(hspi[pSPIObj->SPI_Peripheral_No-1], SPI_INT_TXFF);   //let force trig Tx DMA inside Rx DMA ISR
        //SPI_enableInterrupt(hspi[pSPIObj->SPI_Peripheral_No-1], SPI_INT_RXFF);

        spiTxRx1.txIndex+=burst_size;        

        // TX DMA does not use interrupt, so we must start channel manually 
        DMA_startChannel(SPI1_DMA_TX_base);


        //DMA SW trigger to initiate SPI transaction
        DMA_forceTrigger(SPI1_DMA_TX_base);                
         return true;
         #else
         return false;
         #endif
     }
     else if (2 == pSPIObj->SPI_Peripheral_No) {
         #if defined(USE_SPI2) && defined (USE_SPI2_DMA ) 
         if (spiTxRx2.busy ) return false;
         spiTxRx2.txBuf=txBuf;
         spiTxRx2.rxBuf=rxBuf;
         spiTxRx2.length=length;
         spiTxRx2.txIndex = 0;   //Track how many transmit
         spiTxRx2.rxIndex = 0;  //no usein DMA
         spiTxRx2.busy = true; 
         #ifndef SPI2_USE16BIT_WIDTH
             //8 bits bus
             uint16_t i;
             for (i=0;i<length;i++) {
                *(spiTxRx2.txBuf+i)=(*(spiTxRx2.txBuf+i))<<8;
             }
         #endif

         uint16_t burst_size; 
         uint16_t transfer_size;
         SPI_disableInterrupt(hspi[pSPIObj->SPI_Peripheral_No-1], SPI_INT_TXFF);
         SPI_disableInterrupt(hspi[pSPIObj->SPI_Peripheral_No-1], SPI_INT_RXFF); 
         SPI_clearInterruptStatus(hspi[pSPIObj->SPI_Peripheral_No-1], SPI_INT_RXFF);
         SPI_clearInterruptStatus(hspi[pSPIObj->SPI_Peripheral_No-1], SPI_INT_TXFF);
         //Reset the TX / RX FIFO buffers to default state
         SPI_disableFIFO(hspi[pSPIObj->SPI_Peripheral_No-1]); //Disable FIFO register
         SPI_enableFIFO(hspi[pSPIObj->SPI_Peripheral_No-1]);  //Enable FIFO register
         SPI_setTxFifoTransmitDelay(hspi[pSPIObj->SPI_Peripheral_No-1], 4);  //delay =1 to 4 for DMA with FIFO enabled, please increase or decrease adjust speed , unit is clock cycle
         if (length<16)  {
            SPI_setFIFOInterruptLevel(hspi[pSPIObj->SPI_Peripheral_No-1], SPI_FIFO_TXEMPTY, length);   
            burst_size=length;
         }
         else  {
            SPI_setFIFOInterruptLevel(hspi[pSPIObj->SPI_Peripheral_No-1], SPI_FIFO_TXEMPTY, 16);  
            burst_size=16;
         }
        transfer_size=length /16;
        if (0==transfer_size) transfer_size=1;
        SPI_enableInterrupt(hspi[pSPIObj->SPI_Peripheral_No-1], SPI_INT_RXFF);
          // Initialize DMA
        DMA_initController();
         //uint32_t dmaTX_IntNum = selectDMA_PIE_Interrupt(SPI2_DMA_TX_base);
         //Interrupt_register(dmaTX_IntNum, &SPI2_DMA_TX_ISR);
         uint16_t *psrcAddr  = spiTxRx2.txBuf;
         uint16_t *pdestAddr = (uint16_t *)(hspi[pSPIObj->SPI_Peripheral_No-1] + SPI_O_TXBUF);
         DMA_configAddresses(SPI2_DMA_TX_base, pdestAddr, psrcAddr);
        DMA_configBurst(SPI2_DMA_TX_base, burst_size, 1, 0);  //src burst step=1, dest burst step=0
        DMA_configTransfer(SPI2_DMA_TX_base, transfer_size, 1, 0); //src trsnsfer step = burst_size, dest transfer step=0  -> but in example , src trsnsfer step= 1
        DMA_configMode(SPI2_DMA_TX_base, DMA_TRIGGER_SOFTWARE, DMA_CFG_ONESHOT_DISABLE | DMA_CFG_CONTINUOUS_ENABLE |
                                                    DMA_CFG_SIZE_16BIT);


        DMA_setEmulationMode(DMA_EMULATION_FREE_RUN);

        // DMA  trigger enabel, so wait for trigger source coming
        DMA_enableTrigger(SPI2_DMA_TX_base);
        
        /********************************************************************************/
        // DMA RX Channel configuration
        /********************************************************************************/   
        uint32_t dmaRX_IntNum = selectDMA_PIE_Interrupt(SPI2_DMA_RX_base);
        Interrupt_register(dmaRX_IntNum, &SPI2_DMA_RX_ISR);

        psrcAddr  = (uint16_t *)(hspi[pSPIObj->SPI_Peripheral_No-1] + SPI_O_RXBUF);
        pdestAddr =  spiTxRx2.rxBuf;

        //Enable RXFIFO interrupt to ensure DMA RX channel is triggered
        SPI_enableInterrupt(hspi[pSPIObj->SPI_Peripheral_No-1], SPI_INT_RXFF);

        DMA_configAddresses(SPI2_DMA_RX_base, pdestAddr, psrcAddr);
        //DMA_configBurst(SPI2_DMA_RX_base, burst_size, 0, 1);  //src burst step=0, dest burst step=1
        DMA_configBurst(SPI2_DMA_RX_base, burst_size, 0, 1);  //src burst step=0, dest burst step=1
       // DMA_configTransfer(SPI2_DMA_RX_base, transfer_size, 0, 1); //src trsnsfer step = 0, dest transfer step= burst_size  -> but in example , dest trsnsfer step=1
       DMA_configTransfer(SPI2_DMA_RX_base, 1, 0, 1); //src trsnsfer step = 0, dest transfer step= burst_size  -> but in example , dest trsnsfer step=1
        //DMA_Trigger Rx_trigger;
        if (hspi[pSPIObj->SPI_Peripheral_No-1]==SPIA_BASE) {
            Rx_trigger=DMA_TRIGGER_SPIARX;
        }
        #ifdef SPIB_BASE
        else if (hspi[pSPIObj->SPI_Peripheral_No-1]==SPIB_BASE) {
            Rx_trigger=DMA_TRIGGER_SPIBRX;
        }
        #ifdef SPIC_BASE
        else if (hspi[pSPIObj->SPI_Peripheral_No-1]==SPIC_BASE) {
            Rx_trigger=DMA_TRIGGER_SPICRX;
        }   
        #ifdef SPID_BASE
        else if (hspi[pSPIObj->SPI_Peripheral_No-1]==SPID_BASE) {
            Rx_trigger=DMA_TRIGGER_SPIDRX;
        }        
        #endif     
        #endif
        #endif
        DMA_configMode(SPI2_DMA_RX_base, Rx_trigger, DMA_CFG_ONESHOT_DISABLE |
                    DMA_CFG_CONTINUOUS_ENABLE | DMA_CFG_SIZE_16BIT);

        //
        // Configure DMA RX interrupts
        //
        DMA_setInterruptMode(SPI2_DMA_RX_base, DMA_INT_AT_END);
        DMA_enableInterrupt(SPI2_DMA_RX_base);
        DMA_enableTrigger(SPI2_DMA_RX_base);  // DMA  trigger enabel, so wait for trigger source coming

        SPI_disableInterrupt(hspi[pSPIObj->SPI_Peripheral_No-1], SPI_INT_TXFF);   //let force trig Tx DMA inside Rx DMA ISR
        //SPI_enableInterrupt(hspi[pSPIObj->SPI_Peripheral_No-1], SPI_INT_RXFF);

        spiTxRx2.txIndex+=burst_size;        
        
        // TX DMA does not use interrupt, so we must start channel manually 
        DMA_startChannel(SPI2_DMA_TX_base);


        //DMA SW trigger to initiate SPI transaction
        DMA_forceTrigger(SPI2_DMA_TX_base);                
         return true;
         #else
         return false;
         #endif
     }
     else if (3 == pSPIObj->SPI_Peripheral_No) {
         #if defined(USE_SPI3) && defined (USE_SPI3_DMA ) 
         if (spiTxRx3.busy ) return false;
         spiTxRx3.txBuf=txBuf;
         spiTxRx3.rxBuf=rxBuf;
         spiTxRx3.length=length;
         spiTxRx3.txIndex = 0;   //Track how many transmit
         spiTxRx3.rxIndex = 0;  //no usein DMA
         spiTxRx3.busy = true; 
         #ifndef SPI3_USE16BIT_WIDTH
             //8 bits bus
             uint16_t i;
             for (i=0;i<length;i++) {
                *(spiTxRx3.txBuf+i)=(*(spiTxRx3.txBuf+i))<<8;
             }
         #endif

         uint16_t burst_size; 
         uint16_t transfer_size;
         SPI_disableInterrupt(hspi[pSPIObj->SPI_Peripheral_No-1], SPI_INT_TXFF);
         SPI_disableInterrupt(hspi[pSPIObj->SPI_Peripheral_No-1], SPI_INT_RXFF); 
         SPI_clearInterruptStatus(hspi[pSPIObj->SPI_Peripheral_No-1], SPI_INT_RXFF);
         SPI_clearInterruptStatus(hspi[pSPIObj->SPI_Peripheral_No-1], SPI_INT_TXFF);
         //Reset the TX / RX FIFO buffers to default state
         SPI_disableFIFO(hspi[pSPIObj->SPI_Peripheral_No-1]); //Disable FIFO register
         SPI_enableFIFO(hspi[pSPIObj->SPI_Peripheral_No-1]);  //Enable FIFO register
         SPI_setTxFifoTransmitDelay(hspi[pSPIObj->SPI_Peripheral_No-1], 4);  //delay =1 to 4 for DMA with FIFO enabled, please increase or decrease adjust speed , unit is clock cycle
         if (length<16)  {
            SPI_setFIFOInterruptLevel(hspi[pSPIObj->SPI_Peripheral_No-1], SPI_FIFO_TXEMPTY, length);   
            burst_size=length;
         }
         else  {
            SPI_setFIFOInterruptLevel(hspi[pSPIObj->SPI_Peripheral_No-1], SPI_FIFO_TXEMPTY, 16);  
            burst_size=16;
         }
        transfer_size=length /16;
        if (0==transfer_size) transfer_size=1;
        SPI_enableInterrupt(hspi[pSPIObj->SPI_Peripheral_No-1], SPI_INT_RXFF);
          // Initialize DMA
        DMA_initController();
         //uint32_t dmaTX_IntNum = selectDMA_PIE_Interrupt(SPI3_DMA_TX_base);
         //Interrupt_register(dmaTX_IntNum, &SPI3_DMA_TX_ISR);
         uint16_t *psrcAddr  = spiTxRx3.txBuf;
         uint16_t *pdestAddr = (uint16_t *)(hspi[pSPIObj->SPI_Peripheral_No-1] + SPI_O_TXBUF);
         DMA_configAddresses(SPI3_DMA_TX_base, pdestAddr, psrcAddr);
        DMA_configBurst(SPI3_DMA_TX_base, burst_size, 1, 0);  //src burst step=1, dest burst step=0
        DMA_configTransfer(SPI3_DMA_TX_base, transfer_size, 1, 0); //src trsnsfer step = burst_size, dest transfer step=0  -> but in example , src trsnsfer step= 1
        DMA_configMode(SPI3_DMA_TX_base, DMA_TRIGGER_SOFTWARE, DMA_CFG_ONESHOT_DISABLE | DMA_CFG_CONTINUOUS_ENABLE |
                                                    DMA_CFG_SIZE_16BIT);


        DMA_setEmulationMode(DMA_EMULATION_FREE_RUN);

        // DMA  trigger enabel, so wait for trigger source coming
        DMA_enableTrigger(SPI3_DMA_TX_base);
        
        /********************************************************************************/
        // DMA RX Channel configuration
        /********************************************************************************/   
        uint32_t dmaRX_IntNum = selectDMA_PIE_Interrupt(SPI3_DMA_RX_base);
        Interrupt_register(dmaRX_IntNum, &SPI3_DMA_RX_ISR);

        psrcAddr  = (uint16_t *)(hspi[pSPIObj->SPI_Peripheral_No-1] + SPI_O_RXBUF);
        pdestAddr =  spiTxRx3.rxBuf;

        //Enable RXFIFO interrupt to ensure DMA RX channel is triggered
        SPI_enableInterrupt(hspi[pSPIObj->SPI_Peripheral_No-1], SPI_INT_RXFF);

        DMA_configAddresses(SPI3_DMA_RX_base, pdestAddr, psrcAddr);
        //DMA_configBurst(SPI3_DMA_RX_base, burst_size, 0, 1);  //src burst step=0, dest burst step=1
        DMA_configBurst(SPI3_DMA_RX_base, burst_size, 0, 1);  //src burst step=0, dest burst step=1
       // DMA_configTransfer(SPI3_DMA_RX_base, transfer_size, 0, 1); //src trsnsfer step = 0, dest transfer step= burst_size  -> but in example , dest trsnsfer step=1
       DMA_configTransfer(SPI3_DMA_RX_base, 1, 0, 1); //src trsnsfer step = 0, dest transfer step= burst_size  -> but in example , dest trsnsfer step=1
        //DMA_Trigger Rx_trigger;
        if (hspi[pSPIObj->SPI_Peripheral_No-1]==SPIA_BASE) {
            Rx_trigger=DMA_TRIGGER_SPIARX;
        }
        #ifdef SPIB_BASE
        else if (hspi[pSPIObj->SPI_Peripheral_No-1]==SPIB_BASE) {
            Rx_trigger=DMA_TRIGGER_SPIBRX;
        }
        #ifdef SPIC_BASE
        else if (hspi[pSPIObj->SPI_Peripheral_No-1]==SPIC_BASE) {
            Rx_trigger=DMA_TRIGGER_SPICRX;
        }   
        #ifdef SPID_BASE
        else if (hspi[pSPIObj->SPI_Peripheral_No-1]==SPID_BASE) {
            Rx_trigger=DMA_TRIGGER_SPIDRX;
        }        
        #endif     
        #endif
        #endif
        DMA_configMode(SPI3_DMA_RX_base, Rx_trigger, DMA_CFG_ONESHOT_DISABLE |
                    DMA_CFG_CONTINUOUS_ENABLE | DMA_CFG_SIZE_16BIT);

        //
        // Configure DMA RX interrupts
        //
        DMA_setInterruptMode(SPI3_DMA_RX_base, DMA_INT_AT_END);
        DMA_enableInterrupt(SPI3_DMA_RX_base);
        DMA_enableTrigger(SPI3_DMA_RX_base);  // DMA  trigger enabel, so wait for trigger source coming

        SPI_disableInterrupt(hspi[pSPIObj->SPI_Peripheral_No-1], SPI_INT_TXFF);   //let force trig Tx DMA inside Rx DMA ISR
        //SPI_enableInterrupt(hspi[pSPIObj->SPI_Peripheral_No-1], SPI_INT_RXFF);

        spiTxRx3.txIndex+=burst_size;        
        
        // TX DMA does not use interrupt, so we must start channel manually 
        DMA_startChannel(SPI3_DMA_TX_base);


        //DMA SW trigger to initiate SPI transaction
        DMA_forceTrigger(SPI3_DMA_TX_base);                
         return true;
         #else
         return false;
         #endif
     }
     else if (4 == pSPIObj->SPI_Peripheral_No) {
         #if defined(USE_SPI4) && defined (USE_SPI4_DMA ) 
         if (spiTxRx4.busy ) return false;
         spiTxRx4.txBuf=txBuf;
         spiTxRx4.rxBuf=rxBuf;
         spiTxRx4.length=length;
         spiTxRx4.txIndex = 0;   //Track how many transmit
         spiTxRx4.rxIndex = 0;  //no usein DMA
         spiTxRx4.busy = true; 
         #ifndef SPI4_USE16BIT_WIDTH
             //8 bits bus
             uint16_t i;
             for (i=0;i<length;i++) {
                *(spiTxRx4.txBuf+i)=(*(spiTxRx4.txBuf+i))<<8;
             }
         #endif

         uint16_t burst_size; 
         uint16_t transfer_size;
         SPI_disableInterrupt(hspi[pSPIObj->SPI_Peripheral_No-1], SPI_INT_TXFF);
         SPI_disableInterrupt(hspi[pSPIObj->SPI_Peripheral_No-1], SPI_INT_RXFF); 
         SPI_clearInterruptStatus(hspi[pSPIObj->SPI_Peripheral_No-1], SPI_INT_RXFF);
         SPI_clearInterruptStatus(hspi[pSPIObj->SPI_Peripheral_No-1], SPI_INT_TXFF);
         //Reset the TX / RX FIFO buffers to default state
         SPI_disableFIFO(hspi[pSPIObj->SPI_Peripheral_No-1]); //Disable FIFO register
         SPI_enableFIFO(hspi[pSPIObj->SPI_Peripheral_No-1]);  //Enable FIFO register
         SPI_setTxFifoTransmitDelay(hspi[pSPIObj->SPI_Peripheral_No-1], 4);  //delay =1 to 4 for DMA with FIFO enabled, please increase or decrease adjust speed , unit is clock cycle
         if (length<16)  {
            SPI_setFIFOInterruptLevel(hspi[pSPIObj->SPI_Peripheral_No-1], SPI_FIFO_TXEMPTY, length);   
            burst_size=length;
         }
         else  {
            SPI_setFIFOInterruptLevel(hspi[pSPIObj->SPI_Peripheral_No-1], SPI_FIFO_TXEMPTY, 16);  
            burst_size=16;
         }
        transfer_size=length /16;
        if (0==transfer_size) transfer_size=1;
        SPI_enableInterrupt(hspi[pSPIObj->SPI_Peripheral_No-1], SPI_INT_RXFF);
          // Initialize DMA
        DMA_initController();
         //uint32_t dmaTX_IntNum = selectDMA_PIE_Interrupt(SPI4_DMA_TX_base);
         //Interrupt_register(dmaTX_IntNum, &SPI4_DMA_TX_ISR);
         uint16_t *psrcAddr  = spiTxRx4.txBuf;
         uint16_t *pdestAddr = (uint16_t *)(hspi[pSPIObj->SPI_Peripheral_No-1] + SPI_O_TXBUF);
         DMA_configAddresses(SPI4_DMA_TX_base, pdestAddr, psrcAddr);
        DMA_configBurst(SPI4_DMA_TX_base, burst_size, 1, 0);  //src burst step=1, dest burst step=0
        DMA_configTransfer(SPI4_DMA_TX_base, transfer_size, 1, 0); //src trsnsfer step = burst_size, dest transfer step=0  -> but in example , src trsnsfer step= 1
        DMA_configMode(SPI4_DMA_TX_base, DMA_TRIGGER_SOFTWARE, DMA_CFG_ONESHOT_DISABLE | DMA_CFG_CONTINUOUS_ENABLE |
                                                    DMA_CFG_SIZE_16BIT);


        DMA_setEmulationMode(DMA_EMULATION_FREE_RUN);

        // DMA  trigger enabel, so wait for trigger source coming
        DMA_enableTrigger(SPI4_DMA_TX_base);
        
        /********************************************************************************/
        // DMA RX Channel configuration
        /********************************************************************************/   
        uint32_t dmaRX_IntNum = selectDMA_PIE_Interrupt(SPI4_DMA_RX_base);
        Interrupt_register(dmaRX_IntNum, &SPI4_DMA_RX_ISR);

        psrcAddr  = (uint16_t *)(hspi[pSPIObj->SPI_Peripheral_No-1] + SPI_O_RXBUF);
        pdestAddr =  spiTxRx4.rxBuf;

        //Enable RXFIFO interrupt to ensure DMA RX channel is triggered
        SPI_enableInterrupt(hspi[pSPIObj->SPI_Peripheral_No-1], SPI_INT_RXFF);

        DMA_configAddresses(SPI4_DMA_RX_base, pdestAddr, psrcAddr);
        //DMA_configBurst(SPI4_DMA_RX_base, burst_size, 0, 1);  //src burst step=0, dest burst step=1
        DMA_configBurst(SPI4_DMA_RX_base, burst_size, 0, 1);  //src burst step=0, dest burst step=1
       // DMA_configTransfer(SPI4_DMA_RX_base, transfer_size, 0, 1); //src trsnsfer step = 0, dest transfer step= burst_size  -> but in example , dest trsnsfer step=1
       DMA_configTransfer(SPI4_DMA_RX_base, 1, 0, 1); //src trsnsfer step = 0, dest transfer step= burst_size  -> but in example , dest trsnsfer step=1
        //DMA_Trigger Rx_trigger;
        if (hspi[pSPIObj->SPI_Peripheral_No-1]==SPIA_BASE) {
            Rx_trigger=DMA_TRIGGER_SPIARX;
        }
        #ifdef SPIB_BASE
        else if (hspi[pSPIObj->SPI_Peripheral_No-1]==SPIB_BASE) {
            Rx_trigger=DMA_TRIGGER_SPIBRX;
        }
        #ifdef SPIC_BASE
        else if (hspi[pSPIObj->SPI_Peripheral_No-1]==SPIC_BASE) {
            Rx_trigger=DMA_TRIGGER_SPICRX;
        }   
        #ifdef SPID_BASE
        else if (hspi[pSPIObj->SPI_Peripheral_No-1]==SPID_BASE) {
            Rx_trigger=DMA_TRIGGER_SPIDRX;
        }        
        #endif     
        #endif
        #endif
        DMA_configMode(SPI4_DMA_RX_base, Rx_trigger, DMA_CFG_ONESHOT_DISABLE |
                    DMA_CFG_CONTINUOUS_ENABLE | DMA_CFG_SIZE_16BIT);

        //
        // Configure DMA RX interrupts
        //
        DMA_setInterruptMode(SPI4_DMA_RX_base, DMA_INT_AT_END);
        DMA_enableInterrupt(SPI4_DMA_RX_base);
        DMA_enableTrigger(SPI4_DMA_RX_base);  // DMA  trigger enabel, so wait for trigger source coming

        SPI_disableInterrupt(hspi[pSPIObj->SPI_Peripheral_No-1], SPI_INT_TXFF);   //let force trig Tx DMA inside Rx DMA ISR
        //SPI_enableInterrupt(hspi[pSPIObj->SPI_Peripheral_No-1], SPI_INT_RXFF);

        spiTxRx4.txIndex+=burst_size;        
        
        // TX DMA does not use interrupt, so we must start channel manually 
        DMA_startChannel(SPI4_DMA_TX_base);


        //DMA SW trigger to initiate SPI transaction
        DMA_forceTrigger(SPI4_DMA_TX_base);                
         return true;
         #else
         return false;
         #endif
     }
}





