/******************************************************************************
 * @file     ssp.c
 * @brief    SSP firmware functions.
 * @version  V4.0.0
 * @date     30-July-2026
 *
 * @note
 * Copyright (C) 2022 Spintrol Electronic Technology (Shanghai) Co., Ltd.. All rights reserved.
 *
 * @attention
 * THIS SOFTWARE JUST PROVIDES CUSTOMERS WITH CODING INFORMATION REGARDING
 * THEIR PRODUCTS, WHICH AIMS AT SAVING TIME FOR THEM. SPINTROL SHALL NOT BE
 * LIABLE FOR THE USE OF THE SOFTWARE. SPINTROL DOES NOT GUARANTEE THE
 * CORRECTNESS OF THIS SOFTWARE AND RESERVES THE RIGHT TO MODIFY THE SOFTWARE
 * WITHOUT NOTIFICATION.
 *
 ******************************************************************************/

#include "ssp.h"


#if defined(__CC_ARM)
    #pragma push
    #pragma O1
#endif




/******************************************************************************
 * @brief      Initializes the SSP
 *
 * @param[in]  SSPx            :  Select the SSP port
 * @param[in]  u8MasterOrSlave :  Define SSP in master or slave mode
 *                                 - \ref SSP_MASTER_MODE
 *                                 - \ref SSP_SLAVE_MODE
 * @param[in]  u8DataSize      :  Define SSP data size in one frame
 * @param[in]  u32Baudrate     :  Define SSP baudrate
 * @param[in]  u1FramePolarity :  Select frame polarity from
 *                                SSP_FramePolarityEnum
 * @param[in]  u1ClockIdleLevel:  Select clock idle state from
 *                                SSP_ClockIdleLevelEnum
 * @param[in]  u1DataSendEdge  :  Select send data on which clock edge from
 *                                SSP_SendDataEdgeEnum
 *
 * @return     none
 *
 ******************************************************************************/
#if defined(__ICCARM__)
#pragma optimize=low
#endif
void SSP_Init(SSP_REGS *SSPx, uint8_t u8MasterOrSlave, uint8_t u8DataSize, uint32_t u32Baudrate, SSP_FramePolarityEnum u1FramePolarity, SSP_ClockIdleLevelEnum u1ClockIdleLevel, SSP_SendDataEdgeEnum u1DataSendEdge)
{
    /* Enable SSP clock */
    CLOCK_EnableModule(SSP_MODULE);

    /* Set SSP clock divider */
    CLOCK->SSPCLKCTL.bit.DIV = (SysInfo.u32HCLK / u32Baudrate - 1);

    /* Disable SSP */
    SSP_Disable(SSPx);

    /* Configure SSP function mode: Master or Slave */
    if (u8MasterOrSlave == SSP_MASTER_MODE)
    {
        SSPx->SSPCTL1.bit.FRMDIR = SSPCTL1_BIT_FRMDIR_MASTER_MODE;
        SSPx->SSPCTL1.bit.CLKDIR = SSPCTL1_BIT_CLKDIR_MASTER_MODE;
    }
    else
    {
        SSPx->SSPCTL1.bit.FRMDIR = SSPCTL1_BIT_FRMDIR_SLAVE_MODE;
        SSPx->SSPCTL1.bit.CLKDIR = SSPCTL1_BIT_CLKDIR_SLAVE_MODE;
        /* Use external clock in slave mode */
        SSPx->SSPCTL1.bit.SLVCLKSEL = SSPCTL1_BIT_SLVCLKSEL_SLAVE_EXTENAL_SCLK;
    }

    /* Configure SSP data size */
    if (u8DataSize <= 16)
    {
        SSPx->SSPCTL0.bit.ESIZESEL = SSPCTL0_BIT_ESIZESEL_DISABLE;
        SSPx->SSPCTL0.bit.SIZESEL = u8DataSize - 1;
    }
    else
    {
        SSPx->SSPCTL0.bit.ESIZESEL = SSPCTL0_BIT_ESIZESEL_ENABLE;
        SSPx->SSPCTL0.bit.SIZESEL = u8DataSize - 17;
    }

    /* Configure SSP Frame level according to user selection */
    SSPx->SSPCTL1.bit.FRMINV = u1FramePolarity;

    /* Configure SSP clock idle level according to user selection */
    SSPx->SSPCTL1.bit.CLKPOL = u1ClockIdleLevel;

    /* Configure SSP clock phase according to user selection */
    if (u1DataSendEdge == SSP_SEND_ON_RISING_EDGE)
    {
        /* CLKPHS = !CLKPOL */
        SSPx->SSPCTL1.bit.CLKPHS = ((u1ClockIdleLevel == 0) ? 1 : 0);
    }
    else
    {
        /* CLKPHS = CLKPOS */
        SSPx->SSPCTL1.bit.CLKPHS = u1ClockIdleLevel;
    }

    /* Disable TXUDF and RXOVF interrupt */
    SSPx->SSPCTL0.bit.TFINTMSK = SSPCTL0_BIT_TFINTMSK_MASK;
    SSPx->SSPCTL0.bit.RFINTMSK = SSPCTL0_BIT_RFINTMSK_MASK;
}




/******************************************************************************
 * @brief      Initializes the SSP with pre-define settings
 *
 * @param[in]  SSPx           :  Select the SSP port
 * @param[in]  u8MasterOrSlave:  Define SSP in master or slave mode
 * @param[in]  u8DataSize     :  Define SSP data size in one frame
 * @param[in]  u32Baudrate    :  Define SSP baudrate
 *
 * @return     none
 *
 * @detail     As in a lot of SPI application scenario,
 *             Frame is active Low
 *             Clock idle      Low
 *             Data send on    Rising edge
 *             In these cases, user can use this funtion as a simple method to configure SSP
 *
 ******************************************************************************/
#if defined(__ICCARM__)
#pragma optimize=low
#endif
void SSP_InitEasy(SSP_REGS *SSPx, uint8_t u8MasterOrSlave, uint8_t u8DataSize, uint32_t u32Baudrate)
{
    SSP_Init(SSPx, u8MasterOrSlave, u8DataSize, u32Baudrate, SSP_FRM_ACTIVE_LOW, SSP_CLK_IDLE_LOW, SSP_SEND_ON_RISING_EDGE);
}




/******************************************************************************
 * @brief      Send data to SSP peripheral (Single Frame mode, Send only)
 *
 * @param[in]  SSPx    :  Select the SSP port
 * @param[in]  pu32Buf :  Pointer to the array that stored data to be sent
 * @param[in]  u32Count:  Number of data to be sent
 *
 * @return     none
 *
 ******************************************************************************/
#if defined(__ICCARM__)
#pragma optimize=low
#endif
ErrorStatus SSP_Send(SSP_REGS *SSPx, uint32_t *pu32Buf, uint32_t u32Count)
{
    uint32_t i;
    volatile uint32_t u32TimeOut = 0;

    for (i = 0; i < u32Count; i++)
    {
        /* Wait until TxFIFO empty */
        /* When CPU is 200MHz and SPI is 50MHz, bps = 32bit * 10^9ns / 50MHz * 65536 = 41.943 ms, approximately 42ms.
           Taking FIFO usage into consideration, the timeout period should be multiplied by the FIFO depth. 
           In total, approximately 42 * 16 = 672 ms. In 1ms, CPU executes 200,000 instructions. Thus, in 672 ms, 
           a total of 134,400,000 instructions are executed.  */
        for (u32TimeOut = 134400000UL; u32TimeOut > 0U; u32TimeOut--)
        {
            if (!SSP_GetTxFIFOLevel(SSPx))
            {
                break;
            }
        }
        if (u32TimeOut == 0)
        {
            return ERROR;
        }

        /* Send data */
        SSP_SendData(SSPx, pu32Buf[i]);
    }

    return SUCCESS;
}




/******************************************************************************
 * @brief      Receive data from SSP peripheral
 *
 * @param[in]  SSPx    :  Select the SSP port
 * @param[in]  pu32Buf :  Pointer to the buffer that stored the reveived data
 * @param[in]  u32Count:  Number of data to be received
 *
 * @return     Number of data that has been received
 *
 ******************************************************************************/
#if defined(__ICCARM__)
#pragma optimize=low
#endif
uint32_t SSP_Receive(SSP_REGS *SSPx, uint32_t *pu32Buf, uint32_t u32Count)
{
    uint32_t i;

    for (i = 0; i < u32Count; i++)
    {
        /* If RxFIFO was empty, just return */
        if (!SSP_IsRxNotEmpty(SSPx))
        {
            return i;
        }

        /* Receive data */
        pu32Buf[i] = SSP_ReceiveData(SSPx);
    }

    return i;
}




/******************************************************************************
 * @brief      SSP Master Transmit and Receive data (Single Frame mode, Full Duplex)
 *
 * @param[in]  SSPx           :  Select the SSP port
 * @param[in]  pu32WriteBuffer:  Pointer to the buffer that stored the data to be send
 * @param[in]  pu32ReadBuffer :  Pointer to the buffer that stored the reveived data
 * @param[in]  u32Count       :  Number of data to be send or received
 *
 * @return     none
 *
 ******************************************************************************/
#if defined(__ICCARM__)
#pragma optimize=low
#endif
ErrorStatus SSP_MasterTransceive(SSP_REGS *SSPx, uint32_t *pu32WriteBuffer, uint32_t *pu32ReadBuffer, uint32_t u32Count)
{
    uint32_t i;
    volatile uint32_t u32TimeOut = 0;

    for (i = 0; i < u32Count; i++)
    {
        /* Wait until TxFIFO is empty */
        /* When CPU is 200MHz and SPI is 50MHz, bps = 32bit * 10^9ns / 50MHz * 65536 = 41.943 ms, approximately 42ms.
           Taking FIFO usage into consideration, the timeout period should be multiplied by the FIFO depth. 
           In total, approximately 42 * 16 = 672 ms. In 1ms, CPU executes 200,000 instructions. Thus, in 672 ms, 
           a total of 134,400,000 instructions are executed.  */
        for (u32TimeOut = 134400000UL; u32TimeOut > 0U; u32TimeOut--)
        {
            if (!SSP_GetTxFIFOLevel(SSPx))
            {
                break;
            }
        }
        if (u32TimeOut == 0)
        {
            return ERROR;
        }

        /* Write data to TxFIFO */
        SSP_SendData(SSPx, *pu32WriteBuffer++);

        /* Wait until RxFIFO is not empty */
        /* When CPU is 200MHz and SPI is 50MHz, bps = 32bit * 10^9ns / 50MHz * 65536 = 41.943 ms, approximately 42ms.
           Taking FIFO usage into consideration, the timeout period should be multiplied by the FIFO depth. 
           In total, approximately 42 * 16 = 672 ms. In 1ms, CPU executes 200,000 instructions. Thus, in 672 ms, 
           a total of 134,400,000 instructions are executed.  */
        for (u32TimeOut = 134400000UL; u32TimeOut > 0U; u32TimeOut--)
        {
            if (SSP_IsRxNotEmpty(SSPx))
            {
                break;
            }
        }

        /* Read data from RxFIFO */
        *pu32ReadBuffer++ = SSP_ReceiveData(SSPx);

        if (u32TimeOut == 0)
        {
            return ERROR;
        }
    }

    return SUCCESS;
}




/******************************************************************************
 * @brief      SSP Master Back-to-back Transmit and Receive data (Back to Back Mode)
 *
 * @param[in]  SSPx           :  Select the SSP port
 * @param[in]  pu32WriteBuffer:  Pointer to the buffer that stored the data to be send
 * @param[in]  pu32ReadBuffer :  Pointer to the buffer that stored the reveived data
 * @param[in]  u32Count       :  Number of data to be send or received
 *
 * @return     none
 *
 ******************************************************************************/
#if defined(__ICCARM__)
#pragma optimize=low
#endif
ErrorStatus SSP_MasterB2BTransceive(SSP_REGS *SSPx, uint32_t *pu32WriteBuffer, uint32_t *pu32ReadBuffer, uint32_t u32Count)
{
    uint32_t u32TxCount = 0U;
    uint32_t u32RxCount = 0U;
    uint32_t u32TxTimeOut = 0;
    uint32_t u32RxTimeOut = 0;

    uint32_t u32WriteFlag = SSPSTS_ALL_TNF_Msk
                            | ((0 != SSPx->SSPCTL0.bit.FPACKEN)
                               ? SSPSTS_ALL_TFODDSTS_Msk : 0U
                              ) ;

    uint32_t u32ReadFlag  = SSPSTS_ALL_RNE_Msk
                            | ((0 != SSPx->SSPCTL0.bit.FPACKEN)
                               ? SSPSTS_ALL_RFODDSTS_Msk : 0U
                              ) ;

    uint32_t u32Dummy     = (u32Count < SSP_FIFO_DEPTH) ? u32Count :
                            SSP_FIFO_DEPTH;

    /* Note: make sure TXFIFO empty */

    do
    {
        /* Send one data */
        SSP_SendData(SSPx, pu32WriteBuffer[u32TxCount]);
        u32TxCount++;
    }
    while (u32TxCount < u32Dummy);

    /* When CPU is 200MHz and SPI is 50MHz, bps = 32bit * 10^9ns / 50MHz * 65536 = 41.943 ms, approximately 42ms.
       Taking FIFO usage into consideration, the timeout period should be multiplied by the FIFO depth. 
       In total, approximately 42 * 16 = 672 ms. In 1ms, CPU executes 200,000 instructions. Thus, in 672 ms, 
       a total of 134,400,000 instructions are executed.  */
    u32TxTimeOut = 134400000UL;
    u32RxTimeOut = 134400000UL;
    while (u32TxCount < u32Count)
    {
        /* Try receive one data */
        if ((--u32RxTimeOut > 0) && ((SSPx->SSPSTS.all & u32ReadFlag) == SSPSTS_ALL_RNE_NOT_EMPTY))
        {
            pu32ReadBuffer[u32RxCount] = SSP_ReceiveData(SSPx);
            u32RxCount++;
            u32RxTimeOut = 134400000UL;
        }
        if (u32RxTimeOut == 0)
        {
            return ERROR;
        }

        /* Try send one data */
        if ((--u32TxTimeOut > 0) && ((SSPx->SSPSTS.all & u32WriteFlag) == SSPSTS_ALL_TNF_NOT_FULL))
        {
            SSP_SendData(SSPx, pu32WriteBuffer[u32TxCount]);
            u32TxCount++;
            u32TxTimeOut = 134400000UL;
        }
        if (u32TxTimeOut == 0)
        {
            return ERROR;
        }
    }

    /* When CPU is 200MHz and SPI is 50MHz, bps = 32bit * 10^9ns / 50MHz * 65536 = 41.943 ms, approximately 42ms.
       Taking FIFO usage into consideration, the timeout period should be multiplied by the FIFO depth. 
       In total, approximately 42 * 16 = 672 ms. In 1ms, CPU executes 200,000 instructions. Thus, in 672 ms, 
       a total of 134,400,000 instructions are executed.  */
    u32RxTimeOut = 134400000UL;
    while (u32RxCount < u32Count)
    {
        if ((--u32RxTimeOut > 0) && ((SSPx->SSPSTS.all & u32ReadFlag) == SSPSTS_ALL_RNE_NOT_EMPTY))
        {
            pu32ReadBuffer[u32RxCount] = SSP_ReceiveData(SSPx);
            u32RxCount++;
            u32RxTimeOut = 134400000UL;
        }
        if (u32RxTimeOut == 0)
        {
            return ERROR;
        }
    }

    return SUCCESS;
}




/******************************************************************************
 * @brief      SSP Slave Transmit and Receive data (Full Duplex)
 *
 * @param[in]  SSPx            :  Select the SSP port
 * @param[in]  pu32WriteBuffer :  Pointer to the buffer that stored the data to be send
 * @param[in]  pu32ReadBuffer  :  Pointer to the buffer that stored the reveived data
 * @param[in]  u32Count        :  Number of data to be send or received
 *
 * @return     none
 *
 ******************************************************************************/
#if defined(__ICCARM__)
#pragma optimize=low
#endif
void SSP_SlaveTransceive(SSP_REGS *SSPx, uint32_t *pu32WriteBuffer, uint32_t *pu32ReadBuffer, uint32_t u32Count)
{
    uint32_t u32TxCount = 0U;
    uint32_t u32RxCount = 0U;

    uint32_t u32WriteFlag = SSPSTS_ALL_TNF_Msk
                            | ((0 != SSPx->SSPCTL0.bit.FPACKEN)
                               ? SSPSTS_ALL_TFODDSTS_Msk : 0U
                              ) ;

    uint32_t u32ReadFlag  = SSPSTS_ALL_RNE_Msk
                            | ((0 != SSPx->SSPCTL0.bit.FPACKEN)
                               ? SSPSTS_ALL_RFODDSTS_Msk : 0U
                              ) ;

    while (u32TxCount < u32Count)
    {
         /* Try receive one data */
        if ((SSPx->SSPSTS.all & u32ReadFlag) == SSPSTS_ALL_RNE_NOT_EMPTY)
        {
            pu32ReadBuffer[u32RxCount] = SSP_ReceiveData(SSPx);
            u32RxCount++;
        }

        /* Try send one data */
        if ((SSPx->SSPSTS.all & u32WriteFlag) == SSPSTS_ALL_TNF_NOT_FULL)
        {
            SSP_SendData(SSPx, pu32WriteBuffer[u32TxCount]);
            u32TxCount++;
        }
    }

    while (u32RxCount < u32Count)
    {
        if ((SSPx->SSPSTS.all & u32ReadFlag) == SSPSTS_ALL_RNE_NOT_EMPTY)
        {
            pu32ReadBuffer[u32RxCount] = SSP_ReceiveData(SSPx);
            u32RxCount++;
        }
    }

}




/******************************************************************************
 * @brief      Get Receive FIFO Level
 *
 * @param[in]  SSPx :  Select the SSP port
 *
 * @return     Receive FIFO level
 *
 ******************************************************************************/
#if defined(__ICCARM__)
#pragma optimize=low
#endif
__INLINE uint32_t SSP_GetRxFIFOLevel(SSP_REGS *SSPx)
{
    uint32_t u32RxFIFOLevel = 0;
    if (!SSP_IsRxNotEmpty(SSPx))
    {
        u32RxFIFOLevel = 0;
    }
    else if (SSP_IsRxNotEmpty(SSPx) && ((SSPx)->SSPSTS.bit.RFLVL == SSP_FIFO_DEPTH - 1))
    {
        u32RxFIFOLevel = SSP_FIFO_DEPTH;
    }
    else
    {
        u32RxFIFOLevel = (SSPx)->SSPSTS.bit.RFLVL + 1;
    }

    return u32RxFIFOLevel;
}




/******************************************************************************
 * @brief      SSP Master/Slave half-duplex transmit data
 *
 * @param[in]  SSPx            :  Select the SSP port
 * @param[in]  pu32WriteBuf    :  Pointer to the buffer that stored the data to be send
 * @param[in]  u32WCount       :  Number of data to be send
 *
 * @return     none
 *
 ******************************************************************************/
#if defined(__ICCARM__)
#pragma optimize=low
#endif
void SSP_HalfDuplexTx(SSP_REGS *SSPx, uint32_t *pu32WriteBuf, uint32_t u32WCount)
{
    uint32_t u32TxCount = 0U;
    uint32_t u32RxCount = 0U;

    uint32_t u32WriteFlag = SSPSTS_ALL_TNF_Msk
                            | ((0 != SSPx->SSPCTL0.bit.FPACKEN)
                               ? SSPSTS_ALL_TFODDSTS_Msk : 0U
                              ) ;

    uint32_t u32ReadFlag  = SSPSTS_ALL_RNE_Msk
                            | ((0 != SSPx->SSPCTL0.bit.FPACKEN)
                               ? SSPSTS_ALL_RFODDSTS_Msk : 0U
                              ) ;

    uint32_t u32Dummy     = (u32WCount < SSP_FIFO_DEPTH) ? u32WCount :
                            SSP_FIFO_DEPTH;

    do
    {
        /* Send one data */
        SSP_SendData(SSPx, pu32WriteBuf[u32TxCount]);
        u32TxCount++;
    }
    while (u32TxCount < u32Dummy);

    while (u32TxCount < u32WCount)
    {
        /* Try receive dummy data */
        if ((SSPx->SSPSTS.all & u32ReadFlag) == SSPSTS_ALL_RNE_NOT_EMPTY)
        {
            SSP_ReceiveData(SSPx);
            u32RxCount++;
        }

        /* Try send one data */
        if ((SSPx->SSPSTS.all & u32WriteFlag) == SSPSTS_ALL_TNF_NOT_FULL)
        {
            SSP_SendData(SSPx, pu32WriteBuf[u32TxCount]);
            u32TxCount++;
        }
    }

    /* Clear RX FIFO */
    while((SSP_GetRxFIFOLevel(SSPx) > 0) || (u32RxCount < u32WCount))
    {
        /* Try receive one data */
        if ((SSPx->SSPSTS.all & u32ReadFlag) == SSPSTS_ALL_RNE_NOT_EMPTY)
        {
            SSP_ReceiveData(SSPx);
            u32RxCount++;
        }
    }
}




/******************************************************************************
 * @brief      SSP Master/Slave half-duplex receive data
 *
 * @param[in]  SSPx            :  Select the SSP port
 * @param[in]  pu32ReadBuf     :  Pointer to the buffer that stored the reveived data
 * @param[in]  u32RCount       :  Number of data to be received
 *
 * @return     none
 *
 ******************************************************************************/
#if defined(__ICCARM__)
#pragma optimize=low
#endif
void SSP_HalfDuplexRx(SSP_REGS *SSPx, uint32_t *pu32ReadBuf, uint32_t u32RCount)
{
    uint32_t u32TxCount = 0U;
    uint32_t u32RxCount = 0U;

    uint32_t u32WriteFlag = SSPSTS_ALL_TNF_Msk
                            | ((0 != SSPx->SSPCTL0.bit.FPACKEN)
                               ? SSPSTS_ALL_TFODDSTS_Msk : 0U
                              ) ;

    uint32_t u32ReadFlag  = SSPSTS_ALL_RNE_Msk
                            | ((0 != SSPx->SSPCTL0.bit.FPACKEN)
                               ? SSPSTS_ALL_RFODDSTS_Msk : 0U
                              ) ;

    uint32_t u32Dummy     = (u32RCount < SSP_FIFO_DEPTH) ? u32RCount :
                            SSP_FIFO_DEPTH;

    do
    {
        /* Send one data */
        SSP_SendData(SSPx, 0xff);
        u32TxCount++;
    }
    while (u32TxCount < u32Dummy);

    while (u32TxCount < u32RCount)
    {
        /* Try receive one data */
        if ((SSPx->SSPSTS.all & u32ReadFlag) == SSPSTS_ALL_RNE_NOT_EMPTY)
        {
            pu32ReadBuf[u32RxCount] = SSP_ReceiveData(SSPx);
            u32RxCount++;
        }

        /* Try send dummy data */
        if ((SSPx->SSPSTS.all & u32WriteFlag) == SSPSTS_ALL_TNF_NOT_FULL)
        {
            SSP_SendData(SSPx, 0xff);
            u32TxCount++;
        }
    }

    /* Clear RX FIFO */
    while((SSP_GetRxFIFOLevel(SSPx) > 0) || (u32RxCount < u32RCount))
    {
        /* Try receive one data */
        if ((SSPx->SSPSTS.all & u32ReadFlag) == SSPSTS_ALL_RNE_NOT_EMPTY)
        {
            pu32ReadBuf[u32RxCount] = SSP_ReceiveData(SSPx);
            u32RxCount++;
        }
    }
}




/******************************************************************************
 * @brief      SSP Master/Slave full duplex transmit data
 *
 * @param[in]  SSPx              :  Select the SSP port
 * @param[in]  pu32WriteBuffer   :  Pointer to the buffer that stored the data to be send
 * @param[in]  pu32ReadBuffer    :  Pointer to the buffer that stored the reveived data
 * @param[in]  u32Count          :  Number of data to be send or received
 *
 * @return     none
 *
 ******************************************************************************/
#if defined(__ICCARM__)
#pragma optimize=low
#endif
void SSP_FullDuplexTransceive(SSP_REGS *SSPx, uint32_t *pu32WriteBuffer, uint32_t *pu32ReadBuffer, uint32_t u32Count)
{
    uint32_t u32TxCount = 0U;
    uint32_t u32RxCount = 0U;

    uint32_t u32WriteFlag = SSPSTS_ALL_TNF_Msk
                            | ((0 != SSPx->SSPCTL0.bit.FPACKEN)
                               ? SSPSTS_ALL_TFODDSTS_Msk : 0U
                              ) ;

    uint32_t u32ReadFlag  = SSPSTS_ALL_RNE_Msk
                            | ((0 != SSPx->SSPCTL0.bit.FPACKEN)
                               ? SSPSTS_ALL_RFODDSTS_Msk : 0U
                              ) ;

    uint32_t u32Dummy     = (u32Count < SSP_FIFO_DEPTH) ? u32Count :
                            SSP_FIFO_DEPTH;

    /* Note: make sure TXFIFO empty */
    do
    {
        /* Send one data */
        SSP_SendData(SSPx, pu32WriteBuffer[u32TxCount]);
        u32TxCount++;
    }
    while (u32TxCount < u32Dummy);

    while (u32TxCount < u32Count)
    {
        /* Try receive one data */
        if ((SSPx->SSPSTS.all & u32ReadFlag) == SSPSTS_ALL_RNE_NOT_EMPTY)
        {
            pu32ReadBuffer[u32RxCount] = SSP_ReceiveData(SSPx);
            u32RxCount++;
        }

        /* Try send one data */
        if ((SSPx->SSPSTS.all & u32WriteFlag) == SSPSTS_ALL_TNF_NOT_FULL)
        {
            SSP_SendData(SSPx, pu32WriteBuffer[u32TxCount]);
            u32TxCount++;
        }
    }

    while (u32RxCount < u32Count)
    {
        if ((SSPx->SSPSTS.all & u32ReadFlag) == SSPSTS_ALL_RNE_NOT_EMPTY)
        {
            pu32ReadBuffer[u32RxCount] = SSP_ReceiveData(SSPx);
            u32RxCount++;
        }
    }
}


#if defined(__CC_ARM)
    #pragma pop
#endif


/******************* Copyright (C) 2022 Spintrol Electronic Technology (Shanghai) Co., Ltd. ***** END OF FILE ****/
