#include "bsp_spi.h"

/********************************************************************************/\

#define SPI_RX_TIMEOUT    2000
#define SPI_TX_DMA_TIMEOUT    2000
volatile uint32_t ReceiveTimeOut = SPI_RX_TIMEOUT;
volatile uint32_t TX_DMA_TimeOut = SPI_TX_DMA_TIMEOUT;

uint32_t SPI_Master_Transmit(SPI_TypeDef* SPIx, uint8_t *Buf, uint32_t Size, uint32_t Timeout)
{
    uint32_t i;
    uint32_t tx_cnt = 0;
    __IO uint32_t uiTimeout;
    
    assert_param(READ_BIT(SPIx->CTL, SPI_CTL_MST_MODE));

    /* Check SPI Parameter */
    if(!Size)    return SPI_ERROR;
    if (Buf == NULL)    return SPI_ERROR;
    
    uiTimeout = Timeout;

    /* Clear Batch Done Flag  */
    SPI_ClearFlag(SPIx, SPI_STATUS_BATCH_DONE);
    
    /* Clear TX FIFO */
    SPI_ClearTxFifo(SPIx);
    
    /* Set Data Size */
    SPI_WriteBatch(SPIx, Size);
    
    /* Tx Enable */
    SPI_TxCmd(SPIx, ENABLE);

    /* Transmit Start */
    SPI_SSOutputCmd(SPIx, ENABLE);
   
    while(Size > 0)
    {
        /* Wait Tx FIFO Not Full */
        while(SPI_GetFlagStatus(SPIx, SPI_STATUS_TX_FIFO_FULL) == SET)
        {
            if(uiTimeout)
            {
                uiTimeout--;
                if (uiTimeout == 0)
                {
                    goto End;
                }
            }
        }        
        SPI_SendData(SPIx, Buf[tx_cnt++]);
        Size--;
        uiTimeout = Timeout;
    }    
    
    /* Wait Transmit Done */
    while (SPI_GetFlagStatus(SPIx, SPI_STATUS_TX_BATCH_DONE) == RESET);    
    
End:
    /* Clear Batch Done Flag  */
    SPI_ClearFlag(SPIx, SPI_STATUS_BATCH_DONE);

    /* Tx Disable */
    SPI_TxCmd(SPIx, DISABLE); 
    
    /* Transmit End */
    SPI_SSOutputCmd(SPIx, DISABLE);
    
    return tx_cnt;
}

uint32_t SPI_Slave_Transmit(SPI_TypeDef* SPIx, uint8_t *Buf, uint32_t Size, uint32_t Timeout)
{
    uint32_t i;
    uint32_t tx_cnt = 0;
    __IO uint32_t uiTimeout;
    
    assert_param(!READ_BIT(SPIx->CTL, SPI_CTL_MST_MODE));

    /* Check SPI Parameter */
    if(!Size)    return (uint32_t)(-1);
    if (Buf == NULL)    return (uint32_t)(-2) ;
        
    uiTimeout = Timeout;

    /* Clear Batch Done Flag  */
    SPI_ClearFlag(SPIx, SPI_STATUS_BATCH_DONE);
    
    /* Clear TX FIFO */
    SPI_ClearTxFifo(SPIx);
    
    /* Set Data Size */
    SPI_WriteBatch(SPIx, Size);
    
    /* Tx Enable */
    SPI_TxCmd(SPIx, ENABLE);

    /* Rx Disable */
    SPI_RxCmd(SPIx, DISABLE);
    
    while(Size > 0)
    {
        /* Wait Tx FIFO Not Full */
        while(SPI_GetFlagStatus(SPIx, SPI_STATUS_TX_FIFO_FULL) == SET)
        {
            if(uiTimeout)
            {
                uiTimeout--;
                if (uiTimeout == 0)
                {
                    goto End;
                }
            }
        }        
        SPI_SendData(SPIx, Buf[tx_cnt++]);
        Size--;
        uiTimeout = Timeout;
    }
    
    /* Wait Transmit Done */
    while(SPI_GetFlagStatus(SPIx, SPI_STATUS_TX_BUSY) == RESET);
    while(SPI_GetFlagStatus(SPIx, SPI_STATUS_TX_BUSY) == SET)
    {
        if(uiTimeout)
        {
            uiTimeout--;
            if (uiTimeout == 0)
            {
                goto End;
            }
        }
    }
    
End:
    /* Clear Batch Done Flag  */
    SPI_ClearFlag(SPIx, SPI_STATUS_BATCH_DONE);

    /* Tx Disable */
    SPI_TxCmd(SPIx, DISABLE);

    return tx_cnt;
}

uint32_t SPI_Master_Receive(SPI_TypeDef* SPIx, uint8_t *Buf, uint32_t Size, uint32_t Timeout)
{
    uint32_t i;
    uint32_t cnt = 0;
    __IO uint32_t uiTimeout;
    
    assert_param(READ_BIT(SPIx->CTL, SPI_CTL_MST_MODE));
        
    /* Check SPI Parameter */
    if (Buf == NULL)    return 0xFFFFFFFF;
    
    uiTimeout = Timeout;
    
    /* Clear Batch Done Flag  */
    SPI_ClearFlag(SPIx, SPI_STATUS_BATCH_DONE);
    
    /* Set Data Size */
    SPI_WriteBatch(SPIx, Size);
    
    /* Rx Enable */
    SPI_RxCmd(SPIx, ENABLE);
    
    /* Receive Start */
    SPI_SSOutputCmd(SPIx, ENABLE);
    
    while(Size > 0)
    //while(SPI_GetFlagStatus(SPIx, SPI_STATUS_RX_BATCH_DONE) == RESET)
    {
        /* have no timeout */
        if (uiTimeout == 0) 
        {
            /* Wait Rx FIFO Not Empty */
            while(SPI_GetFlagStatus(SPIx, SPI_STATUS_RX_FIFO_EMPTY) == SET);
        }
        else
        {
            while(SPI_GetFlagStatus(SPIx, SPI_STATUS_RX_FIFO_EMPTY) == SET)
            {
                if (uiTimeout-- == 0) 
                {
                    goto End; 
                }
            }
        }
        
        Buf[cnt++] = SPI_ReceiveData(SPIx);
        Size--;
    }

    /* Wait Transmit Done */
    while(SPI_GetFlagStatus(SPIx, SPI_STATUS_RX_BATCH_DONE) == RESET);

End:   
    /* Clear Batch Done Flag  */
    SPI_ClearFlag(SPIx, SPI_STATUS_BATCH_DONE);

    /* Rx Disable */
    SPI_RxCmd(SPIx, DISABLE);

    /* Receive End */
    SPI_SSOutputCmd(SPIx, DISABLE);
    
    return cnt;
}


uint32_t SPI_Slave_Receive(SPI_TypeDef* SPIx, uint8_t *Buf, uint32_t Size, uint32_t Timeout)
{
    uint32_t i;
    __IO uint32_t uiTimeout;
    uint32_t cnt = 0;
    
    assert_param(!READ_BIT(SPIx->CTL, SPI_CTL_MST_MODE));
    
    /* Check SPI Parameter */
    if (Buf == NULL)    return 0xFFFFFFFF;
    
    uiTimeout = Timeout;
    
    SPI_WriteBatch(SPIx, 1);
    /* Rx Enable */
    SPI_RxCmd(SPIx, ENABLE);
    
    while (Size > 0) 
    { 
        while(SPI_GetFlagStatus(SPIx, SPI_STATUS_RX_FIFO_EMPTY) == SET)
        {
            if(uiTimeout)
            {
                uiTimeout--;
                if (uiTimeout == 0) 
                {
                    /* Rx Disable */
                    SPI_RxCmd(SPIx, DISABLE);
                    return cnt;
                }
            }
        }           
        
        Buf[cnt++] = SPI_ReceiveData(SPIx);
        Size--;
        uiTimeout = Timeout;
    }

    /* Rx Disable */
    SPI_RxCmd(SPIx, DISABLE);
    return cnt;

}

SPI_StatusTypeDef SPI_Master_Transmit_IT(SPI_TypeDef* SPIx, SPI_Handler_t* hspi, uint8_t *pData, uint32_t Size)
{    
    assert_param(READ_BIT(SPIx->CTL, SPI_CTL_MST_MODE));
    
    /* Tx machine is running */
    if (hspi->TxState != SPI_TX_STATE_IDLE) 
    {
        return SPI_ERROR;
    }
    
    hspi->Tx_Size   = Size;
    hspi->Tx_Buffer = pData; 
    hspi->Tx_Count = 0;   

    /* Set machine is Sending */
    hspi->TxState = SPI_TX_STATE_SENDING;
    
    /* Clear Tx FIFO */
    SPI_ClearTxFifo(SPIx);
    
    /* Clear Batch Done Flag  */
    SPI_ClearFlag(SPIx, SPI_STATUS_BATCH_DONE);
    
    /* Set Data Size */
    SPI_WriteBatch(SPIx, Size);

    /* Tx Enable */
    SPI_TxCmd(SPIx, ENABLE);

    /* Transmit Start */
    SPI_SSOutputCmd(SPIx, ENABLE);
    
    while (hspi->Tx_Count < hspi->Tx_Size)   
    {
        if (SPI_GetFlagStatus(SPIx, SPI_STATUS_TX_FIFO_FULL) == RESET)
            SPI_SendData(SPIx, hspi->Tx_Buffer[hspi->Tx_Count++]);
        else
            break;           
    }

    /* Enable Tx FIFO half empty Interrupt and Tx batch done Interrupt*/
    SPI_ITConfig(SPIx, (SPI_IE_TX_FIFO_HALF_EMPTY_EN | SPI_IE_TX_BATCH_DONE_EN), ENABLE);
    
    return SPI_OK;
}


SPI_StatusTypeDef SPI_Slave_Transmit_IT(SPI_TypeDef* SPIx, SPI_Handler_t* hspi, uint8_t *pData, uint32_t Size)
{    
    assert_param( !READ_BIT(SPIx->CTL, SPI_CTL_MST_MODE) );
    /* Tx machine is running */
    if (hspi->TxState != SPI_TX_STATE_IDLE) 
    {
        return SPI_ERROR;
    }
    
    hspi->Tx_Size   = Size;
    hspi->Tx_Buffer = pData; 
    hspi->Tx_Count = 0;   

    /* Set machine is Sending */
    hspi->TxState = SPI_TX_STATE_SENDING;
    
    /* Clear Tx FIFO */
    SPI_ClearTxFifo(SPIx);
    
    /* Clear Batch Done Flag  */
    SPI_ClearFlag(SPIx, SPI_STATUS_BATCH_DONE);
    
    /* Set Data Size */
    SPI_WriteBatch(SPIx, Size);

    /* Tx Enable */
    SPI_TxCmd(SPIx, ENABLE);

    /* Rx Disable */
    SPI_RxCmd(SPIx, DISABLE);
    
    while (hspi->Tx_Count < hspi->Tx_Size)   
    {
        if (SPI_GetFlagStatus(SPIx, SPI_STATUS_TX_FIFO_FULL) == RESET)
            SPI_SendData(SPIx, hspi->Tx_Buffer[hspi->Tx_Count++]);
        else
            break;           
    }

    /* Enable Tx FIFO half empty Interrupt and Tx batch done Interrupt*/
    SPI_ITConfig(SPIx, (SPI_IE_TX_FIFO_HALF_EMPTY_EN | SPI_IE_TX_BATCH_DONE_EN), ENABLE);
    
    return SPI_OK;
}

SPI_StatusTypeDef SPI_Master_Receive_IT(SPI_TypeDef* SPIx, SPI_Handler_t* hspi, uint8_t *pData, uint32_t Size)
{    
    assert_param(READ_BIT(SPIx->CTL, SPI_CTL_MST_MODE));
    
    /* Rx machine is running */
    if (hspi->RxState != SPI_RX_STATE_IDLE) 
    {
        return SPI_ERROR;
    }
    
    /* Set Slave machine is receiving */
    hspi->RxState = SPI_RX_STATE_RECEIVING;

    /* Clear Batch Done Flag  */
    SPI_ClearFlag(SPIx, SPI_STATUS_BATCH_DONE);
    
    /* Set Data Size */
    SPI_WriteBatch(SPIx, Size);
    
    /* Rx Enable */
    SPI_RxCmd(SPIx, ENABLE);
    
    /* Receive Start */
    SPI_SSOutputCmd(SPIx, ENABLE);
    
    hspi->Rx_Size   = Size;
    hspi->Rx_Buffer = pData; 
    hspi->Rx_Count = 0;   
    ReceiveTimeOut = SPI_RX_TIMEOUT;   

    /* Enable Rx FIFO Not Empty Interrupt */
    SPI_ITConfig(SPIx, SPI_IE_RX_FIFO_NOT_EMPTY_EN, ENABLE);
    
    return SPI_OK;
}

SPI_StatusTypeDef SPI_Slave_Receive_IT(SPI_TypeDef* SPIx, SPI_Handler_t* hspi, uint8_t *pData, uint32_t Size)
{    
    assert_param(!READ_BIT(SPIx->CTL, SPI_CTL_MST_MODE));
    /* Rx machine is running */
    if (hspi->RxState != SPI_RX_STATE_IDLE) 
    {
        return SPI_ERROR;
    }
    
    /* Set Slave machine is receiving */
    hspi->RxState = SPI_RX_STATE_RECEIVING;

    /* Reset BATCH register */
    SPI_WriteBatch(SPIx, 1);
    SPI_RxCmd(SPIx, ENABLE);   

    
    hspi->Rx_Size   = Size;
    hspi->Rx_Buffer = pData; 
    hspi->Rx_Count = 0;   
    ReceiveTimeOut = SPI_RX_TIMEOUT;   

    /* Enable Rx FIFO Not Empty Interrupt */
    SPI_ITConfig(SPIx, SPI_IE_RX_FIFO_NOT_EMPTY_EN, ENABLE);
    
    return SPI_OK;
}

SPI_StatusTypeDef SPI_Master_TransmitReceive(SPI_TypeDef* SPIx, uint8_t *pTxData, uint8_t *pRxData, uint32_t Size, uint32_t Timeout)
{
    uint32_t i;
    uint32_t Tx_Count;
    uint32_t Rx_Count;
    uint32_t Tx_Size;
    uint32_t Rx_Size;
    __IO uint32_t TxFlag = 1U, uiTimeout;
    SPI_StatusTypeDef Status = SPI_OK;
    
    assert_param(READ_BIT(SPIx->CTL, SPI_CTL_MST_MODE));

    /* Check SPI Parameter */
    if ((pTxData == NULL)||(pRxData == NULL))    return SPI_ERROR;
    
    Tx_Count = 0;
    Rx_Count = 0;
    //Tx_Buffer = pTxData;
    //Rx_Buffer = pRxData;
    Tx_Size = Size;   
    Rx_Size = Size;   
    uiTimeout = Timeout;
    
    /* Clear Batch Done Flag  */
    SPI_ClearFlag(SPIx, SPI_STATUS_BATCH_DONE);

    /* Tx Enable */
    SPI_TxCmd(SPIx, ENABLE);

    /* Rx Enable */
    SPI_RxCmd(SPIx, ENABLE);

    /* Clear TX FIFO */
    SPI_ClearTxFifo(SPIx);        

    /* Set Data Size */
    SPI_WriteBatch(SPIx, Tx_Size);

    /* Transmit Start */
    SPI_SSOutputCmd(SPIx, ENABLE);
    TxFlag = 1;
    
    while((Tx_Size > 0) || (Rx_Size > 0))
    {     
        /* Wait Tx FIFO Not Full */
        if((SPI_GetFlagStatus(SPIx, SPI_STATUS_TX_FIFO_FULL) == RESET) && (Tx_Size > 0) && (TxFlag == 1U))
        {
            SPI_SendData(SPIx, pTxData[Tx_Count++]);
            Tx_Size--;
            TxFlag = 0;
        }
        
        /* Wait Rx FIFO Not Empty */
        if((SPI_GetFlagStatus(SPIx, SPI_STATUS_RX_FIFO_EMPTY) == RESET) && (Rx_Size>0))
        {
            pRxData[Rx_Count++] = SPI_ReceiveData(SPIx);
            Rx_Size--;
            TxFlag = 1U;
        }
        
        /* Wait Timeout */
        if(uiTimeout)
        {
            uiTimeout--;
            if(uiTimeout == 0)
            {
                Status = SPI_TIMEOUT;
                goto End;
            }
        }
    }        
    /* Wait Transmit Done */
    while(SPI_GetFlagStatus(SPIx, SPI_STATUS_TX_BATCH_DONE) == RESET);
    
    Status = SPI_OK;

End:    
    /* Clear Batch Done Flag  */
    SPI_ClearFlag(SPIx, SPI_STATUS_BATCH_DONE);

    /* Tx Disable */
    SPI_TxCmd(SPIx, DISABLE);
    
    /* Rx Disable */
    SPI_RxCmd(SPIx, DISABLE);
    
    /* Transmit End */
    SPI_SSOutputCmd(SPIx, DISABLE);

    return Status;
}

SPI_StatusTypeDef SPI_Slave_TransmitReceive(SPI_TypeDef* SPIx, uint8_t *pTxData, uint8_t *pRxData, uint32_t Size, uint32_t Timeout)
{
    uint32_t i;
    uint32_t Tx_Count;
    uint32_t Rx_Count;
    uint32_t Tx_Size;
    uint32_t Rx_Size;
    __IO uint32_t TxFlag = 1U, uiTimeout;
    SPI_StatusTypeDef Status = SPI_OK;
    
    assert_param( !READ_BIT(SPIx->CTL, SPI_CTL_MST_MODE));

    /* Check SPI Parameter */
    if ((pTxData == NULL)||(pRxData == NULL))    return SPI_ERROR;
    
    Tx_Count = 0;
    Rx_Count = 0;
    //Tx_Buffer = pTxData;
    //Rx_Buffer = pRxData;
    Tx_Size = Size;   
    Rx_Size = Size;   
    uiTimeout = Timeout;
    
    /* Clear Batch Done Flag  */
    SPI_ClearFlag(SPIx, SPI_STATUS_BATCH_DONE);

    /* Tx Enable */
    SPI_TxCmd(SPIx, ENABLE);

    /* Rx Enable */
    SPI_RxCmd(SPIx, ENABLE);

    /* Clear TX FIFO */
    SPI_ClearTxFifo(SPIx);
             
    while((SPI_GetFlagStatus(SPIx, SPI_STATUS_TX_FIFO_FULL) == RESET) && (Tx_Size > 0))
    {
        SPI_SendData(SPIx, pTxData[Tx_Count++]);
        Tx_Size--;
    }
    TxFlag = 0;
    
    while((Tx_Size > 0) || (Rx_Size > 0))
    {
        /* Wait Rx FIFO Not Empty */
        if((SPI_GetFlagStatus(SPIx, SPI_STATUS_RX_FIFO_EMPTY) == RESET) && (Rx_Size > 0))
        {
            pRxData[Rx_Count++] = SPI_ReceiveData(SPIx);
            Rx_Size--;
            TxFlag = 1U;
        }        
        /* Wait Tx FIFO Not Full */
        if((SPI_GetFlagStatus(SPIx, SPI_STATUS_TX_FIFO_FULL) == RESET) && (Tx_Size > 0) && (TxFlag == 1U))
        {
            while((SPI_GetFlagStatus(SPIx, SPI_STATUS_TX_FIFO_FULL) == RESET) && (Tx_Size > 0))
            {
                SPI_SendData(SPIx, pTxData[Tx_Count++]);
                Tx_Size--;
            }
            TxFlag = 0;
        }
        
        /* Wait Timeout */
        if(uiTimeout)
        {
            uiTimeout--;
            if(uiTimeout == 0)
            {
                Status = SPI_TIMEOUT;
                goto End;
            }
        }
    }        
    /* Wait Transmit Done */
    while(SPI_GetFlagStatus(SPIx, SPI_STATUS_TX_BATCH_DONE) == RESET);
    
    Status = SPI_OK;

End:    
    /* Clear Batch Done Flag  */
    SPI_ClearFlag(SPIx, SPI_STATUS_BATCH_DONE);

    /* Tx Disable */
    SPI_TxCmd(SPIx, DISABLE);
    
    /* Rx Disable */
    SPI_RxCmd(SPIx, DISABLE);

    return Status;
}

/************************************************************************
 * function   : SPI_IRQProcess
 * Description: SPI IRQ process function.
 ************************************************************************/
void SPI_IRQHandler(SPI_TypeDef* SPIx, SPI_Handler_t* hspi)
{
    uint8_t TempValue = 0;
    
    uint32_t Length = 0;
    
    uint32_t role = READ_BIT(SPIx->CTL, SPI_CTL_MST_MODE) ? SPI_MODE_MASTER : SPI_MODE_SLAVE;
    /* 
      NOTE : This function should be modified by the user.
    */    
    if ((SPI_GetFlagStatus(SPIx, SPI_STATUS_RX_FIFO_NOT_EMPTY) == SET) && (SPI_ITGet(SPIx, SPI_IE_RX_FIFO_NOT_EMPTY_EN) == SET))
    {
        /* In master mode */
        if (role == SPI_MODE_MASTER) 
        {
            while (SPI_GetFlagStatus(SPIx, SPI_STATUS_RX_FIFO_NOT_EMPTY) == SET)
            {
                hspi->Rx_Buffer[hspi->Rx_Count++] = SPI_ReceiveData(SPIx);
                
                if (hspi->Rx_Count >= hspi->Rx_Size) 
                {
                    /* Wait Transmit Done */
                    while (SPI_GetFlagStatus(SPIx, SPI_STATUS_RX_BATCH_DONE) == RESET);
                    
                    
                    /* Clear Batch Done Flag  */
                    SPI_ClearFlag(SPIx, SPI_STATUS_BATCH_DONE);

                    /* Rx Disable */
                    SPI_RxCmd(SPIx, DISABLE);

                    /* Receive End */
                    SPI_SSOutputCmd(SPIx, DISABLE);


                    /* Disable Rx Not Empty Interrupt */
                    SPI_ITConfig(SPIx, SPI_IE_RX_FIFO_NOT_EMPTY_EN, DISABLE);

                    //NVIC_ClearPendingIRQ(SPI_BSP_IRQ);
                    
                    /* Clear Batch Done Flag  */
                    SPI_ClearFlag(SPIx, SPI_STATUS_BATCH_DONE);
                    
                    /* Set machine is DILE */
                    hspi->RxState = SPI_RX_STATE_IDLE;
                }
            }
        }
        /* In Slave mode */
        else 
        {
            while ((hspi->Rx_Count < hspi->Rx_Size) && (ReceiveTimeOut > 0) )   
            {
                if (SPI_GetFlagStatus(SPIx, SPI_STATUS_RX_FIFO_NOT_EMPTY) == SET)
                {
                    hspi->Rx_Buffer[hspi->Rx_Count++] = SPI_ReceiveData(SPIx);
                    ReceiveTimeOut = SPI_RX_TIMEOUT;       //If recieve data, Reset the timeout value  
                }
                else
                {
                    ReceiveTimeOut--;   
                }
                
            }

            /* Rx Disable */
            SPI_RxCmd(SPIx, DISABLE);
            
            /* Disable Rx Not Empty Interrupt */
            SPI_ITConfig(SPIx, SPI_IE_RX_FIFO_NOT_EMPTY_EN, DISABLE);

            //NVIC_ClearPendingIRQ(SPI_BSP_IRQ);
            
            /* Clear Batch Done Flag  */
            SPI_ClearFlag(SPIx, SPI_STATUS_BATCH_DONE);
            
            /* Set machine is DILE */
            hspi->RxState = SPI_RX_STATE_IDLE;
        }
    }
    
    if ((SPI_GetFlagStatus(SPIx, SPI_STATUS_TX_FIFO_HALF_EMPTY) == SET) && (SPI_ITGet(SPIx, SPI_IE_TX_FIFO_HALF_EMPTY_EN) == SET))
    {
        while (hspi->Tx_Count < hspi->Tx_Size)   
        {
            if (SPI_GetFlagStatus(SPIx, SPI_STATUS_TX_FIFO_FULL) == RESET)
            {
                SPI_SendData(SPIx, hspi->Tx_Buffer[hspi->Tx_Count++]);
            }
            else
            {
                break;   
            }
            
        }
        /* Clear Tx FIFO half empty Flag  */
        if(hspi->Tx_Count == hspi->Tx_Size)
        {
            /* Disable Tx FIFO half empty Interrupt  */
            SPI_ITConfig(SPIx, SPI_IE_TX_FIFO_HALF_EMPTY_EN, DISABLE);
        }                
    }
    if ((SPI_GetFlagStatus(SPIx, SPI_STATUS_TX_BATCH_DONE) == SET) && (SPI_ITGet(SPIx, SPI_IE_TX_BATCH_DONE_EN) == SET))
    {
        /* Clear Batch Done Flag  */
        SPI_ClearFlag(SPIx, SPI_STATUS_BATCH_DONE);

        /* Disable TX Batch Done Interrupt */
        SPI_ITConfig(SPIx, SPI_STATUS_TX_BATCH_DONE, DISABLE);
        /* Disable Tx FIFO half empty Interrupt  */
        SPI_ITConfig(SPIx, SPI_IE_TX_FIFO_HALF_EMPTY_EN, DISABLE);

        //NVIC_ClearPendingIRQ(SPI_BSP_IRQ);

        TX_DMA_TimeOut = SPI_TX_DMA_TIMEOUT;   
        while((SPI_GetFlagStatus(SPIx, SPI_STATUS_TX_BUSY) == SET))
        {
             TX_DMA_TimeOut--;
             if(0 == TX_DMA_TimeOut) 
             {
                 break;  
             }
        }

        /* Tx Disable */
        SPI_TxCmd(SPIx, DISABLE);  
        SPI_DMACmd(SPIx, SPI_DMAReq_TX, DISABLE); 
        
        if (role == SPI_MODE_MASTER) 
        {
            /* Transmit End */
            SPI_SSOutputCmd(SPIx, DISABLE);
        }

        hspi->TxState = SPI_TX_STATE_IDLE;
    }

    if ((SPI_GetFlagStatus(SPIx, SPI_STATUS_RX_BATCH_DONE) == SET) && (SPI_ITGet(SPIx, SPI_IE_RX_BATCH_DONE_EN) == SET))
    {
        /* Clear Batch Done Flag  */
        SPI_ClearFlag(SPIx, SPI_STATUS_BATCH_DONE);

        /* Disable RX Batch Done Interrupt */
        SPI_ITConfig(SPIx, SPI_IE_RX_BATCH_DONE_EN, DISABLE);

        //NVIC_ClearPendingIRQ(SPI_BSP_IRQ);

        /* Rx Disable */
        SPI_DMACmd(SPIx, SPI_DMAReq_RX, DISABLE); 
        SPI_RxCmd(SPIx, DISABLE);

        if (role == SPI_MODE_MASTER) 
        {
            /* Receive End */
            SPI_SSOutputCmd(SPIx, DISABLE);
        }

        hspi->RxState = SPI_RX_STATE_IDLE;
    }
}

