
/*
 * Copyright 2020-2022 Yuntu Microelectronics Co., Ltd.
 * All rights reserved.
 *
 * SPDX-License-Identifier: BSD-3-Clause
 */

/*!
 * @file sai_hw_access.h
 * @version 1.4.0
 */

#ifndef SAI_HW_ACCESS_H
#define SAI_HW_ACCESS_H

#include "device_registers.h"

/*maximum size of frame, unit word*/
#define SAI0_FRAME_SIZE         (16)
#define SAI1_FRAME_SIZE         (16)
#define SAI_RFR_WFP_WIDTH       (4u)
#if(SAI_INSTANCE_COUNT == 1)
static const uint8_t saiFrameSize[SAI_INSTANCE_COUNT] = {SAI0_FRAME_SIZE};
#elif(SAI_INSTANCE_COUNT == 2)
static const uint8_t saiFrameSize[SAI_INSTANCE_COUNT] = {SAI0_FRAME_SIZE, SAI1_FRAME_SIZE};
#else
    #error "No valid SAI"
#endif



/*FUNCTION**********************************************************************
 *
 * Function Name : SAI_DRV_GetParamFrameSize
 * Description   : Return frame maximum size 
 *
 *END**************************************************************************/
static inline uint8_t SAI_DRV_GetParamFrameSize(uint32_t instance)
{
    return saiFrameSize[instance];
}

/*FUNCTION**********************************************************************
 *
 * Function Name : SAI_DRV_TxGetFifoReqFlag
 * Description   : Return fifo request flag
 *
 *END**************************************************************************/
static inline bool SAI_DRV_TxGetFifoReqFlag(const SAI_Type* base)
{
    uint32_t temp = base->TSTS;
    uint32_t temp1 = base->TINTE;
    return (((temp & SAI_TSTS_FRF_MASK) != 0UL) && ((temp1 & SAI_TINTE_FRIE_MASK) != 0UL));
}

/*FUNCTION**********************************************************************
 *
 * Function Name : SAI_DRV_IsTxChannelEnabled
 * Description   : check if channel is enabled
 *
 *END**************************************************************************/
static inline bool SAI_DRV_IsTxChannelEnabled(const SAI_Type* base, uint8_t channel)
{
    bool ret;

    if ((base->TCFG1 & SAI_TCFG1_TCE(1UL << (uint32_t)channel)) != 0UL)
    {
        ret = true;
    }
    else
    {
        ret = false;
    }
    return ret;
}

/*FUNCTION**********************************************************************
 *
 * Function Name : SAI_DRV_TxWrite
 * Description   : Write data register once
 *
 *END**************************************************************************/
static inline void SAI_DRV_TxWrite(SAI_Type* base,
                     uint8_t channel,
                     uint32_t data)
{
    base->TDATA[channel] = data;
}

/*FUNCTION**********************************************************************
 *
 * Function Name : SAI_DRV_TxDisableFifoReqInt
 * Description   : Disable fifo request interrupt
 *
 *END**************************************************************************/
static inline void SAI_DRV_TxDisableFifoReqInt(SAI_Type* base)
{
    uint32_t val = base->TINTE;
    /* disable fifo request int */
    val &= ~(1UL << SAI_TINTE_FRIE_SHIFT);
    base->TINTE = val;
}

/*FUNCTION**********************************************************************
 *
 * Function Name : SAI_DRV_TxGetFifoErrorFlag
 * Description   : Return tx fifo error flag
 *
 *END**************************************************************************/
static inline bool SAI_DRV_TxGetFifoErrorFlag(const SAI_Type* base)
{
    uint32_t temp  = base->TSTS;
    uint32_t temp1 = base->TINTE;
    return (((temp & SAI_TSTS_FEF_MASK) != 0UL) && ((temp1 & SAI_TINTE_FEIE_MASK) != 0UL));
}

/*FUNCTION**********************************************************************
 *
 * Function Name : SAI_DRV_TxGetSyncErrorFlag
 * Description   : Return tx sync error flag
 *
 *END**************************************************************************/
static inline bool SAI_DRV_TxGetSyncErrorFlag(const SAI_Type* base)
{
    uint32_t temp = base->TSTS;
    uint32_t temp1 = base->TINTE;
    return (((temp & SAI_TSTS_SEF_MASK) != 0UL) && ((temp1 & SAI_TINTE_SEIE_MASK) != 0UL));
}

/*FUNCTION**********************************************************************
 *
 * Function Name : SAI_DRV_RxGetFifoErrorFlag
 * Description   : Return rx sync error flag
 *
 *END**************************************************************************/
static inline bool SAI_DRV_RxGetSyncErrorFlag(const SAI_Type* base)
{
    uint32_t temp = base->RSTS;
    uint32_t temp1 = base->RINTE;
    return (((temp & SAI_RSTS_SEF_MASK) != 0UL) && ((temp1 & SAI_RINTE_SEIE_MASK) != 0UL));
}

/*FUNCTION**********************************************************************
 *
 * Function Name : SAI_DRV_IsTxFifoEmpty
 * Description   : Check if Tx fifo is empty
 *
 *END**************************************************************************/
static inline bool SAI_DRV_IsTxFifoEmpty(const SAI_Type* base,
                          uint8_t channel)
{
    uint8_t wfp;
    uint8_t rfp;
    bool ret;

    wfp = (uint8_t)((base->TFR[channel] & SAI_TFR_WFP_MASK) >> SAI_TFR_WFP_SHIFT);
    rfp = (uint8_t)((base->TFR[channel] & SAI_TFR_RFP_MASK) >> SAI_TFR_RFP_SHIFT);

    /* if WFP and RFP is identical then fifo is empty */
    if (wfp == rfp)
    {
        ret = true;
    }
    else
    {
        ret = false;
    }
    return ret;
}

/*FUNCTION**********************************************************************
 *
 * Function Name : SAI_DRV_TxClearFlag
 * Description   : Clear one of folowing flags: word start, fifo erro,
 *                 sync error
 *
 *END**************************************************************************/
static inline void SAI_DRV_TxClearFlag (SAI_Type* base, uint32_t shift)
{
    uint32_t val = base->TSTS;
    /* careful not to clear flags */
    val &= ~((1UL << SAI_TSTS_WSF_SHIFT) | (1UL << SAI_TSTS_SEF_SHIFT) | (1UL << SAI_TSTS_FEF_SHIFT) | (1UL << SAI_TSTS_FRF_SHIFT));
    /* clear fifo error flag */
    val |= 1UL << shift;
    base->TSTS = val;
}

/*FUNCTION**********************************************************************
 *
 * Function Name : SAI_DRV_RxGetFifoReqFlag
 * Description   : Return fifo request flag
 *
 *END**************************************************************************/
static inline bool SAI_DRV_RxGetFifoReqFlag(const SAI_Type* base)
{
    uint32_t temp = base->RSTS;
    uint32_t temp1 = base->RINTE;
    return (((temp & SAI_RSTS_FRF_MASK) != 0UL) && ((temp1 & SAI_RINTE_FRIE_MASK) != 0UL));
}

/*FUNCTION**********************************************************************
 *
 * Function Name : SAI_DRV_IsRxChannelEnabled
 * Description   : check if channel is enabled
 *
 *END**************************************************************************/
static inline bool SAI_DRV_IsRxChannelEnabled(const SAI_Type* base, uint8_t channel)
{
    bool ret;

    if ((base->RCFG1 & SAI_RCFG1_RCE((uint32_t)1UL << (uint32_t)channel)) != 0UL)
    {
        ret = true;
    }
    else
    {
        ret =false;
    }
    return ret;
}

/*FUNCTION**********************************************************************
 *
 * Function Name : SAI_DRV_RxRead
 * Description   : Read data register once
 *
 *END**************************************************************************/
static inline uint32_t SAI_DRV_RxRead(const SAI_Type* base,
                     uint8_t channel)
{
    return base->RDATA[channel];
}

/*FUNCTION**********************************************************************
 *
 * Function Name : SAI_DRV_RxSetWatermark
 * Description   : Set fifo watermark
 *
 *END**************************************************************************/
static inline void SAI_DRV_RxSetWatermark(SAI_Type* base, uint8_t level)
{
    uint32_t val = base->RFCR;
    val &= ~SAI_RFCR_TFW_MASK;
    val |= SAI_RFCR_TFW((uint32_t) level);
    base->RFCR = val;
}

/*FUNCTION**********************************************************************
 *
 * Function Name : SAI_DRV_RxDisableFifoReqInt
 * Description   : Disable fifo request interrupt
 *
 *END**************************************************************************/
static inline void SAI_DRV_RxDisableFifoReqInt(SAI_Type* base)
{
    uint32_t val = base->RINTE;

    /* disable fifo request int */
    val &= ~(1UL << SAI_RINTE_FRIE_SHIFT);
    base->RINTE = val;
}

/*FUNCTION**********************************************************************
 *
 * Function Name : SAI_DRV_RxGetFifoErrorFlag
 * Description   : Return rx fifo error flag
 *
 *END**************************************************************************/

static inline bool SAI_DRV_RxGetFifoErrorFlag(const SAI_Type* base)
{
    uint32_t temp  = base->RSTS;
    uint32_t temp1 = base->RINTE;
    return (((temp & SAI_RSTS_FEF_MASK) != 0UL) && ((temp1 & SAI_RINTE_FEIE_MASK) != 0UL));
}

/*FUNCTION**********************************************************************
 *
 * Function Name : SAI_DRV_IsRxFifoFull
 * Description   : Check if Rx fifo is full
 *
 *END**************************************************************************/
static inline bool SAI_DRV_IsRxFifoFull(const SAI_Type* base,
                          uint8_t channel)
{
    uint8_t wfp;
    uint8_t rfp;
    bool ret;

    wfp = (uint8_t)((base->RFR[channel] & SAI_RFR_WFP_MASK) >> SAI_RFR_WFP_SHIFT);
    rfp = (uint8_t)((base->RFR[channel] & SAI_RFR_RFP_MASK) >> SAI_RFR_RFP_SHIFT);

    /* if WFP and RFP is identical except msb then fifo is full */
    if (((uint32_t)wfp ^ (uint32_t)rfp) == (1UL << ((uint32_t)SAI_RFR_WFP_WIDTH - 1UL)))
    {
        ret = true;
    }
    else
    {
        ret = false;
    }
    return ret;
}

/*FUNCTION**********************************************************************
 *
 * Function Name : SAI_DRV_RxClearFlag
 * Description   : Clear one of folowing flags: word start, fifo erro,
 *                 sync error
 *
 *END**************************************************************************/
static inline void SAI_DRV_RxClearFlag (SAI_Type* base, uint32_t shift)
{
    uint32_t val = base->RSTS;
    /* careful not to clear flags */
    val &= ~((1UL << SAI_RSTS_WSF_SHIFT) | (1UL << SAI_RSTS_SEF_SHIFT) | (1UL << SAI_RSTS_FEF_SHIFT) | (1UL << SAI_RSTS_FRF_SHIFT));
    /* clear fifo flag */
    val |= 1UL << shift;
    base->RSTS = val;
}

/*FUNCTION**********************************************************************
 *
 * Function Name : SAI_DRV_RxGetWordStartFlag
 * Description   : Return rx word start flag
 *
 *END**************************************************************************/
static inline bool SAI_DRV_RxGetWordStartFlag(const SAI_Type* base)
{
    uint32_t temp  = base->RSTS;
    uint32_t temp1 = base->RINTE;
    return (((temp & SAI_RSTS_WSF_MASK) != 0UL) && ((temp1 & SAI_RINTE_WSIE_MASK) != 0UL));
}

/*FUNCTION**********************************************************************
 *
 * Function Name : SAI_DRV_IsRxEnable
 * Description   : Return rx enable or disable
 *
 *END**************************************************************************/
static inline bool SAI_DRV_IsRxEnable(const SAI_Type* base)
{
    bool ret;
    uint32_t temp  = base->RCTRL;
    
    if ((temp & SAI_RCTRL_RE_MASK) == (1UL << ((uint32_t)SAI_RCTRL_RE_SHIFT)))
    {
        ret = true;
    }
    else
    {
        ret = false;
    }
    return ret;
}

/*FUNCTION**********************************************************************
 *
 * Function Name : SAI_DRV_IsTxEnable
 * Description   : Return tx enable or disable
 *
 *END**************************************************************************/
static inline bool SAI_DRV_IsTxEnable(const SAI_Type* base)
{
    bool ret;
    uint32_t temp  = base->TCTRL;
    
    if ((temp & SAI_TCTRL_TE_MASK) == (1UL << ((uint32_t)SAI_TCTRL_TE_SHIFT)))
    {
        ret = true;
    }
    else
    {
        ret = false;
    }
    return ret;
}

/*FUNCTION**********************************************************************
 *
 * Function Name : SAI_DRV_SetTxEnable
 * Description   : Enable transmitter
 *
 *END**************************************************************************/
static inline void SAI_DRV_SetTxEnable(SAI_Type* base)
{
    uint32_t temp  = base->TCTRL;
    temp |= SAI_TCTRL_TE(1);
    base->TCTRL = temp;
}

/*FUNCTION**********************************************************************
 *
 * Function Name : SAI_DRV_SetRxEnable
 * Description   : Enable receiver
 *
 *END**************************************************************************/
static inline void SAI_DRV_SetRxEnable(SAI_Type* base)
{
    uint32_t temp  = base->RCTRL;
    temp |= SAI_RCTRL_RE(1);
    base->RCTRL = temp;
}

/*FUNCTION**********************************************************************
 *
 * Function Name : SAI_DRV_SetTxDisable
 * Description   : Disable transmitter
 *
 *END**************************************************************************/
static inline void SAI_DRV_SetTxDisable(SAI_Type* base)
{
    uint32_t temp  = base->TCTRL;
    temp &= (~SAI_TCTRL_TE(1)); 
    base->TCTRL = temp;
}

/*FUNCTION**********************************************************************
 *
 * Function Name : SAI_DRV_SetRxDisable
 * Description   : Disable receiver
 *
 *END**************************************************************************/
static inline void SAI_DRV_SetRxDisable(SAI_Type* base)
{
    uint32_t temp  = base->RCTRL;
    temp &= (~SAI_RCTRL_RE(1)); 
    base->RCTRL = temp;
}

/*FUNCTION**********************************************************************
 *
 * Function Name : SAI_DRV_isTxBitClockDirInternal
 * Description   : Return tx bit clock direction, true -> internal; false -> external
 *
 *END**************************************************************************/
static inline bool SAI_DRV_isTxBitClockDirInternal(const SAI_Type* base)
{
    bool ret;
    uint32_t temp  = base->TCFG0;
    
    if ((temp & SAI_TCFG0_BCD_MASK) == (1UL << ((uint32_t)SAI_TCFG0_BCD_SHIFT)))
    {
        ret = true;
    }
    else
    {
        ret = false;
    }
    return ret;
}

/*FUNCTION**********************************************************************
 *
 * Function Name : SAI_DRV_isRxBitClockDirInternal
 * Description   : Return rx bit clock direction, true -> internal; false -> external
 *
 *END**************************************************************************/
static inline bool SAI_DRV_isRxBitClockDirInternal(const SAI_Type* base)
{
    bool ret;
    uint32_t temp  = base->RCFG0;
    
    if ((temp & SAI_RCFG0_BCD_MASK) == (1UL << ((uint32_t)SAI_RCFG0_BCD_SHIFT)))
    {
        ret = true;
    }
    else
    {
        ret = false;
    }
    return ret;
}

/*FUNCTION**********************************************************************
 *
 * Function Name : SAI_DRV_isMasterClockEnable
 * Description   : Return master clock is enable or disable, true -> enable; false -> disable
 *
 *END**************************************************************************/
static inline bool SAI_DRV_isMasterClockEnable(const SAI_Type* base)
{
    bool ret;
    uint32_t temp  = base->MCLK_CTRL;
    /*Judge whether MCLK is enabled*/
    if ((temp & SAI_MCLK_CTRL_MCKEN_MASK) == (1UL << ((uint32_t)SAI_MCLK_CTRL_MCKEN_SHIFT)))
    {
        ret = true;
    }
    else
    {
        ret = false;
    }
    return ret;
}

/*FUNCTION**********************************************************************
 *
 * Function Name : SAI_DRV_GetMaterClockSource
 * Description   : Return master clock source
 *
 *END**************************************************************************/
static inline uint32_t SAI_DRV_GetMaterClockSource(const SAI_Type* base)
{
    uint32_t temp  = base->MCLK_CTRL;   
    /* Get MCLK Source */
    return ((temp & SAI_MCLK_CTRL_CLKSEL_MASK) >> SAI_MCLK_CTRL_CLKSEL_SHIFT);

}

/*FUNCTION**********************************************************************
 *
 * Function Name : SAI_DRV_TxEnableFifoReqInt
 * Description   : Enable fifo request interrupt
 *
 *END**************************************************************************/
static inline void SAI_DRV_TxEnableFifoReqInt(SAI_Type* base)
{
    uint32_t val = base->TINTE; 

    /* enable fifo request int */
    val |= 1UL << SAI_TINTE_FRIE_SHIFT;
    base->TINTE = val;
}

/*FUNCTION**********************************************************************
 *
 * Function Name : SAI_DRV_RxEnableFifoReqInt
 * Description   : Enable fifo request interrupt
 *
 *END**************************************************************************/
static inline void SAI_DRV_RxEnableFifoReqInt(SAI_Type* base)
{
    uint32_t val = base->RINTE; 
    /* enable fifo request int */
    val |= 1UL << SAI_RINTE_FRIE_SHIFT;
    base->RINTE = val;
}

/*FUNCTION**********************************************************************
 *
 * Function Name : SAI_DRV_TxDisableFifoReqDma
 * Description   : Disable fifo request dma
 *
 *END**************************************************************************/
static inline void SAI_DRV_TxDisableFifoReqDma(SAI_Type* base)
{
    uint32_t val = base->TFCR; 
    /* disable fifo request dma */
    val &= ~(0x0FU << SAI_TFCR_FRDE_SHIFT);
    base->TFCR = val;
}

/*FUNCTION**********************************************************************
 *
 * Function Name : SAI_DRV_TxEnableFifoReqDma
 * Description   : Enable fifo request dma
 *
 *END**************************************************************************/
static inline void SAI_DRV_TxEnableFifoReqDma(SAI_Type* base, uint8_t chnEnable)
{
    uint32_t val = base->TFCR; 

    /* enable fifo request int */
    val |= ((uint32_t)chnEnable << SAI_TFCR_FRDE_SHIFT);
    base->TFCR = val;
}

/*FUNCTION**********************************************************************
 *
 * Function Name : SAI_DRV_RxDisableFifoReqDma
 * Description   : Disable fifo request dma
 *
 *END**************************************************************************/
static inline void SAI_DRV_RxDisableFifoReqDma(SAI_Type* base)
{
    uint32_t val = base->RFCR;

    /* enable fifo request int */
    val &= ~(0xFUL << SAI_RFCR_FRDE_SHIFT);
    base->RFCR = val;
}

/*FUNCTION**********************************************************************
 *
 * Function Name : SAI_DRV_RxEnableFifoReqDma
 * Description   : Enable fifo request dma
 *
 *END**************************************************************************/
static inline void SAI_DRV_RxEnableFifoReqDma(SAI_Type* base, uint8_t chnEnable)
{
    uint32_t val = base->RFCR;
    /* enable fifo request DMA */
    val |= ((uint32_t)chnEnable << SAI_RFCR_FRDE_SHIFT) & SAI_RFCR_FRDE_MASK;
    base->RFCR = val;
}

/*FUNCTION**********************************************************************
 *
 * Function Name : SAI_DRV_TxReset
 * Description   : Reset transmitter
 *
 *END**************************************************************************/
static inline void SAI_DRV_TxReset(SAI_Type* base)
{
    uint32_t val = base->TCTRL;
    val |= (1UL << SAI_TCTRL_SR_SHIFT);
    base->TCTRL= val;
    val = base->TCTRL;
    val &= ~(1UL << SAI_TCTRL_SR_SHIFT);
    base->TCTRL = val;
}

/*FUNCTION**********************************************************************
 *
 * Function Name : SAI_DRV_RxReset
 * Description   : Reset receiver
 *
 *END**************************************************************************/
static inline void SAI_DRV_RxReset(SAI_Type* base)
{
    uint32_t val = base->RCTRL;
    val |= (1UL << SAI_RCTRL_SR_SHIFT);
    base->RCTRL = val;
    val = base->RCTRL;
    val &= ~(1UL << SAI_TCTRL_SR_SHIFT);
    base->RCTRL = val;
}

/*FUNCTION**********************************************************************
 *
 * Function Name : SAI_DRV_TxResetFifo
 * Description   : Reset fifo
 *
 *END**************************************************************************/
static inline void SAI_DRV_TxResetFifo(SAI_Type* base)
{
    uint32_t val = base->TFCR;
    val |= (1UL << SAI_TFCR_FR_SHIFT);
    base->TFCR = val;
}

/*FUNCTION**********************************************************************
 *
 * Function Name : SAI_DRV_RxResetFifo
 * Description   : Reset fifo
 *
 *END**************************************************************************/
static inline void SAI_DRV_RxResetFifo(SAI_Type* base)
{
    uint32_t val = base->RFCR;
    val |= (1UL << SAI_RFCR_FR_SHIFT);
    base->RFCR = val;
}

/*FUNCTION**********************************************************************
 *
 * Function Name : SAI_DRV_TxGetWordStartFlag
 * Description   : Return tx word start flag
 *
 *END**************************************************************************/
static inline bool SAI_DRV_TxGetWordStartFlag(const SAI_Type* base)
{
    uint32_t temp = base->TSTS;
    uint32_t temp1 = base->TINTE;
    return (((temp & SAI_TSTS_WSF_MASK) != 0UL) && ((temp1 & SAI_TINTE_WSIE_MASK) != 0UL));
}

/*FUNCTION**********************************************************************
 *
 * Function Name : SAI_DRV_TxGetFifoWarningFlag
 * Description   : Return tx warning interrupt flag
 *
 *END**************************************************************************/
static inline bool SAI_DRV_TxGetFifoWarningFlag(const SAI_Type* base)
{
    uint32_t temp = base->TSTS;
    uint32_t temp1 = base->TINTE;
    return (((temp & SAI_TSTS_FWF_MASK) != 0UL) && ((temp1 & SAI_TINTE_FWIE_MASK) != 0UL));
}
/*******************************************************************************
 * EOF
 ******************************************************************************/
 #endif
